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->handle = bdev_open_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->handle);
197 die("Error opening device to format %s: %s", dev->path, strerror(-ret));
198 dev->bdev = dev->handle->bdev;
200 if (!(pr = blkid_new_probe()))
201 die("blkid error 1");
202 if (blkid_probe_set_device(pr, dev->bdev->bd_fd, 0, 0))
203 die("blkid error 2");
204 if (blkid_probe_enable_partitions(pr, true) ||
205 blkid_probe_enable_superblocks(pr, true) ||
206 blkid_probe_set_superblocks_flags(pr,
207 BLKID_SUBLKS_LABEL|BLKID_SUBLKS_TYPE|BLKID_SUBLKS_MAGIC))
208 die("blkid error 3");
209 if (blkid_do_fullprobe(pr) < 0)
210 die("blkid error 4");
212 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
213 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
217 printf("%s contains a %s filesystem labelled '%s'\n",
218 dev->path, fs_type, fs_label);
220 printf("%s contains a %s filesystem\n",
223 fputs("Proceed anyway?", stdout);
227 while (blkid_do_probe(pr) == 0) {
228 if (blkid_do_wipe(pr, 0))
229 die("Failed to wipe preexisting metadata.");
233 blkid_free_probe(pr);
239 const char *short_yes = "yY";
244 fputs(" (y,n) ", stdout);
247 if (getline(&buf, &buflen, stdin) < 0)
248 die("error reading from standard input");
250 ret = strchr(short_yes, buf[0]);
255 static int range_cmp(const void *_l, const void *_r)
257 const struct range *l = _l, *r = _r;
259 if (l->start < r->start)
261 if (l->start > r->start)
266 void ranges_sort_merge(ranges *r)
270 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
272 /* Merge contiguous ranges: */
273 darray_for_each(*r, i) {
274 struct range *t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
276 if (t && t->end >= i->start)
277 t->end = max(t->end, i->end);
279 darray_push(&tmp, *i);
286 void ranges_roundup(ranges *r, unsigned block_size)
288 darray_for_each(*r, i) {
289 i->start = round_down(i->start, block_size);
290 i->end = round_up(i->end, block_size);
294 void ranges_rounddown(ranges *r, unsigned block_size)
296 darray_for_each(*r, i) {
297 i->start = round_up(i->start, block_size);
298 i->end = round_down(i->end, block_size);
299 i->end = max(i->end, i->start);
303 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
305 struct fiemap_extent e;
307 BUG_ON(iter->idx > iter->f->fm_mapped_extents);
309 if (iter->idx == iter->f->fm_mapped_extents) {
310 xioctl(iter->fd, FS_IOC_FIEMAP, iter->f);
312 if (!iter->f->fm_mapped_extents)
313 return (struct fiemap_extent) { .fe_length = 0 };
318 e = iter->f->fm_extents[iter->idx++];
319 BUG_ON(!e.fe_length);
321 iter->f->fm_start = e.fe_logical + e.fe_length;
326 char *strcmp_prefix(char *a, const char *a_prefix)
328 while (*a_prefix && *a == *a_prefix) {
332 return *a_prefix ? NULL : a;
337 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
339 static const u32 crc32c_tab[] = {
340 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
341 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
342 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
343 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
344 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
345 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
346 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
347 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
348 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
349 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
350 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
351 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
352 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
353 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
354 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
355 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
356 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
357 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
358 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
359 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
360 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
361 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
362 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
363 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
364 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
365 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
366 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
367 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
368 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
369 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
370 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
371 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
372 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
373 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
374 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
375 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
376 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
377 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
378 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
379 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
380 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
381 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
382 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
383 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
384 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
385 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
386 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
387 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
388 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
389 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
390 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
391 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
392 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
393 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
394 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
395 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
396 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
397 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
398 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
399 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
400 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
401 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
402 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
403 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
408 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
413 #include <linux/compiler.h>
418 #define REX_PRE "0x48, "
423 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
425 while (size >= sizeof(long)) {
426 const unsigned long *d = buf;
428 __asm__ __volatile__(
429 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
434 size -= sizeof(long);
440 __asm__ __volatile__(
441 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
454 static void *resolve_crc32c(void)
457 if (__builtin_cpu_supports("sse4.2"))
460 return crc32c_default;
464 * ifunc is buggy and I don't know what breaks it (LTO?)
466 #ifdef HAVE_WORKING_IFUNC
468 static void *ifunc_resolve_crc32c(void)
470 __builtin_cpu_init();
472 return resolve_crc32c
475 u32 crc32c(u32, const void *, size_t)
476 __attribute__((ifunc("ifunc_resolve_crc32c")));
480 u32 crc32c(u32 crc, const void *buf, size_t size)
482 static u32 (*real_crc32c)(u32, const void *, size_t);
484 if (unlikely(!real_crc32c))
485 real_crc32c = resolve_crc32c();
487 return real_crc32c(crc, buf, size);
490 #endif /* HAVE_WORKING_IFUNC */
492 char *dev_to_name(dev_t dev)
494 char *line = NULL, *name = NULL;
497 FILE *f = fopen("/proc/partitions", "r");
499 die("error opening /proc/partitions: %m");
501 while (getline(&line, &n, f) != -1) {
505 name = realloc(name, n + 1);
507 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
508 ma == major(dev) && mi == minor(dev))
520 char *dev_to_path(dev_t dev)
522 char *name = dev_to_name(dev);
526 char *path = mprintf("/dev/%s", name);
532 struct mntent *dev_to_mount(char *dev)
534 struct mntent *mnt, *ret = NULL;
535 FILE *f = setmntent("/proc/mounts", "r");
537 die("error opening /proc/mounts: %m");
539 struct stat d1 = xstat(dev);
541 while ((mnt = getmntent(f))) {
542 char *d, *p = mnt->mnt_fsname;
544 while ((d = strsep(&p, ":"))) {
550 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
553 if (S_ISBLK(d1.st_mode)) {
554 if (d1.st_rdev != d2.st_rdev)
557 if (d1.st_dev != d2.st_dev ||
558 d1.st_ino != d2.st_ino)
571 int dev_mounted(char *dev)
573 struct mntent *mnt = dev_to_mount(dev);
577 if (hasmntopt(mnt, "ro"))
582 static int kstrtoull_symbolic(const char *s, unsigned int base, unsigned long long *res)
584 if (!strcmp(s, "U64_MAX")) {
589 if (!strcmp(s, "U32_MAX")) {
594 return kstrtoull(s, base, res);
597 static int kstrtouint_symbolic(const char *s, unsigned int base, unsigned *res)
599 unsigned long long tmp;
602 rv = kstrtoull_symbolic(s, base, &tmp);
605 if (tmp != (unsigned long long)(unsigned int)tmp)
611 struct bpos bpos_parse(char *buf)
613 char *orig = strdup(buf);
616 char *inode_s = strsep(&s, ":");
617 char *offset_s = strsep(&s, ":");
618 char *snapshot_s = strsep(&s, ":");
620 if (!inode_s || !offset_s || s)
621 die("invalid bpos %s", orig);
624 u64 inode_v = 0, offset_v = 0;
626 if (kstrtoull_symbolic(inode_s, 10, &inode_v))
627 die("invalid bpos.inode %s", inode_s);
629 if (kstrtoull_symbolic(offset_s, 10, &offset_v))
630 die("invalid bpos.offset %s", offset_s);
633 kstrtouint_symbolic(snapshot_s, 10, &snapshot_v))
634 die("invalid bpos.snapshot %s", snapshot_s);
636 return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
639 struct bbpos bbpos_parse(char *buf)
641 char *s = buf, *field;
644 if (!(field = strsep(&s, ":")))
645 die("invalid bbpos %s", buf);
647 ret.btree = read_string_list_or_die(field, __bch2_btree_ids, "btree id");
650 die("invalid bbpos %s", buf);
652 ret.pos = bpos_parse(s);
656 darray_str get_or_split_cmdline_devs(int argc, char *argv[])
661 bch2_split_devs(argv[0], &ret);
663 for (unsigned i = 0; i < argc; i++)
664 darray_push(&ret, strdup(argv[i]));