Update bcachefs sources to 5d7142b75a bcachefs: Redo filesystem usage ioctls

This commit is contained in:
Kent Overstreet 2019-12-18 16:11:04 -05:00
parent 54fc3909b4
commit f026d7cc81
5 changed files with 153 additions and 109 deletions

View File

@ -1 +1 @@
a8faf2472b83bb675aceca3e43f20d232409b1cc 5d7142b75a6eb52f7398fd119971c14d76add6ba

View File

@ -1080,6 +1080,9 @@ struct bch_replicas_entry {
__u8 devs[0]; __u8 devs[0];
} __attribute__((packed)); } __attribute__((packed));
#define replicas_entry_bytes(_i) \
(offsetof(typeof(*(_i)), devs) + (_i)->nr_devs)
struct bch_sb_field_replicas { struct bch_sb_field_replicas {
struct bch_sb_field field; struct bch_sb_field field;
struct bch_replicas_entry entries[0]; struct bch_replicas_entry entries[0];

View 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_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_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_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_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_GET_IDX _IOW(0xbc, 13, struct bch_ioctl_disk_get_idx)
#define BCH_IOCTL_DISK_RESIZE _IOW(0xbc, 14, struct bch_ioctl_disk_resize) #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))); } __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 { struct bch_ioctl_dev_usage {
__u64 dev;
__u32 flags;
__u8 state; __u8 state;
__u8 alive; __u8 pad[7];
__u8 pad[6];
__u32 dev;
__u32 bucket_size; __u32 bucket_size;
__u64 nr_buckets; __u64 nr_buckets;
@ -237,35 +280,6 @@ struct bch_ioctl_dev_usage {
__u64 sectors[BCH_DATA_NR]; __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 * BCH_IOCTL_READ_SUPER: read filesystem superblock
* *

View File

@ -6,6 +6,7 @@
#include "buckets.h" #include "buckets.h"
#include "chardev.h" #include "chardev.h"
#include "move.h" #include "move.h"
#include "replicas.h"
#include "super.h" #include "super.h"
#include "super-io.h" #include "super-io.h"
@ -371,13 +372,85 @@ err:
return ret; return ret;
} }
static long bch2_ioctl_usage(struct bch_fs *c, static long bch2_ioctl_fs_usage(struct bch_fs *c,
struct bch_ioctl_usage __user *user_arg) 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; struct bch_dev *ca;
unsigned i, j; unsigned i;
int ret;
if (!test_bit(BCH_FS_STARTED, &c->flags)) if (!test_bit(BCH_FS_STARTED, &c->flags))
return -EINVAL; return -EINVAL;
@ -385,75 +458,30 @@ static long bch2_ioctl_usage(struct bch_fs *c,
if (copy_from_user(&arg, user_arg, sizeof(arg))) if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT; return -EFAULT;
for (i = 0; i < arg.nr_devices; i++) { if ((arg.flags & ~BCH_BY_INDEX) ||
struct bch_ioctl_dev_usage dst = { .alive = 0 }; arg.pad[0] ||
arg.pad[1] ||
arg.pad[2])
return -EINVAL;
ret = copy_to_user(&user_arg->devs[i], &dst, sizeof(dst)); ca = bch2_device_lookup(c, arg.dev, arg.flags);
if (ret) if (IS_ERR(ca))
return ret; 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];
} }
{ percpu_ref_put(&ca->ref);
struct bch_fs_usage *src;
struct bch_ioctl_fs_usage dst = {
.capacity = c->capacity,
};
src = bch2_fs_usage_read(c); return copy_to_user(user_arg, &arg, sizeof(arg));
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;
} }
static long bch2_ioctl_read_super(struct bch_fs *c, 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) { switch (cmd) {
case BCH_IOCTL_QUERY_UUID: case BCH_IOCTL_QUERY_UUID:
return bch2_ioctl_query_uuid(c, arg); return bch2_ioctl_query_uuid(c, arg);
case BCH_IOCTL_USAGE: case BCH_IOCTL_FS_USAGE:
return bch2_ioctl_usage(c, arg); return bch2_ioctl_fs_usage(c, arg);
case BCH_IOCTL_DEV_USAGE:
return bch2_ioctl_dev_usage(c, arg);
} }
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))

View File

@ -72,9 +72,6 @@ int bch2_replicas_set_usage(struct bch_fs *,
/* iterate over superblock replicas - used by userspace tools: */ /* 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) \ #define replicas_entry_next(_i) \
((typeof(_i)) ((void *) (_i) + replicas_entry_bytes(_i))) ((typeof(_i)) ((void *) (_i) + replicas_entry_bytes(_i)))