diff options
author | Nick Piggin <npiggin@suse.de> | 2010-01-29 15:38:29 -0800 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-04-27 17:32:45 +0200 |
commit | b1491cd9f0e4716fb890b4230b514e3fa59198a3 (patch) | |
tree | d3b775c8a48b11c87f203fe8f3f5ec0dda388ab4 | |
parent | 3e9014b7ae2e05b53552f6524a2efd5d22a20400 (diff) | |
download | lwn-b1491cd9f0e4716fb890b4230b514e3fa59198a3.tar.gz lwn-b1491cd9f0e4716fb890b4230b514e3fa59198a3.zip |
fs-inode_lock-scale-6b
Protect i_hash, i_sb_list etc members with i_lock.
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/hugetlbfs/inode.c | 1 | ||||
-rw-r--r-- | fs/inode.c | 29 |
2 files changed, 27 insertions, 3 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index a0bbd3d1b41a..ab1e261738bf 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -382,6 +382,7 @@ static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock) if (generic_detach_inode(inode)) { truncate_hugepages(inode, 0); clear_inode(inode); + /* XXX: why no wake_up_inode? */ destroy_inode(inode); } } diff --git a/fs/inode.c b/fs/inode.c index ea96254bd490..b04e902da355 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -356,12 +356,14 @@ static void dispose_list(struct list_head *head) clear_inode(inode); spin_lock(&inode_lock); + spin_lock(&sb_inode_list_lock); + spin_lock(&inode->i_lock); spin_lock(&inode_hash_lock); hlist_del_init(&inode->i_hash); spin_unlock(&inode_hash_lock); - spin_lock(&sb_inode_list_lock); list_del_init(&inode->i_sb_list); spin_unlock(&sb_inode_list_lock); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); wake_up_inode(inode); @@ -663,7 +665,6 @@ __inode_add_to_lists(struct super_block *sb, struct hlist_head *head, struct inode *inode) { atomic_inc(&inodes_stat.nr_inodes); - spin_lock(&sb_inode_list_lock); list_add(&inode->i_sb_list, &sb->s_inodes); spin_unlock(&sb_inode_list_lock); spin_lock(&wb_inode_list_lock); @@ -693,7 +694,10 @@ void inode_add_to_lists(struct super_block *sb, struct inode *inode) struct hlist_head *head = inode_hashtable + hash(sb, inode->i_ino); spin_lock(&inode_lock); + spin_lock(&sb_inode_list_lock); + spin_lock(&inode->i_lock); __inode_add_to_lists(sb, head, inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } EXPORT_SYMBOL_GPL(inode_add_to_lists); @@ -725,9 +729,12 @@ struct inode *new_inode(struct super_block *sb) inode = alloc_inode(sb); if (inode) { spin_lock(&inode_lock); + spin_lock(&sb_inode_list_lock); + spin_lock(&inode->i_lock); inode->i_ino = ++last_ino; inode->i_state = 0; __inode_add_to_lists(sb, NULL, inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } return inode; @@ -791,11 +798,14 @@ static struct inode *get_new_inode(struct super_block *sb, /* We released the lock, so.. */ old = find_inode(sb, head, test, data); if (!old) { + spin_lock(&sb_inode_list_lock); + spin_lock(&inode->i_lock); if (set(inode, data)) goto set_failed; inode->i_state = I_NEW; __inode_add_to_lists(sb, head, inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); /* Return the locked inode with I_NEW set, the @@ -820,6 +830,7 @@ static struct inode *get_new_inode(struct super_block *sb, set_failed: spin_unlock(&inode->i_lock); + spin_unlock(&sb_inode_list_lock); spin_unlock(&inode_lock); destroy_inode(inode); return NULL; @@ -842,9 +853,12 @@ static struct inode *get_new_inode_fast(struct super_block *sb, /* We released the lock, so.. */ old = find_inode_fast(sb, head, ino); if (!old) { + spin_lock(&sb_inode_list_lock); + spin_lock(&inode->i_lock); inode->i_ino = ino; inode->i_state = I_NEW; __inode_add_to_lists(sb, head, inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); /* Return the locked inode with I_NEW set, the @@ -1180,6 +1194,7 @@ repeat: break; } if (likely(!node)) { + /* XXX: initialize inode->i_lock to locked? */ hlist_add_head(&inode->i_hash, head); spin_unlock(&inode_hash_lock); spin_unlock(&inode_lock); @@ -1228,6 +1243,7 @@ repeat: break; } if (likely(!node)) { + /* XXX: initialize inode->i_lock to locked? */ hlist_add_head(&inode->i_hash, head); spin_unlock(&inode_hash_lock); spin_unlock(&inode_lock); @@ -1258,10 +1274,13 @@ EXPORT_SYMBOL(insert_inode_locked4); void __insert_inode_hash(struct inode *inode, unsigned long hashval) { struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval); + spin_lock(&inode_lock); + spin_lock(&inode->i_lock); spin_lock(&inode_hash_lock); hlist_add_head(&inode->i_hash, head); spin_unlock(&inode_hash_lock); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } EXPORT_SYMBOL(__insert_inode_hash); @@ -1275,9 +1294,11 @@ EXPORT_SYMBOL(__insert_inode_hash); void remove_inode_hash(struct inode *inode) { spin_lock(&inode_lock); + spin_lock(&inode->i_lock); spin_lock(&inode_hash_lock); hlist_del_init(&inode->i_hash); spin_unlock(&inode_hash_lock); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } EXPORT_SYMBOL(remove_inode_hash); @@ -1325,9 +1346,11 @@ void generic_delete_inode(struct inode *inode) clear_inode(inode); } spin_lock(&inode_lock); + spin_lock(&inode->i_lock); spin_lock(&inode_hash_lock); hlist_del_init(&inode->i_hash); spin_unlock(&inode_hash_lock); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); wake_up_inode(inode); BUG_ON(inode->i_state != I_CLEAR); @@ -1372,10 +1395,10 @@ int generic_detach_inode(struct inode *inode) spin_lock(&inode->i_lock); WARN_ON(inode->i_state & I_NEW); inode->i_state &= ~I_WILL_FREE; - atomic_dec(&inodes_stat.nr_unused); spin_lock(&inode_hash_lock); hlist_del_init(&inode->i_hash); spin_unlock(&inode_hash_lock); + atomic_dec(&inodes_stat.nr_unused); } spin_lock(&wb_inode_list_lock); list_del_init(&inode->i_list); |