]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - tools-util.c
Update bcachefs sources to 1a510b00b6 bcachefs: Increase BTREE_TRANS_MEM_MAX
[bcachefs-tools-debian] / tools-util.c
index 90bbda2a46f835dc6897897e3cb9bfc9d5e473a9..361419aec5fc09a09611ef9e84f9d8e393076d1b 100644 (file)
@@ -10,6 +10,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -30,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, ...)
@@ -70,12 +71,27 @@ void *xmalloc(size_t size)
        return p;
 }
 
-void xpread(int fd, void *buf, size_t count, off_t offset)
+void *xrealloc(void *p, size_t size)
 {
-       ssize_t r = pread(fd, buf, count, offset);
+       p = realloc(p, size);
+       if (!p)
+               die("insufficient memory");
 
-       if (r != count)
-               die("read error (ret %zi)", r);
+       return p;
+}
+
+void xpread(int fd, void *buf, size_t count, off_t offset)
+{
+       while (count) {
+               ssize_t r = pread(fd, buf, count, offset);
+
+               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)
@@ -102,29 +118,59 @@ struct stat xfstat(int fd)
        return stat;
 }
 
-/* Integer stuff: */
+struct stat xstat(const char *path)
+{
+       struct stat statbuf;
+       if (stat(path, &statbuf))
+               die("stat error statting %s: %m", path);
+       return statbuf;
+}
+
+/* Formatting: */
 
-struct units_buf __pr_units(u64 v, enum units units)
+int printf_pad(unsigned pad, const char * fmt, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = vprintf(fmt, args);
+       va_end(args);
+
+       while (ret++ < pad)
+              putchar(' ');
+
+       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(ret.b, sizeof(ret.b), "%llu", v << 9);
+               snprintf(out, end - out, "%llu", v << 9);
                break;
        case SECTORS:
-               snprintf(ret.b, sizeof(ret.b), "%llu", v);
+               snprintf(out, end - out, "%llu", v);
                break;
        case HUMAN_READABLE:
                v <<= 9;
 
                if (v >= 1024) {
                        int exp = log(v) / log(1024);
-                       snprintf(ret.b, sizeof(ret.b), "%.1f%c",
+                       snprintf(out, end - out, "%.1f%c",
                                 v / pow(1024, exp),
                                 "KMGTPE"[exp-1]);
                } else {
-                       snprintf(ret.b, sizeof(ret.b), "%llu", v);
+                       snprintf(out, end - out, "%llu", v);
                }
 
                break;
@@ -151,6 +197,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);
 
@@ -172,7 +222,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);
 
@@ -245,51 +295,6 @@ int open_for_format(const char *dev, bool force)
        return fd;
 }
 
-/* Global control device: */
-int bcachectl_open(void)
-{
-       return xopen("/dev/bcachefs-ctl", O_RDWR);
-}
-
-/* Filesystem handles (ioctl, sysfs dir): */
-
-#define SYSFS_BASE "/sys/fs/bcachefs/"
-
-struct bcache_handle bcache_fs_open(const char *path)
-{
-       struct bcache_handle ret;
-       uuid_t tmp;
-
-       if (!uuid_parse(path, tmp)) {
-               /* It's a UUID, look it up in sysfs: */
-               char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
-               ret.sysfs_fd = xopen(sysfs, O_RDONLY);
-
-               char *minor = read_file_str(ret.sysfs_fd, "minor");
-               char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
-               ret.ioctl_fd = xopen(ctl, O_RDWR);
-
-               free(sysfs);
-               free(minor);
-               free(ctl);
-       } else {
-               /* It's a path: */
-               ret.ioctl_fd = xopen(path, O_RDONLY);
-
-               struct bch_ioctl_query_uuid uuid;
-               xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid);
-
-               char uuid_str[40];
-               uuid_unparse(uuid.uuid.b, uuid_str);
-
-               char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
-               ret.sysfs_fd = xopen(sysfs, O_RDONLY);
-               free(sysfs);
-       }
-
-       return ret;
-}
-
 bool ask_yn(void)
 {
        const char *short_yes = "yY";
@@ -385,7 +390,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++;
@@ -529,10 +534,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;
@@ -545,8 +550,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
 
@@ -562,4 +574,111 @@ u32 crc32c(u32 crc, const void *buf, size_t size)
 
 #endif /* HAVE_WORKING_IFUNC */
 
-#endif
+char *dev_to_name(dev_t dev)
+{
+       char *line = NULL, *name = NULL;
+       size_t n = 0;
+
+       FILE *f = fopen("/proc/partitions", "r");
+       if (!f)
+               die("error opening /proc/partitions: %m");
+
+       while (getline(&line, &n, f) != -1) {
+               unsigned ma, mi;
+               u64 sectors;
+
+               name = realloc(name, n + 1);
+
+               if (sscanf(line, " %u %u %llu %s", &ma, &mi, &sectors, name) == 4 &&
+                   ma == major(dev) && mi == minor(dev))
+                       goto found;
+       }
+
+       free(name);
+       name = NULL;
+found:
+       fclose(f);
+       free(line);
+       return name;
+}
+
+char *dev_to_path(dev_t dev)
+{
+       char *name = dev_to_name(dev);
+       if (!name)
+               return NULL;
+
+       char *path = mprintf("/dev/%s", name);
+
+       free(name);
+       return path;
+}
+
+struct mntent *dev_to_mount(char *dev)
+{
+       struct mntent *mnt, *ret = NULL;
+       FILE *f = setmntent("/proc/mounts", "r");
+       if (!f)
+               die("error opening /proc/mounts: %m");
+
+       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);
+       return ret;
+}
+
+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 };
+}