From patchwork Tue Mar 27 07:06:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lu Fengqi X-Patchwork-Id: 10309377 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 33FE860325 for ; Tue, 27 Mar 2018 07:07:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1807D29BB6 for ; Tue, 27 Mar 2018 07:07:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0CDDE29BB8; Tue, 27 Mar 2018 07:07:20 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 7818729BB9 for ; Tue, 27 Mar 2018 07:07:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752086AbeC0HHS (ORCPT ); Tue, 27 Mar 2018 03:07:18 -0400 Received: from mail.cn.fujitsu.com ([183.91.158.132]:35533 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752055AbeC0HHQ (ORCPT ); Tue, 27 Mar 2018 03:07:16 -0400 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="38221612" Received: from localhost (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 27 Mar 2018 15:07:08 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id C40E94D0EFF5 for ; Tue, 27 Mar 2018 15:07:07 +0800 (CST) Received: from fnst.localdomain (10.167.226.155) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.361.1; Tue, 27 Mar 2018 15:07:10 +0800 From: Lu Fengqi To: Subject: [PATCH v2 02/10] btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol Date: Tue, 27 Mar 2018 15:06:50 +0800 Message-ID: <20180327070658.13064-3-lufq.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180327070658.13064-1-lufq.fnst@cn.fujitsu.com> References: <20180327070658.13064-1-lufq.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.226.155] X-yoursite-MailScanner-ID: C40E94D0EFF5.ACD18 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: lufq.fnst@cn.fujitsu.com 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 The original btrfs_mksubvol is too specific to specify the directory that the subvolume will link to. Furthermore, in this transaction, we don't only need to create root_ref/dir-item, but also update the refs or flags of root_item. Extract a generic btrfs_link_subvol that allow the caller pass a trans argument for later subvolume undelete. No functional changes for the btrfs_mksubvol. Signed-off-by: Lu Fengqi --- convert/main.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ctree.h | 5 +++-- inode.c | 46 +++++++++++++++++++++------------------------- 3 files changed, 81 insertions(+), 27 deletions(-) diff --git a/convert/main.c b/convert/main.c index 6bdfab40d0b0..dd6b42a1f2b1 100644 --- a/convert/main.c +++ b/convert/main.c @@ -1002,6 +1002,63 @@ err: return ret; } +/* + * Link the subvolume specified by @root_objectid to the root_dir of @root. + * + * @root the root of the file tree which the subvolume will + * be linked to. + * @subvol_name the name of the subvolume which will be linked. + * @root_objectid specify the subvolume which will be linked. + * @convert the flag to determine whether to try to resolve + * the name conflict. + * + * Return the root of the subvolume if success, otherwise return NULL. + */ +static struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, + const char *subvol_name, + u64 root_objectid, + bool convert) +{ + struct btrfs_trans_handle *trans; + struct btrfs_root *subvol_root = NULL; + struct btrfs_key key; + u64 dirid = btrfs_root_dirid(&root->root_item); + int ret; + + + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + error("unable to start transaction"); + goto fail; + } + + ret = btrfs_link_subvol(trans, root, subvol_name, root_objectid, dirid, + true); + if (ret) { + error("unable to link subvolume %s", subvol_name); + goto fail; + } + + ret = btrfs_commit_transaction(trans, root); + if (ret) { + error("transaction commit failed: %d", ret); + goto fail; + } + + key.objectid = root_objectid; + key.offset = (u64)-1; + key.type = BTRFS_ROOT_ITEM_KEY; + + subvol_root = btrfs_read_fs_root(root->fs_info, &key); + if (!subvol_root) { + error("unable to link subvolume %s", subvol_name); + goto fail; + } + +fail: + return subvol_root; +} + /* * Migrate super block to its default position and zero 0 ~ 16k */ diff --git a/ctree.h b/ctree.h index 0fc31dd8d998..4bff0b821472 100644 --- a/ctree.h +++ b/ctree.h @@ -2797,8 +2797,9 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 offset); int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root, char *name, int namelen, u64 parent_ino, u64 *ino, int mode); -struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, const char *base, - u64 root_objectid, bool convert); +int btrfs_link_subvol(struct btrfs_trans_handle *trans, struct btrfs_root *root, + const char *base, u64 root_objectid, u64 dirid, + bool convert); /* file.c */ int btrfs_get_extent(struct btrfs_trans_handle *trans, diff --git a/inode.c b/inode.c index 8d0812c7cf50..478036562652 100644 --- a/inode.c +++ b/inode.c @@ -606,19 +606,28 @@ out: return ret; } -struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, - const char *base, u64 root_objectid, - bool convert) +/* + * Link the subvolume specified by @root_objectid to the directory specified by + * @dirid on the file tree specified by @root. + * + * @root the root of the file tree where the directory on. + * @base the name of the subvolume which will be linked. + * @root_objectid specify the subvolume which will be linked. + * @dirid specify the directory which the subvolume will be + * linked to. + * @convert the flag to determine whether to try to resolve + * the name conflict. + */ +int btrfs_link_subvol(struct btrfs_trans_handle *trans, struct btrfs_root *root, + const char *base, u64 root_objectid, u64 dirid, + bool convert) { - struct btrfs_trans_handle *trans; struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *tree_root = fs_info->tree_root; - struct btrfs_root *new_root = NULL; struct btrfs_path path; struct btrfs_inode_item *inode_item; struct extent_buffer *leaf; struct btrfs_key key; - u64 dirid = btrfs_root_dirid(&root->root_item); u64 index = 2; char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */ int len; @@ -627,8 +636,9 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, len = strlen(base); if (len == 0 || len > BTRFS_NAME_LEN) - return NULL; + return -EINVAL; + /* find the free dir_index */ btrfs_init_path(&path); key.objectid = dirid; key.type = BTRFS_DIR_INDEX_KEY; @@ -649,12 +659,7 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, } btrfs_release_path(&path); - trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { - error("unable to start transaction"); - goto fail; - } - + /* add the dir_item/dir_index */ key.objectid = dirid; key.offset = 0; key.type = BTRFS_INODE_ITEM_KEY; @@ -675,6 +680,7 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, memcpy(buf, base, len); if (convert) { + /* try to resolve name conflict by adding the number suffix */ for (i = 0; i < 1024; i++) { ret = btrfs_insert_dir_item(trans, root, buf, len, dirid, &key, BTRFS_FT_DIR, index); @@ -719,18 +725,8 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, goto fail; } - ret = btrfs_commit_transaction(trans, root); - if (ret) { - error("transaction commit failed: %d", ret); - goto fail; - } - new_root = btrfs_read_fs_root(fs_info, &key); - if (IS_ERR(new_root)) { - error("unable to fs read root: %lu", PTR_ERR(new_root)); - new_root = NULL; - } fail: - btrfs_init_path(&path); - return new_root; + btrfs_release_path(&path); + return ret; }