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)
298 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
300 /* Merge contiguous ranges: */
301 darray_for_each(*r, i) {
302 struct range *t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
304 if (t && t->end >= i->start)
305 t->end = max(t->end, i->end);
307 darray_push(&tmp, *i);
314 void ranges_roundup(ranges *r, unsigned block_size)
316 darray_for_each(*r, i) {
317 i->start = round_down(i->start, block_size);
318 i->end = round_up(i->end, block_size);
322 void ranges_rounddown(ranges *r, unsigned block_size)
324 darray_for_each(*r, i) {
325 i->start = round_up(i->start, block_size);
326 i->end = round_down(i->end, block_size);
327 i->end = max(i->end, i->start);
331 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
333 struct fiemap_extent e;
335 BUG_ON(iter->idx > iter->f->fm_mapped_extents);
337 if (iter->idx == iter->f->fm_mapped_extents) {
338 xioctl(iter->fd, FS_IOC_FIEMAP, iter->f);
340 if (!iter->f->fm_mapped_extents)
341 return (struct fiemap_extent) { .fe_length = 0 };
346 e = iter->f->fm_extents[iter->idx++];
347 BUG_ON(!e.fe_length);
349 iter->f->fm_start = e.fe_logical + e.fe_length;
354 char *strcmp_prefix(char *a, const char *a_prefix)
356 while (*a_prefix && *a == *a_prefix) {
360 return *a_prefix ? NULL : a;
365 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
367 static const u32 crc32c_tab[] = {
368 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
369 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
370 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
371 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
372 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
373 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
374 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
375 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
376 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
377 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
378 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
379 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
380 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
381 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
382 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
383 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
384 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
385 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
386 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
387 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
388 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
389 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
390 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
391 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
392 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
393 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
394 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
395 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
396 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
397 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
398 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
399 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
400 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
401 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
402 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
403 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
404 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
405 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
406 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
407 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
408 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
409 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
410 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
411 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
412 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
413 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
414 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
415 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
416 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
417 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
418 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
419 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
420 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
421 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
422 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
423 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
424 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
425 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
426 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
427 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
428 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
429 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
430 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
431 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
436 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
441 #include <linux/compiler.h>
446 #define REX_PRE "0x48, "
451 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
453 while (size >= sizeof(long)) {
454 const unsigned long *d = buf;
456 __asm__ __volatile__(
457 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
462 size -= sizeof(long);
468 __asm__ __volatile__(
469 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
482 static void *resolve_crc32c(void)
485 if (__builtin_cpu_supports("sse4.2"))
488 return crc32c_default;
492 * ifunc is buggy and I don't know what breaks it (LTO?)
494 #ifdef HAVE_WORKING_IFUNC
496 static void *ifunc_resolve_crc32c(void)
498 __builtin_cpu_init();
500 return resolve_crc32c
503 u32 crc32c(u32, const void *, size_t)
504 __attribute__((ifunc("ifunc_resolve_crc32c")));
508 u32 crc32c(u32 crc, const void *buf, size_t size)
510 static u32 (*real_crc32c)(u32, const void *, size_t);
512 if (unlikely(!real_crc32c))
513 real_crc32c = resolve_crc32c();
515 return real_crc32c(crc, buf, size);
518 #endif /* HAVE_WORKING_IFUNC */
520 char *dev_to_name(dev_t dev)
522 char *line = NULL, *name = NULL;
525 FILE *f = fopen("/proc/partitions", "r");
527 die("error opening /proc/partitions: %m");
529 while (getline(&line, &n, f) != -1) {
533 name = realloc(name, n + 1);
535 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
536 ma == major(dev) && mi == minor(dev))
548 char *dev_to_path(dev_t dev)
550 char *name = dev_to_name(dev);
554 char *path = mprintf("/dev/%s", name);
560 struct mntent *dev_to_mount(char *dev)
562 struct mntent *mnt, *ret = NULL;
563 FILE *f = setmntent("/proc/mounts", "r");
565 die("error opening /proc/mounts: %m");
567 struct stat d1 = xstat(dev);
569 while ((mnt = getmntent(f))) {
570 char *d, *p = mnt->mnt_fsname;
572 while ((d = strsep(&p, ":"))) {
578 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
581 if (S_ISBLK(d1.st_mode)) {
582 if (d1.st_rdev != d2.st_rdev)
585 if (d1.st_dev != d2.st_dev ||
586 d1.st_ino != d2.st_ino)
599 int dev_mounted(char *dev)
601 struct mntent *mnt = dev_to_mount(dev);
605 if (hasmntopt(mnt, "ro"))
610 static int kstrtoull_symbolic(const char *s, unsigned int base, unsigned long long *res)
612 if (!strcmp(s, "U64_MAX")) {
617 if (!strcmp(s, "U32_MAX")) {
622 return kstrtoull(s, base, res);
625 static int kstrtouint_symbolic(const char *s, unsigned int base, unsigned *res)
627 unsigned long long tmp;
630 rv = kstrtoull_symbolic(s, base, &tmp);
633 if (tmp != (unsigned long long)(unsigned int)tmp)
639 struct bpos bpos_parse(char *buf)
641 char *orig = strdup(buf);
644 char *inode_s = strsep(&s, ":");
645 char *offset_s = strsep(&s, ":");
646 char *snapshot_s = strsep(&s, ":");
648 if (!inode_s || !offset_s || s)
649 die("invalid bpos %s", orig);
652 u64 inode_v = 0, offset_v = 0;
654 if (kstrtoull_symbolic(inode_s, 10, &inode_v))
655 die("invalid bpos.inode %s", inode_s);
657 if (kstrtoull_symbolic(offset_s, 10, &offset_v))
658 die("invalid bpos.offset %s", offset_s);
661 kstrtouint_symbolic(snapshot_s, 10, &snapshot_v))
662 die("invalid bpos.snapshot %s", snapshot_s);
664 return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
667 struct bbpos bbpos_parse(char *buf)
669 char *s = buf, *field;
672 if (!(field = strsep(&s, ":")))
673 die("invalid bbpos %s", buf);
675 ret.btree = read_string_list_or_die(field, __bch2_btree_ids, "btree id");
678 die("invalid bbpos %s", buf);
680 ret.pos = bpos_parse(s);