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 (bch2_strtou64_h(buf, &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;
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 = open(dev, O_RDWR|O_EXCL);
267 die("Error opening device to format %s: %m", dev);
272 if (!(pr = blkid_new_probe()))
273 die("blkid error 1");
274 if (blkid_probe_set_device(pr, fd, 0, 0))
275 die("blkid error 2");
276 if (blkid_probe_enable_partitions(pr, true))
277 die("blkid error 3");
278 if (blkid_do_fullprobe(pr) < 0)
279 die("blkid error 4");
281 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
282 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
286 printf("%s contains a %s filesystem labelled '%s'\n",
287 dev, fs_type, fs_label);
289 printf("%s contains a %s filesystem\n",
291 fputs("Proceed anyway?", stdout);
294 while (blkid_do_probe(pr) == 0)
295 blkid_do_wipe(pr, 0);
298 blkid_free_probe(pr);
304 const char *short_yes = "yY";
309 fputs(" (y,n) ", stdout);
312 if (getline(&buf, &buflen, stdin) < 0)
313 die("error reading from standard input");
315 ret = strchr(short_yes, buf[0]);
320 static int range_cmp(const void *_l, const void *_r)
322 const struct range *l = _l, *r = _r;
324 if (l->start < r->start)
326 if (l->start > r->start)
331 void ranges_sort_merge(ranges *r)
334 ranges tmp = { NULL };
336 sort(&darray_item(*r, 0), darray_size(*r),
337 sizeof(darray_item(*r, 0)), range_cmp, NULL);
339 /* Merge contiguous ranges: */
340 darray_foreach(i, *r) {
341 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
343 if (t && t->end >= i->start)
344 t->end = max(t->end, i->end);
346 darray_append(tmp, *i);
353 void ranges_roundup(ranges *r, unsigned block_size)
357 darray_foreach(i, *r) {
358 i->start = round_down(i->start, block_size);
359 i->end = round_up(i->end, block_size);
363 void ranges_rounddown(ranges *r, unsigned block_size)
367 darray_foreach(i, *r) {
368 i->start = round_up(i->start, block_size);
369 i->end = round_down(i->end, block_size);
370 i->end = max(i->end, i->start);
374 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
376 struct fiemap_extent e;
378 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
380 if (iter->idx == iter->f.fm_mapped_extents) {
381 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
383 if (!iter->f.fm_mapped_extents)
384 return (struct fiemap_extent) { .fe_length = 0 };
389 e = iter->f.fm_extents[iter->idx++];
390 BUG_ON(!e.fe_length);
392 iter->f.fm_start = e.fe_logical + e.fe_length;
397 char *strcmp_prefix(char *a, const char *a_prefix)
399 while (*a_prefix && *a == *a_prefix) {
403 return *a_prefix ? NULL : a;
406 unsigned hatoi_validate(const char *s, const char *msg)
410 if (bch2_strtoull_h(s, &v))
411 die("bad %s %s", msg, s);
416 die("%s too large\n", msg);
419 die("%s too small\n", msg);
426 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
428 static const u32 crc32c_tab[] = {
429 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
430 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
431 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
432 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
433 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
434 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
435 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
436 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
437 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
438 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
439 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
440 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
441 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
442 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
443 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
444 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
445 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
446 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
447 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
448 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
449 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
450 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
451 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
452 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
453 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
454 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
455 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
456 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
457 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
458 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
459 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
460 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
461 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
462 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
463 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
464 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
465 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
466 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
467 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
468 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
469 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
470 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
471 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
472 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
473 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
474 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
475 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
476 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
477 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
478 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
479 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
480 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
481 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
482 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
483 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
484 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
485 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
486 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
487 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
488 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
489 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
490 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
491 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
492 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
497 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
502 #include <linux/compiler.h>
507 #define REX_PRE "0x48, "
512 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
514 while (size >= sizeof(long)) {
515 const unsigned long *d = buf;
517 __asm__ __volatile__(
518 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
523 size -= sizeof(long);
529 __asm__ __volatile__(
530 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
543 static void *resolve_crc32c(void)
546 if (__builtin_cpu_supports("sse4.2"))
549 return crc32c_default;
553 * ifunc is buggy and I don't know what breaks it (LTO?)
555 #ifdef HAVE_WORKING_IFUNC
557 static void *ifunc_resolve_crc32c(void)
559 __builtin_cpu_init();
561 return resolve_crc32c
564 u32 crc32c(u32, const void *, size_t)
565 __attribute__((ifunc("ifunc_resolve_crc32c")));
569 u32 crc32c(u32 crc, const void *buf, size_t size)
571 static u32 (*real_crc32c)(u32, const void *, size_t);
573 if (unlikely(!real_crc32c))
574 real_crc32c = resolve_crc32c();
576 return real_crc32c(crc, buf, size);
579 #endif /* HAVE_WORKING_IFUNC */
581 char *dev_to_name(dev_t dev)
583 char *line = NULL, *name = NULL;
586 FILE *f = fopen("/proc/partitions", "r");
588 die("error opening /proc/partitions: %m");
590 while (getline(&line, &n, f) != -1) {
594 name = realloc(name, n + 1);
596 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
597 ma == major(dev) && mi == minor(dev))
609 char *dev_to_path(dev_t dev)
611 char *name = dev_to_name(dev);
615 char *path = mprintf("/dev/%s", name);
621 struct mntent *dev_to_mount(char *dev)
623 struct mntent *mnt, *ret = NULL;
624 FILE *f = setmntent("/proc/mounts", "r");
626 die("error opening /proc/mounts: %m");
628 struct stat d1 = xstat(dev);
630 while ((mnt = getmntent(f))) {
631 char *d, *p = mnt->mnt_fsname;
633 while ((d = strsep(&p, ":"))) {
639 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
642 if (S_ISBLK(d1.st_mode)) {
643 if (d1.st_rdev != d2.st_rdev)
646 if (d1.st_dev != d2.st_dev ||
647 d1.st_ino != d2.st_ino)
660 int dev_mounted(char *dev)
662 struct mntent *mnt = dev_to_mount(dev);
666 if (hasmntopt(mnt, "ro"))
671 struct bpos bpos_parse(char *buf)
673 char *s = buf, *field;
674 u64 inode_v = 0, offset_v = 0;
676 if (!(field = strsep(&s, ":")) ||
677 kstrtoull(field, 10, &inode_v))
678 die("invalid bpos %s", buf);
680 if ((field = strsep(&s, ":")) &&
681 kstrtoull(field, 10, &offset_v))
682 die("invalid bpos %s", buf);
685 die("invalid bpos %s", buf);
687 return (struct bpos) { .inode = inode_v, .offset = offset_v };