From patchwork Wed Apr 17 14:49:51 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Shilong X-Patchwork-Id: 2453951 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 326C03FD8C for ; Wed, 17 Apr 2013 14:50:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966655Ab3DQOui (ORCPT ); Wed, 17 Apr 2013 10:50:38 -0400 Received: from mail-pd0-f178.google.com ([209.85.192.178]:62912 "EHLO mail-pd0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S966531Ab3DQOuh (ORCPT ); Wed, 17 Apr 2013 10:50:37 -0400 Received: by mail-pd0-f178.google.com with SMTP id w11so902571pde.23 for ; Wed, 17 Apr 2013 07:50:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer; bh=bInT5/laYESMSCS+mIC5el6orLLUH2jzefxJRauypp0=; b=KKeMDDsL8DQ2SLy3LQ8yLbkttbQDwM7jEqvUHCq8QCzm4+QpEr1GOYwHpKKP/FthWQ tfCM0U23YmATErNjqcUsC+2PWaawWmm83aK0guOVfhJsznatjx2AS7bjdIHKsGJhswUE dYH56VrAj0QQoNVvCODNQHTgF+Np5cl4wVCmALW8D3WBfOrZgTCA13gVyjhxet4mPtkU d190hxIXaFHKUtMaFHMUphCsq2siBnBwX5etoah6g0c/goozdde2o5PWPudjHUo5qmnA +jqzF8jemAPvw5bMB0X1xz5UqT14BgXOrht+2aa8G0Q6d/eoh2WxVzFfX8wuEPdNBsMY zvRg== X-Received: by 10.68.222.165 with SMTP id qn5mr9490736pbc.54.1366210236890; Wed, 17 Apr 2013 07:50:36 -0700 (PDT) Received: from localhost.localdomain.localdomain ([112.2.228.143]) by mx.google.com with ESMTPS id ts3sm6555118pbc.12.2013.04.17.07.50.34 (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 17 Apr 2013 07:50:36 -0700 (PDT) From: Wang Shilong To: linux-btrfs@vger.kernel.org Cc: Wang Shilong Subject: [PATCH] Btrfs: add all ioctl checks before user change for quota operations Date: Wed, 17 Apr 2013 22:49:51 +0800 Message-Id: <1366210191-7456-1-git-send-email-wangshilong1991@gmail.com> X-Mailer: git-send-email 1.7.11.7 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org From: Wang Shilong Since all the quota configurations are loaded in memory, and we can have ioctl checks before operating in the disk. It is safe to do such things because qgroup_ioctl_lock is held outside. Without these extra checks firstly, it should be ok to do user change for quota operations. For example: if we want to add an existed qgroup, we will do: ->add_qgroup_item() ->add_qgroup_rb() add_qgroup_item() will return -EEXIST to us, however, qgroups are all in memory, why not check them in memory firstly. Signed-off-by: Wang Shilong --- Since this patch relies on my previous patchset, so it is based on the latest btrfs-next branch. --- fs/btrfs/qgroup.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index f9fb52e..f175471 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -956,6 +956,7 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, struct btrfs_root *quota_root; struct btrfs_qgroup *parent; struct btrfs_qgroup *member; + struct btrfs_qgroup_list *list; int ret = 0; mutex_lock(&fs_info->qgroup_ioctl_lock); @@ -971,6 +972,14 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, goto out; } + /* check if such qgroup relation exist firstly */ + list_for_each_entry(list, &member->groups, next_group) { + if (list->group == parent) { + ret = -EEXIST; + goto out; + } + } + ret = add_qgroup_relation_item(trans, quota_root, src, dst); if (ret) goto out; @@ -993,6 +1002,9 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 src, u64 dst) { struct btrfs_root *quota_root; + struct btrfs_qgroup *parent; + struct btrfs_qgroup *member; + struct btrfs_qgroup_list *list; int ret = 0; int err; @@ -1003,6 +1015,21 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, goto out; } + member = find_qgroup_rb(fs_info, src); + parent = find_qgroup_rb(fs_info, dst); + if (!member || !parent) { + ret = -EINVAL; + goto out; + } + + /* check if such qgroup relation exist firstly */ + list_for_each_entry(list, &member->groups, next_group) { + if (list->group == parent) + goto exist; + } + ret = -ENOENT; + goto out; +exist: ret = del_qgroup_relation_item(trans, quota_root, src, dst); err = del_qgroup_relation_item(trans, quota_root, dst, src); if (err && !ret) @@ -1010,7 +1037,6 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, spin_lock(&fs_info->qgroup_lock); del_relation_rb(fs_info, src, dst); - spin_unlock(&fs_info->qgroup_lock); out: mutex_unlock(&fs_info->qgroup_ioctl_lock); @@ -1030,8 +1056,15 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, ret = -EINVAL; goto out; } + qgroup = find_qgroup_rb(fs_info, qgroupid); + if (qgroup) { + ret = -EEXIST; + goto out; + } ret = add_qgroup_item(trans, quota_root, qgroupid); + if (ret) + goto out; spin_lock(&fs_info->qgroup_lock); qgroup = add_qgroup_rb(fs_info, qgroupid); @@ -1058,15 +1091,18 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, goto out; } - /* check if there are no relations to this qgroup */ qgroup = find_qgroup_rb(fs_info, qgroupid); - if (qgroup) { - if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) { + if (!qgroup) { + ret = -ENOENT; + goto out; + } else { + /* check if there are no relations to this qgroup */ + if (!list_empty(&qgroup->groups) || + !list_empty(&qgroup->members)) { ret = -EBUSY; goto out; } } - ret = del_qgroup_item(trans, quota_root, qgroupid); spin_lock(&fs_info->qgroup_lock);