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)
struct dentry *dentry;
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
/* Directory should have only one entry. */
BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
return dentry;
}
......
......@@ -129,6 +129,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
struct list_head *head, *next;
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
head = &inode->i_dentry;
next = head->next;
while (next != head) {
......@@ -139,6 +140,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
}
next = next->next;
}
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
}
......
......@@ -810,12 +810,15 @@ inode_has_hashed_dentries(struct inode *inode)
struct dentry *dentry;
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
return true;
}
}
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
return false;
}
......
This diff is collapsed.
......@@ -48,8 +48,10 @@ find_acceptable_alias(struct dentry *result,
return result;
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
dget_locked(dentry);
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
if (toput)
dput(toput);
......@@ -58,8 +60,10 @@ find_acceptable_alias(struct dentry *result,
return dentry;
}
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
toput = dentry;
}
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
if (toput)
......
......@@ -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.
*/
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
spin_lock(&sb->s_root->d_lock);
list_del_init(&sb->s_root->d_alias);
spin_unlock(&sb->s_root->d_lock);
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
}
return 0;
......
......@@ -60,6 +60,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
watched = fsnotify_inode_watches_children(inode);
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
/* 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 */
list_for_each_entry(alias, &inode->i_dentry, d_alias) {
......@@ -82,6 +83,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
}
spin_unlock(&alias->d_lock);
}
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
}
......
......@@ -170,7 +170,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
struct dentry *dentry = NULL;
spin_lock(&dcache_lock);
spin_lock(&dcache_inode_lock);
list_for_each(p, &inode->i_dentry) {
dentry = list_entry(p, struct dentry, d_alias);
......@@ -188,6 +188,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
dentry = NULL;
}
spin_unlock(&dcache_inode_lock);
spin_unlock(&dcache_lock);
return dentry;
......
......@@ -181,6 +181,7 @@ struct dentry_operations {
#define DCACHE_CANT_MOUNT 0x0100
extern spinlock_t dcache_inode_lock;
extern spinlock_t dcache_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