11 #include <sys/ioctl.h>
13 #include <sys/sysmacros.h>
14 #include <sys/types.h>
18 #include <uuid/uuid.h>
20 #include "libbcachefs.h"
21 #include "libbcachefs/bcachefs_ioctl.h"
22 #include "linux/sort.h"
23 #include "tools-util.h"
24 #include "libbcachefs/util.h"
26 void die(const char *fmt, ...)
31 vfprintf(stderr, fmt, args);
38 char *mprintf(const char *fmt, ...)
45 ret = vasprintf(&str, fmt, args);
49 die("insufficient memory");
54 void xpread(int fd, void *buf, size_t count, off_t offset)
57 ssize_t r = pread(fd, buf, count, offset);
60 die("read error: %m");
62 die("pread error: unexpected eof");
68 void xpwrite(int fd, const void *buf, size_t count, off_t offset, const char *msg)
70 ssize_t r = pwrite(fd, buf, count, offset);
73 die("error writing %s (ret %zi err %m)", msg, r);
76 struct stat xfstatat(int dirfd, const char *path, int flags)
79 if (fstatat(dirfd, path, &stat, flags))
80 die("stat error: %m");
84 struct stat xfstat(int fd)
88 die("stat error: %m");
92 struct stat xstat(const char *path)
95 if (stat(path, &statbuf))
96 die("stat error statting %s: %m", path);
100 /* File parsing (i.e. sysfs) */
102 void write_file_str(int dirfd, const char *path, const char *str)
104 int fd = xopenat(dirfd, path, O_WRONLY);
105 ssize_t wrote, len = strlen(str);
107 wrote = write(fd, str, len);
109 die("read error: %m");
113 char *read_file_str(int dirfd, const char *path)
115 int fd = xopenat(dirfd, path, O_RDONLY);
116 ssize_t len = xfstat(fd).st_size;
118 char *buf = xmalloc(len + 1);
120 len = read(fd, buf, len);
122 die("read error: %m");
125 if (len && buf[len - 1] == '\n')
137 u64 read_file_u64(int dirfd, const char *path)
139 char *buf = read_file_str(dirfd, path);
141 if (bch2_strtou64_h(buf, &v))
142 die("read_file_u64: error parsing %s (got %s)", path, buf);
147 /* String list options: */
149 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
152 ssize_t v = match_string(list, -1, opt);
154 die("Bad %s %s", msg, opt);
159 /* Returns size of file or block device: */
162 struct stat statbuf = xfstat(fd);
164 if (!S_ISBLK(statbuf.st_mode))
165 return statbuf.st_size;
168 xioctl(fd, BLKGETSIZE64, &ret);
172 /* Returns blocksize, in bytes: */
173 unsigned get_blocksize(int fd)
175 struct stat statbuf = xfstat(fd);
177 if (!S_ISBLK(statbuf.st_mode))
178 return statbuf.st_blksize;
181 xioctl(fd, BLKPBSZGET, &ret);
185 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
186 int open_for_format(struct dev_opts *dev, bool force)
189 const char *fs_type = NULL, *fs_label = NULL;
190 size_t fs_type_len, fs_label_len;
192 dev->bdev = blkdev_get_by_path(dev->path, BLK_OPEN_READ|BLK_OPEN_WRITE|BLK_OPEN_EXCL,
194 int ret = PTR_ERR_OR_ZERO(dev->bdev);
196 die("Error opening device to format %s: %s", dev->path, strerror(-ret));
198 if (!(pr = blkid_new_probe()))
199 die("blkid error 1");
200 if (blkid_probe_set_device(pr, dev->bdev->bd_buffered_fd, 0, 0))
201 die("blkid error 2");
202 if (blkid_probe_enable_partitions(pr, true) ||
203 blkid_probe_enable_superblocks(pr, true) ||
204 blkid_probe_set_superblocks_flags(pr,
205 BLKID_SUBLKS_LABEL|BLKID_SUBLKS_TYPE|BLKID_SUBLKS_MAGIC))
206 die("blkid error 3");
207 if (blkid_do_fullprobe(pr) < 0)
208 die("blkid error 4");
210 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
211 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
215 printf("%s contains a %s filesystem labelled '%s'\n",
216 dev->path, fs_type, fs_label);
218 printf("%s contains a %s filesystem\n",
221 fputs("Proceed anyway?", stdout);
225 while (blkid_do_probe(pr) == 0) {
226 if (blkid_do_wipe(pr, 0))
227 die("Failed to wipe preexisting metadata.");
231 blkid_free_probe(pr);
237 const char *short_yes = "yY";
242 fputs(" (y,n) ", stdout);
245 if (getline(&buf, &buflen, stdin) < 0)
246 die("error reading from standard input");
248 ret = strchr(short_yes, buf[0]);
253 static int range_cmp(const void *_l, const void *_r)
255 const struct range *l = _l, *r = _r;
257 if (l->start < r->start)
259 if (l->start > r->start)
264 void ranges_sort_merge(ranges *r)
268 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
270 /* Merge contiguous ranges: */
271 darray_for_each(*r, i) {
272 struct range *t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
274 if (t && t->end >= i->start)
275 t->end = max(t->end, i->end);
277 darray_push(&tmp, *i);
284 void ranges_roundup(ranges *r, unsigned block_size)
286 darray_for_each(*r, i) {
287 i->start = round_down(i->start, block_size);
288 i->end = round_up(i->end, block_size);
292 void ranges_rounddown(ranges *r, unsigned block_size)
294 darray_for_each(*r, i) {
295 i->start = round_up(i->start, block_size);
296 i->end = round_down(i->end, block_size);
297 i->end = max(i->end, i->start);
301 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
303 struct fiemap_extent e;
305 BUG_ON(iter->idx > iter->f->fm_mapped_extents);
307 if (iter->idx == iter->f->fm_mapped_extents) {
308 xioctl(iter->fd, FS_IOC_FIEMAP, iter->f);
310 if (!iter->f->fm_mapped_extents)
311 return (struct fiemap_extent) { .fe_length = 0 };
316 e = iter->f->fm_extents[iter->idx++];
317 BUG_ON(!e.fe_length);
319 iter->f->fm_start = e.fe_logical + e.fe_length;
324 char *strcmp_prefix(char *a, const char *a_prefix)
326 while (*a_prefix && *a == *a_prefix) {
330 return *a_prefix ? NULL : a;
335 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
337 static const u32 crc32c_tab[] = {
338 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
339 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
340 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
341 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
342 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
343 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
344 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
345 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
346 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
347 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
348 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
349 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
350 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
351 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
352 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
353 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
354 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
355 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
356 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
357 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
358 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
359 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
360 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
361 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
362 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
363 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
364 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
365 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
366 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
367 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
368 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
369 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
370 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
371 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
372 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
373 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
374 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
375 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
376 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
377 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
378 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
379 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
380 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
381 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
382 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
383 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
384 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
385 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
386 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
387 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
388 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
389 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
390 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
391 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
392 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
393 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
394 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
395 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
396 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
397 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
398 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
399 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
400 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
401 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
406 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
411 #include <linux/compiler.h>
416 #define REX_PRE "0x48, "
421 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
423 while (size >= sizeof(long)) {
424 const unsigned long *d = buf;
426 __asm__ __volatile__(
427 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
432 size -= sizeof(long);
438 __asm__ __volatile__(
439 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
452 static void *resolve_crc32c(void)
455 if (__builtin_cpu_supports("sse4.2"))
458 return crc32c_default;
462 * ifunc is buggy and I don't know what breaks it (LTO?)
464 #ifdef HAVE_WORKING_IFUNC
466 static void *ifunc_resolve_crc32c(void)
468 __builtin_cpu_init();
470 return resolve_crc32c
473 u32 crc32c(u32, const void *, size_t)
474 __attribute__((ifunc("ifunc_resolve_crc32c")));
478 u32 crc32c(u32 crc, const void *buf, size_t size)
480 static u32 (*real_crc32c)(u32, const void *, size_t);
482 if (unlikely(!real_crc32c))
483 real_crc32c = resolve_crc32c();
485 return real_crc32c(crc, buf, size);
488 #endif /* HAVE_WORKING_IFUNC */
490 char *dev_to_name(dev_t dev)
492 char *line = NULL, *name = NULL;
495 FILE *f = fopen("/proc/partitions", "r");
497 die("error opening /proc/partitions: %m");
499 while (getline(&line, &n, f) != -1) {
503 name = realloc(name, n + 1);
505 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
506 ma == major(dev) && mi == minor(dev))
518 char *dev_to_path(dev_t dev)
520 char *name = dev_to_name(dev);
524 char *path = mprintf("/dev/%s", name);
530 struct mntent *dev_to_mount(char *dev)
532 struct mntent *mnt, *ret = NULL;
533 FILE *f = setmntent("/proc/mounts", "r");
535 die("error opening /proc/mounts: %m");
537 struct stat d1 = xstat(dev);
539 while ((mnt = getmntent(f))) {
540 char *d, *p = mnt->mnt_fsname;
542 while ((d = strsep(&p, ":"))) {
548 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
551 if (S_ISBLK(d1.st_mode)) {
552 if (d1.st_rdev != d2.st_rdev)
555 if (d1.st_dev != d2.st_dev ||
556 d1.st_ino != d2.st_ino)
569 int dev_mounted(char *dev)
571 struct mntent *mnt = dev_to_mount(dev);
575 if (hasmntopt(mnt, "ro"))
580 static int kstrtoull_symbolic(const char *s, unsigned int base, unsigned long long *res)
582 if (!strcmp(s, "U64_MAX")) {
587 if (!strcmp(s, "U32_MAX")) {
592 return kstrtoull(s, base, res);
595 static int kstrtouint_symbolic(const char *s, unsigned int base, unsigned *res)
597 unsigned long long tmp;
600 rv = kstrtoull_symbolic(s, base, &tmp);
603 if (tmp != (unsigned long long)(unsigned int)tmp)
609 struct bpos bpos_parse(char *buf)
611 char *orig = strdup(buf);
614 char *inode_s = strsep(&s, ":");
615 char *offset_s = strsep(&s, ":");
616 char *snapshot_s = strsep(&s, ":");
618 if (!inode_s || !offset_s || s)
619 die("invalid bpos %s", orig);
622 u64 inode_v = 0, offset_v = 0;
624 if (kstrtoull_symbolic(inode_s, 10, &inode_v))
625 die("invalid bpos.inode %s", inode_s);
627 if (kstrtoull_symbolic(offset_s, 10, &offset_v))
628 die("invalid bpos.offset %s", offset_s);
631 kstrtouint_symbolic(snapshot_s, 10, &snapshot_v))
632 die("invalid bpos.snapshot %s", snapshot_s);
634 return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
637 struct bbpos bbpos_parse(char *buf)
639 char *s = buf, *field;
642 if (!(field = strsep(&s, ":")))
643 die("invalid bbpos %s", buf);
645 ret.btree = read_string_list_or_die(field, __bch2_btree_ids, "btree id");
648 die("invalid bbpos %s", buf);
650 ret.pos = bpos_parse(s);
654 darray_str get_or_split_cmdline_devs(int argc, char *argv[])
659 bch2_split_devs(argv[0], &ret);
661 for (unsigned i = 0; i < argc; i++)
662 darray_push(&ret, strdup(argv[i]));