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')
206 u64 read_file_u64(int dirfd, const char *path)
208 char *buf = read_file_str(dirfd, path);
210 if (kstrtou64(buf, 10, &v))
211 die("read_file_u64: error parsing %s (got %s)", path, buf);
216 /* String list options: */
218 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
221 ssize_t v = match_string(list, -1, opt);
223 die("Bad %s %s", msg, opt);
228 /* Returns size of file or block device: */
229 u64 get_size(const char *path, int fd)
231 struct stat statbuf = xfstat(fd);
233 if (!S_ISBLK(statbuf.st_mode))
234 return statbuf.st_size;
237 xioctl(fd, BLKGETSIZE64, &ret);
241 /* Returns blocksize in units of 512 byte sectors: */
242 unsigned get_blocksize(const char *path, int fd)
244 struct stat statbuf = xfstat(fd);
246 if (!S_ISBLK(statbuf.st_mode))
247 return statbuf.st_blksize >> 9;
250 xioctl(fd, BLKPBSZGET, &ret);
254 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
255 int open_for_format(const char *dev, bool force)
258 const char *fs_type = NULL, *fs_label = NULL;
259 size_t fs_type_len, fs_label_len;
261 int fd = xopen(dev, O_RDWR|O_EXCL);
266 if (!(pr = blkid_new_probe()))
267 die("blkid error 1");
268 if (blkid_probe_set_device(pr, fd, 0, 0))
269 die("blkid error 2");
270 if (blkid_probe_enable_partitions(pr, true))
271 die("blkid error 3");
272 if (blkid_do_fullprobe(pr) < 0)
273 die("blkid error 4");
275 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
276 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
280 printf("%s contains a %s filesystem labelled '%s'\n",
281 dev, fs_type, fs_label);
283 printf("%s contains a %s filesystem\n",
285 fputs("Proceed anyway?", stdout);
290 blkid_free_probe(pr);
296 const char *short_yes = "yY";
301 fputs(" (y,n) ", stdout);
304 if (getline(&buf, &buflen, stdin) < 0)
305 die("error reading from standard input");
307 ret = strchr(short_yes, buf[0]);
312 static int range_cmp(const void *_l, const void *_r)
314 const struct range *l = _l, *r = _r;
316 if (l->start < r->start)
318 if (l->start > r->start)
323 void ranges_sort_merge(ranges *r)
326 ranges tmp = { NULL };
328 sort(&darray_item(*r, 0), darray_size(*r),
329 sizeof(darray_item(*r, 0)), range_cmp, NULL);
331 /* Merge contiguous ranges: */
332 darray_foreach(i, *r) {
333 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
335 if (t && t->end >= i->start)
336 t->end = max(t->end, i->end);
338 darray_append(tmp, *i);
345 void ranges_roundup(ranges *r, unsigned block_size)
349 darray_foreach(i, *r) {
350 i->start = round_down(i->start, block_size);
351 i->end = round_up(i->end, block_size);
355 void ranges_rounddown(ranges *r, unsigned block_size)
359 darray_foreach(i, *r) {
360 i->start = round_up(i->start, block_size);
361 i->end = round_down(i->end, block_size);
362 i->end = max(i->end, i->start);
366 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
368 struct fiemap_extent e;
370 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
372 if (iter->idx == iter->f.fm_mapped_extents) {
373 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
375 if (!iter->f.fm_mapped_extents)
376 return (struct fiemap_extent) { .fe_length = 0 };
381 e = iter->f.fm_extents[iter->idx++];
382 BUG_ON(!e.fe_length);
384 iter->f.fm_start = e.fe_logical + e.fe_length;
389 char *strcmp_prefix(char *a, const char *a_prefix)
391 while (*a_prefix && *a == *a_prefix) {
395 return *a_prefix ? NULL : a;
398 unsigned hatoi_validate(const char *s, const char *msg)
402 if (bch2_strtoull_h(s, &v))
403 die("bad %s %s", msg, s);
408 die("%s too large\n", msg);
411 die("%s too small\n", msg);
418 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
420 static const u32 crc32c_tab[] = {
421 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
422 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
423 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
424 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
425 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
426 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
427 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
428 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
429 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
430 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
431 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
432 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
433 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
434 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
435 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
436 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
437 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
438 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
439 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
440 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
441 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
442 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
443 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
444 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
445 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
446 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
447 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
448 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
449 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
450 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
451 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
452 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
453 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
454 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
455 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
456 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
457 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
458 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
459 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
460 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
461 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
462 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
463 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
464 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
465 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
466 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
467 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
468 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
469 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
470 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
471 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
472 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
473 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
474 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
475 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
476 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
477 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
478 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
479 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
480 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
481 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
482 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
483 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
484 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
489 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
494 #include <linux/compiler.h>
499 #define REX_PRE "0x48, "
504 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
506 while (size >= sizeof(long)) {
507 const unsigned long *d = buf;
509 __asm__ __volatile__(
510 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
515 size -= sizeof(long);
521 __asm__ __volatile__(
522 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
535 static void *resolve_crc32c(void)
538 if (__builtin_cpu_supports("sse4.2"))
541 return crc32c_default;
545 * ifunc is buggy and I don't know what breaks it (LTO?)
547 #ifdef HAVE_WORKING_IFUNC
549 static void *ifunc_resolve_crc32c(void)
551 __builtin_cpu_init();
553 return resolve_crc32c
556 u32 crc32c(u32, const void *, size_t)
557 __attribute__((ifunc("ifunc_resolve_crc32c")));
561 u32 crc32c(u32 crc, const void *buf, size_t size)
563 static u32 (*real_crc32c)(u32, const void *, size_t);
565 if (unlikely(!real_crc32c))
566 real_crc32c = resolve_crc32c();
568 return real_crc32c(crc, buf, size);
571 #endif /* HAVE_WORKING_IFUNC */
573 char *dev_to_name(dev_t dev)
575 char *line = NULL, *name = NULL;
578 FILE *f = fopen("/proc/partitions", "r");
580 die("error opening /proc/partitions: %m");
582 while (getline(&line, &n, f) != -1) {
586 name = realloc(name, n + 1);
588 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
589 ma == major(dev) && mi == minor(dev))
601 char *dev_to_path(dev_t dev)
603 char *name = dev_to_name(dev);
607 char *path = mprintf("/dev/%s", name);
613 struct mntent *dev_to_mount(char *dev)
615 struct mntent *mnt, *ret = NULL;
616 FILE *f = setmntent("/proc/mounts", "r");
618 die("error opening /proc/mounts: %m");
620 struct stat d1 = xstat(dev);
622 while ((mnt = getmntent(f))) {
623 char *d, *p = mnt->mnt_fsname;
625 while ((d = strsep(&p, ":"))) {
631 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
634 if (S_ISBLK(d1.st_mode)) {
635 if (d1.st_rdev != d2.st_rdev)
638 if (d1.st_dev != d2.st_dev ||
639 d1.st_ino != d2.st_ino)
652 bool dev_mounted_rw(char *dev)
654 struct mntent *mnt = dev_to_mount(dev);
656 return mnt && !hasmntopt(mnt, "ro");