On Mon, Jan 27, 2014 at 04:52:50PM +0800, Anand Jain wrote: > The user land progs needs a simple way to read > the raw list of disks and its parameters as > btrfs kernel understands it. This patch will > introduce BTRFS_IOC_GET_DEVS which dumps > every thing under fs_devices. > > As of now btrfs-devlist uses this ioctl. > > In the long run this ioctl would help to optimize > some part of btrfs-progs, mainly the current > btrfs filesystem show
Just thinking out loud here, really, but can we export this information in /sys instead, rather than adding yet more ioctls? Hugo. > Signed-off-by: Anand Jain <[email protected]> > --- > fs/btrfs/super.c | 56 +++++++++++++++++++++++++ > fs/btrfs/volumes.c | 99 > ++++++++++++++++++++++++++++++++++++++++++++ > fs/btrfs/volumes.h | 2 + > include/uapi/linux/btrfs.h | 45 ++++++++++++++++++++ > 4 files changed, 202 insertions(+), 0 deletions(-) > > diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c > index 878874b..2fc0e2b 100644 > --- a/fs/btrfs/super.c > +++ b/fs/btrfs/super.c > @@ -1693,6 +1693,59 @@ static struct file_system_type btrfs_fs_type = { > }; > MODULE_ALIAS_FS("btrfs"); > > +static int btrfs_ioc_get_devlist(void __user *arg) > +{ > + int ret = 0; > + u64 sz_devlist_arg; > + u64 sz_devlist; > + u64 sz_out; > + > + struct btrfs_ioctl_devlist_args *devlist_arg; > + struct btrfs_ioctl_devlist_args *tmp_devlist_arg; > + struct btrfs_ioctl_devlist *devlist; > + > + u64 cnt = 0, ucnt; > + > + sz_devlist_arg = sizeof(*devlist_arg); > + sz_devlist = sizeof(*devlist); > + > + if (copy_from_user(&ucnt, > + (struct btrfs_ioctl_devlist_args __user *)(arg + > + offsetof(struct btrfs_ioctl_devlist_args, count)), > + sizeof(ucnt))) > + return -EFAULT; > + > + cnt = btrfs_get_devlist_cnt(); > + > + if (cnt > ucnt) { > + if (copy_to_user(arg + > + offsetof(struct btrfs_ioctl_devlist_args, count), > + &cnt, sizeof(cnt))) > + return -EFAULT; > + return 1; > + } > + > + sz_out = sz_devlist_arg + sz_devlist * cnt; > + > + tmp_devlist_arg = devlist_arg = memdup_user(arg, sz_out); > + if (IS_ERR(devlist_arg)) > + return PTR_ERR(devlist_arg); > + > + devlist = (struct btrfs_ioctl_devlist *) (++tmp_devlist_arg); > + cnt = btrfs_get_devlist(devlist, cnt); > + devlist_arg->count = cnt; > + > + if (copy_to_user(arg, devlist_arg, sz_out)) { > + ret = -EFAULT; > + goto out; > + } > + ret = 0; > +out: > + kfree(devlist_arg); > + return ret; > + > +} > + > static int btrfs_ioc_get_fslist(void __user *arg) > { > int ret = 0; > @@ -1777,6 +1830,9 @@ static long btrfs_control_ioctl(struct file *file, > unsigned int cmd, > case BTRFS_IOC_GET_FSLIST: > ret = btrfs_ioc_get_fslist(argp); > break; > + case BTRFS_IOC_GET_DEVS: > + ret = btrfs_ioc_get_devlist(argp); > + break; > } > > return ret; > diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c > index 2ca91fc..f00ba27 100644 > --- a/fs/btrfs/volumes.c > +++ b/fs/btrfs/volumes.c > @@ -6322,3 +6322,102 @@ u64 btrfs_get_fslist(struct btrfs_ioctl_fslist > *fslist, u64 ucnt) > > return cnt; > } > + > +int btrfs_get_devlist_cnt(void) > +{ > + int cnt = 0; > + struct btrfs_device *device; > + struct btrfs_fs_devices *fs_devices; > + > + mutex_lock(&uuid_mutex); > + list_for_each_entry(fs_devices, &fs_uuids, list) > + list_for_each_entry(device, &fs_devices->devices, dev_list) > + cnt++; > + mutex_unlock(&uuid_mutex); > + > + return cnt; > +} > + > +u64 btrfs_get_devlist(struct btrfs_ioctl_devlist *dev, u64 alloc_cnt) > +{ > + u64 cnt = 0; > + > + struct btrfs_device *device; > + struct btrfs_fs_devices *fs_devices; > + > + mutex_lock(&uuid_mutex); > + /* Todo: there must be better way of doing this */ > + list_for_each_entry(fs_devices, &fs_uuids, list) { > + > + mutex_lock(&fs_devices->device_list_mutex); > + > + list_for_each_entry(device, &fs_devices->devices, dev_list) { > + > + if (!(cnt < alloc_cnt)) > + break; > + > + memcpy(dev->fsid, fs_devices->fsid, BTRFS_FSID_SIZE); > + dev->fs_latest_devid = fs_devices->latest_devid; > + dev->fs_latest_trans = fs_devices->latest_trans; > + dev->fs_num_devices = fs_devices->num_devices; > + dev->fs_open_devices = fs_devices->open_devices; > + dev->fs_rw_devices = fs_devices->rw_devices; > + dev->fs_missing_devices = fs_devices->missing_devices; > + dev->fs_total_rw_bytes = fs_devices->total_rw_bytes; > + dev->fs_num_can_discard = fs_devices->num_can_discard; > + dev->fs_total_devices = fs_devices->total_devices; > + > + if (fs_devices->opened) > + dev->flags = BTRFS_FS_MOUNTED; > + if (fs_devices->seeding) > + dev->flags |= BTRFS_FS_SEEDING; > + if (fs_devices->rotating) > + dev->flags |= BTRFS_FS_ROTATING; > + > + if (device->writeable) > + dev->flags |= BTRFS_DEV_WRITEABLE; > + if (device->in_fs_metadata) > + dev->flags |= BTRFS_DEV_IN_FS_MD; > + if (device->missing) > + dev->flags |= BTRFS_DEV_MISSING; > + if (device->can_discard) > + dev->flags |= BTRFS_DEV_CAN_DISCARD; > + if (device->is_tgtdev_for_dev_replace) > + dev->flags |= BTRFS_DEV_SUBSTITUTED; > + if (device->running_pending) > + dev->flags |= BTRFS_DEV_RUN_PENDING; > + if (device->nobarriers) > + dev->flags |= BTRFS_DEV_NOBARRIERS; > + if (device->dev_stats_valid) > + dev->flags |= BTRFS_DEV_STATS_VALID; > + if (device->dev_stats_dirty) > + dev->flags |= BTRFS_DEV_STATS_DIRTY; > + > + dev->gen = device->generation; > + dev->devid = device->devid; > + dev->total_bytes = device->total_bytes; > + dev->disk_total_bytes = device->disk_total_bytes; > + dev->bytes_used = device->bytes_used; > + dev->type = device->type; > + dev->io_align = device->io_align; > + dev->io_width = device->io_width; > + dev->sector_size = device->sector_size; > + memcpy(dev->uuid, device->uuid, BTRFS_UUID_SIZE); > + if (device->name) { > + rcu_read_lock(); > + memcpy(dev->name, rcu_str_deref(device->name), > + BTRFS_PATH_NAME_MAX); > + rcu_read_unlock(); > + } else { > + memset(dev->name, 0, BTRFS_PATH_NAME_MAX); > + } > + dev++; > + cnt++; > + } > + > + mutex_unlock(&fs_devices->device_list_mutex); > + } > + mutex_unlock(&uuid_mutex); > + > + return cnt; > +} > diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h > index ebb0d0c..82a459c 100644 > --- a/fs/btrfs/volumes.h > +++ b/fs/btrfs/volumes.h > @@ -392,4 +392,6 @@ static inline void btrfs_dev_stat_reset(struct > btrfs_device *dev, > } > int btrfs_get_fslist_cnt(void); > u64 btrfs_get_fslist(struct btrfs_ioctl_fslist *fslist, u64 ucnt); > +int btrfs_get_devlist_cnt(void); > +u64 btrfs_get_devlist(struct btrfs_ioctl_devlist *devlist, u64 ucnt); > #endif > diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h > index 7d7f776..2983019 100644 > --- a/include/uapi/linux/btrfs.h > +++ b/include/uapi/linux/btrfs.h > @@ -520,6 +520,8 @@ static inline char *btrfs_err_str(enum btrfs_err_code > err_code) > > /* fs flags */ > #define BTRFS_FS_MOUNTED (1LLU << 0) > +#define BTRFS_FS_SEEDING (1LLU << 1) > +#define BTRFS_FS_ROTATING (1LLU << 2) > > struct btrfs_ioctl_fslist { > __u64 self_sz; /* in/out */ > @@ -535,6 +537,47 @@ struct btrfs_ioctl_fslist_args { > __u64 count; /* out */ > }; > > +#define BTRFS_DEV_WRITEABLE (1LLU << 8) > +#define BTRFS_DEV_IN_FS_MD (1LLU << 9) > +#define BTRFS_DEV_MISSING (1LLU << 10) > +#define BTRFS_DEV_CAN_DISCARD (1LLU << 11) > +#define BTRFS_DEV_SUBSTITUTED (1LLU << 12) > +#define BTRFS_DEV_RUN_PENDING (1LLU << 13) > +#define BTRFS_DEV_NOBARRIERS (1LLU << 14) > +#define BTRFS_DEV_STATS_VALID (1LLU << 15) > +#define BTRFS_DEV_STATS_DIRTY (1LLU << 16) > + > +struct btrfs_ioctl_devlist { > + __u64 sz_self; > + __u64 fs_latest_devid; > + __u64 fs_latest_trans; > + __u64 fs_num_devices; > + __u64 fs_open_devices; > + __u64 fs_rw_devices; > + __u64 fs_missing_devices; > + __u64 fs_total_rw_bytes; > + __u64 fs_num_can_discard; > + __u64 fs_total_devices; > + __u64 gen; > + __u64 flags; > + __u64 devid; > + __u64 total_bytes; > + __u64 disk_total_bytes; > + __u64 bytes_used; > + __u64 type; > + __u32 io_align; > + __u32 io_width; > + __u32 sector_size; > + __u8 fsid[BTRFS_FSID_SIZE]; > + __u8 uuid[BTRFS_UUID_SIZE]; > + __u8 name[BTRFS_PATH_NAME_MAX]; > +}__attribute__ ((__packed__)); > + > +struct btrfs_ioctl_devlist_args { > + __u64 self_sz; /* in/out */ > + __u64 count; /* in/out */ > +}; > + > #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ > struct btrfs_ioctl_vol_args) > #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ > @@ -638,5 +681,7 @@ struct btrfs_ioctl_fslist_args { > struct btrfs_ioctl_feature_flags[2]) > #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ > struct btrfs_ioctl_feature_flags[3]) > +#define BTRFS_IOC_GET_DEVS _IOWR(BTRFS_IOCTL_MAGIC, 58, \ > + struct btrfs_ioctl_devlist_args) > > #endif /* _UAPI_LINUX_BTRFS_H */ -- === Hugo Mills: hugo@... carfax.org.uk | darksatanic.net | lug.org.uk === PGP key: 65E74AC0 from wwwkeys.eu.pgp.net or http://www.carfax.org.uk --- All mushrooms are edible, but some are only edible once. ---
signature.asc
Description: Digital signature
