aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2010-01-29 18:38:30 -0500
committerThomas Gleixner <tglx@linutronix.de>2010-04-27 11:32:47 -0400
commit1ea5ba6f5b20144fa59a8cf7c54efe17459d1236 (patch)
treeb2c272a63ca6f953397b0da6fcbd9f8bdb0a61f6
parent280c10e37fa879b97c0942e024e0b02059173ea0 (diff)
fs-inode_lock-scale-8
Make inode_hash_lock private by adding a function __remove_inode_hash that can be used by filesystems defining their own drop_inode functions. 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>
-rw-r--r--fs/inode.c42
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/writeback.h1
3 files changed, 28 insertions, 16 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 77dacd47b492..3ce2a15768dc 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -86,7 +86,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
86 */ 86 */
87DEFINE_SPINLOCK(sb_inode_list_lock); 87DEFINE_SPINLOCK(sb_inode_list_lock);
88DEFINE_SPINLOCK(wb_inode_list_lock); 88DEFINE_SPINLOCK(wb_inode_list_lock);
89DEFINE_SPINLOCK(inode_hash_lock); 89static DEFINE_SPINLOCK(inode_hash_lock);
90 90
91/* 91/*
92 * iprune_sem provides exclusion between the kswapd or try_to_free_pages 92 * iprune_sem provides exclusion between the kswapd or try_to_free_pages
@@ -356,9 +356,7 @@ static void dispose_list(struct list_head *head)
356 356
357 spin_lock(&sb_inode_list_lock); 357 spin_lock(&sb_inode_list_lock);
358 spin_lock(&inode->i_lock); 358 spin_lock(&inode->i_lock);
359 spin_lock(&inode_hash_lock); 359 __remove_inode_hash(inode);
360 hlist_del_init(&inode->i_hash);
361 spin_unlock(&inode_hash_lock);
362 list_del_init(&inode->i_sb_list); 360 list_del_init(&inode->i_sb_list);
363 spin_unlock(&inode->i_lock); 361 spin_unlock(&inode->i_lock);
364 spin_unlock(&sb_inode_list_lock); 362 spin_unlock(&sb_inode_list_lock);
@@ -1261,6 +1259,20 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
1261EXPORT_SYMBOL(__insert_inode_hash); 1259EXPORT_SYMBOL(__insert_inode_hash);
1262 1260
1263/** 1261/**
1262 * __remove_inode_hash - remove an inode from the hash
1263 * @inode: inode to unhash
1264 *
1265 * Remove an inode from the superblock. inode->i_lock must be
1266 * held.
1267 */
1268void __remove_inode_hash(struct inode *inode)
1269{
1270 spin_lock(&inode_hash_lock);
1271 hlist_del_init(&inode->i_hash);
1272 spin_unlock(&inode_hash_lock);
1273}
1274
1275/**
1264 * remove_inode_hash - remove an inode from the hash 1276 * remove_inode_hash - remove an inode from the hash
1265 * @inode: inode to unhash 1277 * @inode: inode to unhash
1266 * 1278 *
@@ -1269,9 +1281,7 @@ EXPORT_SYMBOL(__insert_inode_hash);
1269void remove_inode_hash(struct inode *inode) 1281void remove_inode_hash(struct inode *inode)
1270{ 1282{
1271 spin_lock(&inode->i_lock); 1283 spin_lock(&inode->i_lock);
1272 spin_lock(&inode_hash_lock); 1284 __remove_inode_hash(inode);
1273 hlist_del_init(&inode->i_hash);
1274 spin_unlock(&inode_hash_lock);
1275 spin_unlock(&inode->i_lock); 1285 spin_unlock(&inode->i_lock);
1276} 1286}
1277EXPORT_SYMBOL(remove_inode_hash); 1287EXPORT_SYMBOL(remove_inode_hash);
@@ -1317,11 +1327,15 @@ void generic_delete_inode(struct inode *inode)
1317 truncate_inode_pages(&inode->i_data, 0); 1327 truncate_inode_pages(&inode->i_data, 0);
1318 clear_inode(inode); 1328 clear_inode(inode);
1319 } 1329 }
1320 spin_lock(&inode->i_lock); 1330 /*
1321 spin_lock(&inode_hash_lock); 1331 * i_lock not required to delete from hash. If there was a
1322 hlist_del_init(&inode->i_hash); 1332 * concurrency window, then it would be possible for the other
1323 spin_unlock(&inode_hash_lock); 1333 * thread to touch the inode after it has been freed, with
1324 spin_unlock(&inode->i_lock); 1334 * destroy_inode.
1335 * XXX: yes it is because find_inode_fast checks it. Maybe we
1336 * can avoid it though...
1337 */
1338 remove_inode_hash(inode);
1325 wake_up_inode(inode); 1339 wake_up_inode(inode);
1326 BUG_ON(inode->i_state != I_CLEAR); 1340 BUG_ON(inode->i_state != I_CLEAR);
1327 destroy_inode(inode); 1341 destroy_inode(inode);
@@ -1362,9 +1376,7 @@ int generic_detach_inode(struct inode *inode)
1362 spin_lock(&inode->i_lock); 1376 spin_lock(&inode->i_lock);
1363 WARN_ON(inode->i_state & I_NEW); 1377 WARN_ON(inode->i_state & I_NEW);
1364 inode->i_state &= ~I_WILL_FREE; 1378 inode->i_state &= ~I_WILL_FREE;
1365 spin_lock(&inode_hash_lock); 1379 __remove_inode_hash(inode);
1366 hlist_del_init(&inode->i_hash);
1367 spin_unlock(&inode_hash_lock);
1368 atomic_dec(&inodes_stat.nr_unused); 1380 atomic_dec(&inodes_stat.nr_unused);
1369 } 1381 }
1370 spin_lock(&wb_inode_list_lock); 1382 spin_lock(&wb_inode_list_lock);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index fc4222374cd7..3551528a25f6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2184,6 +2184,7 @@ extern int should_remove_suid(struct dentry *);
2184extern int file_remove_suid(struct file *); 2184extern int file_remove_suid(struct file *);
2185 2185
2186extern void __insert_inode_hash(struct inode *, unsigned long hashval); 2186extern void __insert_inode_hash(struct inode *, unsigned long hashval);
2187extern void __remove_inode_hash(struct inode *);
2187extern void remove_inode_hash(struct inode *); 2188extern void remove_inode_hash(struct inode *);
2188static inline void insert_inode_hash(struct inode *inode) { 2189static inline void insert_inode_hash(struct inode *inode) {
2189 __insert_inode_hash(inode, inode->i_ino); 2190 __insert_inode_hash(inode, inode->i_ino);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 3e504f49753c..05479e576a77 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -11,7 +11,6 @@ struct backing_dev_info;
11 11
12extern spinlock_t sb_inode_list_lock; 12extern spinlock_t sb_inode_list_lock;
13extern spinlock_t wb_inode_list_lock; 13extern spinlock_t wb_inode_list_lock;
14extern spinlock_t inode_hash_lock;
15extern struct list_head inode_in_use; 14extern struct list_head inode_in_use;
16extern struct list_head inode_unused; 15extern struct list_head inode_unused;
17 16