summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c_src/bcachefs.c3
-rw-r--r--c_src/cmd_top.c98
-rw-r--r--c_src/cmds.h1
3 files changed, 102 insertions, 0 deletions
diff --git a/c_src/bcachefs.c b/c_src/bcachefs.c
index 77bf6215..db5acedb 100644
--- a/c_src/bcachefs.c
+++ b/c_src/bcachefs.c
@@ -52,6 +52,7 @@ void bcachefs_usage(void)
#endif
"Commands for managing a running filesystem:\n"
" fs usage Show disk usage\n"
+ " fs top Show runtime performance information\n"
"\n"
"Commands for managing devices within a running filesystem:\n"
" device add Add a new device to an existing filesystem\n"
@@ -119,6 +120,8 @@ int fs_cmds(int argc, char *argv[])
}
if (!strcmp(cmd, "usage"))
return cmd_fs_usage(argc, argv);
+ if (!strcmp(cmd, "top"))
+ return cmd_fs_top(argc, argv);
return 0;
}
diff --git a/c_src/cmd_top.c b/c_src/cmd_top.c
new file mode 100644
index 00000000..05845340
--- /dev/null
+++ b/c_src/cmd_top.c
@@ -0,0 +1,98 @@
+#include <dirent.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "cmds.h"
+#include "libbcachefs.h"
+#include "libbcachefs/sb-counters.h"
+
+static const u8 counters_to_stable_map[] = {
+#define x(n, id, ...) [BCH_COUNTER_##n] = BCH_COUNTER_STABLE_##n,
+ BCH_PERSISTENT_COUNTERS()
+#undef x
+};
+
+static struct bch_ioctl_query_counters *read_counters(struct bchfs_handle fs)
+{
+ struct bch_ioctl_query_counters *ret =
+ kzalloc(sizeof(*ret) + sizeof(ret->d[0]) * BCH_COUNTER_NR, GFP_KERNEL);
+
+ ret->nr = BCH_COUNTER_NR;
+
+ xioctl(fs.ioctl_fd, BCH_IOCTL_QUERY_COUNTERS, ret);
+ return ret;
+}
+
+static void fs_top(const char *path, bool human_readable)
+{
+ struct bchfs_handle fs = bcache_fs_open(path);
+
+ struct bch_ioctl_query_counters *curr, *prev = NULL;
+
+ curr = read_counters(fs);
+
+ while (true) {
+ sleep(1);
+ kfree(prev);
+ prev = curr;
+ curr = read_counters(fs);
+
+ printf("\033[2J");
+ printf("\033[H");
+
+ for (unsigned i = 0; i < BCH_COUNTER_NR; i++) {
+ unsigned stable = counters_to_stable_map[i];
+ u64 v = stable < curr->nr
+ ? curr->d[stable] - prev->d[stable]
+ : 0;
+ printf("%-48s %llu\n",
+ bch2_counter_names[i],
+ v);
+ }
+ }
+
+ bcache_fs_close(fs);
+}
+
+static void fs_top_usage(void)
+{
+ puts("bcachefs fs top - display runtime perfomance info\n"
+ "Usage: bcachefs fs top [OPTION]... <mountpoint>\n"
+ "\n"
+ "Options:\n"
+ " -h, --human-readable Human readable units\n"
+ " -H, --help Display this help and exit\n"
+ "Report bugs to <linux-bcachefs@vger.kernel.org>");
+}
+
+int cmd_fs_top(int argc, char *argv[])
+{
+ static const struct option longopts[] = {
+ { "help", no_argument, NULL, 'H' },
+ { "human-readable", no_argument, NULL, 'h' },
+ { NULL }
+ };
+ bool human_readable = false;
+ int opt;
+
+ while ((opt = getopt_long(argc, argv, "Hh",
+ longopts, NULL)) != -1)
+ switch (opt) {
+ case 'h':
+ human_readable = true;
+ break;
+ case 'H':
+ fs_top_usage();
+ exit(EXIT_SUCCESS);
+ default:
+ fs_top_usage();
+ exit(EXIT_FAILURE);
+ }
+ args_shift(optind);
+
+ fs_top(arg_pop() ?: ".", human_readable) ;
+ return 0;
+}
diff --git a/c_src/cmds.h b/c_src/cmds.h
index 64267dc4..bcbfb0d0 100644
--- a/c_src/cmds.h
+++ b/c_src/cmds.h
@@ -15,6 +15,7 @@ int cmd_reset_counters(int argc, char *argv[]);
int cmd_set_option(int argc, char *argv[]);
int cmd_fs_usage(int argc, char *argv[]);
+int cmd_fs_top(int argc, char *argv[]);
int device_usage(void);
int cmd_device_add(int argc, char *argv[]);