This was a request from the systemd guys. They need a quick and easy way to get all devices attached to a Btrfs filesystem in order to check if any of the disks are SSD for...something, I didn't ask :). I've tested this with the btrfs-progs patch that accompanies this patch. Thanks,
Signed-off-by: Josef Bacik <jo...@redhat.com> --- fs/btrfs/ioctl.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/ioctl.h | 7 ++++++ 2 files changed, 71 insertions(+), 0 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9254b3d..f59b0bc 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1957,6 +1957,68 @@ out: return ret; } +static noinline long btrfs_ioctl_disk_info(struct btrfs_root *root, + void __user *arg) +{ + struct btrfs_ioctl_disk_info_args di_args; + u64 *user_dest; + u64 *dest = NULL; + struct btrfs_device *device; + struct list_head *devices; + int alloc_size = 0; + int ret = 0; + + if (copy_from_user(&di_args, + (struct btrfs_ioctl_disk_info_args __user *)arg, + sizeof(di_args))) + return -EFAULT; + + mutex_lock(&root->fs_info->fs_devices->device_list_mutex); + if (!di_args.num_devices) { + di_args.num_devices = root->fs_info->fs_devices->num_devices; + goto out; + } + alloc_size = sizeof(u64) * di_args.num_devices; + + di_args.num_devices = 0; + + /* + * If we have more than 4k worth of space to hold a bunch of u64's, + * somebody is misbehaving. + */ + if (alloc_size > PAGE_CACHE_SIZE) { + ret = -ENOMEM; + goto out; + } + + dest = kzalloc(alloc_size, GFP_NOFS); + if (!dest) { + ret = -ENOMEM; + goto out; + } + + devices = &root->fs_info->fs_devices->devices; + + list_for_each_entry(device, devices, dev_list) { + dest[di_args.num_devices] = + huge_encode_dev(device->bdev->bd_dev); + di_args.num_devices++; + } + + user_dest = (u64 *) + (arg + sizeof(struct btrfs_ioctl_disk_info_args)); + + if (copy_to_user(user_dest, dest, alloc_size)) + ret = -EFAULT; +out: + mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + if (ret == 0 && copy_to_user(arg, &di_args, sizeof(di_args))) + ret = -EFAULT; + kfree(dest); + + return ret; +} + /* * there are many ways the trans_start and trans_end ioctls can lead * to deadlocks. They should only be used by applications that @@ -2031,6 +2093,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_ino_lookup(file, argp); case BTRFS_IOC_SPACE_INFO: return btrfs_ioctl_space_info(root, argp); + case BTRFS_IOC_DISK_INFO: + return btrfs_ioctl_disk_info(root, argp); case BTRFS_IOC_SYNC: btrfs_sync_fs(file->f_dentry->d_sb, 1); return 0; diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 424694a..294e8c3 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h @@ -138,6 +138,11 @@ struct btrfs_ioctl_space_args { struct btrfs_ioctl_space_info spaces[0]; }; +struct btrfs_ioctl_disk_info_args { + __u32 num_devices; + __u64 devices[0]; +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -178,4 +183,6 @@ struct btrfs_ioctl_space_args { #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64) #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ struct btrfs_ioctl_space_args) +#define BTRFS_IOC_DISK_INFO _IOWR(BTRFS_IOCTL_MAGIC, 21, \ + struct btrfs_ioctl_disk_info_args) #endif -- 1.6.6.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html