11 #include <sys/ioctl.h>
13 #include <sys/types.h>
17 #include <uuid/uuid.h>
19 #include "bcachefs_ioctl.h"
20 #include "linux/sort.h"
21 #include "tools-util.h"
24 void die(const char *fmt, ...)
29 vfprintf(stderr, fmt, args);
36 char *mprintf(const char *fmt, ...)
43 ret = vasprintf(&str, fmt, args);
47 die("insufficient memory");
52 void *xcalloc(size_t count, size_t size)
54 void *p = calloc(count, size);
57 die("insufficient memory");
62 void *xmalloc(size_t size)
64 void *p = malloc(size);
67 die("insufficient memory");
73 void xpread(int fd, void *buf, size_t count, off_t offset)
75 ssize_t r = pread(fd, buf, count, offset);
78 die("read error (ret %zi)", r);
81 void xpwrite(int fd, const void *buf, size_t count, off_t offset)
83 ssize_t r = pwrite(fd, buf, count, offset);
86 die("write error (ret %zi err %m)", r);
89 struct stat xfstatat(int dirfd, const char *path, int flags)
92 if (fstatat(dirfd, path, &stat, flags))
93 die("stat error: %m");
97 struct stat xfstat(int fd)
100 if (fstat(fd, &stat))
101 die("stat error: %m");
107 struct units_buf __pr_units(u64 v, enum units units)
109 struct units_buf ret;
113 snprintf(ret.b, sizeof(ret.b), "%llu", v << 9);
116 snprintf(ret.b, sizeof(ret.b), "%llu", v);
122 int exp = log(v) / log(1024);
123 snprintf(ret.b, sizeof(ret.b), "%.1f%c",
127 snprintf(ret.b, sizeof(ret.b), "%llu", v);
136 /* Argument parsing stuff: */
138 /* File parsing (i.e. sysfs) */
140 char *read_file_str(int dirfd, const char *path)
142 int fd = xopenat(dirfd, path, O_RDONLY);
143 ssize_t len = xfstat(fd).st_size;
145 char *buf = xmalloc(len + 1);
147 len = read(fd, buf, len);
149 die("read error: %m");
152 if (len && buf[len - 1] == '\n')
160 u64 read_file_u64(int dirfd, const char *path)
162 char *buf = read_file_str(dirfd, path);
164 if (kstrtou64(buf, 10, &v))
165 die("read_file_u64: error parsing %s (got %s)", path, buf);
170 /* String list options: */
172 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
175 ssize_t v = bch2_read_string_list(opt, list);
177 die("Bad %s %s", msg, opt);
182 /* Returns size of file or block device: */
183 u64 get_size(const char *path, int fd)
185 struct stat statbuf = xfstat(fd);
187 if (!S_ISBLK(statbuf.st_mode))
188 return statbuf.st_size;
191 xioctl(fd, BLKGETSIZE64, &ret);
195 /* Returns blocksize in units of 512 byte sectors: */
196 unsigned get_blocksize(const char *path, int fd)
198 struct stat statbuf = xfstat(fd);
200 if (!S_ISBLK(statbuf.st_mode))
201 return statbuf.st_blksize >> 9;
204 xioctl(fd, BLKPBSZGET, &ret);
208 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
209 int open_for_format(const char *dev, bool force)
212 const char *fs_type = NULL, *fs_label = NULL;
213 size_t fs_type_len, fs_label_len;
215 int fd = xopen(dev, O_RDWR|O_EXCL);
220 if (!(pr = blkid_new_probe()))
221 die("blkid error 1");
222 if (blkid_probe_set_device(pr, fd, 0, 0))
223 die("blkid error 2");
224 if (blkid_probe_enable_partitions(pr, true))
225 die("blkid error 3");
226 if (blkid_do_fullprobe(pr) < 0)
227 die("blkid error 4");
229 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
230 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
234 printf("%s contains a %s filesystem labelled '%s'\n",
235 dev, fs_type, fs_label);
237 printf("%s contains a %s filesystem\n",
239 fputs("Proceed anyway?", stdout);
244 blkid_free_probe(pr);
248 /* Global control device: */
249 int bcachectl_open(void)
251 return xopen("/dev/bcachefs-ctl", O_RDWR);
254 /* Filesystem handles (ioctl, sysfs dir): */
256 #define SYSFS_BASE "/sys/fs/bcachefs/"
258 struct bcache_handle bcache_fs_open(const char *path)
260 struct bcache_handle ret;
263 if (!uuid_parse(path, tmp)) {
264 /* It's a UUID, look it up in sysfs: */
265 char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
266 ret.sysfs_fd = xopen(sysfs, O_RDONLY);
268 char *minor = read_file_str(ret.sysfs_fd, "minor");
269 char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
270 ret.ioctl_fd = xopen(ctl, O_RDWR);
277 ret.ioctl_fd = xopen(path, O_RDONLY);
279 struct bch_ioctl_query_uuid uuid;
280 xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid);
283 uuid_unparse(uuid.uuid.b, uuid_str);
285 char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
286 ret.sysfs_fd = xopen(sysfs, O_RDONLY);
295 const char *short_yes = "yY";
300 fputs(" (y,n) ", stdout);
303 if (getline(&buf, &buflen, stdin) < 0)
304 die("error reading from standard input");
306 ret = strchr(short_yes, buf[0]);
311 static int range_cmp(const void *_l, const void *_r)
313 const struct range *l = _l, *r = _r;
315 if (l->start < r->start)
317 if (l->start > r->start)
322 void ranges_sort_merge(ranges *r)
325 ranges tmp = { NULL };
327 sort(&darray_item(*r, 0), darray_size(*r),
328 sizeof(darray_item(*r, 0)), range_cmp, NULL);
330 /* Merge contiguous ranges: */
331 darray_foreach(i, *r) {
332 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
334 if (t && t->end >= i->start)
335 t->end = max(t->end, i->end);
337 darray_append(tmp, *i);
344 void ranges_roundup(ranges *r, unsigned block_size)
348 darray_foreach(i, *r) {
349 i->start = round_down(i->start, block_size);
350 i->end = round_up(i->end, block_size);
354 void ranges_rounddown(ranges *r, unsigned block_size)
358 darray_foreach(i, *r) {
359 i->start = round_up(i->start, block_size);
360 i->end = round_down(i->end, block_size);
361 i->end = max(i->end, i->start);
365 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
367 struct fiemap_extent e;
369 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
371 if (iter->idx == iter->f.fm_mapped_extents) {
372 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
374 if (!iter->f.fm_mapped_extents)
375 return (struct fiemap_extent) { .fe_length = 0 };
380 e = iter->f.fm_extents[iter->idx++];
381 BUG_ON(!e.fe_length);
383 iter->f.fm_start = e.fe_logical + e.fe_length;
388 const char *strcmp_prefix(const char *a, const char *a_prefix)
390 while (*a_prefix && *a == *a_prefix) {
394 return *a_prefix ? NULL : a;
397 unsigned hatoi_validate(const char *s, const char *msg)
401 if (bch2_strtoull_h(s, &v))
402 die("bad %s %s", msg, s);
405 die("%s must be a power of two", msg);
410 die("%s too large\n", msg);
413 die("%s too small\n", msg);
420 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
422 static const u32 crc32c_tab[] = {
423 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
424 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
425 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
426 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
427 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
428 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
429 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
430 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
431 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
432 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
433 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
434 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
435 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
436 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
437 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
438 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
439 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
440 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
441 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
442 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
443 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
444 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
445 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
446 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
447 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
448 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
449 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
450 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
451 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
452 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
453 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
454 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
455 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
456 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
457 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
458 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
459 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
460 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
461 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
462 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
463 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
464 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
465 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
466 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
467 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
468 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
469 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
470 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
471 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
472 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
473 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
474 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
475 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
476 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
477 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
478 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
479 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
480 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
481 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
482 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
483 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
484 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
485 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
486 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
491 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
496 #include <linux/compiler.h>
501 #define REX_PRE "0x48, "
506 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
508 while (size >= sizeof(long)) {
509 const unsigned long *d = buf;
511 __asm__ __volatile__(
512 ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
517 size -= sizeof(long);
523 __asm__ __volatile__(
524 ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
535 static void *resolve_crc32c(void)
537 __builtin_cpu_init();
540 if (__builtin_cpu_supports("sse4.2"))
543 return crc32c_default;
547 * ifunc is buggy and I don't know what breaks it (LTO?)
549 #ifdef HAVE_WORKING_IFUNC
551 u32 crc32c(u32, const void *, size_t)
552 __attribute__((ifunc("resolve_crc32c")));
556 u32 crc32c(u32 crc, const void *buf, size_t size)
558 static u32 (*real_crc32c)(u32, const void *, size_t);
560 if (unlikely(!real_crc32c))
561 real_crc32c = resolve_crc32c();
563 return real_crc32c(crc, buf, size);
566 #endif /* HAVE_WORKING_IFUNC */