]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to 5d7142b75a bcachefs: Redo filesystem usage ioctls
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 18 Dec 2019 21:11:04 +0000 (16:11 -0500)
committerKent Overstreet <kent.overstreet@gmail.com>
Wed, 18 Dec 2019 21:11:04 +0000 (16:11 -0500)
.bcachefs_revision
libbcachefs/bcachefs_format.h
libbcachefs/bcachefs_ioctl.h
libbcachefs/chardev.c
libbcachefs/replicas.h

index d8ca95c6b073cf56756d579314b2e1cb63166e5f..ede4a3deb98f934cca3a4e6c877ce0d5979b83e0 100644 (file)
@@ -1 +1 @@
-a8faf2472b83bb675aceca3e43f20d232409b1cc
+5d7142b75a6eb52f7398fd119971c14d76add6ba
index 3d85012a15fdcda704310de7666da26183641d64..66af4f4cdd53b6713612ef77a90052f85fa63aa3 100644 (file)
@@ -1080,6 +1080,9 @@ struct bch_replicas_entry {
        __u8                    devs[0];
 } __attribute__((packed));
 
+#define replicas_entry_bytes(_i)                                       \
+       (offsetof(typeof(*(_i)), devs) + (_i)->nr_devs)
+
 struct bch_sb_field_replicas {
        struct bch_sb_field     field;
        struct bch_replicas_entry entries[0];
index d668ede5491a05d8fbf6610f3b38c30a8d10c9a5..ba8c75706bf12f4a2507f10c84532dc05313e10f 100644 (file)
@@ -68,7 +68,8 @@ struct bch_ioctl_incremental {
 #define BCH_IOCTL_DISK_OFFLINE _IOW(0xbc,      7,  struct bch_ioctl_disk)
 #define BCH_IOCTL_DISK_SET_STATE _IOW(0xbc,    8,  struct bch_ioctl_disk_set_state)
 #define BCH_IOCTL_DATA         _IOW(0xbc,      10, struct bch_ioctl_data)
-#define BCH_IOCTL_USAGE                _IOWR(0xbc,     11, struct bch_ioctl_usage)
+#define BCH_IOCTL_FS_USAGE     _IOWR(0xbc,     11, struct bch_ioctl_fs_usage)
+#define BCH_IOCTL_DEV_USAGE    _IOWR(0xbc,     11, struct bch_ioctl_dev_usage)
 #define BCH_IOCTL_READ_SUPER   _IOW(0xbc,      12, struct bch_ioctl_read_super)
 #define BCH_IOCTL_DISK_GET_IDX _IOW(0xbc,      13,  struct bch_ioctl_disk_get_idx)
 #define BCH_IOCTL_DISK_RESIZE  _IOW(0xbc,      14,  struct bch_ioctl_disk_resize)
@@ -224,46 +225,59 @@ struct bch_ioctl_data_event {
        };
 } __attribute__((packed, aligned(8)));
 
-struct bch_ioctl_dev_usage {
-       __u8                    state;
-       __u8                    alive;
-       __u8                    pad[6];
-       __u32                   dev;
+struct bch_replicas_usage {
+       __u64                   sectors;
+       struct bch_replicas_entry r;
+} __attribute__((packed));
 
-       __u32                   bucket_size;
-       __u64                   nr_buckets;
-
-       __u64                   buckets[BCH_DATA_NR];
-       __u64                   sectors[BCH_DATA_NR];
-};
+static inline struct bch_replicas_usage *
+replicas_usage_next(struct bch_replicas_usage *u)
+{
+       return (void *) u + replicas_entry_bytes(&u->r) + 8;
+}
 
+/*
+ * BCH_IOCTL_FS_USAGE: query filesystem disk space usage
+ *
+ * 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_fs_usage {
        __u64                   capacity;
        __u64                   used;
        __u64                   online_reserved;
        __u64                   persistent_reserved[BCH_REPLICAS_MAX];
-       __u64                   sectors[BCH_DATA_NR][BCH_REPLICAS_MAX];
+
+       __u32                   replica_entries_bytes;
+       __u32                   pad;
+
+       struct bch_replicas_usage replicas[0];
 };
 
 /*
- * BCH_IOCTL_USAGE: query filesystem disk space usage
- *
- * Returns disk space usage broken out by data type, number of replicas, and
- * by component device
+ * BCH_IOCTL_DEV_USAGE: query device disk space usage
  *
- * @nr_devices - number of devices userspace allocated space for in @devs
- *
- * On success, @fs and @devs will be filled out appropriately and devs[i].alive
- * will indicate if a device was present in that slot
- *
- * Returns -ERANGE if @nr_devices was too small
+ * Returns disk space usage broken out by data type - both by buckets and
+ * sectors.
  */
-struct bch_ioctl_usage {
-       __u16                   nr_devices;
-       __u16                   pad[3];
+struct bch_ioctl_dev_usage {
+       __u64                   dev;
+       __u32                   flags;
+       __u8                    state;
+       __u8                    pad[7];
+
+       __u32                   bucket_size;
+       __u64                   nr_buckets;
 
-       struct bch_ioctl_fs_usage fs;
-       struct bch_ioctl_dev_usage devs[0];
+       __u64                   buckets[BCH_DATA_NR];
+       __u64                   sectors[BCH_DATA_NR];
 };
 
 /*
index 059eca01ccc4581f1df7bf07e3129ce711d94d2b..5028d0dcc2d6bc7d8e2e7920c6107216fa898fc0 100644 (file)
@@ -6,6 +6,7 @@
 #include "buckets.h"
 #include "chardev.h"
 #include "move.h"
+#include "replicas.h"
 #include "super.h"
 #include "super-io.h"
 
@@ -371,89 +372,116 @@ err:
        return ret;
 }
 
-static long bch2_ioctl_usage(struct bch_fs *c,
-                            struct bch_ioctl_usage __user *user_arg)
+static long bch2_ioctl_fs_usage(struct bch_fs *c,
+                               struct bch_ioctl_fs_usage __user *user_arg)
 {
-       struct bch_ioctl_usage arg;
-       struct bch_dev *ca;
-       unsigned i, j;
-       int ret;
+       struct bch_ioctl_fs_usage *arg = NULL;
+       struct bch_replicas_usage *dst_e, *dst_end;
+       struct bch_fs_usage *src;
+       u32 replica_entries_bytes;
+       unsigned i;
+       int ret = 0;
 
        if (!test_bit(BCH_FS_STARTED, &c->flags))
                return -EINVAL;
 
-       if (copy_from_user(&arg, user_arg, sizeof(arg)))
+       if (get_user(replica_entries_bytes, &user_arg->replica_entries_bytes))
                return -EFAULT;
 
-       for (i = 0; i < arg.nr_devices; i++) {
-               struct bch_ioctl_dev_usage dst = { .alive = 0 };
+       arg = kzalloc(sizeof(*arg) + replica_entries_bytes, GFP_KERNEL);
+       if (!arg)
+               return -ENOMEM;
 
-               ret = copy_to_user(&user_arg->devs[i], &dst, sizeof(dst));
-               if (ret)
-                       return ret;
+       src = bch2_fs_usage_read(c);
+       if (!src) {
+               ret = -ENOMEM;
+               goto err;
        }
 
-       {
-               struct bch_fs_usage *src;
-               struct bch_ioctl_fs_usage dst = {
-                       .capacity               = c->capacity,
-               };
+       arg->capacity           = c->capacity;
+       arg->used               = bch2_fs_sectors_used(c, src);
+       arg->online_reserved    = src->online_reserved;
 
-               src = bch2_fs_usage_read(c);
-               if (!src)
-                       return -ENOMEM;
+       for (i = 0; i < BCH_REPLICAS_MAX; i++)
+               arg->persistent_reserved[i] = src->persistent_reserved[i];
 
-               dst.used                = bch2_fs_sectors_used(c, src);
-               dst.online_reserved     = src->online_reserved;
+       dst_e   = arg->replicas;
+       dst_end = (void *) arg->replicas + replica_entries_bytes;
 
-               percpu_up_read(&c->mark_lock);
+       for (i = 0; i < c->replicas.nr; i++) {
+               struct bch_replicas_entry *src_e =
+                       cpu_replicas_entry(&c->replicas, i);
 
-               for (i = 0; i < BCH_REPLICAS_MAX; i++) {
-                       dst.persistent_reserved[i] =
-                               src->persistent_reserved[i];
-#if 0
-                       for (j = 0; j < BCH_DATA_NR; j++)
-                               dst.sectors[j][i] = src.replicas[i].data[j];
-#endif
+               if (replicas_usage_next(dst_e) > dst_end) {
+                       ret = -ERANGE;
+                       break;
                }
 
-               kfree(src);
+               dst_e->sectors          = src->replicas[i];
+               dst_e->r                = *src_e;
+
+               /* recheck after setting nr_devs: */
+               if (replicas_usage_next(dst_e) > dst_end) {
+                       ret = -ERANGE;
+                       break;
+               }
 
-               ret = copy_to_user(&user_arg->fs, &dst, sizeof(dst));
-               if (ret)
-                       return ret;
+               memcpy(dst_e->r.devs, src_e->devs, src_e->nr_devs);
+
+               dst_e = replicas_usage_next(dst_e);
        }
 
-       for_each_member_device(ca, c, i) {
-               struct bch_dev_usage src = bch2_dev_usage_read(c, ca);
-               struct bch_ioctl_dev_usage dst = {
-                       .alive          = 1,
-                       .state          = ca->mi.state,
-                       .bucket_size    = ca->mi.bucket_size,
-                       .nr_buckets     = ca->mi.nbuckets - ca->mi.first_bucket,
-               };
-
-               if (ca->dev_idx >= arg.nr_devices) {
-                       percpu_ref_put(&ca->ref);
-                       return -ERANGE;
-               }
+       arg->replica_entries_bytes = (void *) dst_e - (void *) arg->replicas;
 
-               if (percpu_ref_tryget(&ca->io_ref)) {
-                       dst.dev = huge_encode_dev(ca->disk_sb.bdev->bd_dev);
-                       percpu_ref_put(&ca->io_ref);
-               }
+       percpu_up_read(&c->mark_lock);
+       kfree(src);
 
-               for (j = 0; j < BCH_DATA_NR; j++) {
-                       dst.buckets[j] = src.buckets[j];
-                       dst.sectors[j] = src.sectors[j];
-               }
+       if (!ret)
+               ret = copy_to_user(user_arg, arg,
+                       sizeof(*arg) + arg->replica_entries_bytes);
+err:
+       kfree(arg);
+       return ret;
+}
+
+static long bch2_ioctl_dev_usage(struct bch_fs *c,
+                                struct bch_ioctl_dev_usage __user *user_arg)
+{
+       struct bch_ioctl_dev_usage arg;
+       struct bch_dev_usage src;
+       struct bch_dev *ca;
+       unsigned i;
+
+       if (!test_bit(BCH_FS_STARTED, &c->flags))
+               return -EINVAL;
 
-               ret = copy_to_user(&user_arg->devs[i], &dst, sizeof(dst));
-               if (ret)
-                       return ret;
+       if (copy_from_user(&arg, user_arg, sizeof(arg)))
+               return -EFAULT;
+
+       if ((arg.flags & ~BCH_BY_INDEX) ||
+           arg.pad[0] ||
+           arg.pad[1] ||
+           arg.pad[2])
+               return -EINVAL;
+
+       ca = bch2_device_lookup(c, arg.dev, arg.flags);
+       if (IS_ERR(ca))
+               return PTR_ERR(ca);
+
+       src = bch2_dev_usage_read(c, ca);
+
+       arg.state       = ca->mi.state;
+       arg.bucket_size = ca->mi.bucket_size;
+       arg.nr_buckets  = ca->mi.nbuckets - ca->mi.first_bucket;
+
+       for (i = 0; i < BCH_DATA_NR; i++) {
+               arg.buckets[i] = src.buckets[i];
+               arg.sectors[i] = src.sectors[i];
        }
 
-       return 0;
+       percpu_ref_put(&ca->ref);
+
+       return copy_to_user(user_arg, &arg, sizeof(arg));
 }
 
 static long bch2_ioctl_read_super(struct bch_fs *c,
@@ -547,8 +575,10 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
        switch (cmd) {
        case BCH_IOCTL_QUERY_UUID:
                return bch2_ioctl_query_uuid(c, arg);
-       case BCH_IOCTL_USAGE:
-               return bch2_ioctl_usage(c, arg);
+       case BCH_IOCTL_FS_USAGE:
+               return bch2_ioctl_fs_usage(c, arg);
+       case BCH_IOCTL_DEV_USAGE:
+               return bch2_ioctl_dev_usage(c, arg);
        }
 
        if (!capable(CAP_SYS_ADMIN))
index 0d6e191260217d125a76f36d5b1e70f1932fb6ae..8527d82841bbdb725c8c412905eef2b6585e2703 100644 (file)
@@ -72,9 +72,6 @@ int bch2_replicas_set_usage(struct bch_fs *,
 
 /* iterate over superblock replicas - used by userspace tools: */
 
-#define replicas_entry_bytes(_i)                                       \
-       (offsetof(typeof(*(_i)), devs) + (_i)->nr_devs)
-
 #define replicas_entry_next(_i)                                                \
        ((typeof(_i)) ((void *) (_i) + replicas_entry_bytes(_i)))