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);
294 blkid_free_probe(pr);
300 const char *short_yes = "yY";
305 fputs(" (y,n) ", stdout);
308 if (getline(&buf, &buflen, stdin) < 0)
309 die("error reading from standard input");
311 ret = strchr(short_yes, buf[0]);
316 static int range_cmp(const void *_l, const void *_r)
318 const struct range *l = _l, *r = _r;
320 if (l->start < r->start)
322 if (l->start > r->start)
327 void ranges_sort_merge(ranges *r)
330 ranges tmp = { NULL };
332 sort(&darray_item(*r, 0), darray_size(*r),
333 sizeof(darray_item(*r, 0)), range_cmp, NULL);
335 /* Merge contiguous ranges: */
336 darray_foreach(i, *r) {
337 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
339 if (t && t->end >= i->start)
340 t->end = max(t->end, i->end);
342 darray_append(tmp, *i);
349 void ranges_roundup(ranges *r, unsigned block_size)
353 darray_foreach(i, *r) {
354 i->start = round_down(i->start, block_size);
355 i->end = round_up(i->end, block_size);
359 void ranges_rounddown(ranges *r, unsigned block_size)
363 darray_foreach(i, *r) {
364 i->start = round_up(i->start, block_size);
365 i->end = round_down(i->end, block_size);
366 i->end = max(i->end, i->start);
370 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
372 struct fiemap_extent e;
374 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
376 if (iter->idx == iter->f.fm_mapped_extents) {
377 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
379 if (!iter->f.fm_mapped_extents)
380 return (struct fiemap_extent) { .fe_length = 0 };
385 e = iter->f.fm_extents[iter->idx++];
386 BUG_ON(!e.fe_length);
388 iter->f.fm_start = e.fe_logical + e.fe_length;
393 char *strcmp_prefix(char *a, const char *a_prefix)
395 while (*a_prefix && *a == *a_prefix) {
399 return *a_prefix ? NULL : a;
402 unsigned hatoi_validate(const char *s, const char *msg)
406 if (bch2_strtoull_h(s, &v))
407 die("bad %s %s", msg, s);
412 die("%s too large\n", msg);
415 die("%s too small\n", msg);
422 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
424 static const u32 crc32c_tab[] = {
425 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
426 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
427 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
428 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
429 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
430 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
431 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
432 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
433 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
434 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
435 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
436 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
437 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
438 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
439 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
440 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
441 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
442 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
443 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
444 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
445 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
446 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
447 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
448 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
449 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
450 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
451 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
452 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
453 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
454 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
455 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
456 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
457 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
458 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
459 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
460 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
461 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
462 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
463 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
464 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
465 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
466 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
467 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
468 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
469 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
470 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
471 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
472 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
473 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
474 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
475 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
476 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
477 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
478 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
479 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
480 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
481 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
482 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
483 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
484 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
485 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
486 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
487 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
488 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
493 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
498 #include <linux/compiler.h>
503 #define REX_PRE "0x48, "
508 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
510 while (size >= sizeof(long)) {
511 const unsigned long *d = buf;
513 __asm__ __volatile__(
514 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
519 size -= sizeof(long);
525 __asm__ __volatile__(
526 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
539 static void *resolve_crc32c(void)
542 if (__builtin_cpu_supports("sse4.2"))
545 return crc32c_default;
549 * ifunc is buggy and I don't know what breaks it (LTO?)
551 #ifdef HAVE_WORKING_IFUNC
553 static void *ifunc_resolve_crc32c(void)
555 __builtin_cpu_init();
557 return resolve_crc32c
560 u32 crc32c(u32, const void *, size_t)
561 __attribute__((ifunc("ifunc_resolve_crc32c")));
565 u32 crc32c(u32 crc, const void *buf, size_t size)
567 static u32 (*real_crc32c)(u32, const void *, size_t);
569 if (unlikely(!real_crc32c))
570 real_crc32c = resolve_crc32c();
572 return real_crc32c(crc, buf, size);
575 #endif /* HAVE_WORKING_IFUNC */
577 char *dev_to_name(dev_t dev)
579 char *line = NULL, *name = NULL;
582 FILE *f = fopen("/proc/partitions", "r");
584 die("error opening /proc/partitions: %m");
586 while (getline(&line, &n, f) != -1) {
590 name = realloc(name, n + 1);
592 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
593 ma == major(dev) && mi == minor(dev))
605 char *dev_to_path(dev_t dev)
607 char *name = dev_to_name(dev);
611 char *path = mprintf("/dev/%s", name);
617 struct mntent *dev_to_mount(char *dev)
619 struct mntent *mnt, *ret = NULL;
620 FILE *f = setmntent("/proc/mounts", "r");
622 die("error opening /proc/mounts: %m");
624 struct stat d1 = xstat(dev);
626 while ((mnt = getmntent(f))) {
627 char *d, *p = mnt->mnt_fsname;
629 while ((d = strsep(&p, ":"))) {
635 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
638 if (S_ISBLK(d1.st_mode)) {
639 if (d1.st_rdev != d2.st_rdev)
642 if (d1.st_dev != d2.st_dev ||
643 d1.st_ino != d2.st_ino)
656 bool dev_mounted_rw(char *dev)
658 struct mntent *mnt = dev_to_mount(dev);
660 return mnt && !hasmntopt(mnt, "ro");