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 *xcalloc(size_t count, size_t size)
56 void *p = calloc(count, size);
59 die("insufficient memory");
64 void *xmalloc(size_t size)
66 void *p = malloc(size);
69 die("insufficient memory");
75 void *xrealloc(void *p, size_t size)
79 die("insufficient memory");
84 void xpread(int fd, void *buf, size_t count, off_t offset)
87 ssize_t r = pread(fd, buf, count, offset);
90 die("read error: %m");
92 die("pread error: unexpected eof");
98 void xpwrite(int fd, const void *buf, size_t count, off_t offset, const char *msg)
100 ssize_t r = pwrite(fd, buf, count, offset);
103 die("error writing %s (ret %zi err %m)", msg, r);
106 struct stat xfstatat(int dirfd, const char *path, int flags)
109 if (fstatat(dirfd, path, &stat, flags))
110 die("stat error: %m");
114 struct stat xfstat(int fd)
117 if (fstat(fd, &stat))
118 die("stat error: %m");
122 struct stat xstat(const char *path)
125 if (stat(path, &statbuf))
126 die("stat error statting %s: %m", path);
130 /* File parsing (i.e. sysfs) */
132 void write_file_str(int dirfd, const char *path, const char *str)
134 int fd = xopenat(dirfd, path, O_WRONLY);
135 ssize_t wrote, len = strlen(str);
137 wrote = write(fd, str, len);
139 die("read error: %m");
143 char *read_file_str(int dirfd, const char *path)
145 int fd = xopenat(dirfd, path, O_RDONLY);
146 ssize_t len = xfstat(fd).st_size;
148 char *buf = xmalloc(len + 1);
150 len = read(fd, buf, len);
152 die("read error: %m");
155 if (len && buf[len - 1] == '\n')
167 u64 read_file_u64(int dirfd, const char *path)
169 char *buf = read_file_str(dirfd, path);
171 if (bch2_strtou64_h(buf, &v))
172 die("read_file_u64: error parsing %s (got %s)", path, buf);
177 /* String list options: */
179 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
182 ssize_t v = match_string(list, -1, opt);
184 die("Bad %s %s", msg, opt);
189 /* Returns size of file or block device: */
192 struct stat statbuf = xfstat(fd);
194 if (!S_ISBLK(statbuf.st_mode))
195 return statbuf.st_size;
198 xioctl(fd, BLKGETSIZE64, &ret);
202 /* Returns blocksize, in bytes: */
203 unsigned get_blocksize(int fd)
205 struct stat statbuf = xfstat(fd);
207 if (!S_ISBLK(statbuf.st_mode))
208 return statbuf.st_blksize;
211 xioctl(fd, BLKPBSZGET, &ret);
215 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
216 int open_for_format(struct dev_opts *dev, bool force)
219 const char *fs_type = NULL, *fs_label = NULL;
220 size_t fs_type_len, fs_label_len;
222 dev->bdev = blkdev_get_by_path(dev->path, BLK_OPEN_READ|BLK_OPEN_WRITE|BLK_OPEN_EXCL,
224 int ret = PTR_ERR_OR_ZERO(dev->bdev);
226 die("Error opening device to format %s: %s", dev->path, strerror(-ret));
228 if (!(pr = blkid_new_probe()))
229 die("blkid error 1");
230 if (blkid_probe_set_device(pr, dev->bdev->bd_buffered_fd, 0, 0))
231 die("blkid error 2");
232 if (blkid_probe_enable_partitions(pr, true) ||
233 blkid_probe_enable_superblocks(pr, true) ||
234 blkid_probe_set_superblocks_flags(pr,
235 BLKID_SUBLKS_LABEL|BLKID_SUBLKS_TYPE|BLKID_SUBLKS_MAGIC))
236 die("blkid error 3");
237 if (blkid_do_fullprobe(pr) < 0)
238 die("blkid error 4");
240 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
241 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
245 printf("%s contains a %s filesystem labelled '%s'\n",
246 dev->path, fs_type, fs_label);
248 printf("%s contains a %s filesystem\n",
251 fputs("Proceed anyway?", stdout);
255 while (blkid_do_probe(pr) == 0) {
256 if (blkid_do_wipe(pr, 0))
257 die("Failed to wipe preexisting metadata.");
261 blkid_free_probe(pr);
267 const char *short_yes = "yY";
272 fputs(" (y,n) ", stdout);
275 if (getline(&buf, &buflen, stdin) < 0)
276 die("error reading from standard input");
278 ret = strchr(short_yes, buf[0]);
283 static int range_cmp(const void *_l, const void *_r)
285 const struct range *l = _l, *r = _r;
287 if (l->start < r->start)
289 if (l->start > r->start)
294 void ranges_sort_merge(ranges *r)
299 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
301 /* Merge contiguous ranges: */
302 darray_for_each(*r, i) {
303 t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
305 if (t && t->end >= i->start)
306 t->end = max(t->end, i->end);
308 darray_push(&tmp, *i);
315 void ranges_roundup(ranges *r, unsigned block_size)
319 darray_for_each(*r, i) {
320 i->start = round_down(i->start, block_size);
321 i->end = round_up(i->end, block_size);
325 void ranges_rounddown(ranges *r, unsigned block_size)
329 darray_for_each(*r, i) {
330 i->start = round_up(i->start, block_size);
331 i->end = round_down(i->end, block_size);
332 i->end = max(i->end, i->start);
336 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
338 struct fiemap_extent e;
340 BUG_ON(iter->idx > iter->f->fm_mapped_extents);
342 if (iter->idx == iter->f->fm_mapped_extents) {
343 xioctl(iter->fd, FS_IOC_FIEMAP, iter->f);
345 if (!iter->f->fm_mapped_extents)
346 return (struct fiemap_extent) { .fe_length = 0 };
351 e = iter->f->fm_extents[iter->idx++];
352 BUG_ON(!e.fe_length);
354 iter->f->fm_start = e.fe_logical + e.fe_length;
359 char *strcmp_prefix(char *a, const char *a_prefix)
361 while (*a_prefix && *a == *a_prefix) {
365 return *a_prefix ? NULL : a;
370 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
372 static const u32 crc32c_tab[] = {
373 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
374 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
375 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
376 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
377 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
378 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
379 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
380 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
381 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
382 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
383 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
384 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
385 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
386 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
387 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
388 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
389 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
390 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
391 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
392 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
393 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
394 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
395 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
396 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
397 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
398 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
399 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
400 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
401 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
402 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
403 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
404 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
405 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
406 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
407 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
408 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
409 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
410 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
411 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
412 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
413 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
414 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
415 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
416 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
417 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
418 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
419 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
420 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
421 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
422 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
423 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
424 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
425 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
426 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
427 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
428 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
429 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
430 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
431 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
432 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
433 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
434 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
435 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
436 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
441 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
446 #include <linux/compiler.h>
451 #define REX_PRE "0x48, "
456 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
458 while (size >= sizeof(long)) {
459 const unsigned long *d = buf;
461 __asm__ __volatile__(
462 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
467 size -= sizeof(long);
473 __asm__ __volatile__(
474 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
487 static void *resolve_crc32c(void)
490 if (__builtin_cpu_supports("sse4.2"))
493 return crc32c_default;
497 * ifunc is buggy and I don't know what breaks it (LTO?)
499 #ifdef HAVE_WORKING_IFUNC
501 static void *ifunc_resolve_crc32c(void)
503 __builtin_cpu_init();
505 return resolve_crc32c
508 u32 crc32c(u32, const void *, size_t)
509 __attribute__((ifunc("ifunc_resolve_crc32c")));
513 u32 crc32c(u32 crc, const void *buf, size_t size)
515 static u32 (*real_crc32c)(u32, const void *, size_t);
517 if (unlikely(!real_crc32c))
518 real_crc32c = resolve_crc32c();
520 return real_crc32c(crc, buf, size);
523 #endif /* HAVE_WORKING_IFUNC */
525 char *dev_to_name(dev_t dev)
527 char *line = NULL, *name = NULL;
530 FILE *f = fopen("/proc/partitions", "r");
532 die("error opening /proc/partitions: %m");
534 while (getline(&line, &n, f) != -1) {
538 name = realloc(name, n + 1);
540 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
541 ma == major(dev) && mi == minor(dev))
553 char *dev_to_path(dev_t dev)
555 char *name = dev_to_name(dev);
559 char *path = mprintf("/dev/%s", name);
565 struct mntent *dev_to_mount(char *dev)
567 struct mntent *mnt, *ret = NULL;
568 FILE *f = setmntent("/proc/mounts", "r");
570 die("error opening /proc/mounts: %m");
572 struct stat d1 = xstat(dev);
574 while ((mnt = getmntent(f))) {
575 char *d, *p = mnt->mnt_fsname;
577 while ((d = strsep(&p, ":"))) {
583 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
586 if (S_ISBLK(d1.st_mode)) {
587 if (d1.st_rdev != d2.st_rdev)
590 if (d1.st_dev != d2.st_dev ||
591 d1.st_ino != d2.st_ino)
604 int dev_mounted(char *dev)
606 struct mntent *mnt = dev_to_mount(dev);
610 if (hasmntopt(mnt, "ro"))
615 static int kstrtoull_symbolic(const char *s, unsigned int base, unsigned long long *res)
617 if (!strcmp(s, "U64_MAX")) {
622 if (!strcmp(s, "U32_MAX")) {
627 return kstrtoull(s, base, res);
630 static int kstrtouint_symbolic(const char *s, unsigned int base, unsigned *res)
632 unsigned long long tmp;
635 rv = kstrtoull_symbolic(s, base, &tmp);
638 if (tmp != (unsigned long long)(unsigned int)tmp)
644 struct bpos bpos_parse(char *buf)
646 char *orig = strdup(buf);
649 char *inode_s = strsep(&s, ":");
650 char *offset_s = strsep(&s, ":");
651 char *snapshot_s = strsep(&s, ":");
653 if (!inode_s || !offset_s || s)
654 die("invalid bpos %s", orig);
657 u64 inode_v = 0, offset_v = 0;
659 if (kstrtoull_symbolic(inode_s, 10, &inode_v))
660 die("invalid bpos.inode %s", inode_s);
662 if (kstrtoull_symbolic(offset_s, 10, &offset_v))
663 die("invalid bpos.offset %s", offset_s);
666 kstrtouint_symbolic(snapshot_s, 10, &snapshot_v))
667 die("invalid bpos.snapshot %s", snapshot_s);
669 return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
672 struct bbpos bbpos_parse(char *buf)
674 char *s = buf, *field;
677 if (!(field = strsep(&s, ":")))
678 die("invalid bbpos %s", buf);
680 ret.btree = read_string_list_or_die(field, __bch2_btree_ids, "btree id");
683 die("invalid bbpos %s", buf);
685 ret.pos = bpos_parse(s);