mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: npiggin@suse.de
To: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [patch 30/33] fs: inode lazy lru
Date: Fri, 04 Sep 2009 16:52:11 +1000	[thread overview]
Message-ID: <20090904065538.693437484@nick.local0.net> (raw)
In-Reply-To: <20090904065142.114706411@nick.local0.net>

[-- Attachment #1: fs-inode_lock-scale-10.patch --]
[-- Type: text/plain, Size: 6918 bytes --]

Impelemnt lazy inode lru similarly to dcache. This should reduce inode list
lock acquisition (todo: measure).
---
 fs/fs-writeback.c         |    2 -
 fs/inode.c                |   61 +++++++++++++++++++---------------------------
 include/linux/fs.h        |    7 ++++-
 include/linux/writeback.h |    1 
 4 files changed, 33 insertions(+), 38 deletions(-)

Index: linux-2.6/fs/inode.c
===================================================================
--- linux-2.6.orig/fs/inode.c
+++ linux-2.6/fs/inode.c
@@ -74,7 +74,6 @@ static unsigned int i_hash_shift __read_
  * allowing for low-overhead inode sync() operations.
  */
 
-LIST_HEAD(inode_in_use);
 LIST_HEAD(inode_unused);
 
 struct inode_hash_bucket {
@@ -273,6 +272,7 @@ void inode_init_once(struct inode *inode
 	INIT_HLIST_NODE(&inode->i_hash);
 	INIT_LIST_HEAD(&inode->i_dentry);
 	INIT_LIST_HEAD(&inode->i_devices);
+	INIT_LIST_HEAD(&inode->i_list);
 	INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
 	spin_lock_init(&inode->i_data.tree_lock);
 	spin_lock_init(&inode->i_data.i_mmap_lock);
@@ -298,24 +298,6 @@ static void init_once(void *foo)
 	inode_init_once(inode);
 }
 
-/*
- * inode_lock must be held
- */
-void __iget(struct inode *inode)
-{
-	assert_spin_locked(&inode->i_lock);
-	inode->i_count++;
-	if (inode->i_count > 1)
-		return;
-
-	if (!(inode->i_state & (I_DIRTY|I_SYNC))) {
-		spin_lock(&wb_inode_list_lock);
-		list_move(&inode->i_list, &inode_in_use);
-		spin_unlock(&wb_inode_list_lock);
-	}
-	atomic_dec(&inodes_stat.nr_unused);
-}
-
 /**
  * clear_inode - clear an inode
  * @inode: inode to clear
@@ -359,7 +341,7 @@ static void dispose_list(struct list_hea
 		struct inode *inode;
 
 		inode = list_first_entry(head, struct inode, i_list);
-		list_del(&inode->i_list);
+		list_del_init(&inode->i_list);
 
 		if (inode->i_data.nrpages)
 			truncate_inode_pages(&inode->i_data, 0);
@@ -412,11 +394,12 @@ static int invalidate_list(struct list_h
 		invalidate_inode_buffers(inode);
 		if (!inode->i_count) {
 			spin_lock(&wb_inode_list_lock);
-			list_move(&inode->i_list, dispose);
+			list_del(&inode->i_list);
 			spin_unlock(&wb_inode_list_lock);
 			WARN_ON(inode->i_state & I_NEW);
 			inode->i_state |= I_FREEING;
 			spin_unlock(&inode->i_lock);
+			list_add(&inode->i_list, dispose);
 			count++;
 			continue;
 		}
@@ -503,7 +486,13 @@ again:
 			spin_unlock(&wb_inode_list_lock);
 			goto again;
 		}
-		if (inode->i_state || inode->i_count) {
+		if (inode->i_count) {
+			list_del_init(&inode->i_list);
+			spin_unlock(&inode->i_lock);
+			atomic_dec(&inodes_stat.nr_unused);
+			continue;
+		}
+		if (inode->i_state) {
 			list_move(&inode->i_list, &inode_unused);
 			spin_unlock(&inode->i_lock);
 			continue;
@@ -519,6 +508,7 @@ again:
 again2:
 			spin_lock(&wb_inode_list_lock);
 
+			/* XXX: may no longer work well */
 			if (inode != list_entry(inode_unused.next,
 						struct inode, i_list))
 				continue;	/* wrong inode or list_empty */
@@ -667,9 +657,6 @@ __inode_add_to_lists(struct super_block
 	atomic_inc(&inodes_stat.nr_inodes);
 	list_add(&inode->i_sb_list, &sb->s_inodes);
 	spin_unlock(&sb_inode_list_lock);
-	spin_lock(&wb_inode_list_lock);
-	list_add(&inode->i_list, &inode_in_use);
-	spin_unlock(&wb_inode_list_lock);
 	if (b) {
 		spin_lock(&b->lock);
 		hlist_add_head(&inode->i_hash, &b->head);
@@ -1316,9 +1303,11 @@ void generic_delete_inode(struct inode *
 {
 	const struct super_operations *op = inode->i_sb->s_op;
 
-	spin_lock(&wb_inode_list_lock);
-	list_del_init(&inode->i_list);
-	spin_unlock(&wb_inode_list_lock);
+	if (!list_empty(&inode->i_list)) {
+		spin_lock(&wb_inode_list_lock);
+		list_del_init(&inode->i_list);
+		spin_unlock(&wb_inode_list_lock);
+	}
 	list_del_init(&inode->i_sb_list);
 	spin_unlock(&sb_inode_list_lock);
 	WARN_ON(inode->i_state & I_NEW);
@@ -1355,12 +1344,12 @@ static void generic_forget_inode(struct
 	struct super_block *sb = inode->i_sb;
 
 	if (!hlist_unhashed(&inode->i_hash)) {
-		if (!(inode->i_state & (I_DIRTY|I_SYNC))) {
+		if (list_empty(&inode->i_list)) {
 			spin_lock(&wb_inode_list_lock);
-			list_move(&inode->i_list, &inode_unused);
+			list_add(&inode->i_list, &inode_unused);
 			spin_unlock(&wb_inode_list_lock);
+			atomic_inc(&inodes_stat.nr_unused);
 		}
-		atomic_inc(&inodes_stat.nr_unused);
 		if (sb->s_flags & MS_ACTIVE) {
 			spin_unlock(&inode->i_lock);
 			spin_unlock(&sb_inode_list_lock);
@@ -1376,11 +1365,13 @@ static void generic_forget_inode(struct
 		WARN_ON(inode->i_state & I_NEW);
 		inode->i_state &= ~I_WILL_FREE;
 		__remove_inode_hash(inode);
+	}
+	if (!list_empty(&inode->i_list)) {
+		spin_lock(&wb_inode_list_lock);
+		list_del_init(&inode->i_list);
+		spin_unlock(&wb_inode_list_lock);
 		atomic_dec(&inodes_stat.nr_unused);
 	}
-	spin_lock(&wb_inode_list_lock);
-	list_del_init(&inode->i_list);
-	spin_unlock(&wb_inode_list_lock);
 	list_del_init(&inode->i_sb_list);
 	spin_unlock(&sb_inode_list_lock);
 	WARN_ON(inode->i_state & I_NEW);
@@ -1705,7 +1696,7 @@ void __init inode_init(void)
 
 	inode_hashtable =
 		alloc_large_system_hash("Inode-cache",
-					sizeof(struct hlist_head),
+					sizeof(struct inode_hash_bucket),
 					ihash_entries,
 					14,
 					0,
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -2166,7 +2166,6 @@ extern int insert_inode_locked4(struct i
 extern int insert_inode_locked(struct inode *);
 extern void unlock_new_inode(struct inode *);
 
-extern void __iget(struct inode * inode);
 extern void iget_failed(struct inode *);
 extern void clear_inode(struct inode *);
 extern void destroy_inode(struct inode *);
@@ -2384,6 +2383,12 @@ extern int generic_show_options(struct s
 extern void save_mount_options(struct super_block *sb, char *options);
 extern void replace_mount_options(struct super_block *sb, char *options);
 
+static inline void __iget(struct inode *inode)
+{
+	assert_spin_locked(&inode->i_lock);
+	inode->i_count++;
+}
+
 static inline ino_t parent_ino(struct dentry *dentry)
 {
 	ino_t res;
Index: linux-2.6/fs/fs-writeback.c
===================================================================
--- linux-2.6.orig/fs/fs-writeback.c
+++ linux-2.6/fs/fs-writeback.c
@@ -429,7 +429,7 @@ writeback_single_inode(struct inode *ino
 			/*
 			 * The inode is clean, inuse
 			 */
-			list_move(&inode->i_list, &inode_in_use);
+			list_del_init(&inode->i_list);
 		} else {
 			/*
 			 * The inode is clean, unused
Index: linux-2.6/include/linux/writeback.h
===================================================================
--- linux-2.6.orig/include/linux/writeback.h
+++ linux-2.6/include/linux/writeback.h
@@ -11,7 +11,6 @@ struct backing_dev_info;
 
 extern spinlock_t sb_inode_list_lock;
 extern spinlock_t wb_inode_list_lock;
-extern struct list_head inode_in_use;
 extern struct list_head inode_unused;
 
 /*



  parent reply	other threads:[~2009-09-04  7:01 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-04  6:51 [patch 00/33] my current vfs scalability patch queue npiggin
2009-09-04  6:51 ` [patch 01/33] fs: no games with DCACHE_UNHASHED npiggin
2009-09-04  6:51 ` [patch 02/33] fs: cleanup files_lock npiggin
2009-09-04  6:51 ` [patch 03/33] fs: scale files_lock npiggin
2009-09-28 13:22   ` Peter Zijlstra
2009-09-28 13:24   ` Peter Zijlstra
2009-10-01  2:16     ` Nick Piggin
2009-09-04  6:51 ` [patch 04/33] fs: brlock vfsmount_lock npiggin
2009-09-04 15:19   ` Jens Axboe
2009-09-07  7:39     ` Nick Piggin
2009-09-22 15:17   ` Al Viro
2009-09-27 19:56     ` Nick Piggin
2009-09-28 13:21       ` Peter Zijlstra
2009-10-01  2:10         ` Nick Piggin
2009-09-04  6:51 ` [patch 05/33] fs: scale mntget/mntput npiggin
2009-09-07  9:41   ` Nick Piggin
2009-09-04  6:51 ` [patch 06/33] fs: dcache scale hash npiggin
2009-09-04  6:51 ` [patch 07/33] fs: dcache scale lru npiggin
2009-09-04  6:51 ` [patch 08/33] fs: dcache scale nr_dentry npiggin
2009-09-04 14:41   ` Daniel Walker
2009-09-07  7:36     ` Nick Piggin
2009-09-04  6:51 ` [patch 09/33] fs: dcache scale dentry refcount npiggin
2009-09-06 18:01   ` Eric Paris
2009-09-07  7:44     ` Nick Piggin
2009-09-07 11:21       ` Eric Paris
2009-09-07 11:35         ` Nick Piggin
2009-09-04  6:51 ` [patch 10/33] fs: dcache scale d_unhashed npiggin
2009-09-04  6:51 ` [patch 11/33] fs: dcache scale subdirs npiggin
2010-06-17 15:13   ` Peter Zijlstra
2010-06-17 16:53     ` Nick Piggin
2010-06-21 13:35       ` Peter Zijlstra
2010-06-21 14:48         ` Nick Piggin
2010-06-21 14:55           ` Peter Zijlstra
2010-06-22  6:02             ` john stultz
2010-06-22  6:06               ` Nick Piggin
2010-06-22  7:27               ` Peter Zijlstra
2010-06-23  2:03                 ` john stultz
2010-06-23  7:23                   ` Peter Zijlstra
2009-09-04  6:51 ` [patch 12/33] fs: scale inode alias list npiggin
2009-09-04  6:51 ` [patch 13/33] fs: use RCU / seqlock logic for reverse and multi-step operaitons npiggin
2009-09-04  6:51 ` [patch 14/33] fs: dcache remove dcache_lock npiggin
2009-09-04  6:51 ` [patch 15/33] fs: dcache reduce dput locking npiggin
2009-09-04  6:51 ` [patch 16/33] fs: dcache per-bucket dcache hash locking npiggin
2009-09-04 14:51   ` Daniel Walker
2009-09-07  7:38     ` Nick Piggin
2009-09-04  6:51 ` [patch 17/33] fs: dcache reduce dcache_inode_lock npiggin
2009-09-04  6:51 ` [patch 18/33] fs: dcache per-inode inode alias locking npiggin
2009-09-04  6:52 ` [patch 19/33] fs: icache lock s_inodes list npiggin
2009-09-04  6:52 ` [patch 20/33] fs: icache lock inode hash npiggin
2009-09-04  6:52 ` [patch 21/33] fs: icache lock i_state npiggin
2009-09-04  6:52 ` [patch 22/33] fs: icache lock i_count npiggin
2009-09-04  6:52 ` [patch 23/33] fs: icache atomic inodes_stat npiggin
2009-09-04  6:52 ` [patch 24/33] fs: icache lock lru/writeback lists npiggin
2009-09-04  6:52 ` [patch 25/33] fs: icache protect inode state npiggin
2009-09-04  6:52 ` [patch 26/33] fs: inode atomic last_ino, iunique lock npiggin
2009-09-04  6:52 ` [patch 27/33] fs: icache remove inode_lock npiggin
2009-09-04  6:52 ` [patch 28/33] fs: inode factor hash lock into functions npiggin
2009-09-04  6:52 ` [patch 29/33] Remove the global inode_hash_lock and replace it with per-hash-bucket locks. fs: inode per-bucket inode hash locks npiggin
2009-09-04  7:05   ` Nick Piggin
2009-09-04  6:52 ` npiggin [this message]
2009-09-04  6:52 ` [patch 31/33] fs: RCU free inodes npiggin
2009-09-04  6:52 ` [patch 32/33] fs: rcu walk for i_sb_list npiggin
2009-09-04  6:52 ` [patch 33/33] fs: improve scalability of pseudo filesystems npiggin
2009-09-04  7:05 ` [patch 00/33] my current vfs scalability patch queue Nick Piggin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090904065538.693437484@nick.local0.net \
    --to=npiggin@suse.de \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®