From patchwork Fri Apr 22 10:12:24 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miao Xie X-Patchwork-Id: 726761 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 p3MA7Et4031541 for ; Fri, 22 Apr 2011 10:07:15 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754803Ab1DVKHM (ORCPT ); Fri, 22 Apr 2011 06:07:12 -0400 Received: from cn.fujitsu.com ([222.73.24.84]:65509 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1754350Ab1DVKHI (ORCPT ); Fri, 22 Apr 2011 06:07:08 -0400 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 8A3F2170129; Fri, 22 Apr 2011 18:07:06 +0800 (CST) Received: from mailserver.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id p3MA76iL002728; Fri, 22 Apr 2011 18:07:06 +0800 Received: from [10.167.225.64] ([10.167.225.64]) by mailserver.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.1FP4) with ESMTP id 2011042218073772-126023 ; Fri, 22 Apr 2011 18:07:37 +0800 Message-ID: <4DB15488.50005@cn.fujitsu.com> Date: Fri, 22 Apr 2011 18:12:24 +0800 From: Miao Xie Reply-To: miaox@cn.fujitsu.com User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100921 Fedora/3.1.4-1.fc14 Thunderbird/3.1.4 MIME-Version: 1.0 To: Chris Mason CC: Linux Btrfs Subject: [PATCH V6 3/3] btrfs: delay to insert the initial inode X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2011-04-22 18:07:37, Serialize by Router on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2011-04-22 18:07:37, Serialize complete at 2011-04-22 18:07:37 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.6 (demeter1.kernel.org [140.211.167.41]); Fri, 22 Apr 2011 10:07:15 +0000 (UTC) Since we have implemented the delayed update of the inode, we can also delayed to insert the initial inode, then we can merge the inode update and the initial inode insertions to one insertion. Signed-off-by: Miao Xie --- fs/btrfs/delayed-inode.c | 18 +++++++++-- fs/btrfs/delayed-inode.h | 8 ++++- fs/btrfs/inode.c | 74 +++++++++++++++++++++++++++++++-------------- 3 files changed, 72 insertions(+), 28 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 9548531..dd62b7b 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -979,12 +979,20 @@ static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, key.objectid = node->inode_id; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); key.offset = 0; - ret = btrfs_lookup_inode(trans, root, path, &key, 1); + if (node->inode_dirty == BTRFS_INODE_UPDATE) { + ret = btrfs_lookup_inode(trans, root, path, &key, 1); + } else if (node->inode_dirty == BTRFS_INODE_NEW) + ret = btrfs_insert_empty_item(trans, root, path, &key, + sizeof(*inode_item)); + else + BUG(); if (ret > 0) { btrfs_release_path(root, path); mutex_unlock(&node->mutex); return -ENOENT; } else if (ret < 0) { + WARN_ON(ret == -EEXIST && node->inode_dirty == BTRFS_INODE_NEW); + btrfs_release_path(root, path); mutex_unlock(&node->mutex); return ret; } @@ -1591,7 +1599,8 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, } int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode) + struct btrfs_root *root, struct inode *inode, + bool new_ino) { struct btrfs_delayed_node *delayed_node; int ret; @@ -1614,7 +1623,10 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, BUG_ON(ret); fill_stack_inode_item(trans, &delayed_node->inode_item, inode); - delayed_node->inode_dirty = 1; + if (new_ino) + delayed_node->inode_dirty = BTRFS_INODE_NEW; + else + delayed_node->inode_dirty = BTRFS_INODE_UPDATE; delayed_node->count++; atomic_inc(&root->fs_info->delayed_root->items); release_node: diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index eb7d240..79b009f 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -33,6 +33,9 @@ #define BTRFS_DELAYED_INSERTION_ITEM 1 #define BTRFS_DELAYED_DELETION_ITEM 2 +#define BTRFS_INODE_NEW 1 +#define BTRFS_INODE_UPDATE 2 + struct btrfs_delayed_root { spinlock_t lock; struct list_head node_list; @@ -64,8 +67,8 @@ struct btrfs_delayed_node { struct btrfs_inode_item inode_item; atomic_t refs; u64 index_cnt; + u8 inode_dirty; bool in_list; - bool inode_dirty; int count; }; @@ -119,7 +122,8 @@ void btrfs_kill_delayed_inode_items(struct inode *inode); int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode); + struct btrfs_root *root, struct inode *inode, + bool new_ino); /* Used for drop dead root */ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a79ff72..29671f3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2648,11 +2648,11 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, /* * If root is tree root, it means this inode is used to * store free space information. And these inodes are updated - * when committing the transaction, so they needn't delaye to + * when committing the transaction, so they needn't delayed to * be updated, or deadlock will occured. */ if (likely(root != root->fs_info->tree_root)) { - ret = btrfs_delayed_update_inode(trans, root, inode); + ret = btrfs_delayed_update_inode(trans, root, inode, false); if (!ret) btrfs_set_inode_last_trans(trans, inode); return ret; @@ -4578,6 +4578,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, path = btrfs_alloc_path(); BUG_ON(!path); + path->leave_spinning = 1; + inode = new_inode(root->fs_info->sb); if (!inode) { btrfs_free_path(path); @@ -4612,32 +4614,58 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, alloc_hint, owner); - key[0].objectid = objectid; - btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); - key[0].offset = 0; - - key[1].objectid = objectid; - btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY); - key[1].offset = ref_objectid; - - sizes[0] = sizeof(struct btrfs_inode_item); - sizes[1] = name_len + sizeof(*ref); - - path->leave_spinning = 1; - ret = btrfs_insert_empty_items(trans, root, path, key, sizes, 2); - if (ret != 0) - goto fail; - inode_init_owner(inode, dir, mode); inode->i_ino = objectid; inode_set_bytes(inode, 0); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], - struct btrfs_inode_item); - fill_inode_item(trans, path->nodes[0], inode_item, inode); + /* + * If root is not tree root, the inode is a inode of file or directory, + * which we can delay to insert. + */ + if (root == root->fs_info->tree_root) { + key[0].objectid = objectid; + btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); + key[0].offset = 0; + + key[1].objectid = objectid; + btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY); + key[1].offset = ref_objectid; + + sizes[0] = sizeof(struct btrfs_inode_item); + sizes[1] = name_len + sizeof(*ref); + + ret = btrfs_insert_empty_items(trans, root, path, key, sizes, + 2); + if (ret != 0) + goto fail; + + inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_item); + fill_inode_item(trans, path->nodes[0], inode_item, inode); + + ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1, + struct btrfs_inode_ref); + } else { + ret = btrfs_delayed_update_inode(trans, root, inode, true); + if (ret) + goto fail; + + key[0].objectid = objectid; + btrfs_set_key_type(&key[0], BTRFS_INODE_REF_KEY); + key[0].offset = ref_objectid; + + sizes[0] = name_len + sizeof(*ref); + + ret = btrfs_insert_empty_item(trans, root, path, key, sizes[0]); + if (ret) { + btrfs_kill_delayed_inode_items(inode); + goto fail; + } + + ref = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_ref); + } - ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1, - struct btrfs_inode_ref); btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); btrfs_set_inode_ref_index(path->nodes[0], ref, *index); ptr = (unsigned long)(ref + 1);