autofs4 - dont clear DCACHE_NEED_AUTOMOUNT on rootless mount
The DCACHE_NEED_AUTOMOUNT flag is cleared on mount and set on expire for autofs rootless multi-mount dentrys to prevent unnecessary calls to ->d_automount(). Since DCACHE_MANAGE_TRANSIT is always set on autofs dentrys ->d_managed() is always called so the check can be done in ->d_manage() without the need to change the flag. This still avoids unnecessary calls to ->d_automount(), adds negligible overhead and eliminates a seriously ugly check in the expire code. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
29594404d7
commit
f55fb0c243
@ -548,15 +548,6 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
|
|||||||
|
|
||||||
spin_lock(&sbi->fs_lock);
|
spin_lock(&sbi->fs_lock);
|
||||||
ino->flags &= ~AUTOFS_INF_EXPIRING;
|
ino->flags &= ~AUTOFS_INF_EXPIRING;
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
if (!ret) {
|
|
||||||
if ((IS_ROOT(dentry) ||
|
|
||||||
(autofs_type_indirect(sbi->type) &&
|
|
||||||
IS_ROOT(dentry->d_parent))) &&
|
|
||||||
!(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
|
|
||||||
__managed_dentry_set_automount(dentry);
|
|
||||||
}
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
complete_all(&ino->expire_complete);
|
complete_all(&ino->expire_complete);
|
||||||
spin_unlock(&sbi->fs_lock);
|
spin_unlock(&sbi->fs_lock);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
|
@ -355,7 +355,6 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
|||||||
status = autofs4_mount_wait(dentry);
|
status = autofs4_mount_wait(dentry);
|
||||||
if (status)
|
if (status)
|
||||||
return ERR_PTR(status);
|
return ERR_PTR(status);
|
||||||
spin_lock(&sbi->fs_lock);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,8 +363,11 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
|||||||
* having d_mountpoint() true, so there's no need to call back
|
* having d_mountpoint() true, so there's no need to call back
|
||||||
* to the daemon.
|
* to the daemon.
|
||||||
*/
|
*/
|
||||||
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))
|
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
|
||||||
|
spin_unlock(&sbi->fs_lock);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (!d_mountpoint(dentry)) {
|
if (!d_mountpoint(dentry)) {
|
||||||
/*
|
/*
|
||||||
* It's possible that user space hasn't removed directories
|
* It's possible that user space hasn't removed directories
|
||||||
@ -379,8 +381,10 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
|||||||
* require user space behave.
|
* require user space behave.
|
||||||
*/
|
*/
|
||||||
if (sbi->version > 4) {
|
if (sbi->version > 4) {
|
||||||
if (have_submounts(dentry))
|
if (have_submounts(dentry)) {
|
||||||
|
spin_unlock(&sbi->fs_lock);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
spin_lock(&dentry->d_lock);
|
spin_lock(&dentry->d_lock);
|
||||||
if (!list_empty(&dentry->d_subdirs)) {
|
if (!list_empty(&dentry->d_subdirs)) {
|
||||||
@ -399,28 +403,8 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
|
|||||||
return ERR_PTR(status);
|
return ERR_PTR(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
|
||||||
if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
|
|
||||||
/*
|
|
||||||
* Any needed mounting has been completed and the path
|
|
||||||
* updated so clear DCACHE_NEED_AUTOMOUNT so we don't
|
|
||||||
* call ->d_automount() on rootless multi-mounts since
|
|
||||||
* it can lead to an incorrect ELOOP error return.
|
|
||||||
*
|
|
||||||
* Only clear DMANAGED_AUTOMOUNT for rootless multi-mounts and
|
|
||||||
* symlinks as in all other cases the dentry will be covered by
|
|
||||||
* an actual mount so ->d_automount() won't be called during
|
|
||||||
* the follow.
|
|
||||||
*/
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
if ((!d_mountpoint(dentry) &&
|
|
||||||
!list_empty(&dentry->d_subdirs)) ||
|
|
||||||
(dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
|
|
||||||
__managed_dentry_clear_automount(dentry);
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
}
|
|
||||||
spin_unlock(&sbi->fs_lock);
|
spin_unlock(&sbi->fs_lock);
|
||||||
|
done:
|
||||||
/* Mount succeeded, check if we ended up with a new dentry */
|
/* Mount succeeded, check if we ended up with a new dentry */
|
||||||
dentry = autofs4_mountpoint_changed(path);
|
dentry = autofs4_mountpoint_changed(path);
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
@ -432,6 +416,8 @@ done:
|
|||||||
int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
|
int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
|
||||||
{
|
{
|
||||||
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
|
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
|
||||||
|
struct autofs_info *ino = autofs4_dentry_ino(dentry);
|
||||||
|
int status;
|
||||||
|
|
||||||
DPRINTK("dentry=%p %.*s",
|
DPRINTK("dentry=%p %.*s",
|
||||||
dentry, dentry->d_name.len, dentry->d_name.name);
|
dentry, dentry->d_name.len, dentry->d_name.name);
|
||||||
@ -456,7 +442,32 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
|
|||||||
* This dentry may be under construction so wait on mount
|
* This dentry may be under construction so wait on mount
|
||||||
* completion.
|
* completion.
|
||||||
*/
|
*/
|
||||||
return autofs4_mount_wait(dentry);
|
status = autofs4_mount_wait(dentry);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
spin_lock(&sbi->fs_lock);
|
||||||
|
/*
|
||||||
|
* If the dentry has been selected for expire while we slept
|
||||||
|
* on the lock then it might go away. We'll deal with that in
|
||||||
|
* ->d_automount() and wait on a new mount if the expire
|
||||||
|
* succeeds or return here if it doesn't (since there's no
|
||||||
|
* mount to follow with a rootless multi-mount).
|
||||||
|
*/
|
||||||
|
if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
|
||||||
|
/*
|
||||||
|
* Any needed mounting has been completed and the path
|
||||||
|
* updated so check if this is a rootless multi-mount so
|
||||||
|
* we can avoid needless calls ->d_automount() and avoid
|
||||||
|
* an incorrect ELOOP error return.
|
||||||
|
*/
|
||||||
|
if ((!d_mountpoint(dentry) && !simple_empty(dentry)) ||
|
||||||
|
(dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
|
||||||
|
status = -EISDIR;
|
||||||
|
}
|
||||||
|
spin_unlock(&sbi->fs_lock);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookups in the root directory */
|
/* Lookups in the root directory */
|
||||||
|
Loading…
Reference in New Issue
Block a user