summaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4/expire.c')
-rw-r--r--fs/autofs4/expire.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 165fe9e2d57..053d92a745b 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -101,6 +101,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
unsigned long timeout,
int do_now)
{
+ struct autofs_info *ino;
struct dentry *p;
DPRINTK("top %p %.*s",
@@ -110,14 +111,6 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
if (!simple_positive(top))
return 1;
- /* Timeout of a tree mount is determined by its top dentry */
- if (!autofs4_can_expire(top, timeout, do_now))
- return 1;
-
- /* Is someone visiting anywhere in the tree ? */
- if (may_umount_tree(mnt))
- return 1;
-
spin_lock(&dcache_lock);
for (p = top; p; p = next_dentry(p, top)) {
/* Negative dentry - give up */
@@ -130,17 +123,40 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
p = dget(p);
spin_unlock(&dcache_lock);
+ /*
+ * Is someone visiting anywhere in the subtree ?
+ * If there's no mount we need to check the usage
+ * count for the autofs dentry.
+ */
+ ino = autofs4_dentry_ino(p);
if (d_mountpoint(p)) {
- /* First busy => tree busy */
if (autofs4_mount_busy(mnt, p)) {
dput(p);
return 1;
}
+ } else {
+ unsigned int ino_count = atomic_read(&ino->count);
+
+ /* allow for dget above and top is already dgot */
+ if (p == top)
+ ino_count += 2;
+ else
+ ino_count++;
+
+ if (atomic_read(&p->d_count) > ino_count) {
+ dput(p);
+ return 1;
+ }
}
dput(p);
spin_lock(&dcache_lock);
}
spin_unlock(&dcache_lock);
+
+ /* Timeout of a tree mount is ultimately determined by its top dentry */
+ if (!autofs4_can_expire(top, timeout, do_now))
+ return 1;
+
return 0;
}