]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: BCH_IOCTL_QUERY_ACCOUNTING
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 1 Mar 2024 23:43:39 +0000 (18:43 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Jul 2024 23:00:15 +0000 (19:00 -0400)
Add a new ioctl that can return the new accounting counter types; it
takes as input a bitmask of accounting types to return.

This will be used for returning e.g. compression accounting and
rebalance_work accounting.

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

index 0b82a4dd099f4a8c82f2edd779e231cfd670ea2f..3c23bdf788cea4bd92b25259528cd36bc9ccd3f6 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/uuid.h>
 #include <asm/ioctl.h>
 #include "bcachefs_format.h"
+#include "bkey_types.h"
 
 /*
  * Flags common to multiple ioctls:
@@ -85,6 +86,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)
 
 /* ioctl below act on a particular file, not the filesystem as a whole: */
 
@@ -262,6 +264,7 @@ replicas_usage_next(struct bch_replicas_usage *u)
        return (void *) u + replicas_usage_bytes(u);
 }
 
+/* Obsolete */
 /*
  * BCH_IOCTL_FS_USAGE: query filesystem disk space usage
  *
@@ -287,6 +290,7 @@ struct bch_ioctl_fs_usage {
        struct bch_replicas_usage replicas[];
 };
 
+/* Obsolete */
 /*
  * BCH_IOCTL_DEV_USAGE: query device disk space usage
  *
@@ -311,6 +315,7 @@ struct bch_ioctl_dev_usage {
        }                       d[10];
 };
 
+/* Obsolete */
 struct bch_ioctl_dev_usage_v2 {
        __u64                   dev;
        __u32                   flags;
@@ -414,4 +419,28 @@ struct bch_ioctl_fsck_online {
        __u64                   opts;           /* string */
 };
 
+/*
+ * BCH_IOCTL_QUERY_ACCOUNTING: query filesystem disk accounting
+ *
+ * Returns disk space usage broken out by data type, number of replicas, and
+ * by component device
+ *
+ * @replica_entries_bytes - size, in bytes, allocated for replica usage entries
+ *
+ * On success, @replica_entries_bytes will be changed to indicate the number of
+ * bytes actually used.
+ *
+ * Returns -ERANGE if @replica_entries_bytes was too small
+ */
+struct bch_ioctl_query_accounting {
+       __u64                   capacity;
+       __u64                   used;
+       __u64                   online_reserved;
+
+       __u32                   accounting_u64s; /* input parameter */
+       __u32                   accounting_types_mask; /* input parameter */
+
+       struct bkey_i_accounting accounting[];
+};
+
 #endif /* _BCACHEFS_IOCTL_H */
index 0e76e06ab84426a760d14684ea6de6d927a804b7..cbadba4027c29ba74227af75682a512f4bc2c1ef 100644 (file)
@@ -557,6 +557,34 @@ err:
        return ret;
 }
 
+static long bch2_ioctl_query_accounting(struct bch_fs *c,
+                       struct bch_ioctl_query_accounting __user *user_arg)
+{
+       struct bch_ioctl_query_accounting arg;
+       darray_char accounting = {};
+       int ret = 0;
+
+       if (!test_bit(BCH_FS_started, &c->flags))
+               return -EINVAL;
+
+       ret   = copy_from_user_errcode(&arg, user_arg, sizeof(arg)) ?:
+               bch2_fs_accounting_read(c, &accounting, arg.accounting_types_mask) ?:
+               (arg.accounting_u64s * sizeof(u64) < accounting.nr ? -ERANGE : 0) ?:
+               copy_to_user_errcode(&user_arg->accounting, accounting.data, accounting.nr);
+       if (ret)
+               goto err;
+
+       arg.capacity            = c->capacity;
+       arg.used                = bch2_fs_usage_read_short(c).used;
+       arg.online_reserved     = percpu_u64_get(c->online_reserved);
+       arg.accounting_u64s     = accounting.nr / sizeof(u64);
+
+       ret = copy_to_user_errcode(user_arg, &arg, sizeof(arg));
+err:
+       darray_exit(&accounting);
+       return ret;
+}
+
 /* 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)
@@ -910,6 +938,8 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
                BCH_IOCTL(disk_resize_journal, struct bch_ioctl_disk_resize_journal);
        case BCH_IOCTL_FSCK_ONLINE:
                BCH_IOCTL(fsck_online, struct bch_ioctl_fsck_online);
+       case BCH_IOCTL_QUERY_ACCOUNTING:
+               return bch2_ioctl_query_accounting(c, arg);
        default:
                return -ENOTTY;
        }
index bc45f53efc2717e5a64e6cd4c16bfad592dd3d58..510ed683f0a0e285e0ed230aa6eb5888bb3be6e3 100644 (file)
@@ -315,6 +315,44 @@ int bch2_fs_replicas_usage_read(struct bch_fs *c, darray_char *usage)
        return ret;
 }
 
+int bch2_fs_accounting_read(struct bch_fs *c, darray_char *out_buf, unsigned accounting_types_mask)
+{
+
+       struct bch_accounting_mem *acc = &c->accounting[0];
+       int ret = 0;
+
+       darray_init(out_buf);
+
+       percpu_down_read(&c->mark_lock);
+       darray_for_each(acc->k, i) {
+               struct disk_accounting_pos a_p;
+               bpos_to_disk_accounting_pos(&a_p, i->pos);
+
+               if (!(accounting_types_mask & BIT(a_p.type)))
+                       continue;
+
+               ret = darray_make_room(out_buf, sizeof(struct bkey_i_accounting) +
+                                      sizeof(u64) * i->nr_counters);
+               if (ret)
+                       break;
+
+               struct bkey_i_accounting *a_out =
+                       bkey_accounting_init((void *) &darray_top(*out_buf));
+               set_bkey_val_u64s(&a_out->k, i->nr_counters);
+               a_out->k.p = i->pos;
+               bch2_accounting_mem_read(c, i->pos, a_out->v.d, i->nr_counters);
+
+               if (!bch2_accounting_key_is_zero(accounting_i_to_s_c(a_out)))
+                       out_buf->nr += bkey_bytes(&a_out->k);
+       }
+
+       percpu_up_read(&c->mark_lock);
+
+       if (ret)
+               darray_exit(out_buf);
+       return ret;
+}
+
 void bch2_fs_accounting_to_text(struct printbuf *out, struct bch_fs *c)
 {
        struct bch_accounting_mem *acc = &c->accounting[0];
index 5164995f3139b97ce4de2843cfd3461f85f05cce..ab1f74cb97c72a7b8b648c8803584ba84e1f5037 100644 (file)
@@ -193,6 +193,7 @@ static inline void bch2_accounting_mem_read(struct bch_fs *c, struct bpos p,
 }
 
 int bch2_fs_replicas_usage_read(struct bch_fs *, darray_char *);
+int bch2_fs_accounting_read(struct bch_fs *, darray_char *, unsigned);
 void bch2_fs_accounting_to_text(struct printbuf *, struct bch_fs *);
 
 int bch2_accounting_gc_done(struct bch_fs *);