On 2025/1/30 4:49, Kent Overstreet wrote:
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 <[email protected]>
---
  fs/bcachefs/bcachefs_ioctl.h | 10 ++++++++++
  fs/bcachefs/chardev.c        | 32 ++++++++++++++++++++++++++++++++
  fs/bcachefs/sb-counters.c    |  2 +-
  fs/bcachefs/sb-counters.h    |  1 +
  4 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/fs/bcachefs/bcachefs_ioctl.h b/fs/bcachefs/bcachefs_ioctl.h
index 3c23bdf788ce..f1b746fac007 100644
--- a/fs/bcachefs/bcachefs_ioctl.h
+++ b/fs/bcachefs/bcachefs_ioctl.h
@@ -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 */
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index 46e9e32105a9..c2d9efe8db53 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -448,6 +448,36 @@ static long bch2_ioctl_query_accounting(struct bch_fs *c,
        return ret;
  }
+static 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);
This will change the input parameter @nr (records the size of filling space). Instead, how about introducing the extra parameter @max to keep the input array size?

Thanks,
Hongbo
+       if (ret)
+               return ret;
+
+       for (unsigned i = 0; i < arg.nr; i++) {
+               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[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
  /* obsolete, didn't allow for new data types: */
  static long bch2_ioctl_dev_usage(struct bch_fs *c,
                                 struct bch_ioctl_dev_usage __user *user_arg)
@@ -710,6 +740,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;
        }
diff --git a/fs/bcachefs/sb-counters.c b/fs/bcachefs/sb-counters.c
index 6992e7469112..67f4e7a5aa5a 100644
--- a/fs/bcachefs/sb-counters.c
+++ b/fs/bcachefs/sb-counters.c
@@ -5,7 +5,7 @@
/* BCH_SB_FIELD_counters */ -static const char * const bch2_counter_names[] = {
+const char * const bch2_counter_names[] = {
  #define x(t, n, ...) (#t),
        BCH_PERSISTENT_COUNTERS()
  #undef x
diff --git a/fs/bcachefs/sb-counters.h b/fs/bcachefs/sb-counters.h
index 81f8aec9fcb1..eef7211edf42 100644
--- a/fs/bcachefs/sb-counters.h
+++ b/fs/bcachefs/sb-counters.h
@@ -11,6 +11,7 @@ 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;
#endif // _BCACHEFS_SB_COUNTERS_H

Reply via email to