]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Redo cmd_fs_usage for new ioctls
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 18 Dec 2019 21:11:11 +0000 (16:11 -0500)
committerKent Overstreet <kent.overstreet@gmail.com>
Wed, 18 Dec 2019 21:11:11 +0000 (16:11 -0500)
cmd_fs.c
libbcachefs.c
libbcachefs.h

index 44316fc5d3773e18f624b8744dc1f1eb0625599f..26fcdd033bde19f9ed18285582050372c3c654b3 100644 (file)
--- a/cmd_fs.c
+++ b/cmd_fs.c
 #include "cmds.h"
 #include "libbcachefs.h"
 
-static void print_dev_usage(struct bch_ioctl_dev_usage *d, unsigned idx,
-                           const char *label, enum units units)
+static void print_dev_usage(struct bchfs_handle fs,
+                           struct dev_name *d,
+                           enum units units)
 {
-       char *name = NULL;
-       u64 available = d->nr_buckets;
+       struct bch_ioctl_dev_usage u = bchu_dev_usage(fs, d->idx);
+       u64 available = u.nr_buckets;
        unsigned i;
 
        printf("\n");
-       printf_pad(20, "%s (device %u):", label, idx);
-
-       name = !d->dev ? strdup("(offline)")
-               : dev_to_path(d->dev)
-               ?: strdup("(device not found)");
-       printf("%24s%12s\n", name, bch2_dev_state[d->state]);
-       free(name);
+       printf_pad(20, "%s (device %u):", d->label, d->idx);
+       printf("%24s%12s\n", d->dev ?: "(device not found)", bch2_dev_state[u.state]);
 
        printf("%-20s%12s%12s%12s\n",
               "", "data", "buckets", "fragmented");
 
        for (i = BCH_DATA_SB; i < BCH_DATA_NR; i++) {
-               u64 frag = max((s64) d->buckets[i] * d->bucket_size -
-                              (s64) d->sectors[i], 0LL);
+               u64 frag = max((s64) u.buckets[i] * u.bucket_size -
+                              (s64) u.sectors[i], 0LL);
 
                printf_pad(20, "  %s:", bch2_data_types[i]);
                printf("%12s%12llu%12s\n",
-                      pr_units(d->sectors[i], units),
-                      d->buckets[i],
+                      pr_units(u.sectors[i], units),
+                      u.buckets[i],
                       pr_units(frag, units));
 
                if (i != BCH_DATA_CACHED)
-                       available -= d->buckets[i];
+                       available -= u.buckets[i];
        }
 
        printf_pad(20, "  available:");
        printf("%12s%12llu\n",
-              pr_units(available * d->bucket_size, units),
+              pr_units(available * u.bucket_size, units),
               available);
 
        printf_pad(20, "  capacity:");
        printf("%12s%12llu\n",
-              pr_units(d->nr_buckets * d->bucket_size, units),
-              d->nr_buckets);
+              pr_units(u.nr_buckets * u.bucket_size, units),
+              u.nr_buckets);
 }
 
-struct dev_by_label {
-       unsigned        idx;
-       char            *label;
-};
-
 static int dev_by_label_cmp(const void *_l, const void *_r)
 {
-       const struct dev_by_label *l = _l, *r = _r;
+       const struct dev_name *l = _l, *r = _r;
 
        return strcmp(l->label, r->label);
 }
 
 static void print_fs_usage(const char *path, enum units units)
 {
-       unsigned i, j;
+       unsigned i;
        char uuid[40];
 
        struct bchfs_handle fs = bcache_fs_open(path);
-       struct bch_ioctl_usage *u = bchu_usage(fs);
 
-       uuid_unparse(fs.uuid.b, uuid);
-       printf("Filesystem %s:\n", uuid);
+       dev_names dev_names = bchu_fs_get_devices(fs);
 
-       printf("%-20s%12s\n", "Size:", pr_units(u->fs.capacity, units));
-       printf("%-20s%12s\n", "Used:", pr_units(u->fs.used, units));
+       struct bch_ioctl_fs_usage *u = bchu_fs_usage(fs);
 
-       printf("%-20s%12s%12s%12s%12s\n",
-              "By replicas:", "1x", "2x", "3x", "4x");
+       uuid_unparse(fs.uuid.b, uuid);
+       printf("Filesystem %s:\n", uuid);
 
-       for (j = BCH_DATA_SB; j < BCH_DATA_NR; j++) {
-               printf_pad(20, "  %s:", bch2_data_types[j]);
+       printf("%-20s%12s\n", "Size:", pr_units(u->capacity, units));
+       printf("%-20s%12s\n", "Used:", pr_units(u->used, units));
 
-               for (i = 0; i < BCH_REPLICAS_MAX; i++)
-                       printf("%12s", pr_units(u->fs.sectors[j][i], units));
-               printf("\n");
-       }
+       printf("%-20s%12s\n", "Online reserved:", pr_units(u->online_reserved, units));
 
-       printf_pad(20, "  %s:", "reserved");
-       for (i = 0; i < BCH_REPLICAS_MAX; i++)
-               printf("%12s", pr_units(u->fs.persistent_reserved[i], units));
        printf("\n");
+       printf("%-16s%-16s%s\n", "Data type", "Required/total", "Devices");
 
-       printf("%-20s%12s\n", "  online reserved:", pr_units(u->fs.online_reserved, units));
+       for (i = 0; i < BCH_REPLICAS_MAX; i++) {
+               if (!u->persistent_reserved[i])
+                       continue;
 
-       darray(struct dev_by_label) devs_by_label;
-       darray_init(devs_by_label);
+               printf_pad(16, "%s: ", "reserved");
+               printf_pad(16, "%u/%u ", 1, i);
+               printf_pad(32, "[] ");
+               printf("%s\n", pr_units(u->persistent_reserved[i], units));
+       }
+
+       struct bch_replicas_usage *r;
 
-       for (i = 0; i < u->nr_devices; i++) {
-               struct bch_ioctl_dev_usage *d = u->devs + i;
+       for (r = u->replicas;
+            r != (void *) u->replicas + u->replica_entries_bytes;
+            r = replicas_usage_next(r)) {
+               BUG_ON((void *) r > (void *) u->replicas + u->replica_entries_bytes);
 
-               if (!d->alive)
+               if (!r->sectors)
                        continue;
 
-               char *label_attr = mprintf("dev-%u/label", i);
-               char *label = read_file_str(fs.sysfs_fd, label_attr);
-               free(label_attr);
+               char devs[4096], *d = devs;
+               *d++ = '[';
+
+               for (i = 0; i < r->r.nr_devs; i++) {
+                       if (i)
+                               *d++ = ' ';
+                       strcpy(d, dev_names.item[r->r.devs[i]].dev);
+                       d += strlen(dev_names.item[r->r.devs[i]].dev);
+               }
+               *d++ = ']';
+               *d++ = '\0';
 
-               darray_append(devs_by_label,
-                       (struct dev_by_label) { i, label });
+               printf_pad(16, "%s: ", bch2_data_types[r->r.data_type]);
+               printf_pad(16, "%u/%u ", r->r.nr_required, r->r.nr_devs);
+               printf_pad(32, "%s ", devs);
+               printf(" %s\n", pr_units(r->sectors, units));
        }
 
-       sort(&darray_item(devs_by_label, 0), darray_size(devs_by_label),
-            sizeof(darray_item(devs_by_label, 0)), dev_by_label_cmp, NULL);
+       free(u);
+
+       sort(&darray_item(dev_names, 0), darray_size(dev_names),
+            sizeof(darray_item(dev_names, 0)), dev_by_label_cmp, NULL);
 
-       struct dev_by_label *d;
-       darray_foreach(d, devs_by_label)
-               print_dev_usage(u->devs + d->idx, d->idx, d->label, units);
+       struct dev_name *d;
+       darray_foreach(d, dev_names)
+               print_dev_usage(fs, d, units);
 
-       darray_foreach(d, devs_by_label)
+       darray_foreach(d, dev_names) {
+               free(d->dev);
                free(d->label);
-       darray_free(devs_by_label);
+       }
+       darray_free(dev_names);
 
-       free(u);
        bcache_fs_close(fs);
 }
 
index 7c9687d35acff0cd54641a0917703a167f10880b..89c203a15b677dfa2a22d793efcd290f942979cc 100644 (file)
@@ -1,4 +1,5 @@
 #include <ctype.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
@@ -1103,3 +1104,38 @@ void bch2_opts_usage(unsigned opt_types)
                }
        }
 }
+
+dev_names bchu_fs_get_devices(struct bchfs_handle fs)
+{
+       DIR *dir = fdopendir(fs.sysfs_fd);
+       struct dirent *d;
+       dev_names devs;
+
+       darray_init(devs);
+
+       while ((errno = 0), (d = readdir(dir))) {
+               struct dev_name n;
+
+               if (sscanf(d->d_name, "dev-%u", &n.idx) != 1)
+                       continue;
+
+               char *block_attr = mprintf("dev-%u/block", n.idx);
+
+               char sysfs_block_buf[4096];
+               if (readlinkat(fs.sysfs_fd, block_attr,
+                              sysfs_block_buf, sizeof(sysfs_block_buf)) > 0)
+                       n.dev = strdup(basename(sysfs_block_buf));
+
+               free(block_attr);
+
+               char *label_attr = mprintf("dev-%u/label", n.idx);
+               n.label = read_file_str(fs.sysfs_fd, label_attr);
+               free(label_attr);
+
+               darray_append(devs, n);
+       }
+
+       closedir(dir);
+
+       return devs;
+}
index 61d0ea8d05a89e78dd3d035b24647d661e9907e2..30add92c518c4ceae328048b5318b96220f0278a 100644 (file)
@@ -140,24 +140,35 @@ static inline void bchu_disk_set_state(struct bchfs_handle fs, unsigned dev,
        xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_SET_STATE, &i);
 }
 
-static inline struct bch_ioctl_usage *bchu_usage(struct bchfs_handle fs)
+static inline struct bch_ioctl_fs_usage *bchu_fs_usage(struct bchfs_handle fs)
 {
-       struct bch_ioctl_usage *u = NULL;
-       unsigned nr_devices = 4;
+       struct bch_ioctl_fs_usage *u = NULL;
+       size_t replica_entries_bytes = 4096;
 
        while (1) {
-               u = xrealloc(u, sizeof(*u) + sizeof(u->devs[0]) * nr_devices);
-               u->nr_devices = nr_devices;
+               u = xrealloc(u, sizeof(*u) + replica_entries_bytes);
+               u->replica_entries_bytes = replica_entries_bytes;
 
-               if (!ioctl(fs.ioctl_fd, BCH_IOCTL_USAGE, u))
+               if (!ioctl(fs.ioctl_fd, BCH_IOCTL_FS_USAGE, u))
                        return u;
 
                if (errno != ERANGE)
                        die("BCH_IOCTL_USAGE error: %m");
-               nr_devices *= 2;
+
+               replica_entries_bytes *= 2;
        }
 }
 
+static inline struct bch_ioctl_dev_usage bchu_dev_usage(struct bchfs_handle fs,
+                                                       unsigned idx)
+{
+       struct bch_ioctl_dev_usage i = { .dev = idx, .flags = BCH_BY_INDEX};
+
+       if (xioctl(fs.ioctl_fd, BCH_IOCTL_DEV_USAGE, &i))
+               die("BCH_IOCTL_DEV_USAGE error: %m");
+       return i;
+}
+
 static inline struct bch_sb *bchu_read_super(struct bchfs_handle fs, unsigned idx)
 {
        size_t size = 4096;
@@ -205,4 +216,14 @@ static inline void bchu_disk_resize(struct bchfs_handle fs,
 
 int bchu_data(struct bchfs_handle, struct bch_ioctl_data);
 
+struct dev_name {
+       unsigned        idx;
+       char            *dev;
+       char            *label;
+       uuid_le         uuid;
+};
+typedef darray(struct dev_name) dev_names;
+
+dev_names bchu_fs_get_devices(struct bchfs_handle);
+
 #endif /* _LIBBCACHE_H */