X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmd_fs.c;h=67c38af6eafe73f9d9ae8d622d7ab350007513ca;hb=2007d9b6cea540e0cbb7ba72c244f44e91803fc8;hp=8b9d91b80d162a051ce7d7920f43e57dd34a4e98;hpb=9e5d774875df1605c23f38f1da6c9dbb49826471;p=bcachefs-tools-debian diff --git a/cmd_fs.c b/cmd_fs.c index 8b9d91b..67c38af 100644 --- a/cmd_fs.c +++ b/cmd_fs.c @@ -1,69 +1,109 @@ - +#include #include #include #include -#include "ccan/darray/darray.h" - #include "linux/sort.h" #include "libbcachefs/bcachefs_ioctl.h" +#include "libbcachefs/darray.h" #include "libbcachefs/opts.h" +#include "libbcachefs/super-io.h" #include "cmds.h" #include "libbcachefs.h" -static void print_dev_usage_type(const char *type, - unsigned bucket_size, - u64 buckets, u64 sectors, - enum units units) +static void __dev_usage_type_to_text(struct printbuf *out, + const char *type, + unsigned bucket_size, + u64 buckets, u64 sectors, u64 frag) { - u64 frag = max((s64) buckets * bucket_size - (s64) sectors, 0LL); + prt_printf(out, "%s:", type); + prt_tab(out); + + prt_units_u64(out, sectors << 9); + prt_tab_rjust(out); - printf_pad(20, " %s:", type); - printf(" %15s %15llu %15s\n", - pr_units(sectors, units), - buckets, - pr_units(frag, units)); + prt_printf(out, "%llu", buckets); + prt_tab_rjust(out); + + if (frag) { + prt_units_u64(out, frag << 9); + prt_tab_rjust(out); + } + prt_newline(out); } -static void print_dev_usage(struct bchfs_handle fs, - struct dev_name *d, - enum units units) +static void dev_usage_type_to_text(struct printbuf *out, + struct bch_ioctl_dev_usage_v2 *u, + enum bch_data_type type) { - struct bch_ioctl_dev_usage u = bchu_dev_usage(fs, d->idx); - unsigned i; + u64 sectors = 0; + switch (type) { + case BCH_DATA_free: + case BCH_DATA_need_discard: + case BCH_DATA_need_gc_gens: + /* sectors are 0 for these types so calculate sectors for them */ + sectors = u->d[type].buckets * u->bucket_size; + break; + default: + sectors = u->d[type].sectors; + } + + __dev_usage_type_to_text(out, bch2_data_types[type], + u->bucket_size, + u->d[type].buckets, + sectors, + u->d[type].fragmented); +} + +static void dev_usage_to_text(struct printbuf *out, + struct bchfs_handle fs, + struct dev_name *d) +{ + struct bch_ioctl_dev_usage_v2 *u = bchu_dev_usage(fs, d->idx); + + prt_newline(out); + prt_printf(out, "%s (device %u):", d->label ?: "(no label)", d->idx); + prt_tab(out); + prt_str(out, d->dev ?: "(device not found)"); + prt_tab_rjust(out); - printf("\n"); - printf_pad(20, "%s (device %u):", d->label ?: "(no label)", d->idx); - printf("%30s%16s\n", d->dev ?: "(device not found)", bch2_member_states[u.state]); - - printf("%-20s%16s%16s%16s\n", - "", "data", "buckets", "fragmented"); - - for (i = BCH_DATA_sb; i < BCH_DATA_NR; i++) - print_dev_usage_type(bch2_data_types[i], - u.bucket_size, - u.buckets[i], - u.sectors[i], - units); - - print_dev_usage_type("erasure coded", - u.bucket_size, - u.ec_buckets, - u.ec_sectors, - units); - - printf_pad(20, " available:"); - printf(" %15s %15llu\n", - pr_units(u.available_buckets * u.bucket_size, units), - u.available_buckets); - - printf_pad(20, " capacity:"); - printf(" %15s %15llu\n", - pr_units(u.nr_buckets * u.bucket_size, units), - u.nr_buckets); + prt_str(out, bch2_member_states[u->state]); + prt_tab_rjust(out); + + prt_newline(out); + + printbuf_indent_add(out, 2); + prt_tab(out); + + prt_str(out, "data"); + prt_tab_rjust(out); + + prt_str(out, "buckets"); + prt_tab_rjust(out); + + prt_str(out, "fragmented"); + prt_tab_rjust(out); + + prt_newline(out); + + for (unsigned i = 0; i < u->nr_data_types; i++) + dev_usage_type_to_text(out, u, i); + + prt_str(out, "capacity:"); + prt_tab(out); + + prt_units_u64(out, (u->nr_buckets * u->bucket_size) << 9); + prt_tab_rjust(out); + prt_printf(out, "%llu", u->nr_buckets); + prt_tab_rjust(out); + + printbuf_indent_sub(out, 2); + + prt_newline(out); + free(u); } static int dev_by_label_cmp(const void *_l, const void *_r) @@ -79,30 +119,30 @@ static int dev_by_label_cmp(const void *_l, const void *_r) static struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx) { - struct dev_name *dev; - - darray_foreach(dev, *dev_names) + darray_for_each(*dev_names, dev) if (dev->idx == idx) return dev; - return NULL; } -static void print_replicas_usage(const struct bch_replicas_usage *r, - dev_names *dev_names, enum units units) +static void replicas_usage_to_text(struct printbuf *out, + const struct bch_replicas_usage *r, + dev_names *dev_names) { - unsigned i; - if (!r->sectors) return; char devs[4096], *d = devs; *d++ = '['; - for (i = 0; i < r->r.nr_devs; i++) { + unsigned durability = 0; + + for (unsigned 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); + durability += dev->durability; + if (i) *d++ = ' '; @@ -113,10 +153,21 @@ static void print_replicas_usage(const struct bch_replicas_usage *r, *d++ = ']'; *d++ = '\0'; - 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)); + prt_printf(out, "%s: ", bch2_data_types[r->r.data_type]); + prt_tab(out); + + prt_printf(out, "%u/%u ", r->r.nr_required, r->r.nr_devs); + prt_tab(out); + + prt_printf(out, "%u ", durability); + prt_tab(out); + + prt_printf(out, "%s ", devs); + prt_tab(out); + + prt_units_u64(out, r->sectors << 9); + prt_tab_rjust(out); + prt_newline(out); } #define for_each_usage_replica(_u, _r) \ @@ -125,96 +176,173 @@ static void print_replicas_usage(const struct bch_replicas_usage *r, _r = replicas_usage_next(_r), \ BUG_ON((void *) _r > (void *) (_u)->replicas + (_u)->replica_entries_bytes)) -static void print_fs_usage(const char *path, enum units units) +static void fs_usage_to_text(struct printbuf *out, const char *path) { unsigned i; - char uuid[40]; 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); - uuid_unparse(fs.uuid.b, uuid); - printf("Filesystem %s:\n", uuid); + prt_str(out, "Filesystem: "); + pr_uuid(out, fs.uuid.b); + prt_newline(out); + + printbuf_tabstops_reset(out); + printbuf_tabstop_push(out, 20); + printbuf_tabstop_push(out, 16); + + prt_str(out, "Size:"); + prt_tab(out); + prt_units_u64(out, u->capacity << 9); + prt_tab_rjust(out); + prt_newline(out); - printf("%-20s%12s\n", "Size:", pr_units(u->capacity, units)); - printf("%-20s%12s\n", "Used:", pr_units(u->used, units)); + prt_str(out, "Used:"); + prt_tab(out); + prt_units_u64(out, u->used << 9); + prt_tab_rjust(out); + prt_newline(out); - printf("%-20s%12s\n", "Online reserved:", pr_units(u->online_reserved, units)); + prt_str(out, "Online reserved:"); + prt_tab(out); + prt_units_u64(out, u->online_reserved << 9); + prt_tab_rjust(out); + prt_newline(out); - printf("\n"); - printf("%-16s%-16s%s\n", "Data type", "Required/total", "Devices"); + prt_newline(out); + + printbuf_tabstops_reset(out); + + printbuf_tabstop_push(out, 16); + prt_str(out, "Data type"); + prt_tab(out); + + printbuf_tabstop_push(out, 16); + prt_str(out, "Required/total"); + prt_tab(out); + + printbuf_tabstop_push(out, 14); + prt_str(out, "Durability"); + prt_tab(out); + + printbuf_tabstop_push(out, 14); + prt_str(out, "Devices"); + prt_newline(out); + + printbuf_tabstop_push(out, 14); for (i = 0; i < BCH_REPLICAS_MAX; i++) { if (!u->persistent_reserved[i]) continue; - 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)); + prt_str(out, "reserved:"); + prt_tab(out); + prt_printf(out, "%u/%u ", 1, i); + prt_tab(out); + prt_str(out, "[] "); + prt_units_u64(out, u->persistent_reserved[i] << 9); + prt_tab_rjust(out); + prt_newline(out); } struct bch_replicas_usage *r; for_each_usage_replica(u, r) if (r->r.data_type < BCH_DATA_user) - print_replicas_usage(r, &dev_names, units); + replicas_usage_to_text(out, r, &dev_names); for_each_usage_replica(u, r) if (r->r.data_type == BCH_DATA_user && r->r.nr_required <= 1) - print_replicas_usage(r, &dev_names, units); + replicas_usage_to_text(out, r, &dev_names); for_each_usage_replica(u, r) if (r->r.data_type == BCH_DATA_user && r->r.nr_required > 1) - print_replicas_usage(r, &dev_names, units); + replicas_usage_to_text(out, r, &dev_names); for_each_usage_replica(u, r) if (r->r.data_type > BCH_DATA_user) - print_replicas_usage(r, &dev_names, units); + 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); + sort(dev_names.data, dev_names.nr, + sizeof(dev_names.data[0]), dev_by_label_cmp, NULL); - darray_foreach(dev, dev_names) - print_dev_usage(fs, dev, units); + printbuf_tabstops_reset(out); + printbuf_tabstop_push(out, 16); + printbuf_tabstop_push(out, 20); + printbuf_tabstop_push(out, 16); + printbuf_tabstop_push(out, 14); - darray_foreach(dev, dev_names) { + darray_for_each(dev_names, dev) + dev_usage_to_text(out, fs, dev); + + darray_for_each(dev_names, dev) { free(dev->dev); free(dev->label); } - darray_free(dev_names); + darray_exit(&dev_names); bcache_fs_close(fs); } +static void fs_usage_usage(void) +{ + puts("bcachefs fs usage - display detailed filesystem usage\n" + "Usage: bcachefs fs usage [OPTION]... \n" + "\n" + "Options:\n" + " -h, --human-readable Human readable units\n" + " -H, --help Display this help and exit\n" + "Report bugs to "); +} + int cmd_fs_usage(int argc, char *argv[]) { - enum units units = BYTES; + static const struct option longopts[] = { + { "help", no_argument, NULL, 'H' }, + { "human-readable", no_argument, NULL, 'h' }, + { NULL } + }; + bool human_readable = false; + struct printbuf buf = PRINTBUF; char *fs; int opt; - while ((opt = getopt(argc, argv, "h")) != -1) + while ((opt = getopt_long(argc, argv, "h", + longopts, NULL)) != -1) switch (opt) { case 'h': - units = HUMAN_READABLE; + human_readable = true; break; + case 'H': + fs_usage_usage(); + exit(EXIT_SUCCESS); + default: + fs_usage_usage(); + exit(EXIT_FAILURE); } args_shift(optind); if (!argc) { - print_fs_usage(".", units); + printbuf_reset(&buf); + buf.human_readable_units = human_readable; + 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.human_readable_units = human_readable; + fs_usage_to_text(&buf, fs); + printf("%s", buf.buf); + } } + printbuf_exit(&buf); return 0; }