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 <jo...@toxicpanda.com>
> ---
> 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

Reply via email to