aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4/expire.c')
-rw-r--r--fs/autofs4/expire.c292
1 files changed, 183 insertions, 109 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index dc39589df165..b8ce02607d66 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved 5 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
6 * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> 6 * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
7 * Copyright 2001-2003 Ian Kent <raven@themaw.net> 7 * Copyright 2001-2006 Ian Kent <raven@themaw.net>
8 * 8 *
9 * This file is part of the Linux kernel and is made available under 9 * This file is part of the Linux kernel and is made available under
10 * the terms of the GNU General Public License, version 2, or at your 10 * the terms of the GNU General Public License, version 2, or at your
@@ -16,7 +16,7 @@
16 16
17static unsigned long now; 17static unsigned long now;
18 18
19/* Check if a dentry can be expired return 1 if it can else return 0 */ 19/* Check if a dentry can be expired */
20static inline int autofs4_can_expire(struct dentry *dentry, 20static inline int autofs4_can_expire(struct dentry *dentry,
21 unsigned long timeout, int do_now) 21 unsigned long timeout, int do_now)
22{ 22{
@@ -41,14 +41,14 @@ static inline int autofs4_can_expire(struct dentry *dentry,
41 attempts if expire fails the first time */ 41 attempts if expire fails the first time */
42 ino->last_used = now; 42 ino->last_used = now;
43 } 43 }
44
45 return 1; 44 return 1;
46} 45}
47 46
48/* Check a mount point for busyness return 1 if not busy, otherwise */ 47/* Check a mount point for busyness */
49static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry) 48static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
50{ 49{
51 int status = 0; 50 struct dentry *top = dentry;
51 int status = 1;
52 52
53 DPRINTK("dentry %p %.*s", 53 DPRINTK("dentry %p %.*s",
54 dentry, (int)dentry->d_name.len, dentry->d_name.name); 54 dentry, (int)dentry->d_name.len, dentry->d_name.name);
@@ -63,9 +63,14 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
63 if (is_autofs4_dentry(dentry)) 63 if (is_autofs4_dentry(dentry))
64 goto done; 64 goto done;
65 65
66 /* The big question */ 66 /* Update the expiry counter if fs is busy */
67 if (may_umount_tree(mnt) == 0) 67 if (!may_umount_tree(mnt)) {
68 status = 1; 68 struct autofs_info *ino = autofs4_dentry_ino(top);
69 ino->last_used = jiffies;
70 goto done;
71 }
72
73 status = 0;
69done: 74done:
70 DPRINTK("returning = %d", status); 75 DPRINTK("returning = %d", status);
71 mntput(mnt); 76 mntput(mnt);
@@ -73,78 +78,124 @@ done:
73 return status; 78 return status;
74} 79}
75 80
81/*
82 * Calculate next entry in top down tree traversal.
83 * From next_mnt in namespace.c - elegant.
84 */
85static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
86{
87 struct list_head *next = p->d_subdirs.next;
88
89 if (next == &p->d_subdirs) {
90 while (1) {
91 if (p == root)
92 return NULL;
93 next = p->d_u.d_child.next;
94 if (next != &p->d_parent->d_subdirs)
95 break;
96 p = p->d_parent;
97 }
98 }
99 return list_entry(next, struct dentry, d_u.d_child);
100}
101
102/*
103 * Check a direct mount point for busyness.
104 * Direct mounts have similar expiry semantics to tree mounts.
105 * The tree is not busy iff no mountpoints are busy and there are no
106 * autofs submounts.
107 */
108static int autofs4_direct_busy(struct vfsmount *mnt,
109 struct dentry *top,
110 unsigned long timeout,
111 int do_now)
112{
113 DPRINTK("top %p %.*s",
114 top, (int) top->d_name.len, top->d_name.name);
115
116 /* If it's busy update the expiry counters */
117 if (!may_umount_tree(mnt)) {
118 struct autofs_info *ino = autofs4_dentry_ino(top);
119 if (ino)
120 ino->last_used = jiffies;
121 return 1;
122 }
123
124 /* Timeout of a direct mount is determined by its top dentry */
125 if (!autofs4_can_expire(top, timeout, do_now))
126 return 1;
127
128 return 0;
129}
130
76/* Check a directory tree of mount points for busyness 131/* Check a directory tree of mount points for busyness
77 * The tree is not busy iff no mountpoints are busy 132 * The tree is not busy iff no mountpoints are busy
78 * Return 1 if the tree is busy or 0 otherwise
79 */ 133 */
80static int autofs4_check_tree(struct vfsmount *mnt, 134static int autofs4_tree_busy(struct vfsmount *mnt,
81 struct dentry *top, 135 struct dentry *top,
82 unsigned long timeout, 136 unsigned long timeout,
83 int do_now) 137 int do_now)
84{ 138{
85 struct dentry *this_parent = top; 139 struct autofs_info *top_ino = autofs4_dentry_ino(top);
86 struct list_head *next; 140 struct dentry *p;
87 141
88 DPRINTK("parent %p %.*s", 142 DPRINTK("top %p %.*s",
89 top, (int)top->d_name.len, top->d_name.name); 143 top, (int)top->d_name.len, top->d_name.name);
90 144
91 /* Negative dentry - give up */ 145 /* Negative dentry - give up */
92 if (!simple_positive(top)) 146 if (!simple_positive(top))
93 return 0; 147 return 1;
94
95 /* Timeout of a tree mount is determined by its top dentry */
96 if (!autofs4_can_expire(top, timeout, do_now))
97 return 0;
98
99 /* Is someone visiting anywhere in the tree ? */
100 if (may_umount_tree(mnt))
101 return 0;
102 148
103 spin_lock(&dcache_lock); 149 spin_lock(&dcache_lock);
104repeat: 150 for (p = top; p; p = next_dentry(p, top)) {
105 next = this_parent->d_subdirs.next;
106resume:
107 while (next != &this_parent->d_subdirs) {
108 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
109
110 /* Negative dentry - give up */ 151 /* Negative dentry - give up */
111 if (!simple_positive(dentry)) { 152 if (!simple_positive(p))
112 next = next->next;
113 continue; 153 continue;
114 }
115 154
116 DPRINTK("dentry %p %.*s", 155 DPRINTK("dentry %p %.*s",
117 dentry, (int)dentry->d_name.len, dentry->d_name.name); 156 p, (int) p->d_name.len, p->d_name.name);
118
119 if (!simple_empty_nolock(dentry)) {
120 this_parent = dentry;
121 goto repeat;
122 }
123 157
124 dentry = dget(dentry); 158 p = dget(p);
125 spin_unlock(&dcache_lock); 159 spin_unlock(&dcache_lock);
126 160
127 if (d_mountpoint(dentry)) { 161 /*
128 /* First busy => tree busy */ 162 * Is someone visiting anywhere in the subtree ?
129 if (!autofs4_check_mount(mnt, dentry)) { 163 * If there's no mount we need to check the usage
130 dput(dentry); 164 * count for the autofs dentry.
131 return 0; 165 * If the fs is busy update the expiry counter.
166 */
167 if (d_mountpoint(p)) {
168 if (autofs4_mount_busy(mnt, p)) {
169 top_ino->last_used = jiffies;
170 dput(p);
171 return 1;
172 }
173 } else {
174 struct autofs_info *ino = autofs4_dentry_ino(p);
175 unsigned int ino_count = atomic_read(&ino->count);
176
177 /* allow for dget above and top is already dgot */
178 if (p == top)
179 ino_count += 2;
180 else
181 ino_count++;
182
183 if (atomic_read(&p->d_count) > ino_count) {
184 top_ino->last_used = jiffies;
185 dput(p);
186 return 1;
132 } 187 }
133 } 188 }
134 189 dput(p);
135 dput(dentry);
136 spin_lock(&dcache_lock); 190 spin_lock(&dcache_lock);
137 next = next->next;
138 }
139
140 if (this_parent != top) {
141 next = this_parent->d_u.d_child.next;
142 this_parent = this_parent->d_parent;
143 goto resume;
144 } 191 }
145 spin_unlock(&dcache_lock); 192 spin_unlock(&dcache_lock);
146 193
147 return 1; 194 /* Timeout of a tree mount is ultimately determined by its top dentry */
195 if (!autofs4_can_expire(top, timeout, do_now))
196 return 1;
197
198 return 0;
148} 199}
149 200
150static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, 201static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
@@ -152,58 +203,68 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
152 unsigned long timeout, 203 unsigned long timeout,
153 int do_now) 204 int do_now)
154{ 205{
155 struct dentry *this_parent = parent; 206 struct dentry *p;
156 struct list_head *next;
157 207
158 DPRINTK("parent %p %.*s", 208 DPRINTK("parent %p %.*s",
159 parent, (int)parent->d_name.len, parent->d_name.name); 209 parent, (int)parent->d_name.len, parent->d_name.name);
160 210
161 spin_lock(&dcache_lock); 211 spin_lock(&dcache_lock);
162repeat: 212 for (p = parent; p; p = next_dentry(p, parent)) {
163 next = this_parent->d_subdirs.next;
164resume:
165 while (next != &this_parent->d_subdirs) {
166 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
167
168 /* Negative dentry - give up */ 213 /* Negative dentry - give up */
169 if (!simple_positive(dentry)) { 214 if (!simple_positive(p))
170 next = next->next;
171 continue; 215 continue;
172 }
173 216
174 DPRINTK("dentry %p %.*s", 217 DPRINTK("dentry %p %.*s",
175 dentry, (int)dentry->d_name.len, dentry->d_name.name); 218 p, (int) p->d_name.len, p->d_name.name);
176
177 if (!list_empty(&dentry->d_subdirs)) {
178 this_parent = dentry;
179 goto repeat;
180 }
181 219
182 dentry = dget(dentry); 220 p = dget(p);
183 spin_unlock(&dcache_lock); 221 spin_unlock(&dcache_lock);
184 222
185 if (d_mountpoint(dentry)) { 223 if (d_mountpoint(p)) {
186 /* Can we expire this guy */
187 if (!autofs4_can_expire(dentry, timeout, do_now))
188 goto cont;
189
190 /* Can we umount this guy */ 224 /* Can we umount this guy */
191 if (autofs4_check_mount(mnt, dentry)) 225 if (autofs4_mount_busy(mnt, p))
192 return dentry; 226 goto cont;
193 227
228 /* Can we expire this guy */
229 if (autofs4_can_expire(p, timeout, do_now))
230 return p;
194 } 231 }
195cont: 232cont:
196 dput(dentry); 233 dput(p);
197 spin_lock(&dcache_lock); 234 spin_lock(&dcache_lock);
198 next = next->next;
199 } 235 }
236 spin_unlock(&dcache_lock);
237 return NULL;
238}
239
240/* Check if we can expire a direct mount (possibly a tree) */
241static struct dentry *autofs4_expire_direct(struct super_block *sb,
242 struct vfsmount *mnt,
243 struct autofs_sb_info *sbi,
244 int how)
245{
246 unsigned long timeout;
247 struct dentry *root = dget(sb->s_root);
248 int do_now = how & AUTOFS_EXP_IMMEDIATE;
249
250 if (!sbi->exp_timeout || !root)
251 return NULL;
252
253 now = jiffies;
254 timeout = sbi->exp_timeout;
255
256 /* Lock the tree as we must expire as a whole */
257 spin_lock(&sbi->fs_lock);
258 if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
259 struct autofs_info *ino = autofs4_dentry_ino(root);
200 260
201 if (this_parent != parent) { 261 /* Set this flag early to catch sys_chdir and the like */
202 next = this_parent->d_u.d_child.next; 262 ino->flags |= AUTOFS_INF_EXPIRING;
203 this_parent = this_parent->d_parent; 263 spin_unlock(&sbi->fs_lock);
204 goto resume; 264 return root;
205 } 265 }
206 spin_unlock(&dcache_lock); 266 spin_unlock(&sbi->fs_lock);
267 dput(root);
207 268
208 return NULL; 269 return NULL;
209} 270}
@@ -214,10 +275,10 @@ cont:
214 * - it is unused by any user process 275 * - it is unused by any user process
215 * - it has been unused for exp_timeout time 276 * - it has been unused for exp_timeout time
216 */ 277 */
217static struct dentry *autofs4_expire(struct super_block *sb, 278static struct dentry *autofs4_expire_indirect(struct super_block *sb,
218 struct vfsmount *mnt, 279 struct vfsmount *mnt,
219 struct autofs_sb_info *sbi, 280 struct autofs_sb_info *sbi,
220 int how) 281 int how)
221{ 282{
222 unsigned long timeout; 283 unsigned long timeout;
223 struct dentry *root = sb->s_root; 284 struct dentry *root = sb->s_root;
@@ -241,7 +302,7 @@ static struct dentry *autofs4_expire(struct super_block *sb,
241 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); 302 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
242 303
243 /* Negative dentry - give up */ 304 /* Negative dentry - give up */
244 if ( !simple_positive(dentry) ) { 305 if (!simple_positive(dentry)) {
245 next = next->next; 306 next = next->next;
246 continue; 307 continue;
247 } 308 }
@@ -249,31 +310,36 @@ static struct dentry *autofs4_expire(struct super_block *sb,
249 dentry = dget(dentry); 310 dentry = dget(dentry);
250 spin_unlock(&dcache_lock); 311 spin_unlock(&dcache_lock);
251 312
252 /* Case 1: indirect mount or top level direct mount */ 313 /*
314 * Case 1: (i) indirect mount or top level pseudo direct mount
315 * (autofs-4.1).
316 * (ii) indirect mount with offset mount, check the "/"
317 * offset (autofs-5.0+).
318 */
253 if (d_mountpoint(dentry)) { 319 if (d_mountpoint(dentry)) {
254 DPRINTK("checking mountpoint %p %.*s", 320 DPRINTK("checking mountpoint %p %.*s",
255 dentry, (int)dentry->d_name.len, dentry->d_name.name); 321 dentry, (int)dentry->d_name.len, dentry->d_name.name);
256 322
257 /* Can we expire this guy */ 323 /* Can we umount this guy */
258 if (!autofs4_can_expire(dentry, timeout, do_now)) 324 if (autofs4_mount_busy(mnt, dentry))
259 goto next; 325 goto next;
260 326
261 /* Can we umount this guy */ 327 /* Can we expire this guy */
262 if (autofs4_check_mount(mnt, dentry)) { 328 if (autofs4_can_expire(dentry, timeout, do_now)) {
263 expired = dentry; 329 expired = dentry;
264 break; 330 break;
265 } 331 }
266 goto next; 332 goto next;
267 } 333 }
268 334
269 if ( simple_empty(dentry) ) 335 if (simple_empty(dentry))
270 goto next; 336 goto next;
271 337
272 /* Case 2: tree mount, expire iff entire tree is not busy */ 338 /* Case 2: tree mount, expire iff entire tree is not busy */
273 if (!exp_leaves) { 339 if (!exp_leaves) {
274 /* Lock the tree as we must expire as a whole */ 340 /* Lock the tree as we must expire as a whole */
275 spin_lock(&sbi->fs_lock); 341 spin_lock(&sbi->fs_lock);
276 if (autofs4_check_tree(mnt, dentry, timeout, do_now)) { 342 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
277 struct autofs_info *inf = autofs4_dentry_ino(dentry); 343 struct autofs_info *inf = autofs4_dentry_ino(dentry);
278 344
279 /* Set this flag early to catch sys_chdir and the like */ 345 /* Set this flag early to catch sys_chdir and the like */
@@ -283,7 +349,10 @@ static struct dentry *autofs4_expire(struct super_block *sb,
283 break; 349 break;
284 } 350 }
285 spin_unlock(&sbi->fs_lock); 351 spin_unlock(&sbi->fs_lock);
286 /* Case 3: direct mount, expire individual leaves */ 352 /*
353 * Case 3: pseudo direct mount, expire individual leaves
354 * (autofs-4.1).
355 */
287 } else { 356 } else {
288 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); 357 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
289 if (expired) { 358 if (expired) {
@@ -297,7 +366,7 @@ next:
297 next = next->next; 366 next = next->next;
298 } 367 }
299 368
300 if ( expired ) { 369 if (expired) {
301 DPRINTK("returning %p %.*s", 370 DPRINTK("returning %p %.*s",
302 expired, (int)expired->d_name.len, expired->d_name.name); 371 expired, (int)expired->d_name.len, expired->d_name.name);
303 spin_lock(&dcache_lock); 372 spin_lock(&dcache_lock);
@@ -325,7 +394,7 @@ int autofs4_expire_run(struct super_block *sb,
325 pkt.hdr.proto_version = sbi->version; 394 pkt.hdr.proto_version = sbi->version;
326 pkt.hdr.type = autofs_ptype_expire; 395 pkt.hdr.type = autofs_ptype_expire;
327 396
328 if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL) 397 if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
329 return -EAGAIN; 398 return -EAGAIN;
330 399
331 pkt.len = dentry->d_name.len; 400 pkt.len = dentry->d_name.len;
@@ -351,17 +420,22 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
351 if (arg && get_user(do_now, arg)) 420 if (arg && get_user(do_now, arg))
352 return -EFAULT; 421 return -EFAULT;
353 422
354 if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) { 423 if (sbi->type & AUTOFS_TYPE_DIRECT)
355 struct autofs_info *de_info = autofs4_dentry_ino(dentry); 424 dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
425 else
426 dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);
427
428 if (dentry) {
429 struct autofs_info *ino = autofs4_dentry_ino(dentry);
356 430
357 /* This is synchronous because it makes the daemon a 431 /* This is synchronous because it makes the daemon a
358 little easier */ 432 little easier */
359 de_info->flags |= AUTOFS_INF_EXPIRING; 433 ino->flags |= AUTOFS_INF_EXPIRING;
360 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); 434 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
361 de_info->flags &= ~AUTOFS_INF_EXPIRING; 435 ino->flags &= ~AUTOFS_INF_EXPIRING;
362 dput(dentry); 436 dput(dentry);
363 } 437 }
364 438
365 return ret; 439 return ret;
366} 440}
367 441