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)
85 ssize_t r = pread(fd, buf, count, offset);
88 die("read error (ret %zi)", r);
91 void xpwrite(int fd, const void *buf, size_t count, off_t offset)
93 ssize_t r = pwrite(fd, buf, count, offset);
96 die("write error (ret %zi err %m)", r);
99 struct stat xfstatat(int dirfd, const char *path, int flags)
102 if (fstatat(dirfd, path, &stat, flags))
103 die("stat error: %m");
107 struct stat xfstat(int fd)
110 if (fstat(fd, &stat))
111 die("stat error: %m");
117 struct units_buf __pr_units(s64 _v, enum units units)
119 struct units_buf ret;
120 char *out = ret.b, *end = out + sizeof(ret.b);
124 out += scnprintf(out, end - out, "-");
130 snprintf(out, end - out, "%llu", v << 9);
133 snprintf(out, end - out, "%llu", v);
139 int exp = log(v) / log(1024);
140 snprintf(out, end - out, "%.1f%c",
144 snprintf(out, end - out, "%llu", v);
153 /* Argument parsing stuff: */
155 /* File parsing (i.e. sysfs) */
157 char *read_file_str(int dirfd, const char *path)
159 int fd = xopenat(dirfd, path, O_RDONLY);
160 ssize_t len = xfstat(fd).st_size;
162 char *buf = xmalloc(len + 1);
164 len = read(fd, buf, len);
166 die("read error: %m");
169 if (len && buf[len - 1] == '\n')
177 u64 read_file_u64(int dirfd, const char *path)
179 char *buf = read_file_str(dirfd, path);
181 if (kstrtou64(buf, 10, &v))
182 die("read_file_u64: error parsing %s (got %s)", path, buf);
187 /* String list options: */
189 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
192 ssize_t v = bch2_read_string_list(opt, list);
194 die("Bad %s %s", msg, opt);
199 /* Returns size of file or block device: */
200 u64 get_size(const char *path, int fd)
202 struct stat statbuf = xfstat(fd);
204 if (!S_ISBLK(statbuf.st_mode))
205 return statbuf.st_size;
208 xioctl(fd, BLKGETSIZE64, &ret);
212 /* Returns blocksize in units of 512 byte sectors: */
213 unsigned get_blocksize(const char *path, int fd)
215 struct stat statbuf = xfstat(fd);
217 if (!S_ISBLK(statbuf.st_mode))
218 return statbuf.st_blksize >> 9;
221 xioctl(fd, BLKPBSZGET, &ret);
225 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
226 int open_for_format(const char *dev, bool force)
229 const char *fs_type = NULL, *fs_label = NULL;
230 size_t fs_type_len, fs_label_len;
232 int fd = xopen(dev, O_RDWR|O_EXCL);
237 if (!(pr = blkid_new_probe()))
238 die("blkid error 1");
239 if (blkid_probe_set_device(pr, fd, 0, 0))
240 die("blkid error 2");
241 if (blkid_probe_enable_partitions(pr, true))
242 die("blkid error 3");
243 if (blkid_do_fullprobe(pr) < 0)
244 die("blkid error 4");
246 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
247 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
251 printf("%s contains a %s filesystem labelled '%s'\n",
252 dev, fs_type, fs_label);
254 printf("%s contains a %s filesystem\n",
256 fputs("Proceed anyway?", stdout);
261 blkid_free_probe(pr);
267 const char *short_yes = "yY";
272 fputs(" (y,n) ", stdout);
275 if (getline(&buf, &buflen, stdin) < 0)
276 die("error reading from standard input");
278 ret = strchr(short_yes, buf[0]);
283 static int range_cmp(const void *_l, const void *_r)
285 const struct range *l = _l, *r = _r;
287 if (l->start < r->start)
289 if (l->start > r->start)
294 void ranges_sort_merge(ranges *r)
297 ranges tmp = { NULL };
299 sort(&darray_item(*r, 0), darray_size(*r),
300 sizeof(darray_item(*r, 0)), range_cmp, NULL);
302 /* Merge contiguous ranges: */
303 darray_foreach(i, *r) {
304 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
306 if (t && t->end >= i->start)
307 t->end = max(t->end, i->end);
309 darray_append(tmp, *i);
316 void ranges_roundup(ranges *r, unsigned block_size)
320 darray_foreach(i, *r) {
321 i->start = round_down(i->start, block_size);
322 i->end = round_up(i->end, block_size);
326 void ranges_rounddown(ranges *r, unsigned block_size)
330 darray_foreach(i, *r) {
331 i->start = round_up(i->start, block_size);
332 i->end = round_down(i->end, block_size);
333 i->end = max(i->end, i->start);
337 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
339 struct fiemap_extent e;
341 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
343 if (iter->idx == iter->f.fm_mapped_extents) {
344 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
346 if (!iter->f.fm_mapped_extents)
347 return (struct fiemap_extent) { .fe_length = 0 };
352 e = iter->f.fm_extents[iter->idx++];
353 BUG_ON(!e.fe_length);
355 iter->f.fm_start = e.fe_logical + e.fe_length;
360 const char *strcmp_prefix(const char *a, const char *a_prefix)
362 while (*a_prefix && *a == *a_prefix) {
366 return *a_prefix ? NULL : a;
369 unsigned hatoi_validate(const char *s, const char *msg)
373 if (bch2_strtoull_h(s, &v))
374 die("bad %s %s", msg, s);
379 die("%s too large\n", msg);
382 die("%s too small\n", msg);
389 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
391 static const u32 crc32c_tab[] = {
392 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
393 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
394 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
395 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
396 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
397 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
398 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
399 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
400 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
401 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
402 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
403 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
404 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
405 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
406 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
407 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
408 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
409 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
410 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
411 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
412 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
413 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
414 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
415 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
416 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
417 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
418 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
419 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
420 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
421 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
422 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
423 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
424 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
425 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
426 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
427 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
428 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
429 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
430 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
431 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
432 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
433 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
434 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
435 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
436 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
437 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
438 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
439 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
440 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
441 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
442 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
443 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
444 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
445 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
446 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
447 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
448 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
449 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
450 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
451 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
452 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
453 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
454 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
455 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
460 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
465 #include <linux/compiler.h>
470 #define REX_PRE "0x48, "
475 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
477 while (size >= sizeof(long)) {
478 const unsigned long *d = buf;
480 __asm__ __volatile__(
481 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
486 size -= sizeof(long);
492 __asm__ __volatile__(
493 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
504 static void *resolve_crc32c(void)
506 __builtin_cpu_init();
509 if (__builtin_cpu_supports("sse4.2"))
512 return crc32c_default;
516 * ifunc is buggy and I don't know what breaks it (LTO?)
518 #ifdef HAVE_WORKING_IFUNC
520 u32 crc32c(u32, const void *, size_t)
521 __attribute__((ifunc("resolve_crc32c")));
525 u32 crc32c(u32 crc, const void *buf, size_t size)
527 static u32 (*real_crc32c)(u32, const void *, size_t);
529 if (unlikely(!real_crc32c))
530 real_crc32c = resolve_crc32c();
532 return real_crc32c(crc, buf, size);
535 #endif /* HAVE_WORKING_IFUNC */
537 char *dev_to_name(dev_t dev)
539 char *line = NULL, *name = NULL;
542 FILE *f = fopen("/proc/partitions", "r");
544 die("error opening /proc/partitions: %m");
546 while (getline(&line, &n, f) != -1) {
550 name = realloc(name, n + 1);
552 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
553 ma == major(dev) && mi == minor(dev))
565 char *dev_to_path(dev_t dev)
567 char *name = dev_to_name(dev);
571 char *path = mprintf("/dev/%s", name);
577 char *dev_to_mount(char *dev)
579 char *line = NULL, *ret = NULL;
582 FILE *f = fopen("/proc/mounts", "r");
584 die("error opening /proc/mounts: %m");
586 while (getline(&line, &n, f) != -1) {
588 char *devs = strsep(&p, " ");
589 char *mount = strsep(&p, " ");
595 while ((d = strsep(&p, ":")))
596 if (!strcmp(d, dev)) {