Commit b23fb0a6 authored by Nick Piggin's avatar Nick Piggin

fs: scale inode alias list

Add a new lock, dcache_inode_lock, to protect the inode's i_dentry list
from concurrent modification. d_alias is also protected by d_lock.
Signed-off-by: default avatarNick Piggin <npiggin@kernel.dk>
parent 2fd6b7f5
...@@ -271,9 +271,11 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) ...@@ -271,9 +271,11 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
struct dentry *dentry; struct dentry *dentry;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
/* Directory should have only one entry. */ /* Directory should have only one entry. */
BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return dentry; return dentry;
} }
......
...@@ -129,6 +129,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino) ...@@ -129,6 +129,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
struct list_head *head, *next; struct list_head *head, *next;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
head = &inode->i_dentry; head = &inode->i_dentry;
next = head->next; next = head->next;
while (next != head) { while (next != head) {
...@@ -139,6 +140,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino) ...@@ -139,6 +140,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
} }
next = next->next; next = next->next;
} }
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
} }
......
...@@ -810,12 +810,15 @@ inode_has_hashed_dentries(struct inode *inode) ...@@ -810,12 +810,15 @@ inode_has_hashed_dentries(struct inode *inode)
struct dentry *dentry; struct dentry *dentry;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
list_for_each_entry(dentry, &inode->i_dentry, d_alias) { list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
if (!d_unhashed(dentry) || IS_ROOT(dentry)) { if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return true; return true;
} }
} }
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return false; return false;
} }
......
This diff is collapsed.
...@@ -48,8 +48,10 @@ find_acceptable_alias(struct dentry *result, ...@@ -48,8 +48,10 @@ find_acceptable_alias(struct dentry *result,
return result; return result;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) { list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
dget_locked(dentry); dget_locked(dentry);
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
if (toput) if (toput)
dput(toput); dput(toput);
...@@ -58,8 +60,10 @@ find_acceptable_alias(struct dentry *result, ...@@ -58,8 +60,10 @@ find_acceptable_alias(struct dentry *result,
return dentry; return dentry;
} }
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
toput = dentry; toput = dentry;
} }
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
if (toput) if (toput)
......
...@@ -64,7 +64,11 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i ...@@ -64,7 +64,11 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
* Oops, since the test for IS_ROOT() will fail. * Oops, since the test for IS_ROOT() will fail.
*/ */
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
spin_lock(&sb->s_root->d_lock);
list_del_init(&sb->s_root->d_alias); list_del_init(&sb->s_root->d_alias);
spin_unlock(&sb->s_root->d_lock);
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
} }
return 0; return 0;
......
...@@ -60,6 +60,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) ...@@ -60,6 +60,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
watched = fsnotify_inode_watches_children(inode); watched = fsnotify_inode_watches_children(inode);
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
/* run all of the dentries associated with this inode. Since this is a /* run all of the dentries associated with this inode. Since this is a
* directory, there damn well better only be one item on this list */ * directory, there damn well better only be one item on this list */
list_for_each_entry(alias, &inode->i_dentry, d_alias) { list_for_each_entry(alias, &inode->i_dentry, d_alias) {
...@@ -82,6 +83,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) ...@@ -82,6 +83,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
} }
spin_unlock(&alias->d_lock); spin_unlock(&alias->d_lock);
} }
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
} }
......
...@@ -170,7 +170,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, ...@@ -170,7 +170,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
struct dentry *dentry = NULL; struct dentry *dentry = NULL;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
list_for_each(p, &inode->i_dentry) { list_for_each(p, &inode->i_dentry) {
dentry = list_entry(p, struct dentry, d_alias); dentry = list_entry(p, struct dentry, d_alias);
...@@ -188,6 +188,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, ...@@ -188,6 +188,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
dentry = NULL; dentry = NULL;
} }
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return dentry; return dentry;
......
...@@ -181,6 +181,7 @@ struct dentry_operations { ...@@ -181,6 +181,7 @@ struct dentry_operations {
#define DCACHE_CANT_MOUNT 0x0100 #define DCACHE_CANT_MOUNT 0x0100
extern spinlock_t dcache_inode_lock;
extern spinlock_t dcache_lock; extern spinlock_t dcache_lock;
extern seqlock_t rename_lock; extern seqlock_t rename_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment