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 /* Argument parsing stuff: */
148 /* File parsing (i.e. sysfs) */
150 char *read_file_str(int dirfd, const char *path)
152 int fd = xopenat(dirfd, path, O_RDONLY);
153 ssize_t len = xfstat(fd).st_size;
155 char *buf = xmalloc(len + 1);
157 len = read(fd, buf, len);
159 die("read error: %m");
162 if (len && buf[len - 1] == '\n')
174 u64 read_file_u64(int dirfd, const char *path)
176 char *buf = read_file_str(dirfd, path);
178 if (bch2_strtou64_h(buf, &v))
179 die("read_file_u64: error parsing %s (got %s)", path, buf);
184 /* String list options: */
186 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
189 ssize_t v = match_string(list, -1, opt);
191 die("Bad %s %s", msg, opt);
196 /* Returns size of file or block device: */
197 u64 get_size(const char *path, int fd)
199 struct stat statbuf = xfstat(fd);
201 if (!S_ISBLK(statbuf.st_mode))
202 return statbuf.st_size;
205 xioctl(fd, BLKGETSIZE64, &ret);
209 /* Returns blocksize, in bytes: */
210 unsigned get_blocksize(const char *path, int fd)
212 struct stat statbuf = xfstat(fd);
214 if (!S_ISBLK(statbuf.st_mode))
215 return statbuf.st_blksize;
218 xioctl(fd, BLKPBSZGET, &ret);
222 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
223 int open_for_format(const char *dev, bool force)
226 const char *fs_type = NULL, *fs_label = NULL;
227 size_t fs_type_len, fs_label_len;
229 int fd = open(dev, O_RDWR|O_EXCL);
231 die("Error opening device to format %s: %m", dev);
236 if (!(pr = blkid_new_probe()))
237 die("blkid error 1");
238 if (blkid_probe_set_device(pr, fd, 0, 0))
239 die("blkid error 2");
240 if (blkid_probe_enable_partitions(pr, true))
241 die("blkid error 3");
242 if (blkid_do_fullprobe(pr) < 0)
243 die("blkid error 4");
245 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
246 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
250 printf("%s contains a %s filesystem labelled '%s'\n",
251 dev, fs_type, fs_label);
253 printf("%s contains a %s filesystem\n",
255 fputs("Proceed anyway?", stdout);
258 while (blkid_do_probe(pr) == 0)
259 blkid_do_wipe(pr, 0);
262 blkid_free_probe(pr);
268 const char *short_yes = "yY";
273 fputs(" (y,n) ", stdout);
276 if (getline(&buf, &buflen, stdin) < 0)
277 die("error reading from standard input");
279 ret = strchr(short_yes, buf[0]);
284 static int range_cmp(const void *_l, const void *_r)
286 const struct range *l = _l, *r = _r;
288 if (l->start < r->start)
290 if (l->start > r->start)
295 void ranges_sort_merge(ranges *r)
298 ranges tmp = { NULL };
300 sort(&darray_item(*r, 0), darray_size(*r),
301 sizeof(darray_item(*r, 0)), range_cmp, NULL);
303 /* Merge contiguous ranges: */
304 darray_foreach(i, *r) {
305 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
307 if (t && t->end >= i->start)
308 t->end = max(t->end, i->end);
310 darray_append(tmp, *i);
317 void ranges_roundup(ranges *r, unsigned block_size)
321 darray_foreach(i, *r) {
322 i->start = round_down(i->start, block_size);
323 i->end = round_up(i->end, block_size);
327 void ranges_rounddown(ranges *r, unsigned block_size)
331 darray_foreach(i, *r) {
332 i->start = round_up(i->start, block_size);
333 i->end = round_down(i->end, block_size);
334 i->end = max(i->end, i->start);
338 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
340 struct fiemap_extent e;
342 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
344 if (iter->idx == iter->f.fm_mapped_extents) {
345 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
347 if (!iter->f.fm_mapped_extents)
348 return (struct fiemap_extent) { .fe_length = 0 };
353 e = iter->f.fm_extents[iter->idx++];
354 BUG_ON(!e.fe_length);
356 iter->f.fm_start = e.fe_logical + e.fe_length;
361 char *strcmp_prefix(char *a, const char *a_prefix)
363 while (*a_prefix && *a == *a_prefix) {
367 return *a_prefix ? NULL : a;
372 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
374 static const u32 crc32c_tab[] = {
375 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
376 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
377 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
378 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
379 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
380 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
381 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
382 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
383 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
384 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
385 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
386 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
387 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
388 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
389 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
390 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
391 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
392 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
393 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
394 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
395 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
396 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
397 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
398 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
399 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
400 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
401 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
402 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
403 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
404 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
405 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
406 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
407 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
408 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
409 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
410 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
411 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
412 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
413 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
414 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
415 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
416 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
417 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
418 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
419 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
420 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
421 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
422 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
423 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
424 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
425 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
426 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
427 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
428 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
429 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
430 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
431 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
432 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
433 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
434 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
435 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
436 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
437 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
438 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
443 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
448 #include <linux/compiler.h>
453 #define REX_PRE "0x48, "
458 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
460 while (size >= sizeof(long)) {
461 const unsigned long *d = buf;
463 __asm__ __volatile__(
464 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
469 size -= sizeof(long);
475 __asm__ __volatile__(
476 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
489 static void *resolve_crc32c(void)
492 if (__builtin_cpu_supports("sse4.2"))
495 return crc32c_default;
499 * ifunc is buggy and I don't know what breaks it (LTO?)
501 #ifdef HAVE_WORKING_IFUNC
503 static void *ifunc_resolve_crc32c(void)
505 __builtin_cpu_init();
507 return resolve_crc32c
510 u32 crc32c(u32, const void *, size_t)
511 __attribute__((ifunc("ifunc_resolve_crc32c")));
515 u32 crc32c(u32 crc, const void *buf, size_t size)
517 static u32 (*real_crc32c)(u32, const void *, size_t);
519 if (unlikely(!real_crc32c))
520 real_crc32c = resolve_crc32c();
522 return real_crc32c(crc, buf, size);
525 #endif /* HAVE_WORKING_IFUNC */
527 char *dev_to_name(dev_t dev)
529 char *line = NULL, *name = NULL;
532 FILE *f = fopen("/proc/partitions", "r");
534 die("error opening /proc/partitions: %m");
536 while (getline(&line, &n, f) != -1) {
540 name = realloc(name, n + 1);
542 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
543 ma == major(dev) && mi == minor(dev))
555 char *dev_to_path(dev_t dev)
557 char *name = dev_to_name(dev);
561 char *path = mprintf("/dev/%s", name);
567 struct mntent *dev_to_mount(char *dev)
569 struct mntent *mnt, *ret = NULL;
570 FILE *f = setmntent("/proc/mounts", "r");
572 die("error opening /proc/mounts: %m");
574 struct stat d1 = xstat(dev);
576 while ((mnt = getmntent(f))) {
577 char *d, *p = mnt->mnt_fsname;
579 while ((d = strsep(&p, ":"))) {
585 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
588 if (S_ISBLK(d1.st_mode)) {
589 if (d1.st_rdev != d2.st_rdev)
592 if (d1.st_dev != d2.st_dev ||
593 d1.st_ino != d2.st_ino)
606 int dev_mounted(char *dev)
608 struct mntent *mnt = dev_to_mount(dev);
612 if (hasmntopt(mnt, "ro"))
617 struct bpos bpos_parse(char *buf)
619 char *s = buf, *field;
620 u64 inode_v = 0, offset_v = 0;
622 if (!(field = strsep(&s, ":")) ||
623 kstrtoull(field, 10, &inode_v))
624 die("invalid bpos %s", buf);
626 if ((field = strsep(&s, ":")) &&
627 kstrtoull(field, 10, &offset_v))
628 die("invalid bpos %s", buf);
631 die("invalid bpos %s", buf);
633 return (struct bpos) { .inode = inode_v, .offset = offset_v };