From f026d7cc812b5a2e20b83a8a923cb1d6063e85e3 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 18 Dec 2019 16:11:04 -0500 Subject: [PATCH] Update bcachefs sources to 5d7142b75a bcachefs: Redo filesystem usage ioctls --- .bcachefs_revision | 2 +- libbcachefs/bcachefs_format.h | 3 + libbcachefs/bcachefs_ioctl.h | 80 +++++++++------- libbcachefs/chardev.c | 174 ++++++++++++++++++++-------------- libbcachefs/replicas.h | 3 - 5 files changed, 153 insertions(+), 109 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index d8ca95c6..ede4a3de 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -a8faf2472b83bb675aceca3e43f20d232409b1cc +5d7142b75a6eb52f7398fd119971c14d76add6ba diff --git a/libbcachefs/bcachefs_format.h b/libbcachefs/bcachefs_format.h index 3d85012a..66af4f4c 100644 --- a/libbcachefs/bcachefs_format.h +++ b/libbcachefs/bcachefs_format.h @@ -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]; diff --git a/libbcachefs/bcachefs_ioctl.h b/libbcachefs/bcachefs_ioctl.h index d668ede5..ba8c7570 100644 --- a/libbcachefs/bcachefs_ioctl.h +++ b/libbcachefs/bcachefs_ioctl.h @@ -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,11 +225,53 @@ struct bch_ioctl_data_event { }; } __attribute__((packed, aligned(8))); +struct bch_replicas_usage { + __u64 sectors; + struct bch_replicas_entry r; +} __attribute__((packed)); + +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]; + + __u32 replica_entries_bytes; + __u32 pad; + + struct bch_replicas_usage replicas[0]; +}; + +/* + * BCH_IOCTL_DEV_USAGE: query device disk space usage + * + * Returns disk space usage broken out by data type - both by buckets and + * sectors. + */ struct bch_ioctl_dev_usage { + __u64 dev; + __u32 flags; __u8 state; - __u8 alive; - __u8 pad[6]; - __u32 dev; + __u8 pad[7]; __u32 bucket_size; __u64 nr_buckets; @@ -237,35 +280,6 @@ struct bch_ioctl_dev_usage { __u64 sectors[BCH_DATA_NR]; }; -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]; -}; - -/* - * BCH_IOCTL_USAGE: query filesystem disk space usage - * - * Returns disk space usage broken out by data type, number of replicas, and - * by component device - * - * @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 - */ -struct bch_ioctl_usage { - __u16 nr_devices; - __u16 pad[3]; - - struct bch_ioctl_fs_usage fs; - struct bch_ioctl_dev_usage devs[0]; -}; - /* * BCH_IOCTL_READ_SUPER: read filesystem superblock * diff --git a/libbcachefs/chardev.c b/libbcachefs/chardev.c index 059eca01..5028d0dc 100644 --- a/libbcachefs/chardev.c +++ b/libbcachefs/chardev.c @@ -6,6 +6,7 @@ #include "buckets.h" #include "chardev.h" #include "move.h" +#include "replicas.h" #include "super.h" #include "super-io.h" @@ -371,13 +372,85 @@ 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_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 (get_user(replica_entries_bytes, &user_arg->replica_entries_bytes)) + return -EFAULT; + + arg = kzalloc(sizeof(*arg) + replica_entries_bytes, GFP_KERNEL); + if (!arg) + return -ENOMEM; + + src = bch2_fs_usage_read(c); + if (!src) { + ret = -ENOMEM; + goto err; + } + + arg->capacity = c->capacity; + arg->used = bch2_fs_sectors_used(c, src); + arg->online_reserved = src->online_reserved; + + for (i = 0; i < BCH_REPLICAS_MAX; i++) + arg->persistent_reserved[i] = src->persistent_reserved[i]; + + dst_e = arg->replicas; + dst_end = (void *) arg->replicas + replica_entries_bytes; + + for (i = 0; i < c->replicas.nr; i++) { + struct bch_replicas_entry *src_e = + cpu_replicas_entry(&c->replicas, i); + + if (replicas_usage_next(dst_e) > dst_end) { + ret = -ERANGE; + break; + } + + 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; + } + + memcpy(dst_e->r.devs, src_e->devs, src_e->nr_devs); + + dst_e = replicas_usage_next(dst_e); + } + + arg->replica_entries_bytes = (void *) dst_e - (void *) arg->replicas; + + percpu_up_read(&c->mark_lock); + kfree(src); + + 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, j; - int ret; + unsigned i; if (!test_bit(BCH_FS_STARTED, &c->flags)) return -EINVAL; @@ -385,75 +458,30 @@ static long bch2_ioctl_usage(struct bch_fs *c, if (copy_from_user(&arg, user_arg, sizeof(arg))) return -EFAULT; - for (i = 0; i < arg.nr_devices; i++) { - struct bch_ioctl_dev_usage dst = { .alive = 0 }; + if ((arg.flags & ~BCH_BY_INDEX) || + arg.pad[0] || + arg.pad[1] || + arg.pad[2]) + return -EINVAL; - ret = copy_to_user(&user_arg->devs[i], &dst, sizeof(dst)); - if (ret) - return ret; + 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]; } - { - struct bch_fs_usage *src; - struct bch_ioctl_fs_usage dst = { - .capacity = c->capacity, - }; + percpu_ref_put(&ca->ref); - src = bch2_fs_usage_read(c); - if (!src) - return -ENOMEM; - - dst.used = bch2_fs_sectors_used(c, src); - dst.online_reserved = src->online_reserved; - - percpu_up_read(&c->mark_lock); - - 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 - } - - kfree(src); - - ret = copy_to_user(&user_arg->fs, &dst, sizeof(dst)); - if (ret) - return ret; - } - - 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; - } - - if (percpu_ref_tryget(&ca->io_ref)) { - dst.dev = huge_encode_dev(ca->disk_sb.bdev->bd_dev); - percpu_ref_put(&ca->io_ref); - } - - for (j = 0; j < BCH_DATA_NR; j++) { - dst.buckets[j] = src.buckets[j]; - dst.sectors[j] = src.sectors[j]; - } - - ret = copy_to_user(&user_arg->devs[i], &dst, sizeof(dst)); - if (ret) - return ret; - } - - return 0; + 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)) diff --git a/libbcachefs/replicas.h b/libbcachefs/replicas.h index 0d6e1912..8527d828 100644 --- a/libbcachefs/replicas.h +++ b/libbcachefs/replicas.h @@ -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)))