From patchwork Sat Sep 18 13:15:15 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goffredo Baroncelli X-Patchwork-Id: 189712 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o8IDCAdY007928 for ; Sat, 18 Sep 2010 13:12:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754387Ab0IRNMH (ORCPT ); Sat, 18 Sep 2010 09:12:07 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:52528 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753613Ab0IRNMG (ORCPT ); Sat, 18 Sep 2010 09:12:06 -0400 Received: by wwb39 with SMTP id 39so1892901wwb.1 for ; Sat, 18 Sep 2010 06:12:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:reply-to:to:subject:date :user-agent:references:in-reply-to:mime-version:content-type :content-transfer-encoding:message-id; bh=WNLGcnHFvZPWQA8Rkj7OUY7CZtq5F3NuzIB+e9uQ8oY=; b=TIRUWYVoyG71ovzUzg5pnq9rgQrfcq/mrvksGqOcghrmeWuS/k8FE+oycBMmJlPpUq SIyq/Z9PG1mOkf19pa9dDGM5WHHaRqfu4CvoTc6FgBm86FoZhm/CfGNgI5WTb5SFwNJf XxTB1IbW++SJaNRHX92noV0AMim+ziUIO21ds= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:reply-to:to:subject:date:user-agent:references:in-reply-to :mime-version:content-type:content-transfer-encoding:message-id; b=KtTlSym56p/Kc3dqjs7G5gA7U73yeO94hVyjLfjwhg9IWye/U0ftG/rca8DAs6wtnB Nk0mCu6VSxWvOuq/pvCPMTBIVjqqPiB9FCGPKHZPd6JCRU+rLfibnXWkTznhWBhnTbXq MVzkKQncwQ3Kf2z2z+s9JzcazrAkvNTj1vLJE= Received: by 10.216.17.78 with SMTP id i56mr5577436wei.91.1284815523930; Sat, 18 Sep 2010 06:12:03 -0700 (PDT) Received: from venice.localnet (host132-225-dynamic.11-87-r.retail.telecomitalia.it [87.11.225.132]) by mx.google.com with ESMTPS id b10sm3619251wer.17.2010.09.18.06.12.01 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 18 Sep 2010 06:12:02 -0700 (PDT) From: Goffredo Baroncelli Reply-To: kreijack@libero.it To: linux-btrfs@vger.kernel.org Subject: Re: [RFC] Removing a subvolume by an ordinary user Date: Sat, 18 Sep 2010 15:15:15 +0200 User-Agent: KMail/1.13.5 (Linux/2.6.35-trunk-amd64; KDE/4.4.5; x86_64; ; ) References: <6546544.196961284637653794.JavaMail.defaultUser@defaultHost> In-Reply-To: <6546544.196961284637653794.JavaMail.defaultUser@defaultHost> MIME-Version: 1.0 Message-Id: <201009181515.23436.kreijack@libero.it> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sat, 18 Sep 2010 13:12:10 +0000 (UTC) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f08427c..47d11d8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2944,6 +2944,86 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, return 0; } +int may_destroy_subvol(struct btrfs_root *root); +static noinline int btrfs_snap_destroy(struct inode *dir, + struct dentry *dentry) + +{ + + struct inode *inode; + struct btrfs_root *root = BTRFS_I(dir)->root; + struct btrfs_root *dest = NULL; + struct btrfs_trans_handle *trans; + + int ret; + int err = 0; + + + if (IS_ERR(dentry)) { + err = PTR_ERR(dentry); + goto out; + } + + if (!dentry->d_inode) { + err = -ENOENT; + goto out; + } + + inode = dentry->d_inode; + if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) { + err = -EINVAL; + goto out; + } + + dest = BTRFS_I(inode)->root; + + down_write(&root->fs_info->subvol_sem); + + err = may_destroy_subvol(dest); + if (err) + goto out_up_write; + + trans = btrfs_start_transaction(root, 0); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out_up_write; + } + trans->block_rsv = &root->fs_info->global_block_rsv; + + ret = btrfs_unlink_subvol(trans, root, dir, + dest->root_key.objectid, + dentry->d_name.name, + dentry->d_name.len); + BUG_ON(ret); + + btrfs_record_root_in_trans(trans, dest); + + memset(&dest->root_item.drop_progress, 0, + sizeof(dest->root_item.drop_progress)); + dest->root_item.drop_level = 0; + btrfs_set_root_refs(&dest->root_item, 0); + + if (!xchg(&dest->orphan_item_inserted, 1)) { + ret = btrfs_insert_orphan_item(trans, + root->fs_info->tree_root, + dest->root_key.objectid); + BUG_ON(ret); + } + + ret = btrfs_commit_transaction(trans, root); + BUG_ON(ret); + inode->i_flags |= S_DEAD; +out_up_write: + up_write(&root->fs_info->subvol_sem); + if (!err) { + shrink_dcache_sb(root->fs_info->sb); + btrfs_invalidate_inodes(dest); + /*d_delete(dentry);*/ + } +out: + return err; +} + static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; @@ -2952,10 +3032,12 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) struct btrfs_trans_handle *trans; unsigned long nr = 0; - if (inode->i_size > BTRFS_EMPTY_DIR_SIZE || - inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) + if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) return -ENOTEMPTY; + if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) + return btrfs_snap_destroy(dir, dentry); + trans = __unlink_start_trans(dir, dentry); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -4242,7 +4324,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, over = filldir(dirent, name_ptr, name_len, found_key.offset, location.objectid, d_type); - skip: if (name_ptr != tmp_name) kfree(name_ptr); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9254b3d..a7b242e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -855,7 +855,7 @@ out: /* * helper to check if the subvolume references other subvolumes */ -static noinline int may_destroy_subvol(struct btrfs_root *root) +int may_destroy_subvol(struct btrfs_root *root) { struct btrfs_path *path; struct btrfs_key key;