11 #include <sys/ioctl.h>
13 #include <sys/sysmacros.h>
14 #include <sys/types.h>
18 #include <uuid/uuid.h>
20 #include "libbcachefs.h"
21 #include "libbcachefs/bcachefs_ioctl.h"
22 #include "linux/sort.h"
23 #include "tools-util.h"
24 #include "libbcachefs/util.h"
26 void die(const char *fmt, ...)
31 vfprintf(stderr, fmt, args);
38 char *mprintf(const char *fmt, ...)
45 ret = vasprintf(&str, fmt, args);
49 die("insufficient memory");
54 void xpread(int fd, void *buf, size_t count, off_t offset)
57 ssize_t r = pread(fd, buf, count, offset);
60 die("read error: %m");
62 die("pread error: unexpected eof");
68 void xpwrite(int fd, const void *buf, size_t count, off_t offset, const char *msg)
70 ssize_t r = pwrite(fd, buf, count, offset);
73 die("error writing %s (ret %zi err %m)", msg, r);
76 struct stat xfstatat(int dirfd, const char *path, int flags)
79 if (fstatat(dirfd, path, &stat, flags))
80 die("stat error: %m");
84 struct stat xfstat(int fd)
88 die("stat error: %m");
92 struct stat xstat(const char *path)
95 if (stat(path, &statbuf))
96 die("stat error statting %s: %m", path);
100 /* File parsing (i.e. sysfs) */
102 void write_file_str(int dirfd, const char *path, const char *str)
104 int fd = xopenat(dirfd, path, O_WRONLY);
105 ssize_t wrote, len = strlen(str);
107 wrote = write(fd, str, len);
109 die("read error: %m");
113 char *read_file_str(int dirfd, const char *path)
115 int fd = xopenat(dirfd, path, O_RDONLY);
116 ssize_t len = xfstat(fd).st_size;
118 char *buf = xmalloc(len + 1);
120 len = read(fd, buf, len);
122 die("read error: %m");
125 if (len && buf[len - 1] == '\n')
137 u64 read_file_u64(int dirfd, const char *path)
139 char *buf = read_file_str(dirfd, path);
141 if (bch2_strtou64_h(buf, &v))
142 die("read_file_u64: error parsing %s (got %s)", path, buf);
147 /* String list options: */
149 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
152 ssize_t v = match_string(list, -1, opt);
154 die("Bad %s %s", msg, opt);
159 /* Returns size of file or block device: */
162 struct stat statbuf = xfstat(fd);
164 if (!S_ISBLK(statbuf.st_mode))
165 return statbuf.st_size;
168 xioctl(fd, BLKGETSIZE64, &ret);
172 /* Returns blocksize, in bytes: */
173 unsigned get_blocksize(int fd)
175 struct stat statbuf = xfstat(fd);
177 if (!S_ISBLK(statbuf.st_mode))
178 return statbuf.st_blksize;
181 xioctl(fd, BLKPBSZGET, &ret);
185 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
186 int open_for_format(struct dev_opts *dev, bool force)
189 const char *fs_type = NULL, *fs_label = NULL;
190 size_t fs_type_len, fs_label_len;
192 dev->bdev = blkdev_get_by_path(dev->path,
193 BLK_OPEN_READ|BLK_OPEN_WRITE|BLK_OPEN_EXCL|BLK_OPEN_BUFFERED,
195 int ret = PTR_ERR_OR_ZERO(dev->bdev);
197 die("Error opening device to format %s: %s", dev->path, strerror(-ret));
199 if (!(pr = blkid_new_probe()))
200 die("blkid error 1");
201 if (blkid_probe_set_device(pr, dev->bdev->bd_fd, 0, 0))
202 die("blkid error 2");
203 if (blkid_probe_enable_partitions(pr, true) ||
204 blkid_probe_enable_superblocks(pr, true) ||
205 blkid_probe_set_superblocks_flags(pr,
206 BLKID_SUBLKS_LABEL|BLKID_SUBLKS_TYPE|BLKID_SUBLKS_MAGIC))
207 die("blkid error 3");
208 if (blkid_do_fullprobe(pr) < 0)
209 die("blkid error 4");
211 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
212 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
216 printf("%s contains a %s filesystem labelled '%s'\n",
217 dev->path, fs_type, fs_label);
219 printf("%s contains a %s filesystem\n",
222 fputs("Proceed anyway?", stdout);
226 while (blkid_do_probe(pr) == 0) {
227 if (blkid_do_wipe(pr, 0))
228 die("Failed to wipe preexisting metadata.");
232 blkid_free_probe(pr);
238 const char *short_yes = "yY";
243 fputs(" (y,n) ", stdout);
246 if (getline(&buf, &buflen, stdin) < 0)
247 die("error reading from standard input");
249 ret = strchr(short_yes, buf[0]);
254 static int range_cmp(const void *_l, const void *_r)
256 const struct range *l = _l, *r = _r;
258 if (l->start < r->start)
260 if (l->start > r->start)
265 void ranges_sort_merge(ranges *r)
269 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
271 /* Merge contiguous ranges: */
272 darray_for_each(*r, i) {
273 struct range *t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
275 if (t && t->end >= i->start)
276 t->end = max(t->end, i->end);
278 darray_push(&tmp, *i);
285 void ranges_roundup(ranges *r, unsigned block_size)
287 darray_for_each(*r, i) {
288 i->start = round_down(i->start, block_size);
289 i->end = round_up(i->end, block_size);
293 void ranges_rounddown(ranges *r, unsigned block_size)
295 darray_for_each(*r, i) {
296 i->start = round_up(i->start, block_size);
297 i->end = round_down(i->end, block_size);
298 i->end = max(i->end, i->start);
302 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
304 struct fiemap_extent e;
306 BUG_ON(iter->idx > iter->f->fm_mapped_extents);
308 if (iter->idx == iter->f->fm_mapped_extents) {
309 xioctl(iter->fd, FS_IOC_FIEMAP, iter->f);
311 if (!iter->f->fm_mapped_extents)
312 return (struct fiemap_extent) { .fe_length = 0 };
317 e = iter->f->fm_extents[iter->idx++];
318 BUG_ON(!e.fe_length);
320 iter->f->fm_start = e.fe_logical + e.fe_length;
325 char *strcmp_prefix(char *a, const char *a_prefix)
327 while (*a_prefix && *a == *a_prefix) {
331 return *a_prefix ? NULL : a;
336 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
338 static const u32 crc32c_tab[] = {
339 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
340 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
341 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
342 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
343 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
344 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
345 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
346 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
347 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
348 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
349 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
350 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
351 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
352 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
353 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
354 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
355 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
356 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
357 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
358 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
359 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
360 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
361 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
362 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
363 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
364 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
365 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
366 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
367 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
368 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
369 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
370 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
371 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
372 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
373 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
374 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
375 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
376 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
377 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
378 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
379 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
380 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
381 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
382 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
383 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
384 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
385 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
386 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
387 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
388 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
389 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
390 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
391 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
392 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
393 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
394 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
395 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
396 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
397 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
398 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
399 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
400 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
401 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
402 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
407 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
412 #include <linux/compiler.h>
417 #define REX_PRE "0x48, "
422 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
424 while (size >= sizeof(long)) {
425 const unsigned long *d = buf;
427 __asm__ __volatile__(
428 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
433 size -= sizeof(long);
439 __asm__ __volatile__(
440 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
453 static void *resolve_crc32c(void)
456 if (__builtin_cpu_supports("sse4.2"))
459 return crc32c_default;
463 * ifunc is buggy and I don't know what breaks it (LTO?)
465 #ifdef HAVE_WORKING_IFUNC
467 static void *ifunc_resolve_crc32c(void)
469 __builtin_cpu_init();
471 return resolve_crc32c
474 u32 crc32c(u32, const void *, size_t)
475 __attribute__((ifunc("ifunc_resolve_crc32c")));
479 u32 crc32c(u32 crc, const void *buf, size_t size)
481 static u32 (*real_crc32c)(u32, const void *, size_t);
483 if (unlikely(!real_crc32c))
484 real_crc32c = resolve_crc32c();
486 return real_crc32c(crc, buf, size);
489 #endif /* HAVE_WORKING_IFUNC */
491 char *dev_to_name(dev_t dev)
493 char *line = NULL, *name = NULL;
496 FILE *f = fopen("/proc/partitions", "r");
498 die("error opening /proc/partitions: %m");
500 while (getline(&line, &n, f) != -1) {
504 name = realloc(name, n + 1);
506 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
507 ma == major(dev) && mi == minor(dev))
519 char *dev_to_path(dev_t dev)
521 char *name = dev_to_name(dev);
525 char *path = mprintf("/dev/%s", name);
531 struct mntent *dev_to_mount(char *dev)
533 struct mntent *mnt, *ret = NULL;
534 FILE *f = setmntent("/proc/mounts", "r");
536 die("error opening /proc/mounts: %m");
538 struct stat d1 = xstat(dev);
540 while ((mnt = getmntent(f))) {
541 char *d, *p = mnt->mnt_fsname;
543 while ((d = strsep(&p, ":"))) {
549 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
552 if (S_ISBLK(d1.st_mode)) {
553 if (d1.st_rdev != d2.st_rdev)
556 if (d1.st_dev != d2.st_dev ||
557 d1.st_ino != d2.st_ino)
570 int dev_mounted(char *dev)
572 struct mntent *mnt = dev_to_mount(dev);
576 if (hasmntopt(mnt, "ro"))
581 static int kstrtoull_symbolic(const char *s, unsigned int base, unsigned long long *res)
583 if (!strcmp(s, "U64_MAX")) {
588 if (!strcmp(s, "U32_MAX")) {
593 return kstrtoull(s, base, res);
596 static int kstrtouint_symbolic(const char *s, unsigned int base, unsigned *res)
598 unsigned long long tmp;
601 rv = kstrtoull_symbolic(s, base, &tmp);
604 if (tmp != (unsigned long long)(unsigned int)tmp)
610 struct bpos bpos_parse(char *buf)
612 char *orig = strdup(buf);
615 char *inode_s = strsep(&s, ":");
616 char *offset_s = strsep(&s, ":");
617 char *snapshot_s = strsep(&s, ":");
619 if (!inode_s || !offset_s || s)
620 die("invalid bpos %s", orig);
623 u64 inode_v = 0, offset_v = 0;
625 if (kstrtoull_symbolic(inode_s, 10, &inode_v))
626 die("invalid bpos.inode %s", inode_s);
628 if (kstrtoull_symbolic(offset_s, 10, &offset_v))
629 die("invalid bpos.offset %s", offset_s);
632 kstrtouint_symbolic(snapshot_s, 10, &snapshot_v))
633 die("invalid bpos.snapshot %s", snapshot_s);
635 return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
638 struct bbpos bbpos_parse(char *buf)
640 char *s = buf, *field;
643 if (!(field = strsep(&s, ":")))
644 die("invalid bbpos %s", buf);
646 ret.btree = read_string_list_or_die(field, __bch2_btree_ids, "btree id");
649 die("invalid bbpos %s", buf);
651 ret.pos = bpos_parse(s);
655 darray_str get_or_split_cmdline_devs(int argc, char *argv[])
660 bch2_split_devs(argv[0], &ret);
662 for (unsigned i = 0; i < argc; i++)
663 darray_push(&ret, strdup(argv[i]));