You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
fs: dcache scale subdirs
Protect d_subdirs and d_child with d_lock, except in filesystems that aren't using dcache_lock for these anyway (eg. using i_mutex). Note: if we change the locking rule in future so that ->d_child protection is provided only with ->d_parent->d_lock, it may allow us to reduce some locking. But it would be an exception to an otherwise regular locking scheme, so we'd have to see some good results. Probably not worthwhile. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
This commit is contained in:
+17
-2
@@ -877,23 +877,31 @@ static void cgroup_clear_directory(struct dentry *dentry)
|
||||
|
||||
BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
|
||||
spin_lock(&dcache_lock);
|
||||
spin_lock(&dentry->d_lock);
|
||||
node = dentry->d_subdirs.next;
|
||||
while (node != &dentry->d_subdirs) {
|
||||
struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
|
||||
|
||||
spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
|
||||
list_del_init(node);
|
||||
if (d->d_inode) {
|
||||
/* This should never be called on a cgroup
|
||||
* directory with child cgroups */
|
||||
BUG_ON(d->d_inode->i_mode & S_IFDIR);
|
||||
d = dget_locked(d);
|
||||
dget_locked_dlock(d);
|
||||
spin_unlock(&d->d_lock);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
spin_unlock(&dcache_lock);
|
||||
d_delete(d);
|
||||
simple_unlink(dentry->d_inode, d);
|
||||
dput(d);
|
||||
spin_lock(&dcache_lock);
|
||||
}
|
||||
spin_lock(&dentry->d_lock);
|
||||
} else
|
||||
spin_unlock(&d->d_lock);
|
||||
node = dentry->d_subdirs.next;
|
||||
}
|
||||
spin_unlock(&dentry->d_lock);
|
||||
spin_unlock(&dcache_lock);
|
||||
}
|
||||
|
||||
@@ -902,10 +910,17 @@ static void cgroup_clear_directory(struct dentry *dentry)
|
||||
*/
|
||||
static void cgroup_d_remove_dir(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *parent;
|
||||
|
||||
cgroup_clear_directory(dentry);
|
||||
|
||||
spin_lock(&dcache_lock);
|
||||
parent = dentry->d_parent;
|
||||
spin_lock(&parent->d_lock);
|
||||
spin_lock(&dentry->d_lock);
|
||||
list_del_init(&dentry->d_u.d_child);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
spin_unlock(&parent->d_lock);
|
||||
spin_unlock(&dcache_lock);
|
||||
remove_dir(dentry);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user