11 #include <sys/ioctl.h>
13 #include <sys/sysmacros.h>
14 #include <sys/types.h>
18 #include <uuid/uuid.h>
20 #include "libbcachefs/bcachefs_ioctl.h"
21 #include "linux/sort.h"
22 #include "tools-util.h"
23 #include "libbcachefs/util.h"
25 void die(const char *fmt, ...)
30 vfprintf(stderr, fmt, args);
37 char *mprintf(const char *fmt, ...)
44 ret = vasprintf(&str, fmt, args);
48 die("insufficient memory");
53 void *xcalloc(size_t count, size_t size)
55 void *p = calloc(count, size);
58 die("insufficient memory");
63 void *xmalloc(size_t size)
65 void *p = malloc(size);
68 die("insufficient memory");
74 void *xrealloc(void *p, size_t size)
78 die("insufficient memory");
83 void xpread(int fd, void *buf, size_t count, off_t offset)
86 ssize_t r = pread(fd, buf, count, offset);
89 die("read error: %m");
91 die("pread error: unexpected eof");
97 void xpwrite(int fd, const void *buf, size_t count, off_t offset)
99 ssize_t r = pwrite(fd, buf, count, offset);
102 die("write error (ret %zi err %m)", r);
105 struct stat xfstatat(int dirfd, const char *path, int flags)
108 if (fstatat(dirfd, path, &stat, flags))
109 die("stat error: %m");
113 struct stat xfstat(int fd)
116 if (fstat(fd, &stat))
117 die("stat error: %m");
121 struct stat xstat(const char *path)
124 if (stat(path, &statbuf))
125 die("stat error statting %s: %m", path);
131 int printf_pad(unsigned pad, const char * fmt, ...)
137 ret = vprintf(fmt, args);
146 struct units_buf __pr_units(s64 _v, enum units units)
148 struct units_buf ret;
149 char *out = ret.b, *end = out + sizeof(ret.b);
153 out += scnprintf(out, end - out, "-");
159 snprintf(out, end - out, "%llu", v << 9);
162 snprintf(out, end - out, "%llu", v);
168 int exp = log(v) / log(1024);
169 snprintf(out, end - out, "%.1f%c",
173 snprintf(out, end - out, "%llu", v);
182 /* Argument parsing stuff: */
184 /* File parsing (i.e. sysfs) */
186 char *read_file_str(int dirfd, const char *path)
188 int fd = xopenat(dirfd, path, O_RDONLY);
189 ssize_t len = xfstat(fd).st_size;
191 char *buf = xmalloc(len + 1);
193 len = read(fd, buf, len);
195 die("read error: %m");
198 if (len && buf[len - 1] == '\n')
210 u64 read_file_u64(int dirfd, const char *path)
212 char *buf = read_file_str(dirfd, path);
214 if (kstrtou64(buf, 10, &v))
215 die("read_file_u64: error parsing %s (got %s)", path, buf);
220 /* String list options: */
222 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
225 ssize_t v = match_string(list, -1, opt);
227 die("Bad %s %s", msg, opt);
232 /* Returns size of file or block device: */
233 u64 get_size(const char *path, int fd)
235 struct stat statbuf = xfstat(fd);
237 if (!S_ISBLK(statbuf.st_mode))
238 return statbuf.st_size;
241 xioctl(fd, BLKGETSIZE64, &ret);
245 /* Returns blocksize in units of 512 byte sectors: */
246 unsigned get_blocksize(const char *path, int fd)
248 struct stat statbuf = xfstat(fd);
250 if (!S_ISBLK(statbuf.st_mode))
251 return statbuf.st_blksize >> 9;
254 xioctl(fd, BLKPBSZGET, &ret);
258 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
259 int open_for_format(const char *dev, bool force)
262 const char *fs_type = NULL, *fs_label = NULL;
263 size_t fs_type_len, fs_label_len;
265 int fd = xopen(dev, O_RDWR|O_EXCL);
270 if (!(pr = blkid_new_probe()))
271 die("blkid error 1");
272 if (blkid_probe_set_device(pr, fd, 0, 0))
273 die("blkid error 2");
274 if (blkid_probe_enable_partitions(pr, true))
275 die("blkid error 3");
276 if (blkid_do_fullprobe(pr) < 0)
277 die("blkid error 4");
279 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
280 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
284 printf("%s contains a %s filesystem labelled '%s'\n",
285 dev, fs_type, fs_label);
287 printf("%s contains a %s filesystem\n",
289 fputs("Proceed anyway?", stdout);
292 while (blkid_do_probe(pr) == 0)
293 blkid_do_wipe(pr, 0);
296 blkid_free_probe(pr);
302 const char *short_yes = "yY";
307 fputs(" (y,n) ", stdout);
310 if (getline(&buf, &buflen, stdin) < 0)
311 die("error reading from standard input");
313 ret = strchr(short_yes, buf[0]);
318 static int range_cmp(const void *_l, const void *_r)
320 const struct range *l = _l, *r = _r;
322 if (l->start < r->start)
324 if (l->start > r->start)
329 void ranges_sort_merge(ranges *r)
332 ranges tmp = { NULL };
334 sort(&darray_item(*r, 0), darray_size(*r),
335 sizeof(darray_item(*r, 0)), range_cmp, NULL);
337 /* Merge contiguous ranges: */
338 darray_foreach(i, *r) {
339 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
341 if (t && t->end >= i->start)
342 t->end = max(t->end, i->end);
344 darray_append(tmp, *i);
351 void ranges_roundup(ranges *r, unsigned block_size)
355 darray_foreach(i, *r) {
356 i->start = round_down(i->start, block_size);
357 i->end = round_up(i->end, block_size);
361 void ranges_rounddown(ranges *r, unsigned block_size)
365 darray_foreach(i, *r) {
366 i->start = round_up(i->start, block_size);
367 i->end = round_down(i->end, block_size);
368 i->end = max(i->end, i->start);
372 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
374 struct fiemap_extent e;
376 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
378 if (iter->idx == iter->f.fm_mapped_extents) {
379 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
381 if (!iter->f.fm_mapped_extents)
382 return (struct fiemap_extent) { .fe_length = 0 };
387 e = iter->f.fm_extents[iter->idx++];
388 BUG_ON(!e.fe_length);
390 iter->f.fm_start = e.fe_logical + e.fe_length;
395 char *strcmp_prefix(char *a, const char *a_prefix)
397 while (*a_prefix && *a == *a_prefix) {
401 return *a_prefix ? NULL : a;
404 unsigned hatoi_validate(const char *s, const char *msg)
408 if (bch2_strtoull_h(s, &v))
409 die("bad %s %s", msg, s);
414 die("%s too large\n", msg);
417 die("%s too small\n", msg);
424 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
426 static const u32 crc32c_tab[] = {
427 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
428 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
429 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
430 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
431 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
432 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
433 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
434 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
435 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
436 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
437 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
438 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
439 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
440 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
441 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
442 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
443 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
444 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
445 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
446 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
447 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
448 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
449 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
450 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
451 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
452 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
453 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
454 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
455 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
456 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
457 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
458 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
459 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
460 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
461 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
462 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
463 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
464 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
465 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
466 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
467 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
468 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
469 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
470 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
471 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
472 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
473 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
474 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
475 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
476 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
477 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
478 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
479 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
480 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
481 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
482 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
483 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
484 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
485 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
486 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
487 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
488 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
489 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
490 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
495 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
500 #include <linux/compiler.h>
505 #define REX_PRE "0x48, "
510 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
512 while (size >= sizeof(long)) {
513 const unsigned long *d = buf;
515 __asm__ __volatile__(
516 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
521 size -= sizeof(long);
527 __asm__ __volatile__(
528 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
541 static void *resolve_crc32c(void)
544 if (__builtin_cpu_supports("sse4.2"))
547 return crc32c_default;
551 * ifunc is buggy and I don't know what breaks it (LTO?)
553 #ifdef HAVE_WORKING_IFUNC
555 static void *ifunc_resolve_crc32c(void)
557 __builtin_cpu_init();
559 return resolve_crc32c
562 u32 crc32c(u32, const void *, size_t)
563 __attribute__((ifunc("ifunc_resolve_crc32c")));
567 u32 crc32c(u32 crc, const void *buf, size_t size)
569 static u32 (*real_crc32c)(u32, const void *, size_t);
571 if (unlikely(!real_crc32c))
572 real_crc32c = resolve_crc32c();
574 return real_crc32c(crc, buf, size);
577 #endif /* HAVE_WORKING_IFUNC */
579 char *dev_to_name(dev_t dev)
581 char *line = NULL, *name = NULL;
584 FILE *f = fopen("/proc/partitions", "r");
586 die("error opening /proc/partitions: %m");
588 while (getline(&line, &n, f) != -1) {
592 name = realloc(name, n + 1);
594 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
595 ma == major(dev) && mi == minor(dev))
607 char *dev_to_path(dev_t dev)
609 char *name = dev_to_name(dev);
613 char *path = mprintf("/dev/%s", name);
619 struct mntent *dev_to_mount(char *dev)
621 struct mntent *mnt, *ret = NULL;
622 FILE *f = setmntent("/proc/mounts", "r");
624 die("error opening /proc/mounts: %m");
626 struct stat d1 = xstat(dev);
628 while ((mnt = getmntent(f))) {
629 char *d, *p = mnt->mnt_fsname;
631 while ((d = strsep(&p, ":"))) {
637 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
640 if (S_ISBLK(d1.st_mode)) {
641 if (d1.st_rdev != d2.st_rdev)
644 if (d1.st_dev != d2.st_dev ||
645 d1.st_ino != d2.st_ino)
658 int dev_mounted(char *dev)
660 struct mntent *mnt = dev_to_mount(dev);
664 if (hasmntopt(mnt, "ro"))
669 struct bpos bpos_parse(char *buf)
671 char *s = buf, *field;
672 u64 inode_v = 0, offset_v = 0;
674 if (!(field = strsep(&s, ":")) ||
675 kstrtoull(field, 10, &inode_v))
676 die("invalid bpos %s", buf);
678 if ((field = strsep(&s, ":")) &&
679 kstrtoull(field, 10, &offset_v))
680 die("invalid bpos %s", buf);
683 die("invalid bpos %s", buf);
685 return (struct bpos) { .inode = inode_v, .offset = offset_v };