diff options
author | Nick Piggin <npiggin@suse.de> | 2010-01-29 18:38:31 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-04-27 11:32:49 -0400 |
commit | 6f22d55b46fbf80b018009ece79f15b8582843e5 (patch) | |
tree | 4623783cdf5b9c59482617f0a3437a852dc52e24 /fs/fs-writeback.c | |
parent | 20d3da9e29645abfba13536a82cf04a4076f9ce6 (diff) |
fs-inode_lock-scale-10
Impelemnt lazy inode lru similarly to dcache. This should reduce inode list
lock acquisition (todo: measure).
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r-- | fs/fs-writeback.c | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 07d70704078e..df99a99f99a2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -544,7 +544,7 @@ select_queue: | |||
544 | /* | 544 | /* |
545 | * The inode is clean, inuse | 545 | * The inode is clean, inuse |
546 | */ | 546 | */ |
547 | list_move(&inode->i_list, &inode_in_use); | 547 | list_del_init(&inode->i_list); |
548 | } else { | 548 | } else { |
549 | /* | 549 | /* |
550 | * The inode is clean, unused | 550 | * The inode is clean, unused |
@@ -1151,8 +1151,6 @@ static void wait_sb_inodes(struct super_block *sb) | |||
1151 | */ | 1151 | */ |
1152 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1152 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
1153 | 1153 | ||
1154 | spin_lock(&sb_inode_list_lock); | ||
1155 | |||
1156 | /* | 1154 | /* |
1157 | * Data integrity sync. Must wait for all pages under writeback, | 1155 | * Data integrity sync. Must wait for all pages under writeback, |
1158 | * because there may have been pages dirtied before our sync | 1156 | * because there may have been pages dirtied before our sync |
@@ -1160,7 +1158,8 @@ static void wait_sb_inodes(struct super_block *sb) | |||
1160 | * In which case, the inode may not be on the dirty list, but | 1158 | * In which case, the inode may not be on the dirty list, but |
1161 | * we still have to wait for that writeout. | 1159 | * we still have to wait for that writeout. |
1162 | */ | 1160 | */ |
1163 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | 1161 | rcu_read_lock(); |
1162 | list_for_each_entry_rcu(inode, &sb->s_inodes, i_sb_list) { | ||
1164 | struct address_space *mapping; | 1163 | struct address_space *mapping; |
1165 | 1164 | ||
1166 | mapping = inode->i_mapping; | 1165 | mapping = inode->i_mapping; |
@@ -1174,13 +1173,13 @@ static void wait_sb_inodes(struct super_block *sb) | |||
1174 | } | 1173 | } |
1175 | __iget(inode); | 1174 | __iget(inode); |
1176 | spin_unlock(&inode->i_lock); | 1175 | spin_unlock(&inode->i_lock); |
1177 | spin_unlock(&sb_inode_list_lock); | 1176 | rcu_read_unlock(); |
1178 | /* | 1177 | /* |
1179 | * We hold a reference to 'inode' so it couldn't have been | 1178 | * We hold a reference to 'inode' so it couldn't have been |
1180 | * removed from s_inodes list while we dropped the | 1179 | * removed from s_inodes list while we dropped the i_lock. We |
1181 | * sb_inode_list_lock. We cannot iput the inode now as we can | 1180 | * cannot iput the inode now as we can be holding the last |
1182 | * be holding the last reference and we cannot iput it under | 1181 | * reference and we cannot iput it under spinlock. So we keep |
1183 | * spinlock. So we keep the reference and iput it later. | 1182 | * the reference and iput it later. |
1184 | */ | 1183 | */ |
1185 | iput(old_inode); | 1184 | iput(old_inode); |
1186 | old_inode = inode; | 1185 | old_inode = inode; |
@@ -1189,9 +1188,9 @@ static void wait_sb_inodes(struct super_block *sb) | |||
1189 | 1188 | ||
1190 | cond_resched(); | 1189 | cond_resched(); |
1191 | 1190 | ||
1192 | spin_lock(&sb_inode_list_lock); | 1191 | rcu_read_lock(); |
1193 | } | 1192 | } |
1194 | spin_unlock(&sb_inode_list_lock); | 1193 | rcu_read_unlock(); |
1195 | iput(old_inode); | 1194 | iput(old_inode); |
1196 | } | 1195 | } |
1197 | 1196 | ||