diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2017-12-27 17:02:34 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-05-22 00:44:18 -0400 |
commit | 929973774df066a93eb99b802f12c664d8726d77 (patch) | |
tree | 58116639ea5200ae0a0b76fe533d8dc579aa7fa8 | |
parent | 07fec9636341d8bf2238dc336e8db21ae01dab33 (diff) |
bcachefs: add BCH_IOCTL_READ_SUPER
-rw-r--r-- | fs/bcachefs/bcachefs_ioctl.h | 11 | ||||
-rw-r--r-- | fs/bcachefs/chardev.c | 42 |
2 files changed, 53 insertions, 0 deletions
diff --git a/fs/bcachefs/bcachefs_ioctl.h b/fs/bcachefs/bcachefs_ioctl.h index 079e2b556afd..e02e7ebf7f66 100644 --- a/fs/bcachefs/bcachefs_ioctl.h +++ b/fs/bcachefs/bcachefs_ioctl.h @@ -15,6 +15,8 @@ #define BCH_BY_INDEX (1 << 4) +#define BCH_READ_DEV (1 << 5) + /* global control dev: */ #define BCH_IOCTL_ASSEMBLE _IOW(0xbc, 1, struct bch_ioctl_assemble) @@ -46,6 +48,7 @@ struct bch_ioctl_incremental { #define BCH_IOCTL_DISK_EVACUATE _IOW(0xbc, 9, struct bch_ioctl_disk) #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_READ_SUPER _IOW(0xbc, 12, struct bch_ioctl_read_super) struct bch_ioctl_query_uuid { uuid_le uuid; @@ -123,4 +126,12 @@ struct bch_ioctl_usage { struct bch_ioctl_dev_usage devs[0]; }; +struct bch_ioctl_read_super { + __u32 flags; + __u32 pad; + __u64 dev; + __u64 size; + __u64 sb; +}; + #endif /* _BCACHEFS_IOCTL_H */ diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 1ab36ac9f519..ccccd98f5a3e 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -363,6 +363,46 @@ static long bch2_ioctl_usage(struct bch_fs *c, return 0; } +static long bch2_ioctl_read_super(struct bch_fs *c, + struct bch_ioctl_read_super arg) +{ + struct bch_dev *ca = NULL; + struct bch_sb *sb; + int ret = 0; + + if ((arg.flags & ~(BCH_BY_INDEX|BCH_READ_DEV)) || + arg.pad) + return -EINVAL; + + mutex_lock(&c->sb_lock); + + if (arg.flags & BCH_READ_DEV) { + ca = bch2_device_lookup(c, arg.dev, arg.flags); + + if (IS_ERR(ca)) { + ret = PTR_ERR(ca); + goto err; + } + + sb = ca->disk_sb.sb; + } else { + sb = c->disk_sb; + } + + if (vstruct_bytes(sb) > arg.size) { + ret = -ERANGE; + goto err; + } + + ret = copy_to_user((void __user *)(unsigned long)arg.sb, + sb, vstruct_bytes(sb)); +err: + if (ca) + percpu_ref_put(&ca->ref); + mutex_unlock(&c->sb_lock); + return ret; +} + #define BCH_IOCTL(_name, _argtype) \ do { \ _argtype i; \ @@ -404,6 +444,8 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg) BCH_IOCTL(disk_set_state, struct bch_ioctl_disk_set_state); case BCH_IOCTL_DISK_EVACUATE: BCH_IOCTL(disk_evacuate, struct bch_ioctl_disk); + case BCH_IOCTL_READ_SUPER: + BCH_IOCTL(read_super, struct bch_ioctl_read_super); default: return -ENOTTY; |