summaryrefslogtreecommitdiff
path: root/c_src
diff options
context:
space:
mode:
Diffstat (limited to 'c_src')
-rw-r--r--c_src/cmd_format.c3
-rw-r--r--c_src/cmd_fs.c317
-rw-r--r--c_src/cmd_super.c93
-rw-r--r--c_src/cmd_super.h8
4 files changed, 231 insertions, 190 deletions
diff --git a/c_src/cmd_format.c b/c_src/cmd_format.c
index 740b0e81..841a7913 100644
--- a/c_src/cmd_format.c
+++ b/c_src/cmd_format.c
@@ -21,6 +21,7 @@
#include <uuid/uuid.h>
#include "cmds.h"
+#include "cmd_super.h"
#include "tools-util.h"
#include "posix_to_bcachefs.h"
#include "libbcachefs.h"
@@ -293,7 +294,7 @@ int cmd_format(int argc, char *argv[])
struct printbuf buf = PRINTBUF;
buf.human_readable_units = true;
- bch2_sb_to_text(&buf, sb, false, 1 << BCH_SB_FIELD_members_v2);
+ bch2_sb_to_text_with_names(&buf, sb, false, 1 << BCH_SB_FIELD_members_v2, -1);
printf("%s", buf.buf);
printbuf_exit(&buf);
}
diff --git a/c_src/cmd_fs.c b/c_src/cmd_fs.c
index aa825e90..4eca866a 100644
--- a/c_src/cmd_fs.c
+++ b/c_src/cmd_fs.c
@@ -18,96 +18,85 @@
#include "libbcachefs/darray.h"
-static void __dev_usage_type_to_text(struct printbuf *out,
- enum bch_data_type type,
- unsigned bucket_size,
- u64 buckets, u64 sectors, u64 frag)
-{
- bch2_prt_data_type(out, type);
- prt_char(out, ':');
- prt_tab(out);
-
- prt_units_u64(out, sectors << 9);
- prt_tab_rjust(out);
-
- 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 dev_usage_type_to_text(struct printbuf *out,
- struct bch_ioctl_dev_usage_v2 *u,
- enum bch_data_type type)
-{
- 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, type,
- u->bucket_size,
- u->d[type].buckets,
- sectors,
- u->d[type].fragmented);
-}
+#define FS_USAGE_FIELDS() \
+ x(replicas) \
+ x(btree) \
+ x(compression) \
+ x(rebalance_work) \
+ x(devices)
+
+enum __fs_usage_fields {
+#define x(n) __FS_USAGE_##n,
+ FS_USAGE_FIELDS()
+#undef x
+};
+
+enum fs_usage_fields {
+#define x(n) FS_USAGE_##n = BIT(__FS_USAGE_##n),
+ FS_USAGE_FIELDS()
+#undef x
+};
+
+const char * const fs_usage_field_strs[] = {
+#define x(n) [__FS_USAGE_##n] = #n,
+ FS_USAGE_FIELDS()
+#undef x
+ NULL
+};
static void dev_usage_to_text(struct printbuf *out,
struct bchfs_handle fs,
- struct dev_name *d)
+ struct dev_name *d,
+ bool full)
{
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);
-
- prt_str(out, bch2_member_states[u->state]);
- prt_tab_rjust(out);
-
- prt_newline(out);
+ u64 used = 0, capacity = u->nr_buckets * u->bucket_size;
+ for (unsigned type = 0; type < u->nr_data_types; type++) {
+ if (!data_type_is_empty(type))
+ used += u->d[type].sectors;
+ }
- printbuf_indent_add(out, 2);
- prt_tab(out);
+ prt_printf(out, "%s (device %u):\t%s\r%s\r %02u%%\n",
+ d->label ?: "(no label)", d->idx,
+ d->dev ?: "(device not found)",
+ bch2_member_states[u->state],
+ (unsigned) (used * 100 / capacity));
- prt_str(out, "data");
- prt_tab_rjust(out);
+ if (full) {
+ printbuf_indent_add(out, 2);
+ prt_printf(out, "\tdata\rbuckets\rfragmented\r\n");
- prt_str(out, "buckets");
- prt_tab_rjust(out);
+ for (unsigned type = 0; type < u->nr_data_types; type++) {
+ bch2_prt_data_type(out, type);
+ prt_printf(out, ":\t");
- prt_str(out, "fragmented");
- prt_tab_rjust(out);
+ /* sectors are 0 for empty bucket data types, so calculate sectors for them */
+ u64 sectors = data_type_is_empty(type)
+ ? u->d[type].buckets * u->bucket_size
+ : u->d[type].sectors;
+ prt_units_u64(out, sectors << 9);
- prt_newline(out);
+ prt_printf(out, "\r%llu\r", u->d[type].buckets);
- for (unsigned i = 0; i < u->nr_data_types; i++)
- dev_usage_type_to_text(out, u, i);
+ u64 fragmented = u->d[type].buckets * u->bucket_size - sectors;
+ if (fragmented)
+ prt_units_u64(out, fragmented << 9);
+ prt_printf(out, "\r\n");
+ }
- prt_str(out, "capacity:");
- prt_tab(out);
+ prt_printf(out, "capacity:\t");
+ prt_units_u64(out, (u->nr_buckets * u->bucket_size) << 9);
+ prt_printf(out, "\r%llu\r\n", u->nr_buckets);
- 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);
+ prt_printf(out, "bucket size:\t");
+ prt_units_u64(out, u->bucket_size << 9);
+ prt_printf(out, "\r\n");
- printbuf_indent_sub(out, 2);
+ printbuf_indent_sub(out, 2);
+ prt_newline(out);
+ }
- prt_newline(out);
free(u);
}
@@ -124,19 +113,21 @@ static int dev_by_label_cmp(const void *_l, const void *_r)
static void devs_usage_to_text(struct printbuf *out,
struct bchfs_handle fs,
- dev_names dev_names)
+ dev_names dev_names,
+ bool full)
{
sort(dev_names.data, dev_names.nr,
sizeof(dev_names.data[0]), dev_by_label_cmp, NULL);
printbuf_tabstops_reset(out);
+ prt_newline(out);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 20);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 14);
darray_for_each(dev_names, dev)
- dev_usage_to_text(out, fs, dev);
+ dev_usage_to_text(out, fs, dev, full);
darray_for_each(dev_names, dev) {
free(dev->dev);
@@ -150,14 +141,9 @@ static void persistent_reserved_to_text(struct printbuf *out,
if (!sectors)
return;
- prt_str(out, "reserved:");
- prt_tab(out);
- prt_printf(out, "%u/%u ", 1, nr_replicas);
- prt_tab(out);
- prt_str(out, "[] ");
+ prt_printf(out, "reserved:\t%u/%u\t[] ", 1, nr_replicas);
prt_units_u64(out, sectors << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
}
static void replicas_usage_to_text(struct printbuf *out,
@@ -190,21 +176,12 @@ static void replicas_usage_to_text(struct printbuf *out,
*d++ = '\0';
bch2_prt_data_type(out, r->data_type);
- prt_char(out, ':');
- prt_tab(out);
-
- prt_printf(out, "%u/%u ", r->nr_required, r->nr_devs);
- prt_tab(out);
-
- prt_printf(out, "%u ", durability);
- prt_tab(out);
-
- prt_printf(out, "%s ", devs);
- prt_tab(out);
+ prt_printf(out, ":\t%u/%u\t%u\t%s\t",
+ r->nr_required, r->nr_devs,
+ durability, devs);
prt_units_u64(out, sectors << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
}
#define for_each_usage_replica(_u, _r) \
@@ -251,15 +228,27 @@ static void accounting_swab_if_old(struct bch_ioctl_query_accounting *in)
static int fs_usage_v1_to_text(struct printbuf *out,
struct bchfs_handle fs,
- dev_names dev_names)
+ dev_names dev_names,
+ enum fs_usage_fields fields)
{
- struct bch_ioctl_query_accounting *a =
- bchu_fs_accounting(fs,
- BIT(BCH_DISK_ACCOUNTING_persistent_reserved)|
+ unsigned accounting_types = 0;
+
+ if (fields & FS_USAGE_replicas)
+ accounting_types |=
BIT(BCH_DISK_ACCOUNTING_replicas)|
- BIT(BCH_DISK_ACCOUNTING_compression)|
- BIT(BCH_DISK_ACCOUNTING_btree)|
- BIT(BCH_DISK_ACCOUNTING_rebalance_work));
+ BIT(BCH_DISK_ACCOUNTING_persistent_reserved);
+
+ if (fields & FS_USAGE_compression)
+ accounting_types |= BIT(BCH_DISK_ACCOUNTING_compression);
+
+ if (fields & FS_USAGE_btree)
+ accounting_types |= BIT(BCH_DISK_ACCOUNTING_btree);
+
+ if (fields & FS_USAGE_rebalance_work)
+ accounting_types |= BIT(BCH_DISK_ACCOUNTING_rebalance_work);
+
+ struct bch_ioctl_query_accounting *a =
+ bchu_fs_accounting(fs, accounting_types);
if (!a)
return -1;
@@ -277,45 +266,27 @@ static int fs_usage_v1_to_text(struct printbuf *out,
printbuf_tabstop_push(out, 20);
printbuf_tabstop_push(out, 16);
- prt_str(out, "Size:");
- prt_tab(out);
+ prt_printf(out, "Size:\t");
prt_units_u64(out, a->capacity << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
- prt_str(out, "Used:");
- prt_tab(out);
+ prt_printf(out, "Used:\t");
prt_units_u64(out, a->used << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
- prt_str(out, "Online reserved:");
- prt_tab(out);
+ prt_printf(out, "Online reserved:\t");
prt_units_u64(out, a->online_reserved << 9);
- prt_tab_rjust(out);
- prt_newline(out);
-
- 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);
+ prt_printf(out, "\r\n");
+
+ if (fields & FS_USAGE_replicas) {
+ printbuf_tabstops_reset(out);
+ printbuf_tabstop_push(out, 16);
+ printbuf_tabstop_push(out, 16);
+ printbuf_tabstop_push(out, 14);
+ printbuf_tabstop_push(out, 14);
+ printbuf_tabstop_push(out, 14);
+ prt_printf(out, "\nData type\tRequired/total\tDurability\tDevices\n");
+ }
unsigned prev_type = 0;
@@ -364,8 +335,7 @@ static int fs_usage_v1_to_text(struct printbuf *out,
prt_units_u64(out, nr_extents
? div_u64(sectors_uncompressed << 9, nr_extents)
: 0);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
break;
case BCH_DISK_ACCOUNTING_btree:
if (new_type) {
@@ -376,8 +346,7 @@ static int fs_usage_v1_to_text(struct printbuf *out,
}
prt_printf(out, "%s:\t", bch2_btree_id_str(acc_k.btree.id));
prt_units_u64(out, a->v.d[0] << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
break;
case BCH_DISK_ACCOUNTING_rebalance_work:
if (new_type)
@@ -395,7 +364,8 @@ static int fs_usage_v1_to_text(struct printbuf *out,
static void fs_usage_v0_to_text(struct printbuf *out,
struct bchfs_handle fs,
- dev_names dev_names)
+ dev_names dev_names,
+ enum fs_usage_fields fields)
{
struct bch_ioctl_fs_usage *u = bchu_fs_usage(fs);
@@ -410,20 +380,17 @@ static void fs_usage_v0_to_text(struct printbuf *out,
prt_str(out, "Size:");
prt_tab(out);
prt_units_u64(out, u->capacity << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
prt_str(out, "Used:");
prt_tab(out);
prt_units_u64(out, u->used << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
prt_str(out, "Online reserved:");
prt_tab(out);
prt_units_u64(out, u->online_reserved << 9);
- prt_tab_rjust(out);
- prt_newline(out);
+ prt_printf(out, "\r\n");
prt_newline(out);
@@ -473,43 +440,34 @@ static void fs_usage_v0_to_text(struct printbuf *out,
free(u);
}
-static void fs_usage_to_text(struct printbuf *out, const char *path)
+static void fs_usage_to_text(struct printbuf *out, const char *path,
+ enum fs_usage_fields fields)
{
struct bchfs_handle fs = bcache_fs_open(path);
dev_names dev_names = bchu_fs_get_devices(fs);
- if (!fs_usage_v1_to_text(out, fs, dev_names))
+ if (!fs_usage_v1_to_text(out, fs, dev_names, fields))
goto devs;
- fs_usage_v0_to_text(out, fs, dev_names);
+ fs_usage_v0_to_text(out, fs, dev_names, fields);
devs:
- devs_usage_to_text(out, fs, dev_names);
+ devs_usage_to_text(out, fs, dev_names, fields & FS_USAGE_devices);
darray_exit(&dev_names);
bcache_fs_close(fs);
}
-int fs_usage(void)
-{
- puts("bcachefs fs - manage a running filesystem\n"
- "Usage: bcachefs fs <CMD> [OPTIONS]\n"
- "\n"
- "Commands:\n"
- " usage Display detailed filesystem usage\n"
- " top Show runtime performance information\n"
- "\n"
- "Report bugs to <linux-bcachefs@vger.kernel.org>");
- return 0;
-}
-
static void fs_usage_usage(void)
{
puts("bcachefs fs usage - display detailed filesystem usage\n"
"Usage: bcachefs fs usage [OPTION]... <mountpoint>\n"
"\n"
"Options:\n"
+ " -f, --fields=FIELDS List of accounting sections to print\n"
+ " replicas,btree,compression,rebalance_work,devices"
+ " -a Print all accounting fields\n"
" -h, --human-readable Human readable units\n"
" -H, --help Display this help and exit\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
@@ -518,18 +476,26 @@ static void fs_usage_usage(void)
int cmd_fs_usage(int argc, char *argv[])
{
static const struct option longopts[] = {
- { "help", no_argument, NULL, 'H' },
+ { "fields", required_argument, NULL, 'f' },
+ { "all", no_argument, NULL, 'a' },
{ "human-readable", no_argument, NULL, 'h' },
+ { "help", no_argument, NULL, 'H' },
{ NULL }
};
bool human_readable = false;
+ unsigned fields = 0;
struct printbuf buf = PRINTBUF;
char *fs;
int opt;
- while ((opt = getopt_long(argc, argv, "h",
+ while ((opt = getopt_long(argc, argv, "f:ahH",
longopts, NULL)) != -1)
switch (opt) {
+ case 'f':
+ fields |= read_flag_list_or_die(optarg, fs_usage_field_strs, "fields");
+ break;
+ case 'a':
+ fields = ~0;
case 'h':
human_readable = true;
break;
@@ -545,13 +511,13 @@ int cmd_fs_usage(int argc, char *argv[])
if (!argc) {
printbuf_reset(&buf);
buf.human_readable_units = human_readable;
- fs_usage_to_text(&buf, ".");
+ fs_usage_to_text(&buf, ".", fields);
printf("%s", buf.buf);
} else {
while ((fs = arg_pop())) {
printbuf_reset(&buf);
buf.human_readable_units = human_readable;
- fs_usage_to_text(&buf, fs);
+ fs_usage_to_text(&buf, fs, fields);
printf("%s", buf.buf);
}
}
@@ -560,6 +526,19 @@ int cmd_fs_usage(int argc, char *argv[])
return 0;
}
+int fs_usage(void)
+{
+ puts("bcachefs fs - manage a running filesystem\n"
+ "Usage: bcachefs fs <CMD> [OPTIONS]\n"
+ "\n"
+ "Commands:\n"
+ " usage Display detailed filesystem usage\n"
+ " top Show runtime performance information\n"
+ "\n"
+ "Report bugs to <linux-bcachefs@vger.kernel.org>");
+ return 0;
+}
+
int fs_cmds(int argc, char *argv[])
{
char *cmd = pop_cmd(&argc, argv);
diff --git a/c_src/cmd_super.c b/c_src/cmd_super.c
index 3161205f..00776b1b 100644
--- a/c_src/cmd_super.c
+++ b/c_src/cmd_super.c
@@ -21,6 +21,7 @@
#include <uuid/uuid.h>
#include "cmds.h"
+#include "cmd_super.h"
#include "libbcachefs.h"
#include "libbcachefs/opts.h"
#include "libbcachefs/super-io.h"
@@ -28,6 +29,8 @@
#include "libbcachefs/darray.h"
+#include "src/rust_to_c.h"
+
static void show_super_usage(void)
{
puts("bcachefs show-super \n"
@@ -42,6 +45,72 @@ static void show_super_usage(void)
exit(EXIT_SUCCESS);
}
+static struct sb_name *sb_dev_to_name(sb_names sb_names, unsigned idx)
+{
+ darray_for_each(sb_names, i)
+ if (i->sb.sb->dev_idx == idx)
+ return i;
+ return NULL;
+}
+
+static void print_one_member(struct printbuf *out, sb_names sb_names,
+ struct bch_sb *sb,
+ struct bch_sb_field_disk_groups *gi,
+ struct bch_member m, unsigned idx)
+{
+ struct sb_name *name = sb_dev_to_name(sb_names, idx);
+ prt_printf(out, "Device %u:\t%s\t", idx, name ? name->name : "(not found)");
+
+ if (name) {
+ char *model = fd_to_dev_model(name->sb.bdev->bd_fd);
+ prt_str(out, model);
+ free(model);
+ }
+ prt_newline(out);
+
+ printbuf_indent_add(out, 2);
+ bch2_member_to_text(out, &m, gi, sb, idx);
+ printbuf_indent_sub(out, 2);
+}
+
+void bch2_sb_to_text_with_names(struct printbuf *out, struct bch_sb *sb,
+ bool print_layout, unsigned fields, int field_only)
+{
+ CLASS(printbuf, uuid_buf)();
+ prt_str(&uuid_buf, "UUID=");
+ pr_uuid(&uuid_buf, sb->user_uuid.b);
+
+ sb_names sb_names = {};
+ bch2_scan_device_sbs(uuid_buf.buf, &sb_names);
+
+ if (field_only >= 0) {
+ struct bch_sb_field *f = bch2_sb_field_get_id(sb, field_only);
+
+ if (f)
+ __bch2_sb_field_to_text(out, sb, f);
+ } else {
+ printbuf_tabstop_push(out, 44);
+
+ bch2_sb_to_text(out, sb, print_layout,
+ fields & ~(BIT(BCH_SB_FIELD_members_v1)|
+ BIT(BCH_SB_FIELD_members_v2)));
+
+ struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
+
+ struct bch_sb_field_members_v1 *mi1;
+ if ((fields & BIT(BCH_SB_FIELD_members_v1)) &&
+ (mi1 = bch2_sb_field_get(sb, members_v1)))
+ for (unsigned i = 0; i < sb->nr_devices; i++)
+ print_one_member(out, sb_names, sb, gi, bch2_members_v1_get(mi1, i), i);
+
+ struct bch_sb_field_members_v2 *mi2;
+ if ((fields & BIT(BCH_SB_FIELD_members_v2)) &&
+ (mi2 = bch2_sb_field_get(sb, members_v2)))
+ for (unsigned i = 0; i < sb->nr_devices; i++)
+ print_one_member(out, sb_names, sb, gi, bch2_members_v2_get(mi2, i), i);
+ }
+}
+
int cmd_show_super(int argc, char *argv[])
{
static const struct option longopts[] = {
@@ -98,32 +167,16 @@ int cmd_show_super(int argc, char *argv[])
if (print_default_fields) {
fields |= bch2_sb_field_get(sb.sb, members_v2)
- ? 1 << BCH_SB_FIELD_members_v2
- : 1 << BCH_SB_FIELD_members_v1;
- fields |= 1 << BCH_SB_FIELD_errors;
+ ? BIT(BCH_SB_FIELD_members_v2)
+ : BIT(BCH_SB_FIELD_members_v1);
+ fields |= BIT(BCH_SB_FIELD_errors);
}
struct printbuf buf = PRINTBUF;
buf.human_readable_units = true;
- if (field_only >= 0) {
- struct bch_sb_field *f = bch2_sb_field_get_id(sb.sb, field_only);
-
- if (f)
- __bch2_sb_field_to_text(&buf, sb.sb, f);
- } else {
- printbuf_tabstop_push(&buf, 44);
-
- char *model = fd_to_dev_model(sb.bdev->bd_fd);
- prt_str(&buf, "Device:");
- prt_tab(&buf);
- prt_str(&buf, model);
- prt_newline(&buf);
- free(model);
-
- bch2_sb_to_text(&buf, sb.sb, print_layout, fields);
- }
+ bch2_sb_to_text_with_names(&buf, sb.sb, print_layout, fields, field_only);
printf("%s", buf.buf);
bch2_free_super(&sb);
diff --git a/c_src/cmd_super.h b/c_src/cmd_super.h
new file mode 100644
index 00000000..78f71967
--- /dev/null
+++ b/c_src/cmd_super.h
@@ -0,0 +1,8 @@
+#ifndef _TOOLS_CMD_SHOW_SUPER_H
+#define _TOOLS_CMD_SHOW_SUPER_H
+
+#include "libbcachefs/super-io.h"
+
+void bch2_sb_to_text_with_names(struct printbuf *, struct bch_sb *, bool, unsigned, int);
+
+#endif /* _TOOLS_CMD_SHOW_SUPER_H */