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)
300 sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
302 /* Merge contiguous ranges: */
303 darray_for_each(*r, i) {
304 t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
306 if (t && t->end >= i->start)
307 t->end = max(t->end, i->end);
309 darray_push(tmp, *i);
316 void ranges_roundup(ranges *r, unsigned block_size)
320 darray_for_each(*r, i) {
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_for_each(*r, i) {
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 char *strcmp_prefix(char *a, const char *a_prefix)
362 while (*a_prefix && *a == *a_prefix) {
366 return *a_prefix ? NULL : a;
371 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
373 static const u32 crc32c_tab[] = {
374 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
375 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
376 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
377 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
378 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
379 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
380 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
381 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
382 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
383 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
384 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
385 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
386 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
387 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
388 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
389 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
390 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
391 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
392 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
393 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
394 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
395 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
396 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
397 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
398 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
399 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
400 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
401 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
402 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
403 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
404 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
405 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
406 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
407 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
408 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
409 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
410 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
411 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
412 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
413 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
414 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
415 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
416 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
417 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
418 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
419 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
420 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
421 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
422 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
423 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
424 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
425 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
426 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
427 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
428 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
429 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
430 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
431 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
432 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
433 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
434 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
435 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
436 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
437 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
442 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
447 #include <linux/compiler.h>
452 #define REX_PRE "0x48, "
457 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
459 while (size >= sizeof(long)) {
460 const unsigned long *d = buf;
462 __asm__ __volatile__(
463 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
468 size -= sizeof(long);
474 __asm__ __volatile__(
475 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
488 static void *resolve_crc32c(void)
491 if (__builtin_cpu_supports("sse4.2"))
494 return crc32c_default;
498 * ifunc is buggy and I don't know what breaks it (LTO?)
500 #ifdef HAVE_WORKING_IFUNC
502 static void *ifunc_resolve_crc32c(void)
504 __builtin_cpu_init();
506 return resolve_crc32c
509 u32 crc32c(u32, const void *, size_t)
510 __attribute__((ifunc("ifunc_resolve_crc32c")));
514 u32 crc32c(u32 crc, const void *buf, size_t size)
516 static u32 (*real_crc32c)(u32, const void *, size_t);
518 if (unlikely(!real_crc32c))
519 real_crc32c = resolve_crc32c();
521 return real_crc32c(crc, buf, size);
524 #endif /* HAVE_WORKING_IFUNC */
526 char *dev_to_name(dev_t dev)
528 char *line = NULL, *name = NULL;
531 FILE *f = fopen("/proc/partitions", "r");
533 die("error opening /proc/partitions: %m");
535 while (getline(&line, &n, f) != -1) {
539 name = realloc(name, n + 1);
541 if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
542 ma == major(dev) && mi == minor(dev))
554 char *dev_to_path(dev_t dev)
556 char *name = dev_to_name(dev);
560 char *path = mprintf("/dev/%s", name);
566 struct mntent *dev_to_mount(char *dev)
568 struct mntent *mnt, *ret = NULL;
569 FILE *f = setmntent("/proc/mounts", "r");
571 die("error opening /proc/mounts: %m");
573 struct stat d1 = xstat(dev);
575 while ((mnt = getmntent(f))) {
576 char *d, *p = mnt->mnt_fsname;
578 while ((d = strsep(&p, ":"))) {
584 if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
587 if (S_ISBLK(d1.st_mode)) {
588 if (d1.st_rdev != d2.st_rdev)
591 if (d1.st_dev != d2.st_dev ||
592 d1.st_ino != d2.st_ino)
605 int dev_mounted(char *dev)
607 struct mntent *mnt = dev_to_mount(dev);
611 if (hasmntopt(mnt, "ro"))
616 struct bpos bpos_parse(char *buf)
618 char *s = buf, *field;
619 u64 inode_v = 0, offset_v = 0;
621 if (!(field = strsep(&s, ":")) ||
622 kstrtoull(field, 10, &inode_v))
623 die("invalid bpos %s", buf);
625 if ((field = strsep(&s, ":")) &&
626 kstrtoull(field, 10, &offset_v))
627 die("invalid bpos %s", buf);
630 die("invalid bpos %s", buf);
632 return (struct bpos) { .inode = inode_v, .offset = offset_v };