On Sun, May 21, 2017 at 6:39 PM, Qu Wenruo <[email protected]> wrote:
>
>
> At 05/20/2017 04:39 PM, Sargun Dhillon wrote:
>>
>> This patch is to prepare for following patches in this patchset. The
>> purpose is to make it so that we can prevent accidental removal of
>> qgroups that are actively in use.
>>
>> Signed-off-by: Sargun Dhillon <[email protected]>
>> ---
>>   fs/btrfs/ioctl.c  |  4 ++--
>>   fs/btrfs/qgroup.c | 50
>> +++++++++++++++++++++++++++++++++++++++++++++++++-
>>   fs/btrfs/qgroup.h |  3 ++-
>>   3 files changed, 53 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
>> index b10d7bb..2b1a8c1 100644
>> --- a/fs/btrfs/ioctl.c
>> +++ b/fs/btrfs/ioctl.c
>> @@ -2554,7 +2554,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct
>> file *file,
>>          */
>>         if (!btrfs_test_opt(fs_info, QGROUP_KEEP)) {
>>                 ret = btrfs_remove_qgroup(trans, fs_info,
>> -                                         dest->root_key.objectid);
>> +                                         dest->root_key.objectid, 0);
>>                 if (ret && ret != -ENOENT)
>>                         pr_info("Could not automatically delete qgroup:
>> %d\n", ret);
>>         }
>> @@ -4974,7 +4974,7 @@ static long btrfs_ioctl_qgroup_create(struct file
>> *file, void __user *arg)
>>         if (sa->create) {
>>                 ret = btrfs_create_qgroup(trans, fs_info, sa->qgroupid);
>>         } else {
>> -               ret = btrfs_remove_qgroup(trans, fs_info, sa->qgroupid);
>> +               ret = btrfs_remove_qgroup(trans, fs_info, sa->qgroupid,
>> 0);
>>         }
>>         err = btrfs_end_transaction(trans);
>> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
>> index 588248b..a0699fd 100644
>> --- a/fs/btrfs/qgroup.c
>> +++ b/fs/btrfs/qgroup.c
>> @@ -1247,6 +1247,45 @@ int btrfs_del_qgroup_relation(struct
>> btrfs_trans_handle *trans,
>>         return ret;
>>   }
>>   +/*
>> + * Meant to only operate on level-0 qroupid.
>> + *
>> + * It returns 1 if a matching subvolume is found; 0 if none is found.
>> + * < 0 if there is an error.
>> + */
>> +static int btrfs_subvolume_exists(struct btrfs_fs_info *fs_info, u64
>> qgroupid)
>> +{
>> +       struct btrfs_path *path;
>> +       struct btrfs_key key;
>> +       int err, ret = 0;
>> +
>> +       path = btrfs_alloc_path();
>> +       if (!path)
>> +               return -ENOMEM;
>> +
>> +       key.objectid = qgroupid;
>> +       key.type = BTRFS_ROOT_BACKREF_KEY;
>
>
> Fs root (subvolume id equals to 5) has no ROOT_BACKREF key.
> Such search would make fs tree always treated as not existed.
Is it okay to just explicitly exempt 5, or is there a better way to do
this search?

>
> Thanks,
> Qu
>
>> +       key.offset = 0;
>> +
>> +       err = btrfs_search_slot_for_read(fs_info->tree_root, &key, path,
>> 1, 0);
>> +       if (err == 1)
>> +               goto out;
>> +
>> +       if (err) {
>> +               ret = err;
>> +               goto out;
>> +       }
>> +
>> +       btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
>> +       if (key.objectid != qgroupid || key.type !=
>> BTRFS_ROOT_BACKREF_KEY)
>> +               goto out;
>> +
>> +       ret = 1;
>> +out:
>> +       btrfs_free_path(path);
>> +       return ret;
>> +}
>> +
>>   /* Must be called with qgroup_ioctl_lock held */
>>   static int __btrfs_create_qgroup(struct btrfs_trans_handle *trans,
>>                                  struct btrfs_fs_info *fs_info, u64
>> qgroupid)
>> @@ -1333,10 +1372,19 @@ static int __btrfs_remove_qgroup(struct
>> btrfs_trans_handle *trans,
>>   }
>>     int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
>> -                       struct btrfs_fs_info *fs_info, u64 qgroupid)
>> +                       struct btrfs_fs_info *fs_info, u64 qgroupid,
>> +                       int check_in_use)
>>   {
>>         int ret;
>>   +     if (check_in_use && btrfs_qgroup_level(qgroupid) == 0) {
>> +               ret = btrfs_subvolume_exists(fs_info, qgroupid);
>> +               if (ret < 0)
>> +                       return ret;
>> +               if (ret)
>> +                       return -EBUSY;
>> +       }
>> +
>>         mutex_lock(&fs_info->qgroup_ioctl_lock);
>>         ret = __btrfs_remove_qgroup(trans, fs_info, qgroupid);
>>         mutex_unlock(&fs_info->qgroup_ioctl_lock);
>> diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
>> index fb6c7da..fc08bdb 100644
>> --- a/fs/btrfs/qgroup.h
>> +++ b/fs/btrfs/qgroup.h
>> @@ -127,7 +127,8 @@ int btrfs_del_qgroup_relation(struct
>> btrfs_trans_handle *trans,
>>   int btrfs_create_qgroup(struct btrfs_trans_handle *trans,
>>                         struct btrfs_fs_info *fs_info, u64 qgroupid);
>>   int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
>> -                       struct btrfs_fs_info *fs_info, u64 qgroupid);
>> +                       struct btrfs_fs_info *fs_info, u64 qgroupid,
>> +                       int check_in_use);
>>   int btrfs_limit_qgroup(struct btrfs_trans_handle *trans,
>>                        struct btrfs_fs_info *fs_info, u64 qgroupid,
>>                        struct btrfs_qgroup_limit *limit);
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to