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, const char *msg)
99 ssize_t r = pwrite(fd, buf, count, offset);
102 die("error writing %s (ret %zi err %m)", msg, 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 bytes: */
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;
408 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
410 static const u32 crc32c_tab[] = {
411 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
412 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
413 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
414 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
415 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
416 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
417 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
418 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
419 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
420 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
421 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
422 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
423 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
424 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
425 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
426 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
427 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
428 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
429 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
430 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
431 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
432 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
433 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
434 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
435 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
436 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
437 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
438 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
439 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
440 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
441 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
442 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
443 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
444 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
445 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
446 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
447 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
448 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
449 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
450 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
451 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
452 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
453 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
454 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
455 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
456 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
457 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
458 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
459 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
460 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
461 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
462 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
463 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
464 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
465 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
466 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
467 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
468 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
469 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
470 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
471 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
472 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
473 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
474 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
479 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
484 #include <linux/compiler.h>
489 #define REX_PRE "0x48, "
494 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
496 while (size >= sizeof(long)) {
497 const unsigned long *d = buf;
499 __asm__ __volatile__(
500 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
505 size -= sizeof(long);
511 __asm__ __volatile__(
512 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
525 static void *resolve_crc32c(void)
528 if (__builtin_cpu_supports("sse4.2"))
531 return crc32c_default;
535 * ifunc is buggy and I don't know what breaks it (LTO?)
537 #ifdef HAVE_WORKING_IFUNC
539 static void *ifunc_resolve_crc32c(void)
541 __builtin_cpu_init();
543 return resolve_crc32c
546 u32 crc32c(u32, const void *, size_t)
547 __attribute__((ifunc("ifunc_resolve_crc32c")));
551 u32 crc32c(u32 crc, const void *buf, size_t size)
553 static u32 (*real_crc32c)(u32, const void *, size_t);
555 if (unlikely(!real_crc32c))
556 real_crc32c = resolve_crc32c();
558 return real_crc32c(crc, buf, size);
561 #endif /* HAVE_WORKING_IFUNC */
563 char *dev_to_name(dev_t dev)
565 char *line = NULL, *name = NULL;
568 FILE *f = fopen("/proc/partitions", "r");
570 die("error opening /proc/partitions: %m");
572 while (getline(&line, &n, f) != -1) {
576 name = realloc(name, n + 1);
578 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
579 ma == major(dev) && mi == minor(dev))
591 char *dev_to_path(dev_t dev)
593 char *name = dev_to_name(dev);
597 char *path = mprintf("/dev/%s", name);
603 struct mntent *dev_to_mount(char *dev)
605 struct mntent *mnt, *ret = NULL;
606 FILE *f = setmntent("/proc/mounts", "r");
608 die("error opening /proc/mounts: %m");
610 struct stat d1 = xstat(dev);
612 while ((mnt = getmntent(f))) {
613 char *d, *p = mnt->mnt_fsname;
615 while ((d = strsep(&p, ":"))) {
621 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
624 if (S_ISBLK(d1.st_mode)) {
625 if (d1.st_rdev != d2.st_rdev)
628 if (d1.st_dev != d2.st_dev ||
629 d1.st_ino != d2.st_ino)
642 int dev_mounted(char *dev)
644 struct mntent *mnt = dev_to_mount(dev);
648 if (hasmntopt(mnt, "ro"))
653 struct bpos bpos_parse(char *buf)
655 char *s = buf, *field;
656 u64 inode_v = 0, offset_v = 0;
658 if (!(field = strsep(&s, ":")) ||
659 kstrtoull(field, 10, &inode_v))
660 die("invalid bpos %s", buf);
662 if ((field = strsep(&s, ":")) &&
663 kstrtoull(field, 10, &offset_v))
664 die("invalid bpos %s", buf);
667 die("invalid bpos %s", buf);
669 return (struct bpos) { .inode = inode_v, .offset = offset_v };