diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 29 |
1 files changed, 26 insertions, 3 deletions
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); |