From patchwork Sat May 20 08:39:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 9738531 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C42D26034C for ; Sat, 20 May 2017 08:40:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8D30285C8 for ; Sat, 20 May 2017 08:40:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ADB79285D4; Sat, 20 May 2017 08:40:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 498D9285C8 for ; Sat, 20 May 2017 08:40:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755719AbdETIj6 (ORCPT ); Sat, 20 May 2017 04:39:58 -0400 Received: from mail-it0-f47.google.com ([209.85.214.47]:34977 "EHLO mail-it0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755699AbdETIjs (ORCPT ); Sat, 20 May 2017 04:39:48 -0400 Received: by mail-it0-f47.google.com with SMTP id c15so130147139ith.0 for ; Sat, 20 May 2017 01:39:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=date:from:to:subject:message-id:mime-version:content-disposition :user-agent; bh=dgm0zs16VvbxsTZtxgoJMFYtNOPY6uS4RHh1LFYZjh4=; b=Yyj7wAHGpBT6Qx1tMXJyxYH7DFEEfWdIP1yNQllXVFa2LqyPjHUeRtgpIono6zca1t B0P/jx8WFbM7p9NLl8DeZqhzHS74CNOomvSbjJ3cmSXGX4W50LnqRskWuN0wM6IDZNnD DS2Qnp2vG+haXK1+01K+hMRODiA1devjNrJoQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition:user-agent; bh=dgm0zs16VvbxsTZtxgoJMFYtNOPY6uS4RHh1LFYZjh4=; b=rZiRDZWvWWDyHTCFe3/IkSUlkLfNj343LiRnKr13y2qgKuetVuAOR5RFL/1xV+n5db 0LWZgJt+pB4zsTUhLip1pyjNlyBqZthvmfZpiTg43XV1zbSgpNrFgw5hcg2EVc93lkgd 6f7Hc8A95Tbk4CqaMjMe1lovyo8tz0yQdAcD+GEbvKs+NjGVp6V0so47NjsFEl19ovwZ DgFaWs8ZC3oRWSmJMt0M3Q2bWm3uMrvVXe7DjXxyBU7xwL3Qa9ajkMB3tsiqWLC7bOKE HZTgD3eu7iJ3HCMT49ZADrR77LFWUQXnziNDwgO1U+yQrLY40Ip19gq0Ka8DXSVekjvs naig== X-Gm-Message-State: AODbwcC2e6gEBMw6A+vdcvzSeiQIg1rNf0QFJlcpoELLlULaG9HQXTAC 4ZfaQaOdoPRwTQT+cBT7/Q== X-Received: by 10.36.83.147 with SMTP id n141mr34180121itb.104.1495269587691; Sat, 20 May 2017 01:39:47 -0700 (PDT) Received: from ircssh-2.c.rugged-nimbus-611.internal (80.60.198.104.bc.googleusercontent.com. [104.198.60.80]) by smtp.gmail.com with ESMTPSA id 16sm5107964itu.0.2017.05.20.01.39.47 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 20 May 2017 01:39:47 -0700 (PDT) Date: Sat, 20 May 2017 08:39:46 +0000 From: Sargun Dhillon To: linux-btrfs@vger.kernel.org Subject: [PATCH 6/8] btrfs: Add code to check if a qgroup's subvol exists Message-ID: <20170520083944.GA4244@ircssh-2.c.rugged-nimbus-611.internal> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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; + 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);