aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2006-03-27 04:14:46 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:39 -0500
commit1aff3c8b0511b5bb54acf7859e0c6ec9ae7287a9 (patch)
treebe50f4c89a14240b568010da1b0ce3c182352afc /fs/autofs4/expire.c
parent1ce12bad85863478619688c0c7363f93a9e5edb8 (diff)
[PATCH] autofs4: fix false negative return from expire
Fix the case where an expire returns busy on a tree mount when it is in fact not busy. This case was overlooked when the patch to prevent the expiring away of "scaffolding" directories for tree mounts was applied. The problem arises when a tree of mounts is a member of a map with other keys. The current logic will not expire the tree if any other mount in the map is busy. The solution is to maintain a "minimum" use count for each autofs dentry and compare this to the actual dentry usage count during expire. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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 165fe9e2d570..053d92a745b9 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -101,6 +101,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
101 unsigned long timeout, 101 unsigned long timeout,
102 int do_now) 102 int do_now)
103{ 103{
104 struct autofs_info *ino;
104 struct dentry *p; 105 struct dentry *p;
105 106
106 DPRINTK("top %p %.*s", 107 DPRINTK("top %p %.*s",
@@ -110,14 +111,6 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
110 if (!simple_positive(top)) 111 if (!simple_positive(top))
111 return 1; 112 return 1;
112 113
113 /* Timeout of a tree mount is determined by its top dentry */
114 if (!autofs4_can_expire(top, timeout, do_now))
115 return 1;
116
117 /* Is someone visiting anywhere in the tree ? */
118 if (may_umount_tree(mnt))
119 return 1;
120
121 spin_lock(&dcache_lock); 114 spin_lock(&dcache_lock);
122 for (p = top; p; p = next_dentry(p, top)) { 115 for (p = top; p; p = next_dentry(p, top)) {
123 /* Negative dentry - give up */ 116 /* Negative dentry - give up */
@@ -130,17 +123,40 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
130 p = dget(p); 123 p = dget(p);
131 spin_unlock(&dcache_lock); 124 spin_unlock(&dcache_lock);
132 125
126 /*
127 * Is someone visiting anywhere in the subtree ?
128 * If there's no mount we need to check the usage
129 * count for the autofs dentry.
130 */
131 ino = autofs4_dentry_ino(p);
133 if (d_mountpoint(p)) { 132 if (d_mountpoint(p)) {
134 /* First busy => tree busy */
135 if (autofs4_mount_busy(mnt, p)) { 133 if (autofs4_mount_busy(mnt, p)) {
136 dput(p); 134 dput(p);
137 return 1; 135 return 1;
138 } 136 }
137 } else {
138 unsigned int ino_count = atomic_read(&ino->count);
139
140 /* allow for dget above and top is already dgot */
141 if (p == top)
142 ino_count += 2;
143 else
144 ino_count++;
145
146 if (atomic_read(&p->d_count) > ino_count) {
147 dput(p);
148 return 1;
149 }
139 } 150 }
140 dput(p); 151 dput(p);
141 spin_lock(&dcache_lock); 152 spin_lock(&dcache_lock);
142 } 153 }
143 spin_unlock(&dcache_lock); 154 spin_unlock(&dcache_lock);
155
156 /* Timeout of a tree mount is ultimately determined by its top dentry */
157 if (!autofs4_can_expire(top, timeout, do_now))
158 return 1;
159
144 return 0; 160 return 0;
145} 161}
146 162