]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: BCH_IOCTL_QUERY_COUNTERS
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 27 Jan 2025 03:05:02 +0000 (22:05 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:11 +0000 (21:02 -0400)
Add an ioctl for querying counters, the same ones provided in
/sys/fs/bcachefs/<uuid>/counters/, but more suitable for a 'bcachefs
top' command.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs_ioctl.h
fs/bcachefs/chardev.c
fs/bcachefs/sb-counters.c
fs/bcachefs/sb-counters.h

index 3c23bdf788cea4bd92b25259528cd36bc9ccd3f6..f1b746fac0075345fc73f64024120e2f8f353ef8 100644 (file)
@@ -87,6 +87,7 @@ struct bch_ioctl_incremental {
 #define BCH_IOCTL_FSCK_OFFLINE _IOW(0xbc,      19,  struct bch_ioctl_fsck_offline)
 #define BCH_IOCTL_FSCK_ONLINE  _IOW(0xbc,      20,  struct bch_ioctl_fsck_online)
 #define BCH_IOCTL_QUERY_ACCOUNTING _IOW(0xbc,  21,  struct bch_ioctl_query_accounting)
+#define BCH_IOCTL_QUERY_COUNTERS _IOW(0xbc,    21,  struct bch_ioctl_query_counters)
 
 /* ioctl below act on a particular file, not the filesystem as a whole: */
 
@@ -443,4 +444,13 @@ struct bch_ioctl_query_accounting {
        struct bkey_i_accounting accounting[];
 };
 
+#define BCH_IOCTL_QUERY_COUNTERS_MOUNT (1 << 0)
+
+struct bch_ioctl_query_counters {
+       __u16                   nr;
+       __u16                   flags;
+       __u32                   pad;
+       __u64                   d[];
+};
+
 #endif /* _BCACHEFS_IOCTL_H */
index 46e9e32105a9fb393be4df9b7c4bf1caf0c23de7..bab49d5ee598536d89f20322bc6eb2e231db3654 100644 (file)
@@ -11,6 +11,7 @@
 #include "move.h"
 #include "recovery_passes.h"
 #include "replicas.h"
+#include "sb-counters.h"
 #include "super-io.h"
 #include "thread_with_file.h"
 
@@ -710,6 +711,8 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
                BCH_IOCTL(fsck_online, struct bch_ioctl_fsck_online);
        case BCH_IOCTL_QUERY_ACCOUNTING:
                return bch2_ioctl_query_accounting(c, arg);
+       case BCH_IOCTL_QUERY_COUNTERS:
+               return bch2_ioctl_query_counters(c, arg);
        default:
                return -ENOTTY;
        }
index 5153a47ec7d46f352914cafab4bde3b266bb8f65..2b4b8445d418b38770e828b6bc93df9903c77607 100644 (file)
@@ -11,6 +11,13 @@ static const u8 counters_to_stable_map[] = {
 #undef x
 };
 
+const char * const bch2_counter_names[] = {
+#define x(t, n, ...) (#t),
+       BCH_PERSISTENT_COUNTERS()
+#undef x
+       NULL
+};
+
 static size_t bch2_sb_counter_nr_entries(struct bch_sb_field_counters *ctrs)
 {
        if (!ctrs)
@@ -102,3 +109,39 @@ const struct bch_sb_field_ops bch_sb_field_ops_counters = {
        .validate       = bch2_sb_counters_validate,
        .to_text        = bch2_sb_counters_to_text,
 };
+
+#ifndef NO_BCACHEFS_CHARDEV
+long bch2_ioctl_query_counters(struct bch_fs *c,
+                       struct bch_ioctl_query_counters __user *user_arg)
+{
+       struct bch_ioctl_query_counters arg;
+       int ret = copy_from_user_errcode(&arg, user_arg, sizeof(arg));
+       if (ret)
+               return ret;
+
+       if ((arg.flags & ~BCH_IOCTL_QUERY_COUNTERS_MOUNT) ||
+           arg.pad)
+               return -EINVAL;
+
+       arg.nr = min(arg.nr, BCH_COUNTER_NR);
+       ret = put_user(arg.nr, &user_arg->nr);
+       if (ret)
+               return ret;
+
+       for (unsigned i = 0; i < BCH_COUNTER_NR; i++) {
+               unsigned stable = counters_to_stable_map[i];
+
+               if (stable < arg.nr) {
+                       u64 v = !(arg.flags & BCH_IOCTL_QUERY_COUNTERS_MOUNT)
+                               ? percpu_u64_get(&c->counters[i])
+                               : c->counters_on_mount[i];
+
+                       ret = put_user(v, &user_arg->d[stable]);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+#endif
index 81f8aec9fcb1cedf43143f269fdfc1b6fb39e441..a4329ad8dd1baa78fbd8c905680e265aec028ff6 100644 (file)
@@ -11,6 +11,10 @@ int bch2_sb_counters_from_cpu(struct bch_fs *);
 void bch2_fs_counters_exit(struct bch_fs *);
 int bch2_fs_counters_init(struct bch_fs *);
 
+extern const char * const bch2_counter_names[];
 extern const struct bch_sb_field_ops bch_sb_field_ops_counters;
 
+long bch2_ioctl_query_counters(struct bch_fs *,
+                       struct bch_ioctl_query_counters __user *);
+
 #endif // _BCACHEFS_SB_COUNTERS_H