]> git.sesse.net Git - bcachefs-tools-debian/blob - tools-util.c
Update bcachefs sources to 676dd269f0f8 mean and variance: Promote to lib/math
[bcachefs-tools-debian] / tools-util.c
1 #include <assert.h>
2 #include <ctype.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <linux/fs.h>
7 #include <math.h>
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include <sys/sysmacros.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16
17 #include <blkid.h>
18 #include <uuid/uuid.h>
19
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"
25
26 void die(const char *fmt, ...)
27 {
28         va_list args;
29
30         va_start(args, fmt);
31         vfprintf(stderr, fmt, args);
32         va_end(args);
33         fputc('\n', stderr);
34
35         _exit(EXIT_FAILURE);
36 }
37
38 char *mprintf(const char *fmt, ...)
39 {
40         va_list args;
41         char *str;
42         int ret;
43
44         va_start(args, fmt);
45         ret = vasprintf(&str, fmt, args);
46         va_end(args);
47
48         if (ret < 0)
49                 die("insufficient memory");
50
51         return str;
52 }
53
54 void *xcalloc(size_t count, size_t size)
55 {
56         void *p = calloc(count, size);
57
58         if (!p)
59                 die("insufficient memory");
60
61         return p;
62 }
63
64 void *xmalloc(size_t size)
65 {
66         void *p = malloc(size);
67
68         if (!p)
69                 die("insufficient memory");
70
71         memset(p, 0, size);
72         return p;
73 }
74
75 void *xrealloc(void *p, size_t size)
76 {
77         p = realloc(p, size);
78         if (!p)
79                 die("insufficient memory");
80
81         return p;
82 }
83
84 void xpread(int fd, void *buf, size_t count, off_t offset)
85 {
86         while (count) {
87                 ssize_t r = pread(fd, buf, count, offset);
88
89                 if (r < 0)
90                         die("read error: %m");
91                 if (!r)
92                         die("pread error: unexpected eof");
93                 count   -= r;
94                 offset  += r;
95         }
96 }
97
98 void xpwrite(int fd, const void *buf, size_t count, off_t offset, const char *msg)
99 {
100         ssize_t r = pwrite(fd, buf, count, offset);
101
102         if (r != count)
103                 die("error writing %s (ret %zi err %m)", msg, r);
104 }
105
106 struct stat xfstatat(int dirfd, const char *path, int flags)
107 {
108         struct stat stat;
109         if (fstatat(dirfd, path, &stat, flags))
110                 die("stat error: %m");
111         return stat;
112 }
113
114 struct stat xfstat(int fd)
115 {
116         struct stat stat;
117         if (fstat(fd, &stat))
118                 die("stat error: %m");
119         return stat;
120 }
121
122 struct stat xstat(const char *path)
123 {
124         struct stat statbuf;
125         if (stat(path, &statbuf))
126                 die("stat error statting %s: %m", path);
127         return statbuf;
128 }
129
130 /* File parsing (i.e. sysfs) */
131
132 void write_file_str(int dirfd, const char *path, const char *str)
133 {
134         int fd = xopenat(dirfd, path, O_WRONLY);
135         ssize_t wrote, len = strlen(str);
136
137         wrote = write(fd, str, len);
138         if (wrote != len)
139                 die("read error: %m");
140         close(fd);
141 }
142
143 char *read_file_str(int dirfd, const char *path)
144 {
145         int fd = xopenat(dirfd, path, O_RDONLY);
146         ssize_t len = xfstat(fd).st_size;
147
148         char *buf = xmalloc(len + 1);
149
150         len = read(fd, buf, len);
151         if (len < 0)
152                 die("read error: %m");
153
154         buf[len] = '\0';
155         if (len && buf[len - 1] == '\n')
156                 buf[len - 1] = '\0';
157         if (!strlen(buf)) {
158                 free(buf);
159                 buf = NULL;
160         }
161
162         close(fd);
163
164         return buf;
165 }
166
167 u64 read_file_u64(int dirfd, const char *path)
168 {
169         char *buf = read_file_str(dirfd, path);
170         u64 v;
171         if (bch2_strtou64_h(buf, &v))
172                 die("read_file_u64: error parsing %s (got %s)", path, buf);
173         free(buf);
174         return v;
175 }
176
177 /* String list options: */
178
179 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
180                                 const char *msg)
181 {
182         ssize_t v = match_string(list, -1, opt);
183         if (v < 0)
184                 die("Bad %s %s", msg, opt);
185
186         return v;
187 }
188
189 /* Returns size of file or block device: */
190 u64 get_size(int fd)
191 {
192         struct stat statbuf = xfstat(fd);
193
194         if (!S_ISBLK(statbuf.st_mode))
195                 return statbuf.st_size;
196
197         u64 ret;
198         xioctl(fd, BLKGETSIZE64, &ret);
199         return ret;
200 }
201
202 /* Returns blocksize, in bytes: */
203 unsigned get_blocksize(int fd)
204 {
205         struct stat statbuf = xfstat(fd);
206
207         if (!S_ISBLK(statbuf.st_mode))
208                 return statbuf.st_blksize;
209
210         unsigned ret;
211         xioctl(fd, BLKPBSZGET, &ret);
212         return ret;
213 }
214
215 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
216 int open_for_format(struct dev_opts *dev, bool force)
217 {
218         blkid_probe pr;
219         const char *fs_type = NULL, *fs_label = NULL;
220         size_t fs_type_len, fs_label_len;
221
222         dev->bdev = blkdev_get_by_path(dev->path, BLK_OPEN_READ|BLK_OPEN_WRITE|BLK_OPEN_EXCL,
223                                        dev, NULL);
224         int ret = PTR_ERR_OR_ZERO(dev->bdev);
225         if (ret < 0)
226                 die("Error opening device to format %s: %s", dev->path, strerror(-ret));
227
228         if (!(pr = blkid_new_probe()))
229                 die("blkid error 1");
230         if (blkid_probe_set_device(pr, dev->bdev->bd_buffered_fd, 0, 0))
231                 die("blkid error 2");
232         if (blkid_probe_enable_partitions(pr, true) ||
233             blkid_probe_enable_superblocks(pr, true) ||
234             blkid_probe_set_superblocks_flags(pr,
235                         BLKID_SUBLKS_LABEL|BLKID_SUBLKS_TYPE|BLKID_SUBLKS_MAGIC))
236                 die("blkid error 3");
237         if (blkid_do_fullprobe(pr) < 0)
238                 die("blkid error 4");
239
240         blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
241         blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
242
243         if (fs_type) {
244                 if (fs_label)
245                         printf("%s contains a %s filesystem labelled '%s'\n",
246                                dev->path, fs_type, fs_label);
247                 else
248                         printf("%s contains a %s filesystem\n",
249                                dev->path, fs_type);
250                 if (!force) {
251                         fputs("Proceed anyway?", stdout);
252                         if (!ask_yn())
253                                 exit(EXIT_FAILURE);
254                 }
255                 while (blkid_do_probe(pr) == 0) {
256                         if (blkid_do_wipe(pr, 0))
257                                 die("Failed to wipe preexisting metadata.");
258                 }
259         }
260
261         blkid_free_probe(pr);
262         return ret;
263 }
264
265 bool ask_yn(void)
266 {
267         const char *short_yes = "yY";
268         char *buf = NULL;
269         size_t buflen = 0;
270         bool ret;
271
272         fputs(" (y,n) ", stdout);
273         fflush(stdout);
274
275         if (getline(&buf, &buflen, stdin) < 0)
276                 die("error reading from standard input");
277
278         ret = strchr(short_yes, buf[0]);
279         free(buf);
280         return ret;
281 }
282
283 static int range_cmp(const void *_l, const void *_r)
284 {
285         const struct range *l = _l, *r = _r;
286
287         if (l->start < r->start)
288                 return -1;
289         if (l->start > r->start)
290                 return  1;
291         return 0;
292 }
293
294 void ranges_sort_merge(ranges *r)
295 {
296         struct range *t, *i;
297         ranges tmp = { 0 };
298
299         sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
300
301         /* Merge contiguous ranges: */
302         darray_for_each(*r, i) {
303                 t = tmp.nr ?  &tmp.data[tmp.nr - 1] : NULL;
304
305                 if (t && t->end >= i->start)
306                         t->end = max(t->end, i->end);
307                 else
308                         darray_push(&tmp, *i);
309         }
310
311         darray_exit(r);
312         *r = tmp;
313 }
314
315 void ranges_roundup(ranges *r, unsigned block_size)
316 {
317         struct range *i;
318
319         darray_for_each(*r, i) {
320                 i->start = round_down(i->start, block_size);
321                 i->end  = round_up(i->end, block_size);
322         }
323 }
324
325 void ranges_rounddown(ranges *r, unsigned block_size)
326 {
327         struct range *i;
328
329         darray_for_each(*r, i) {
330                 i->start = round_up(i->start, block_size);
331                 i->end  = round_down(i->end, block_size);
332                 i->end  = max(i->end, i->start);
333         }
334 }
335
336 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
337 {
338         struct fiemap_extent e;
339
340         BUG_ON(iter->idx > iter->f->fm_mapped_extents);
341
342         if (iter->idx == iter->f->fm_mapped_extents) {
343                 xioctl(iter->fd, FS_IOC_FIEMAP, iter->f);
344
345                 if (!iter->f->fm_mapped_extents)
346                         return (struct fiemap_extent) { .fe_length = 0 };
347
348                 iter->idx = 0;
349         }
350
351         e = iter->f->fm_extents[iter->idx++];
352         BUG_ON(!e.fe_length);
353
354         iter->f->fm_start = e.fe_logical + e.fe_length;
355
356         return e;
357 }
358
359 char *strcmp_prefix(char *a, const char *a_prefix)
360 {
361         while (*a_prefix && *a == *a_prefix) {
362                 a++;
363                 a_prefix++;
364         }
365         return *a_prefix ? NULL : a;
366 }
367
368 /* crc32c */
369
370 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
371 {
372         static const u32 crc32c_tab[] = {
373                 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
374                 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
375                 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
376                 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
377                 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
378                 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
379                 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
380                 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
381                 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
382                 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
383                 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
384                 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
385                 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
386                 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
387                 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
388                 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
389                 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
390                 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
391                 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
392                 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
393                 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
394                 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
395                 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
396                 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
397                 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
398                 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
399                 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
400                 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
401                 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
402                 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
403                 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
404                 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
405                 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
406                 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
407                 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
408                 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
409                 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
410                 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
411                 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
412                 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
413                 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
414                 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
415                 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
416                 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
417                 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
418                 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
419                 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
420                 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
421                 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
422                 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
423                 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
424                 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
425                 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
426                 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
427                 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
428                 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
429                 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
430                 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
431                 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
432                 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
433                 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
434                 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
435                 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
436                 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
437         };
438         const u8 *p = buf;
439
440         while (size--)
441                 crc = crc32c_tab[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
442
443         return crc;
444 }
445
446 #include <linux/compiler.h>
447
448 #ifdef __x86_64__
449
450 #ifdef CONFIG_X86_64
451 #define REX_PRE "0x48, "
452 #else
453 #define REX_PRE
454 #endif
455
456 static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
457 {
458         while (size >= sizeof(long)) {
459                 const unsigned long *d = buf;
460
461                 __asm__ __volatile__(
462                         ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
463                         :"=S"(crc)
464                         :"0"(crc), "c"(*d)
465                 );
466                 buf     += sizeof(long);
467                 size    -= sizeof(long);
468         }
469
470         while (size) {
471                 const u8 *d = buf;
472
473                 __asm__ __volatile__(
474                         ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
475                         :"=S"(crc)
476                         :"0"(crc), "c"(*d)
477                 );
478                 buf     += 1;
479                 size    -= 1;
480         }
481
482         return crc;
483 }
484
485 #endif
486
487 static void *resolve_crc32c(void)
488 {
489 #ifdef __x86_64__
490         if (__builtin_cpu_supports("sse4.2"))
491                 return crc32c_sse42;
492 #endif
493         return crc32c_default;
494 }
495
496 /*
497  * ifunc is buggy and I don't know what breaks it (LTO?)
498  */
499 #ifdef HAVE_WORKING_IFUNC
500
501 static void *ifunc_resolve_crc32c(void)
502 {
503         __builtin_cpu_init();
504
505         return resolve_crc32c
506 }
507
508 u32 crc32c(u32, const void *, size_t)
509         __attribute__((ifunc("ifunc_resolve_crc32c")));
510
511 #else
512
513 u32 crc32c(u32 crc, const void *buf, size_t size)
514 {
515         static u32 (*real_crc32c)(u32, const void *, size_t);
516
517         if (unlikely(!real_crc32c))
518                 real_crc32c = resolve_crc32c();
519
520         return real_crc32c(crc, buf, size);
521 }
522
523 #endif /* HAVE_WORKING_IFUNC */
524
525 char *dev_to_name(dev_t dev)
526 {
527         char *line = NULL, *name = NULL;
528         size_t n = 0;
529
530         FILE *f = fopen("/proc/partitions", "r");
531         if (!f)
532                 die("error opening /proc/partitions: %m");
533
534         while (getline(&line, &n, f) != -1) {
535                 unsigned ma, mi;
536                 u64 sectors;
537
538                 name = realloc(name, n + 1);
539
540                 if (sscanf(line, " %u %u %llu %s", &ma, &mi, &sectors, name) == 4 &&
541                     ma == major(dev) && mi == minor(dev))
542                         goto found;
543         }
544
545         free(name);
546         name = NULL;
547 found:
548         fclose(f);
549         free(line);
550         return name;
551 }
552
553 char *dev_to_path(dev_t dev)
554 {
555         char *name = dev_to_name(dev);
556         if (!name)
557                 return NULL;
558
559         char *path = mprintf("/dev/%s", name);
560
561         free(name);
562         return path;
563 }
564
565 struct mntent *dev_to_mount(char *dev)
566 {
567         struct mntent *mnt, *ret = NULL;
568         FILE *f = setmntent("/proc/mounts", "r");
569         if (!f)
570                 die("error opening /proc/mounts: %m");
571
572         struct stat d1 = xstat(dev);
573
574         while ((mnt = getmntent(f))) {
575                 char *d, *p = mnt->mnt_fsname;
576
577                 while ((d = strsep(&p, ":"))) {
578                         struct stat d2;
579
580                         if (stat(d, &d2))
581                                 continue;
582
583                         if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
584                                 continue;
585
586                         if (S_ISBLK(d1.st_mode)) {
587                                 if (d1.st_rdev != d2.st_rdev)
588                                         continue;
589                         } else {
590                                 if (d1.st_dev != d2.st_dev ||
591                                     d1.st_ino != d2.st_ino)
592                                         continue;
593                         }
594
595                         ret = mnt;
596                         goto found;
597                 }
598         }
599 found:
600         fclose(f);
601         return ret;
602 }
603
604 int dev_mounted(char *dev)
605 {
606         struct mntent *mnt = dev_to_mount(dev);
607
608         if (!mnt)
609                 return 0;
610         if (hasmntopt(mnt, "ro"))
611                 return 1;
612         return 2;
613 }
614
615 static int kstrtoull_symbolic(const char *s, unsigned int base, unsigned long long *res)
616 {
617         if (!strcmp(s, "U64_MAX")) {
618                 *res = U64_MAX;
619                 return 0;
620         }
621
622         if (!strcmp(s, "U32_MAX")) {
623                 *res = U32_MAX;
624                 return 0;
625         }
626
627         return kstrtoull(s, base, res);
628 }
629
630 static int kstrtouint_symbolic(const char *s, unsigned int base, unsigned *res)
631 {
632         unsigned long long tmp;
633         int rv;
634
635         rv = kstrtoull_symbolic(s, base, &tmp);
636         if (rv < 0)
637                 return rv;
638         if (tmp != (unsigned long long)(unsigned int)tmp)
639                 return -ERANGE;
640         *res = tmp;
641         return 0;
642 }
643
644 struct bpos bpos_parse(char *buf)
645 {
646         char *orig = strdup(buf);
647         char *s = buf;
648
649         char *inode_s   = strsep(&s, ":");
650         char *offset_s  = strsep(&s, ":");
651         char *snapshot_s = strsep(&s, ":");
652
653         if (!inode_s || !offset_s || s)
654                 die("invalid bpos %s", orig);
655         free(orig);
656
657         u64 inode_v = 0, offset_v = 0;
658         u32 snapshot_v = 0;
659         if (kstrtoull_symbolic(inode_s, 10, &inode_v))
660                 die("invalid bpos.inode %s", inode_s);
661
662         if (kstrtoull_symbolic(offset_s, 10, &offset_v))
663                 die("invalid bpos.offset %s", offset_s);
664
665         if (snapshot_s &&
666             kstrtouint_symbolic(snapshot_s, 10, &snapshot_v))
667                 die("invalid bpos.snapshot %s", snapshot_s);
668
669         return (struct bpos) { .inode = inode_v, .offset = offset_v, .snapshot = snapshot_v };
670 }
671
672 struct bbpos bbpos_parse(char *buf)
673 {
674         char *s = buf, *field;
675         struct bbpos ret;
676
677         if (!(field = strsep(&s, ":")))
678                 die("invalid bbpos %s", buf);
679
680         ret.btree = read_string_list_or_die(field, __bch2_btree_ids, "btree id");
681
682         if (!s)
683                 die("invalid bbpos %s", buf);
684
685         ret.pos = bpos_parse(s);
686         return ret;
687 }