]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - tools-util.c
Update bcachefs sources to bdf6d7c135 fixup! bcachefs: Kill journal buf bloom filter
[bcachefs-tools-debian] / tools-util.c
index 04bc6bd2a8c26c600646370204dc1c8ee9a316e7..591e2a0c45b8cb92e21f55a0b12848932523e4a1 100644 (file)
@@ -31,7 +31,7 @@ void die(const char *fmt, ...)
        va_end(args);
        fputc('\n', stderr);
 
-       exit(EXIT_FAILURE);
+       _exit(EXIT_FAILURE);
 }
 
 char *mprintf(const char *fmt, ...)
@@ -82,18 +82,24 @@ void *xrealloc(void *p, size_t size)
 
 void xpread(int fd, void *buf, size_t count, off_t offset)
 {
-       ssize_t r = pread(fd, buf, count, offset);
+       while (count) {
+               ssize_t r = pread(fd, buf, count, offset);
 
-       if (r != count)
-               die("read error (ret %zi)", r);
+               if (r < 0)
+                       die("read error: %m");
+               if (!r)
+                       die("pread error: unexpected eof");
+               count   -= r;
+               offset  += r;
+       }
 }
 
-void xpwrite(int fd, const void *buf, size_t count, off_t offset)
+void xpwrite(int fd, const void *buf, size_t count, off_t offset, const char *msg)
 {
        ssize_t r = pwrite(fd, buf, count, offset);
 
        if (r != count)
-               die("write error (ret %zi err %m)", r);
+               die("error writing %s (ret %zi err %m)", msg, r);
 }
 
 struct stat xfstatat(int dirfd, const char *path, int flags)
@@ -112,6 +118,14 @@ struct stat xfstat(int fd)
        return stat;
 }
 
+struct stat xstat(const char *path)
+{
+       struct stat statbuf;
+       if (stat(path, &statbuf))
+               die("stat error statting %s: %m", path);
+       return statbuf;
+}
+
 /* Formatting: */
 
 int printf_pad(unsigned pad, const char * fmt, ...)
@@ -129,42 +143,6 @@ int printf_pad(unsigned pad, const char * fmt, ...)
        return ret;
 }
 
-struct units_buf __pr_units(s64 _v, enum units units)
-{
-       struct units_buf ret;
-       char *out = ret.b, *end = out + sizeof(ret.b);
-       u64 v = _v;
-
-       if (_v < 0) {
-               out += scnprintf(out, end - out, "-");
-               v = -_v;
-       }
-
-       switch (units) {
-       case BYTES:
-               snprintf(out, end - out, "%llu", v << 9);
-               break;
-       case SECTORS:
-               snprintf(out, end - out, "%llu", v);
-               break;
-       case HUMAN_READABLE:
-               v <<= 9;
-
-               if (v >= 1024) {
-                       int exp = log(v) / log(1024);
-                       snprintf(out, end - out, "%.1f%c",
-                                v / pow(1024, exp),
-                                "KMGTPE"[exp-1]);
-               } else {
-                       snprintf(out, end - out, "%llu", v);
-               }
-
-               break;
-       }
-
-       return ret;
-}
-
 /* Argument parsing stuff: */
 
 /* File parsing (i.e. sysfs) */
@@ -183,6 +161,10 @@ char *read_file_str(int dirfd, const char *path)
        buf[len] = '\0';
        if (len && buf[len - 1] == '\n')
                buf[len - 1] = '\0';
+       if (!strlen(buf)) {
+               free(buf);
+               buf = NULL;
+       }
 
        close(fd);
 
@@ -193,7 +175,7 @@ u64 read_file_u64(int dirfd, const char *path)
 {
        char *buf = read_file_str(dirfd, path);
        u64 v;
-       if (kstrtou64(buf, 10, &v))
+       if (bch2_strtou64_h(buf, &v))
                die("read_file_u64: error parsing %s (got %s)", path, buf);
        free(buf);
        return v;
@@ -204,7 +186,7 @@ u64 read_file_u64(int dirfd, const char *path)
 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
                                const char *msg)
 {
-       ssize_t v = bch2_read_string_list(opt, list);
+       ssize_t v = match_string(list, -1, opt);
        if (v < 0)
                die("Bad %s %s", msg, opt);
 
@@ -224,17 +206,17 @@ u64 get_size(const char *path, int fd)
        return ret;
 }
 
-/* Returns blocksize in units of 512 byte sectors: */
+/* Returns blocksize, in bytes: */
 unsigned get_blocksize(const char *path, int fd)
 {
        struct stat statbuf = xfstat(fd);
 
        if (!S_ISBLK(statbuf.st_mode))
-               return statbuf.st_blksize >> 9;
+               return statbuf.st_blksize;
 
        unsigned ret;
        xioctl(fd, BLKPBSZGET, &ret);
-       return ret >> 9;
+       return ret;
 }
 
 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
@@ -244,7 +226,9 @@ int open_for_format(const char *dev, bool force)
        const char *fs_type = NULL, *fs_label = NULL;
        size_t fs_type_len, fs_label_len;
 
-       int fd = xopen(dev, O_RDWR|O_EXCL);
+       int fd = open(dev, O_RDWR|O_EXCL);
+       if (fd < 0)
+               die("Error opening device to format %s: %m", dev);
 
        if (force)
                return fd;
@@ -271,6 +255,8 @@ int open_for_format(const char *dev, bool force)
                fputs("Proceed anyway?", stdout);
                if (!ask_yn())
                        exit(EXIT_FAILURE);
+               while (blkid_do_probe(pr) == 0)
+                       blkid_do_wipe(pr, 0);
        }
 
        blkid_free_probe(pr);
@@ -309,22 +295,21 @@ static int range_cmp(const void *_l, const void *_r)
 void ranges_sort_merge(ranges *r)
 {
        struct range *t, *i;
-       ranges tmp = { NULL };
+       ranges tmp = { 0 };
 
-       sort(&darray_item(*r, 0), darray_size(*r),
-            sizeof(darray_item(*r, 0)), range_cmp, NULL);
+       sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL);
 
        /* Merge contiguous ranges: */
-       darray_foreach(i, *r) {
-               t = tmp.size ?  &tmp.item[tmp.size - 1] : NULL;
+       darray_for_each(*r, i) {
+               t = tmp.nr ?  &tmp.data[tmp.nr - 1] : NULL;
 
                if (t && t->end >= i->start)
                        t->end = max(t->end, i->end);
                else
-                       darray_append(tmp, *i);
+                       darray_push(&tmp, *i);
        }
 
-       darray_free(*r);
+       darray_exit(r);
        *r = tmp;
 }
 
@@ -332,7 +317,7 @@ void ranges_roundup(ranges *r, unsigned block_size)
 {
        struct range *i;
 
-       darray_foreach(i, *r) {
+       darray_for_each(*r, i) {
                i->start = round_down(i->start, block_size);
                i->end  = round_up(i->end, block_size);
        }
@@ -342,7 +327,7 @@ void ranges_rounddown(ranges *r, unsigned block_size)
 {
        struct range *i;
 
-       darray_foreach(i, *r) {
+       darray_for_each(*r, i) {
                i->start = round_up(i->start, block_size);
                i->end  = round_down(i->end, block_size);
                i->end  = max(i->end, i->start);
@@ -372,7 +357,7 @@ struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
        return e;
 }
 
-const char *strcmp_prefix(const char *a, const char *a_prefix)
+char *strcmp_prefix(char *a, const char *a_prefix)
 {
        while (*a_prefix && *a == *a_prefix) {
                a++;
@@ -381,24 +366,6 @@ const char *strcmp_prefix(const char *a, const char *a_prefix)
        return *a_prefix ? NULL : a;
 }
 
-unsigned hatoi_validate(const char *s, const char *msg)
-{
-       u64 v;
-
-       if (bch2_strtoull_h(s, &v))
-               die("bad %s %s", msg, s);
-
-       v /= 512;
-
-       if (v > USHRT_MAX)
-               die("%s too large\n", msg);
-
-       if (!v)
-               die("%s too small\n", msg);
-
-       return v;
-}
-
 /* crc32c */
 
 static u32 crc32c_default(u32 crc, const void *buf, size_t size)
@@ -516,10 +483,10 @@ static u32 crc32c_sse42(u32 crc, const void *buf, size_t size)
        return crc;
 }
 
+#endif
+
 static void *resolve_crc32c(void)
 {
-       __builtin_cpu_init();
-
 #ifdef __x86_64__
        if (__builtin_cpu_supports("sse4.2"))
                return crc32c_sse42;
@@ -532,8 +499,15 @@ static void *resolve_crc32c(void)
  */
 #ifdef HAVE_WORKING_IFUNC
 
+static void *ifunc_resolve_crc32c(void)
+{
+       __builtin_cpu_init();
+
+       return resolve_crc32c
+}
+
 u32 crc32c(u32, const void *, size_t)
-       __attribute__((ifunc("resolve_crc32c")));
+       __attribute__((ifunc("ifunc_resolve_crc32c")));
 
 #else
 
@@ -589,34 +563,71 @@ char *dev_to_path(dev_t dev)
        return path;
 }
 
-char *dev_to_mount(char *dev)
+struct mntent *dev_to_mount(char *dev)
 {
-       char *line = NULL, *ret = NULL;
-       size_t n = 0;
-
-       FILE *f = fopen("/proc/mounts", "r");
+       struct mntent *mnt, *ret = NULL;
+       FILE *f = setmntent("/proc/mounts", "r");
        if (!f)
                die("error opening /proc/mounts: %m");
 
-       while (getline(&line, &n, f) != -1) {
-               char *d, *p = line;
-               char *devs = strsep(&p, " ");
-               char *mount = strsep(&p, " ");
-
-               if (!devs || !mount)
-                       continue;
-
-               p = devs;
-               while ((d = strsep(&p, ":")))
-                       if (!strcmp(d, dev)) {
-                               ret = strdup(mount);
-                               goto found;
+       struct stat d1 = xstat(dev);
+
+       while ((mnt = getmntent(f))) {
+               char *d, *p = mnt->mnt_fsname;
+
+               while ((d = strsep(&p, ":"))) {
+                       struct stat d2;
+
+                       if (stat(d, &d2))
+                               continue;
+
+                       if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode))
+                               continue;
+
+                       if (S_ISBLK(d1.st_mode)) {
+                               if (d1.st_rdev != d2.st_rdev)
+                                       continue;
+                       } else {
+                               if (d1.st_dev != d2.st_dev ||
+                                   d1.st_ino != d2.st_ino)
+                                       continue;
                        }
+
+                       ret = mnt;
+                       goto found;
+               }
        }
 found:
        fclose(f);
-       free(line);
        return ret;
 }
 
-#endif
+int dev_mounted(char *dev)
+{
+       struct mntent *mnt = dev_to_mount(dev);
+
+       if (!mnt)
+               return 0;
+       if (hasmntopt(mnt, "ro"))
+               return 1;
+       return 2;
+}
+
+struct bpos bpos_parse(char *buf)
+{
+       char *s = buf, *field;
+       u64 inode_v = 0, offset_v = 0;
+
+       if (!(field = strsep(&s, ":")) ||
+           kstrtoull(field, 10, &inode_v))
+               die("invalid bpos %s", buf);
+
+       if ((field = strsep(&s, ":")) &&
+           kstrtoull(field, 10, &offset_v))
+               die("invalid bpos %s", buf);
+
+       if (s)
+               die("invalid bpos %s", buf);
+
+       return (struct bpos) { .inode = inode_v, .offset = offset_v };
+}