X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmd_fs.c;h=6bf00c03f7b9c217a852d83fa3743499c5d94e13;hb=b1a2ab6eeffc62d32f648d9267dc101da77567d1;hp=44316fc5d3773e18f624b8744dc1f1eb0625599f;hpb=9c62b2b4f11374cbffe88e0c31b9b1ab32a2863a;p=bcachefs-tools-debian diff --git a/cmd_fs.c b/cmd_fs.c index 44316fc..6bf00c0 100644 --- a/cmd_fs.c +++ b/cmd_fs.c @@ -14,146 +14,309 @@ #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 dev_usage_type_to_text(struct printbuf *out, + const char *type, + unsigned bucket_size, + u64 buckets, u64 sectors) { - char *name = NULL; - u64 available = d->nr_buckets; + u64 frag = max((s64) buckets * bucket_size - (s64) sectors, 0LL); + + pr_buf(out, "%s:", type); + pr_tab(out); + pr_sectors(out, sectors); + pr_tab_rjust(out); + pr_buf(out, "%llu", buckets); + pr_tab_rjust(out); + pr_sectors(out, frag); + pr_tab_rjust(out); + pr_newline(out); +} + +static void dev_usage_to_text(struct printbuf *out, + struct bchfs_handle fs, + struct dev_name *d) +{ + struct bch_ioctl_dev_usage u = bchu_dev_usage(fs, d->idx); unsigned i; - printf("\n"); - printf_pad(20, "%s (device %u):", label, idx); + pr_newline(out); + pr_buf(out, "%s (device %u):", d->label ?: "(no label)", d->idx); + pr_tab(out); + pr_buf(out, "%s", d->dev ?: "(device not found)"); + pr_tab_rjust(out); - 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); + pr_buf(out, "%s", bch2_member_states[u.state]); + pr_tab_rjust(out); - printf("%-20s%12s%12s%12s\n", - "", "data", "buckets", "fragmented"); + pr_newline(out); - 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); + pr_indent_push(out, 2); + pr_tab(out); - printf_pad(20, " %s:", bch2_data_types[i]); - printf("%12s%12llu%12s\n", - pr_units(d->sectors[i], units), - d->buckets[i], - pr_units(frag, units)); + pr_buf(out, "data"); + pr_tab_rjust(out); - if (i != BCH_DATA_CACHED) - available -= d->buckets[i]; - } + pr_buf(out, "buckets"); + pr_tab_rjust(out); - printf_pad(20, " available:"); - printf("%12s%12llu\n", - pr_units(available * d->bucket_size, units), - available); + pr_buf(out, "fragmented"); + pr_tab_rjust(out); - printf_pad(20, " capacity:"); - printf("%12s%12llu\n", - pr_units(d->nr_buckets * d->bucket_size, units), - d->nr_buckets); -} + pr_newline(out); + + for (i = BCH_DATA_sb; i < BCH_DATA_NR; i++) + dev_usage_type_to_text(out, + bch2_data_types[i], + u.bucket_size, + u.buckets[i], + u.sectors[i]); + + dev_usage_type_to_text(out, + "erasure coded", + u.bucket_size, + u.ec_buckets, + u.ec_sectors); + + pr_buf(out, "available:"); + pr_tab(out); + + pr_sectors(out, u.available_buckets * u.bucket_size); + pr_tab_rjust(out); + + pr_buf(out, "%llu", u.available_buckets); + pr_tab_rjust(out); + pr_newline(out); + + pr_buf(out, "capacity:"); + pr_tab(out); + + pr_sectors(out, u.nr_buckets * u.bucket_size); + pr_tab_rjust(out); + pr_buf(out, "%llu", u.nr_buckets); + pr_tab_rjust(out); + + pr_indent_pop(out, 2); -struct dev_by_label { - unsigned idx; - char *label; -}; + pr_newline(out); +} 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); + return (l->label && r->label + ? strcmp(l->label, r->label) : 0) ?: + (l->dev && r->dev + ? strcmp(l->dev, r->dev) : 0) ?: + cmp_int(l->idx, r->idx); } -static void print_fs_usage(const char *path, enum units units) +static struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx) { - unsigned i, j; - char uuid[40]; + struct dev_name *dev; - struct bchfs_handle fs = bcache_fs_open(path); - struct bch_ioctl_usage *u = bchu_usage(fs); + darray_foreach(dev, *dev_names) + if (dev->idx == idx) + return dev; + + return NULL; +} + +static void replicas_usage_to_text(struct printbuf *out, + const struct bch_replicas_usage *r, + dev_names *dev_names) +{ + unsigned i; - uuid_unparse(fs.uuid.b, uuid); - printf("Filesystem %s:\n", uuid); + if (!r->sectors) + return; - printf("%-20s%12s\n", "Size:", pr_units(u->fs.capacity, units)); - printf("%-20s%12s\n", "Used:", pr_units(u->fs.used, units)); + char devs[4096], *d = devs; + *d++ = '['; - printf("%-20s%12s%12s%12s%12s\n", - "By replicas:", "1x", "2x", "3x", "4x"); + for (i = 0; i < r->r.nr_devs; i++) { + unsigned dev_idx = r->r.devs[i]; + struct dev_name *dev = dev_idx_to_name(dev_names, dev_idx); - for (j = BCH_DATA_SB; j < BCH_DATA_NR; j++) { - printf_pad(20, " %s:", bch2_data_types[j]); + if (i) + *d++ = ' '; - for (i = 0; i < BCH_REPLICAS_MAX; i++) - printf("%12s", pr_units(u->fs.sectors[j][i], units)); - printf("\n"); + d += dev && dev->dev + ? sprintf(d, "%s", dev->dev) + : sprintf(d, "%u", dev_idx); } + *d++ = ']'; + *d++ = '\0'; - 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"); + pr_buf(out, "%s: ", bch2_data_types[r->r.data_type]); + pr_tab(out); - printf("%-20s%12s\n", " online reserved:", pr_units(u->fs.online_reserved, units)); + pr_buf(out, "%u/%u ", r->r.nr_required, r->r.nr_devs); + pr_tab(out); - darray(struct dev_by_label) devs_by_label; - darray_init(devs_by_label); + pr_buf(out, "%s ", devs); + pr_tab(out); - for (i = 0; i < u->nr_devices; i++) { - struct bch_ioctl_dev_usage *d = u->devs + i; + pr_sectors(out, r->sectors); + pr_tab_rjust(out); + pr_newline(out); +} - if (!d->alive) - continue; +#define for_each_usage_replica(_u, _r) \ + 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)) + +static void fs_usage_to_text(struct printbuf *out, const char *path) +{ + unsigned i; + + struct bchfs_handle fs = bcache_fs_open(path); + + struct dev_name *dev; + dev_names dev_names = bchu_fs_get_devices(fs); + + struct bch_ioctl_fs_usage *u = bchu_fs_usage(fs); + + pr_buf(out, "Filesystem: "); + pr_uuid(out, fs.uuid.b); + pr_newline(out); + + out->tabstops[0] = 20; + out->tabstops[1] = 36; + + pr_buf(out, "Size:"); + pr_tab(out); + pr_sectors(out, u->capacity); + pr_tab_rjust(out); + pr_newline(out); + + pr_buf(out, "Used:"); + pr_tab(out); + pr_sectors(out, u->used); + pr_tab_rjust(out); + pr_newline(out); + + pr_buf(out, "Online reserved:"); + pr_tab(out); + pr_sectors(out, u->online_reserved); + pr_tab_rjust(out); + pr_newline(out); + + pr_newline(out); + + out->tabstops[0] = 16; + out->tabstops[1] = 32; + out->tabstops[2] = 50; + out->tabstops[3] = 68; + + pr_buf(out, "Data type"); + pr_tab(out); + + pr_buf(out, "Required/total"); + pr_tab(out); + + pr_buf(out, "Devices"); + pr_newline(out); - char *label_attr = mprintf("dev-%u/label", i); - char *label = read_file_str(fs.sysfs_fd, label_attr); - free(label_attr); + for (i = 0; i < BCH_REPLICAS_MAX; i++) { + if (!u->persistent_reserved[i]) + continue; - darray_append(devs_by_label, - (struct dev_by_label) { i, label }); + pr_buf(out, "reserved:"); + pr_tab(out); + pr_buf(out, "%u/%u ", 1, i); + pr_tab(out); + pr_buf(out, "[] "); + pr_sectors(out, u->persistent_reserved[i]); + pr_tab_rjust(out); + pr_newline(out); } - sort(&darray_item(devs_by_label, 0), darray_size(devs_by_label), - sizeof(darray_item(devs_by_label, 0)), dev_by_label_cmp, NULL); + struct bch_replicas_usage *r; + + for_each_usage_replica(u, r) + if (r->r.data_type < BCH_DATA_user) + replicas_usage_to_text(out, r, &dev_names); - struct dev_by_label *d; - darray_foreach(d, devs_by_label) - print_dev_usage(u->devs + d->idx, d->idx, d->label, units); + for_each_usage_replica(u, r) + if (r->r.data_type == BCH_DATA_user && + r->r.nr_required <= 1) + replicas_usage_to_text(out, r, &dev_names); - darray_foreach(d, devs_by_label) - free(d->label); - darray_free(devs_by_label); + for_each_usage_replica(u, r) + if (r->r.data_type == BCH_DATA_user && + r->r.nr_required > 1) + replicas_usage_to_text(out, r, &dev_names); + + for_each_usage_replica(u, r) + if (r->r.data_type > BCH_DATA_user) + replicas_usage_to_text(out, r, &dev_names); free(u); + + sort(&darray_item(dev_names, 0), darray_size(dev_names), + sizeof(darray_item(dev_names, 0)), dev_by_label_cmp, NULL); + + out->tabstops[0] = 16; + out->tabstops[1] = 36; + out->tabstops[2] = 52; + out->tabstops[3] = 68; + + darray_foreach(dev, dev_names) + dev_usage_to_text(out, fs, dev); + + darray_foreach(dev, dev_names) { + free(dev->dev); + free(dev->label); + } + darray_free(dev_names); + bcache_fs_close(fs); } +int fs_usage(void) +{ + puts("bcachefs fs - manage a running filesystem\n" + "Usage: bcachefs fs [OPTION]... path\n" + "\n" + "Commands:\n" + " usage show disk usage\n" + "\n" + "Report bugs to "); + return 0; +} + int cmd_fs_usage(int argc, char *argv[]) { - enum units units = BYTES; + enum printbuf_units units = PRINTBUF_UNITS_BYTES; + struct printbuf buf = PRINTBUF; char *fs; int opt; while ((opt = getopt(argc, argv, "h")) != -1) switch (opt) { case 'h': - units = HUMAN_READABLE; + units = PRINTBUF_UNITS_HUMAN_READABLE; break; } args_shift(optind); if (!argc) { - print_fs_usage(".", units); + printbuf_reset(&buf); + buf.units = units; + fs_usage_to_text(&buf, "."); + printf("%s", buf.buf); } else { - while ((fs = arg_pop())) - print_fs_usage(fs, units); + while ((fs = arg_pop())) { + printbuf_reset(&buf); + buf.units = units; + fs_usage_to_text(&buf, fs); + printf("%s", buf.buf); + } } + printbuf_exit(&buf); return 0; }