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");
123 int printf_pad(unsigned pad, const char * fmt, ...)
129 ret = vprintf(fmt, args);
138 struct units_buf __pr_units(s64 _v, enum units units)
140 struct units_buf ret;
141 char *out = ret.b, *end = out + sizeof(ret.b);
145 out += scnprintf(out, end - out, "-");
151 snprintf(out, end - out, "%llu", v << 9);
154 snprintf(out, end - out, "%llu", v);
160 int exp = log(v) / log(1024);
161 snprintf(out, end - out, "%.1f%c",
165 snprintf(out, end - out, "%llu", v);
174 /* Argument parsing stuff: */
176 /* File parsing (i.e. sysfs) */
178 char *read_file_str(int dirfd, const char *path)
180 int fd = xopenat(dirfd, path, O_RDONLY);
181 ssize_t len = xfstat(fd).st_size;
183 char *buf = xmalloc(len + 1);
185 len = read(fd, buf, len);
187 die("read error: %m");
190 if (len && buf[len - 1] == '\n')
198 u64 read_file_u64(int dirfd, const char *path)
200 char *buf = read_file_str(dirfd, path);
202 if (kstrtou64(buf, 10, &v))
203 die("read_file_u64: error parsing %s (got %s)", path, buf);
208 /* String list options: */
210 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
213 ssize_t v = bch2_read_string_list(opt, list);
215 die("Bad %s %s", msg, opt);
220 /* Returns size of file or block device: */
221 u64 get_size(const char *path, int fd)
223 struct stat statbuf = xfstat(fd);
225 if (!S_ISBLK(statbuf.st_mode))
226 return statbuf.st_size;
229 xioctl(fd, BLKGETSIZE64, &ret);
233 /* Returns blocksize in units of 512 byte sectors: */
234 unsigned get_blocksize(const char *path, int fd)
236 struct stat statbuf = xfstat(fd);
238 if (!S_ISBLK(statbuf.st_mode))
239 return statbuf.st_blksize >> 9;
242 xioctl(fd, BLKPBSZGET, &ret);
246 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
247 int open_for_format(const char *dev, bool force)
250 const char *fs_type = NULL, *fs_label = NULL;
251 size_t fs_type_len, fs_label_len;
253 int fd = xopen(dev, O_RDWR|O_EXCL);
258 if (!(pr = blkid_new_probe()))
259 die("blkid error 1");
260 if (blkid_probe_set_device(pr, fd, 0, 0))
261 die("blkid error 2");
262 if (blkid_probe_enable_partitions(pr, true))
263 die("blkid error 3");
264 if (blkid_do_fullprobe(pr) < 0)
265 die("blkid error 4");
267 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
268 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
272 printf("%s contains a %s filesystem labelled '%s'\n",
273 dev, fs_type, fs_label);
275 printf("%s contains a %s filesystem\n",
277 fputs("Proceed anyway?", stdout);
282 blkid_free_probe(pr);
288 const char *short_yes = "yY";
293 fputs(" (y,n) ", stdout);
296 if (getline(&buf, &buflen, stdin) < 0)
297 die("error reading from standard input");
299 ret = strchr(short_yes, buf[0]);
304 static int range_cmp(const void *_l, const void *_r)
306 const struct range *l = _l, *r = _r;
308 if (l->start < r->start)
310 if (l->start > r->start)
315 void ranges_sort_merge(ranges *r)
318 ranges tmp = { NULL };
320 sort(&darray_item(*r, 0), darray_size(*r),
321 sizeof(darray_item(*r, 0)), range_cmp, NULL);
323 /* Merge contiguous ranges: */
324 darray_foreach(i, *r) {
325 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
327 if (t && t->end >= i->start)
328 t->end = max(t->end, i->end);
330 darray_append(tmp, *i);
337 void ranges_roundup(ranges *r, unsigned block_size)
341 darray_foreach(i, *r) {
342 i->start = round_down(i->start, block_size);
343 i->end = round_up(i->end, block_size);
347 void ranges_rounddown(ranges *r, unsigned block_size)
351 darray_foreach(i, *r) {
352 i->start = round_up(i->start, block_size);
353 i->end = round_down(i->end, block_size);
354 i->end = max(i->end, i->start);
358 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
360 struct fiemap_extent e;
362 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
364 if (iter->idx == iter->f.fm_mapped_extents) {
365 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
367 if (!iter->f.fm_mapped_extents)
368 return (struct fiemap_extent) { .fe_length = 0 };
373 e = iter->f.fm_extents[iter->idx++];
374 BUG_ON(!e.fe_length);
376 iter->f.fm_start = e.fe_logical + e.fe_length;
381 const char *strcmp_prefix(const char *a, const char *a_prefix)
383 while (*a_prefix && *a == *a_prefix) {
387 return *a_prefix ? NULL : a;
390 unsigned hatoi_validate(const char *s, const char *msg)
394 if (bch2_strtoull_h(s, &v))
395 die("bad %s %s", msg, s);
400 die("%s too large\n", msg);
403 die("%s too small\n", msg);
410 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
412 static const u32 crc32c_tab[] = {
413 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
414 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
415 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
416 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
417 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
418 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
419 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
420 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
421 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
422 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
423 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
424 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
425 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
426 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
427 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
428 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
429 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
430 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
431 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
432 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
433 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
434 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
435 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
436 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
437 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
438 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
439 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
440 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
441 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
442 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
443 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
444 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
445 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
446 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
447 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
448 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
449 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
450 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
451 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
452 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
453 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
454 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
455 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
456 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
457 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
458 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
459 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
460 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
461 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
462 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
463 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
464 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
465 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
466 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
467 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
468 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
469 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
470 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
471 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
472 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
473 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
474 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
475 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
476 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
481 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
486 #include <linux/compiler.h>
491 #define REX_PRE "0x48, "
496 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
498 while (size >= sizeof(long)) {
499 const unsigned long *d = buf;
501 __asm__ __volatile__(
502 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
507 size -= sizeof(long);
513 __asm__ __volatile__(
514 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
525 static void *resolve_crc32c(void)
527 __builtin_cpu_init();
530 if (__builtin_cpu_supports("sse4.2"))
533 return crc32c_default;
537 * ifunc is buggy and I don't know what breaks it (LTO?)
539 #ifdef HAVE_WORKING_IFUNC
541 u32 crc32c(u32, const void *, size_t)
542 __attribute__((ifunc("resolve_crc32c")));
546 u32 crc32c(u32 crc, const void *buf, size_t size)
548 static u32 (*real_crc32c)(u32, const void *, size_t);
550 if (unlikely(!real_crc32c))
551 real_crc32c = resolve_crc32c();
553 return real_crc32c(crc, buf, size);
556 #endif /* HAVE_WORKING_IFUNC */
558 char *dev_to_name(dev_t dev)
560 char *line = NULL, *name = NULL;
563 FILE *f = fopen("/proc/partitions", "r");
565 die("error opening /proc/partitions: %m");
567 while (getline(&line, &n, f) != -1) {
571 name = realloc(name, n + 1);
573 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
574 ma == major(dev) && mi == minor(dev))
586 char *dev_to_path(dev_t dev)
588 char *name = dev_to_name(dev);
592 char *path = mprintf("/dev/%s", name);
598 char *dev_to_mount(char *dev)
600 char *line = NULL, *ret = NULL;
603 FILE *f = fopen("/proc/mounts", "r");
605 die("error opening /proc/mounts: %m");
607 while (getline(&line, &n, f) != -1) {
609 char *devs = strsep(&p, " ");
610 char *mount = strsep(&p, " ");
616 while ((d = strsep(&p, ":")))
617 if (!strcmp(d, dev)) {