]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Add bcachefs fs usage
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 23 Dec 2017 05:50:55 +0000 (00:50 -0500)
committerKent Overstreet <kent.overstreet@gmail.com>
Sat, 23 Dec 2017 05:51:19 +0000 (00:51 -0500)
bcachefs.c
cmd_fs.c
cmds.h
tools-util.c
tools-util.h

index 5dae387db5a2566727f4694a8d7f339c5c619eb8..795334118e645ab9faf7b4fbf25541e775d4ef25 100644 (file)
@@ -42,8 +42,7 @@ static void usage(void)
             "  stop                   Stop a running filesystem\n"
             "\n"
             "Commands for managing a running filesystem:\n"
-            "  fs show              Show various information about a filesystem\n"
-            "  fs set               Modify filesystem options\n"
+            "  fs usage             Show disk usage\n"
             "\n"
             "Commands for managing devices within a running filesystem:\n"
             "  device add           Add a new device to an existing filesystem\n"
@@ -90,10 +89,8 @@ static int fs_cmds(int argc, char *argv[])
 {
        char *cmd = pop_cmd(&argc, argv);
 
-       if (!strcmp(cmd, "show"))
-               return cmd_fs_show(argc, argv);
-       if (!strcmp(cmd, "set"))
-               return cmd_fs_set(argc, argv);
+       if (!strcmp(cmd, "usage"))
+               return cmd_fs_usage(argc, argv);
 
        usage();
        return 0;
index a332db3de1ad520f8070b2e51caa7aa3d785f3a0..65ee539e703820e88882aa74595f3bd04af3f774 100644 (file)
--- a/cmd_fs.c
+++ b/cmd_fs.c
 
-#include "cmds.h"
+#include <stdio.h>
+#include <sys/ioctl.h>
 
-struct bcache_fs {
-       /* options... */
+#include <uuid/uuid.h>
 
-       u64             capacity;
+#include "libbcachefs/bcachefs_ioctl.h"
+#include "libbcachefs/opts.h"
 
-       /* XXX: dirty != used, it doesn't count metadata */
-       u64             bytes_dirty;
-};
+#include "cmds.h"
 
-#if 0
-static struct bcache_fs fill_fs(struct bcache_handle fs)
+static inline int printf_pad(unsigned pad, const char * fmt, ...)
 {
-       return (struct bcache_fs) {
-       };
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = vprintf(fmt, args);
+       va_end(args);
+
+       while (ret++ < pad)
+              putchar(' ');
+
+       return ret;
 }
-#endif
 
-int cmd_fs_show(int argc, char *argv[])
+static void print_fs_usage(const char *path, enum units units)
 {
-       if (argc != 2)
-               die("Please supply a filesystem");
+       unsigned i, j, nr_devices = 4;
+       struct bcache_handle fs = bcache_fs_open(path);
+       struct bch_ioctl_usage *u = NULL;
+       char uuid[40];
 
-#if 0
-       struct bcache_handle fs = bcache_fs_open(argv[1]);
-#endif
+       while (1) {
+               u = xrealloc(u, sizeof(*u) + sizeof(u->devs[0]) * nr_devices);
+               u->nr_devices = nr_devices;
 
-       return 0;
+               if (!ioctl(fs.ioctl_fd, BCH_IOCTL_USAGE, u))
+                       break;
+               if (errno != ENOSPC)
+                       die("BCH_IOCTL_USAGE error: %m");
+               nr_devices *= 2;
+       }
+
+       uuid_unparse(fs.uuid.b, uuid);
+       printf("Filesystem %s:\n", uuid);
+
+       printf("%-20s%12s\n", "Size:", pr_units(u->fs.capacity, units));
+       printf("%-20s%12s\n", "Used:", pr_units(u->fs.used, units));
+
+       printf("%-20s%12s%12s%12s%12s\n",
+              "By replicas:", "1x", "2x", "3x", "4x");
+
+       for (j = BCH_DATA_BTREE; j < BCH_DATA_NR; j++) {
+               printf_pad(20, "  %s:", bch2_data_types[j]);
+
+               for (i = 0; i < BCH_REPLICAS_MAX; i++)
+                       printf("%12s", pr_units(u->fs.sectors[j][i], units));
+               printf("\n");
+       }
+
+       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("%-20s%12s\n", "  online reserved:", pr_units(u->fs.online_reserved, units));
+
+       for (i = 0; i < u->nr_devices; i++) {
+               struct bch_ioctl_dev_usage *d = u->devs + i;
+               char *name = NULL;
+
+               if (!d->alive)
+                       continue;
+
+               printf("\n");
+               printf_pad(20, "Device %u usage:", i);
+               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("%-20s%12s%12s%12s\n",
+                      "", "data", "buckets", "fragmented");
+
+               for (j = BCH_DATA_SB; j < BCH_DATA_NR; j++) {
+                       u64 frag = max((s64) d->buckets[j] * d->bucket_size -
+                                      (s64) d->sectors[j], 0LL);
+
+                       printf_pad(20, "  %s:", bch2_data_types[j]);
+                       printf("%12s%12llu%12s\n",
+                              pr_units(d->sectors[j], units),
+                              d->buckets[j],
+                              pr_units(frag, units));
+               }
+       }
+
+       free(u);
+       bcache_fs_close(fs);
 }
 
-int cmd_fs_set(int argc, char *argv[])
+int cmd_fs_usage(int argc, char *argv[])
 {
-       if (argc != 2)
-               die("Please supply a filesystem");
+       enum units units = BYTES;
+       unsigned i;
+       int opt;
+
+       while ((opt = getopt(argc, argv, "h")) != -1)
+               switch (opt) {
+               case 'h':
+                       units = HUMAN_READABLE;
+                       break;
+               }
 
-#if 0
-       struct bcache_handle fs = bcache_fs_open(argv[1]);
-#endif
+       if (argc - optind < 1) {
+               print_fs_usage(".", units);
+       } else {
+               for (i = optind; i < argc; i++)
+                       print_fs_usage(argv[i], units);
+       }
 
        return 0;
 }
diff --git a/cmds.h b/cmds.h
index fa28904cd66f9525655b853e4181dac325c37fc4..1c07e0729ca13c9afb66f06831580310ee3ee9a3 100644 (file)
--- a/cmds.h
+++ b/cmds.h
@@ -17,8 +17,7 @@ int cmd_incremental(int argc, char *argv[]);
 int cmd_run(int argc, char *argv[]);
 int cmd_stop(int argc, char *argv[]);
 
-int cmd_fs_show(int argc, char *argv[]);
-int cmd_fs_set(int argc, char *argv[]);
+int cmd_fs_usage(int argc, char *argv[]);
 
 int cmd_device_add(int argc, char *argv[]);
 int cmd_device_remove(int argc, char *argv[]);
index 90bbda2a46f835dc6897897e3cb9bfc9d5e473a9..70f5558b2dfa1e5342eaa16d06fa9f436cbba8d4 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>
 
@@ -70,6 +71,15 @@ void *xmalloc(size_t size)
        return p;
 }
 
+void *xrealloc(void *p, size_t size)
+{
+       p = realloc(p, size);
+       if (!p)
+               die("insufficient memory");
+
+       return p;
+}
+
 void xpread(int fd, void *buf, size_t count, off_t offset)
 {
        ssize_t r = pread(fd, buf, count, offset);
@@ -104,27 +114,34 @@ struct stat xfstat(int fd)
 
 /* Integer stuff: */
 
-struct units_buf __pr_units(u64 v, enum units units)
+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;
@@ -255,12 +272,17 @@ int bcachectl_open(void)
 
 #define SYSFS_BASE "/sys/fs/bcachefs/"
 
+void bcache_fs_close(struct bcache_handle fs)
+{
+       close(fs.ioctl_fd);
+       close(fs.sysfs_fd);
+}
+
 struct bcache_handle bcache_fs_open(const char *path)
 {
        struct bcache_handle ret;
-       uuid_t tmp;
 
-       if (!uuid_parse(path, tmp)) {
+       if (!uuid_parse(path, ret.uuid.b)) {
                /* It's a UUID, look it up in sysfs: */
                char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
                ret.sysfs_fd = xopen(sysfs, O_RDONLY);
@@ -279,6 +301,8 @@ struct bcache_handle bcache_fs_open(const char *path)
                struct bch_ioctl_query_uuid uuid;
                xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid);
 
+               ret.uuid = uuid.uuid;
+
                char uuid_str[40];
                uuid_unparse(uuid.uuid.b, uuid_str);
 
@@ -562,4 +586,33 @@ u32 crc32c(u32 crc, const void *buf, size_t size)
 
 #endif /* HAVE_WORKING_IFUNC */
 
+char *dev_to_path(dev_t dev)
+{
+       char *line = NULL, *name = NULL, *path = 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)) {
+                       path = mprintf("/dev/%s", name);
+                       break;
+               }
+
+       }
+
+       fclose(f);
+       free(line);
+       free(name);
+       return path;
+}
+
 #endif
index c8ece0c8d79078f2c6384d1da768c1c94292c5f4..649ea9bb0075f283e200d88f360aec376ecc6b8c 100644 (file)
 #include <linux/log2.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/uuid.h>
 #include "ccan/darray/darray.h"
 
 void die(const char *, ...);
 char *mprintf(const char *, ...);
 void *xcalloc(size_t, size_t);
 void *xmalloc(size_t);
+void *xrealloc(void *, size_t);
 void xpread(int, void *, size_t, off_t);
 void xpwrite(int, const void *, size_t, off_t);
 struct stat xfstatat(int, const char *, int);
@@ -48,7 +50,7 @@ enum units {
        HUMAN_READABLE,
 };
 
-struct units_buf __pr_units(u64, enum units);
+struct units_buf __pr_units(s64, enum units);
 
 struct units_buf {
        char    b[20];
@@ -69,10 +71,12 @@ int open_for_format(const char *, bool);
 int bcachectl_open(void);
 
 struct bcache_handle {
+       uuid_le uuid;
        int     ioctl_fd;
        int     sysfs_fd;
 };
 
+void bcache_fs_close(struct bcache_handle);
 struct bcache_handle bcache_fs_open(const char *);
 
 bool ask_yn(void);
@@ -151,4 +155,6 @@ unsigned hatoi_validate(const char *, const char *);
 
 u32 crc32c(u32, const void *, size_t);
 
+char *dev_to_path(dev_t);
+
 #endif /* _TOOLS_UTIL_H */