diff options
author | Nick Piggin <npiggin@suse.de> | 2010-01-29 18:38:30 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-04-27 11:32:47 -0400 |
commit | 1ea5ba6f5b20144fa59a8cf7c54efe17459d1236 (patch) | |
tree | b2c272a63ca6f953397b0da6fcbd9f8bdb0a61f6 | |
parent | 280c10e37fa879b97c0942e024e0b02059173ea0 (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.c | 42 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | include/linux/writeback.h | 1 |
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 | */ |
87 | DEFINE_SPINLOCK(sb_inode_list_lock); | 87 | DEFINE_SPINLOCK(sb_inode_list_lock); |
88 | DEFINE_SPINLOCK(wb_inode_list_lock); | 88 | DEFINE_SPINLOCK(wb_inode_list_lock); |
89 | DEFINE_SPINLOCK(inode_hash_lock); | 89 | static 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) | |||
1261 | EXPORT_SYMBOL(__insert_inode_hash); | 1259 | EXPORT_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 | */ | ||
1268 | void __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); | |||
1269 | void remove_inode_hash(struct inode *inode) | 1281 | void 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 | } |
1277 | EXPORT_SYMBOL(remove_inode_hash); | 1287 | EXPORT_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 *); | |||
2184 | extern int file_remove_suid(struct file *); | 2184 | extern int file_remove_suid(struct file *); |
2185 | 2185 | ||
2186 | extern void __insert_inode_hash(struct inode *, unsigned long hashval); | 2186 | extern void __insert_inode_hash(struct inode *, unsigned long hashval); |
2187 | extern void __remove_inode_hash(struct inode *); | ||
2187 | extern void remove_inode_hash(struct inode *); | 2188 | extern void remove_inode_hash(struct inode *); |
2188 | static inline void insert_inode_hash(struct inode *inode) { | 2189 | static 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 | ||
12 | extern spinlock_t sb_inode_list_lock; | 12 | extern spinlock_t sb_inode_list_lock; |
13 | extern spinlock_t wb_inode_list_lock; | 13 | extern spinlock_t wb_inode_list_lock; |
14 | extern spinlock_t inode_hash_lock; | ||
15 | extern struct list_head inode_in_use; | 14 | extern struct list_head inode_in_use; |
16 | extern struct list_head inode_unused; | 15 | extern struct list_head inode_unused; |
17 | 16 | ||