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);
129 /* File parsing (i.e. sysfs) */
131 void write_file_str(int dirfd, const char *path, const char *str)
133 int fd = xopenat(dirfd, path, O_WRONLY);
134 ssize_t wrote, len = strlen(str);
136 wrote = write(fd, str, len);
138 die("read error: %m");
142 char *read_file_str(int dirfd, const char *path)
144 int fd = xopenat(dirfd, path, O_RDONLY);
145 ssize_t len = xfstat(fd).st_size;
147 char *buf = xmalloc(len + 1);
149 len = read(fd, buf, len);
151 die("read error: %m");
154 if (len && buf[len - 1] == '\n')
166 u64 read_file_u64(int dirfd, const char *path)
168 char *buf = read_file_str(dirfd, path);
170 if (bch2_strtou64_h(buf, &v))
171 die("read_file_u64: error parsing %s (got %s)", path, buf);
176 /* String list options: */
178 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
181 ssize_t v = match_string(list, -1, opt);
183 die("Bad %s %s", msg, opt);
188 /* Returns size of file or block device: */
189 u64 get_size(const char *path, int fd)
191 struct stat statbuf = xfstat(fd);
193 if (!S_ISBLK(statbuf.st_mode))
194 return statbuf.st_size;
197 xioctl(fd, BLKGETSIZE64, &ret);
201 /* Returns blocksize, in bytes: */
202 unsigned get_blocksize(const char *path, int fd)
204 struct stat statbuf = xfstat(fd);
206 if (!S_ISBLK(statbuf.st_mode))
207 return statbuf.st_blksize;
210 xioctl(fd, BLKPBSZGET, &ret);
214 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
215 int open_for_format(const char *dev, bool force)
218 const char *fs_type = NULL, *fs_label = NULL;
219 size_t fs_type_len, fs_label_len;
221 int fd = open(dev, O_RDWR|O_EXCL);
223 die("Error opening device to format %s: %m", dev);
228 if (!(pr = blkid_new_probe()))
229 die("blkid error 1");
230 if (blkid_probe_set_device(pr, fd, 0, 0))
231 die("blkid error 2");
232 if (blkid_probe_enable_partitions(pr, true))
233 die("blkid error 3");
234 if (blkid_do_fullprobe(pr) < 0)
235 die("blkid error 4");
237 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
238 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
242 printf("%s contains a %s filesystem labelled '%s'\n",
243 dev, fs_type, fs_label);
245 printf("%s contains a %s filesystem\n",
247 fputs("Proceed anyway?", stdout);
250 while (blkid_do_probe(pr) == 0)
251 blkid_do_wipe(pr, 0);
254 blkid_free_probe(pr);
260 const char *short_yes = "yY";
265 fputs(" (y,n) ", stdout);
268 if (getline(&buf, &buflen, stdin) < 0)
269 die("error reading from standard input");
271 ret = strchr(short_yes, buf[0]);
276 static int range_cmp(const void *_l, const void *_r)
278 const struct range *l = _l, *r = _r;
280 if (l->start < r->start)
282 if (l->start > r->start)
287 void ranges_sort_merge(ranges *r)
292 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
294 /* Merge contiguous ranges: */
295 darray_for_each(*r, i) {
296 t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
298 if (t && t->end >= i->start)
299 t->end = max(t->end, i->end);
301 darray_push(&tmp, *i);
308 void ranges_roundup(ranges *r, unsigned block_size)
312 darray_for_each(*r, i) {
313 i->start = round_down(i->start, block_size);
314 i->end = round_up(i->end, block_size);
318 void ranges_rounddown(ranges *r, unsigned block_size)
322 darray_for_each(*r, i) {
323 i->start = round_up(i->start, block_size);
324 i->end = round_down(i->end, block_size);
325 i->end = max(i->end, i->start);
329 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
331 struct fiemap_extent e;
333 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
335 if (iter->idx == iter->f.fm_mapped_extents) {
336 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
338 if (!iter->f.fm_mapped_extents)
339 return (struct fiemap_extent) { .fe_length = 0 };
344 e = iter->f.fm_extents[iter->idx++];
345 BUG_ON(!e.fe_length);
347 iter->f.fm_start = e.fe_logical + e.fe_length;
352 char *strcmp_prefix(char *a, const char *a_prefix)
354 while (*a_prefix && *a == *a_prefix) {
358 return *a_prefix ? NULL : a;
363 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
365 static const u32 crc32c_tab[] = {
366 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
367 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
368 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
369 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
370 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
371 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
372 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
373 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
374 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
375 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
376 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
377 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
378 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
379 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
380 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
381 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
382 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
383 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
384 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
385 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
386 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
387 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
388 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
389 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
390 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
391 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
392 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
393 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
394 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
395 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
396 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
397 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
398 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
399 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
400 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
401 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
402 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
403 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
404 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
405 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
406 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
407 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
408 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
409 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
410 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
411 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
412 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
413 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
414 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
415 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
416 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
417 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
418 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
419 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
420 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
421 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
422 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
423 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
424 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
425 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
426 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
427 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
428 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
429 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
434 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
439 #include <linux/compiler.h>
444 #define REX_PRE "0x48, "
449 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
451 while (size >= sizeof(long)) {
452 const unsigned long *d = buf;
454 __asm__ __volatile__(
455 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
460 size -= sizeof(long);
466 __asm__ __volatile__(
467 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
480 static void *resolve_crc32c(void)
483 if (__builtin_cpu_supports("sse4.2"))
486 return crc32c_default;
490 * ifunc is buggy and I don't know what breaks it (LTO?)
492 #ifdef HAVE_WORKING_IFUNC
494 static void *ifunc_resolve_crc32c(void)
496 __builtin_cpu_init();
498 return resolve_crc32c
501 u32 crc32c(u32, const void *, size_t)
502 __attribute__((ifunc("ifunc_resolve_crc32c")));
506 u32 crc32c(u32 crc, const void *buf, size_t size)
508 static u32 (*real_crc32c)(u32, const void *, size_t);
510 if (unlikely(!real_crc32c))
511 real_crc32c = resolve_crc32c();
513 return real_crc32c(crc, buf, size);
516 #endif /* HAVE_WORKING_IFUNC */
518 char *dev_to_name(dev_t dev)
520 char *line = NULL, *name = NULL;
523 FILE *f = fopen("/proc/partitions", "r");
525 die("error opening /proc/partitions: %m");
527 while (getline(&line, &n, f) != -1) {
531 name = realloc(name, n + 1);
533 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
534 ma == major(dev) && mi == minor(dev))
546 char *dev_to_path(dev_t dev)
548 char *name = dev_to_name(dev);
552 char *path = mprintf("/dev/%s", name);
558 struct mntent *dev_to_mount(char *dev)
560 struct mntent *mnt, *ret = NULL;
561 FILE *f = setmntent("/proc/mounts", "r");
563 die("error opening /proc/mounts: %m");
565 struct stat d1 = xstat(dev);
567 while ((mnt = getmntent(f))) {
568 char *d, *p = mnt->mnt_fsname;
570 while ((d = strsep(&p, ":"))) {
576 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
579 if (S_ISBLK(d1.st_mode)) {
580 if (d1.st_rdev != d2.st_rdev)
583 if (d1.st_dev != d2.st_dev ||
584 d1.st_ino != d2.st_ino)
597 int dev_mounted(char *dev)
599 struct mntent *mnt = dev_to_mount(dev);
603 if (hasmntopt(mnt, "ro"))
608 struct bpos bpos_parse(char *buf)
610 char *orig = strdup(buf);
613 char *inode_s = strsep(&s, ":");
614 char *offset_s = strsep(&s, ":");
615 char *snapshot_s = strsep(&s, ":");
617 if (!inode_s || !offset_s || s)
618 die("invalid bpos %s", orig);
621 u64 inode_v = 0, offset_v = 0;
623 if (kstrtoull(inode_s, 10, &inode_v))
624 die("invalid bpos.inode %s", inode_s);
626 if (kstrtoull(offset_s, 10, &offset_v))
627 die("invalid bpos.offset %s", offset_s);
630 kstrtouint(snapshot_s, 10, &snapshot_v))
631 die("invalid bpos.snapshot %s", snapshot_s);
633 return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
636 struct bbpos bbpos_parse(char *buf)
638 char *s = buf, *field;
641 if (!(field = strsep(&s, ":")))
642 die("invalid bbpos %s", buf);
644 ret.btree = read_string_list_or_die(field, bch2_btree_ids, "btree id");
645 ret.pos = bpos_parse(s);