Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+51 −1
Original line number Original line Diff line number Diff line
@@ -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,
	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 */