From patchwork Mon Mar 21 00:33:34 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mason X-Patchwork-Id: 647001 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 p2L0YvKe004575 for ; Mon, 21 Mar 2011 00:34:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752335Ab1CUAeo (ORCPT ); Sun, 20 Mar 2011 20:34:44 -0400 Received: from rcsinet10.oracle.com ([148.87.113.121]:62091 "EHLO rcsinet10.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752223Ab1CUAen (ORCPT ); Sun, 20 Mar 2011 20:34:43 -0400 Received: from acsinet15.oracle.com (acsinet15.oracle.com [141.146.126.227]) by rcsinet10.oracle.com (Switch-3.4.2/Switch-3.4.2) with ESMTP id p2L0YM9n025470 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 21 Mar 2011 00:34:23 GMT Received: from acsmt356.oracle.com (acsmt356.oracle.com [141.146.40.156]) by acsinet15.oracle.com (Switch-3.4.2/Switch-3.4.1) with ESMTP id p2L0YKaT001946 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 21 Mar 2011 00:34:20 GMT Received: from abhmt004.oracle.com (abhmt004.oracle.com [141.146.116.13]) by acsmt356.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id p2L0YJWV010641; Sun, 20 Mar 2011 19:34:19 -0500 Received: from localhost (/66.66.148.185) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 20 Mar 2011 17:34:19 -0700 From: Chris Mason To: Miao Xie Cc: Linux Btrfs , David Sterba , Ito , Itaru Kitayama Subject: Re: [PATCH V4] btrfs: implement delayed inode items operation In-reply-to: <4D8324DE.4010400@cn.fujitsu.com> References: <4D8324DE.4010400@cn.fujitsu.com> Date: Sun, 20 Mar 2011 20:33:34 -0400 Message-Id: <1300666966-sup-3510@think> User-Agent: Sup/git X-Source-IP: acsmt356.oracle.com [141.146.40.156] X-Auth-Type: Internal IP X-CT-RefId: str=0001.0A090204.4D869D0D.00B3,ss=1,fgs=0 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]); Mon, 21 Mar 2011 00:34:57 +0000 (UTC) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 727d9a8..02e9390 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -32,7 +32,8 @@ int __init btrfs_delayed_inode_init(void) delayed_node_cache = kmem_cache_create("delayed_node", sizeof(struct btrfs_delayed_node), 0, - SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, + SLAB_RECLAIM_ACCOUNT | + SLAB_MEM_SPREAD | SLAB_DESTROY_BY_RCU, NULL); if (!delayed_node_cache) return -ENOMEM; @@ -90,22 +91,35 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( struct btrfs_inode *btrfs_inode = BTRFS_I(inode); struct btrfs_root *root = btrfs_inode->root; - if (btrfs_inode->delayed_node) { - node = btrfs_inode->delayed_node; - atomic_inc(&node->refs); /* can be accessed */ - return node; +again: + rcu_read_lock(); +again_rcu: + node = btrfs_inode->delayed_node; + if (node) { + if (atomic_inc_not_zero(&node->refs)) { + rcu_read_unlock(); + return node; + } +printk("racing on node access!\n"); + goto again_rcu; } + rcu_read_unlock(); node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS); if (!node) return ERR_PTR(-ENOMEM); btrfs_init_delayed_node(node, root->objectid, inode->i_ino); - btrfs_inode->delayed_node = node; node->delayed_root = btrfs_get_delayed_root(root); atomic_inc(&node->refs); /* cached in the btrfs inode */ atomic_inc(&node->refs); /* can be accessed */ + if (cmpxchg(&BTRFS_I(inode)->delayed_node, NULL, node)) { + kmem_cache_free(delayed_node_cache, node); +printk("racing on new node insertion!\n"); + goto again; + } + return node; } @@ -1167,7 +1181,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) nr = trans->blocks_used; btrfs_end_transaction_dmeta(trans, root); - btrfs_btree_balance_dirty(root, nr); + __btrfs_btree_balance_dirty(root, nr); free_path: btrfs_free_path(path); out: diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0f589b1..0c6c336 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2649,6 +2649,28 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) balance_dirty_pages_ratelimited_nr( root->fs_info->btree_inode->i_mapping, 1); } + btrfs_balance_delayed_items(root); + return; +} + +void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) +{ + /* + * looks as though older kernels can get into trouble with + * this code, they end up stuck in balance_dirty_pages forever + */ + u64 num_dirty; + unsigned long thresh = 32 * 1024 * 1024; + + if (current->flags & PF_MEMALLOC) + return; + + num_dirty = root->fs_info->dirty_metadata_bytes; + + if (num_dirty > thresh) { + balance_dirty_pages_ratelimited_nr( + root->fs_info->btree_inode->i_mapping, 1); + } return; } diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 07b20dc..aca35af 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -71,6 +71,7 @@ int btrfs_insert_dev_radix(struct btrfs_root *root, u64 block_start, u64 num_blocks); void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); +void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); void btrfs_mark_buffer_dirty(struct extent_buffer *buf); void btrfs_mark_buffer_dirty_nonblocking(struct extent_buffer *buf); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6b238b2..ef240d8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4449,6 +4449,8 @@ void btrfs_dirty_inode(struct inode *inode) } } btrfs_end_transaction(trans, root); + if (BTRFS_I(inode)->delayed_node) + btrfs_balance_delayed_items(root); } /* diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 31b328b..8f0ca33 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -483,8 +483,6 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, ret = __btrfs_end_transaction(trans, root, 0, 1); if (ret) return ret; - - btrfs_balance_delayed_items(root); return 0; } @@ -496,8 +494,6 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, ret = __btrfs_end_transaction(trans, root, 1, 1); if (ret) return ret; - - btrfs_balance_delayed_items(root); return 0; } @@ -509,8 +505,6 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans, ret = __btrfs_end_transaction(trans, root, 0, 0); if (ret) return ret; - - btrfs_balance_delayed_items(root); return 0; }