Commit d4a85e35 authored by Ian Kent's avatar Ian Kent Committed by Al Viro

autofs4 - fix autofs4_expire_indirect() traversal

The vfs-scale changes changed the traversal used in
autofs4_expire_indirect() from a list to a depth first tree traversal
which isn't right.
Signed-off-by: default avatarIan Kent <raven@themaw.net>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent f9398c23
...@@ -86,6 +86,56 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) ...@@ -86,6 +86,56 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
return status; return status;
} }
/*
* Calculate and dget next entry in the subdirs list under root.
*/
static struct dentry *get_next_positive_subdir(struct dentry *prev,
struct dentry *root)
{
struct list_head *next;
struct dentry *p, *q;
spin_lock(&autofs4_lock);
if (prev == NULL) {
spin_lock(&root->d_lock);
prev = dget_dlock(root);
next = prev->d_subdirs.next;
p = prev;
goto start;
}
p = prev;
spin_lock(&p->d_lock);
again:
next = p->d_u.d_child.next;
start:
if (next == &root->d_subdirs) {
spin_unlock(&p->d_lock);
spin_unlock(&autofs4_lock);
dput(prev);
return NULL;
}
q = list_entry(next, struct dentry, d_u.d_child);
spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
/* Negative dentry - try next */
if (!simple_positive(q)) {
spin_unlock(&p->d_lock);
p = q;
goto again;
}
dget_dlock(q);
spin_unlock(&q->d_lock);
spin_unlock(&p->d_lock);
spin_unlock(&autofs4_lock);
dput(prev);
return q;
}
/* /*
* Calculate and dget next entry in top down tree traversal. * Calculate and dget next entry in top down tree traversal.
*/ */
...@@ -333,7 +383,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, ...@@ -333,7 +383,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
timeout = sbi->exp_timeout; timeout = sbi->exp_timeout;
dentry = NULL; dentry = NULL;
while ((dentry = get_next_positive_dentry(dentry, root))) { while ((dentry = get_next_positive_subdir(dentry, root))) {
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry); ino = autofs4_dentry_ino(dentry);
/* No point expiring a pending mount */ /* No point expiring a pending mount */
......
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