On 2019/8/5 下午9:19, Josef Bacik wrote:
> In testing block group removal it's sometimes handy to be able to create
> block groups on demand. Add an ioctl to allow us to force allocation
> from userspace.
>
> Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
> ---
> v1->v2:
> - I noticed last week when backporting this that btrfs_chunk_alloc doesn't
> figure out the rest of the flags needed for the type. Use
> btrfs_force_chunk_alloc instead so that we get the raid settings for the alloc
> type we're using.
Still not sure if it's worthy to add a debug only ioctl.
If sysfs is not good enough, maybe modify btrfs_force_chunk_alloc() to
do extra chunk allocation depending on a internal return value
overridable function?
At least for the later case, we can trigger empty chunk allocation with
BPF while without messing any interface.
Thanks,
Qu
>
> fs/btrfs/ioctl.c | 30 ++++++++++++++++++++++++++++++
> include/uapi/linux/btrfs.h | 1 +
> 2 files changed, 31 insertions(+)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index d0743ec1231d..891bf198d46a 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -5553,6 +5553,34 @@ static int _btrfs_ioctl_send(struct file *file, void __user *argp, bool compat)
> return ret;
> }
>
> +static long btrfs_ioctl_alloc_chunk(struct file *file, void __user *arg)
> +{
> + struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
> + struct btrfs_trans_handle *trans;
> + u64 flags;
> + int ret;
> +
> + if (!capable(CAP_SYS_ADMIN))
> + return -EPERM;
> +
> + if (copy_from_user(&flags, arg, sizeof(flags)))
> + return -EFAULT;
> +
> + /* We can only specify one type at a time. */
> + if (flags != BTRFS_BLOCK_GROUP_DATA &&
> + flags != BTRFS_BLOCK_GROUP_METADATA &&
> + flags != BTRFS_BLOCK_GROUP_SYSTEM)
> + return -EINVAL;
> +
> + trans = btrfs_start_transaction(root, 0);
> + if (IS_ERR(trans))
> + return PTR_ERR(trans);
> +
> + ret = btrfs_force_chunk_alloc(trans, flags);
> + btrfs_end_transaction(trans);
> + return ret < 0 ? ret : 0;
> +}
> +
> long btrfs_ioctl(struct file *file, unsigned int
> cmd, unsigned long arg)
> {
> @@ -5699,6 +5727,8 @@ long btrfs_ioctl(struct file *file, unsigned int
> return btrfs_ioctl_get_subvol_rootref(file, argp);
> case BTRFS_IOC_INO_LOOKUP_USER:
> return btrfs_ioctl_ino_lookup_user(file, argp);
> + case BTRFS_IOC_ALLOC_CHUNK:
> + return btrfs_ioctl_alloc_chunk(file, argp);
> }
>
> return -ENOTTY;
> diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
> index c195896d478f..3a6474c34ad0 100644
> --- a/include/uapi/linux/btrfs.h
> +++ b/include/uapi/linux/btrfs.h
> @@ -943,5 +943,6 @@ enum btrfs_err_code {
> struct btrfs_ioctl_get_subvol_rootref_args)
> #define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, \
> struct btrfs_ioctl_ino_lookup_user_args)
> +#define BTRFS_IOC_ALLOC_CHUNK _IOR(BTRFS_IOCTL_MAGIC, 63, __u64)
>
> #endif /* _UAPI_LINUX_BTRFS_H */
>
Attachment:
signature.asc
Description: OpenPGP digital signature
