aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2006-03-27 04:14:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:40 -0500
commit3a15e2ab5d6e79a79291734ac24f33d51c0ae389 (patch)
treec195237286cab27521be8bc266a6f879e7e72e34 /fs/autofs4/expire.c
parent34ca959cfc15cf09ad4da4f31ab034691e51af78 (diff)
[PATCH] autofs4: add v5 expire logic
This patch adds expire logic for autofs direct mounts. Signed-off-by: Ian Kent <raven@themaw.net> Cc: Al Viro <viro@ftp.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> 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.c96
1 files changed, 87 insertions, 9 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 02a218fbde5f..8fd92eaf936d 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
@@ -99,6 +99,39 @@ static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
99 return list_entry(next, struct dentry, d_u.d_child); 99 return list_entry(next, struct dentry, d_u.d_child);
100} 100}
101 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 /* Not a mountpoint - give up */
117 if (!d_mountpoint(top))
118 return 1;
119
120 /* If it's busy update the expiry counters */
121 if (!may_umount_tree(mnt)) {
122 struct autofs_info *ino = autofs4_dentry_ino(top);
123 if (ino)
124 ino->last_used = jiffies;
125 return 1;
126 }
127
128 /* Timeout of a direct mount is determined by its top dentry */
129 if (!autofs4_can_expire(top, timeout, do_now))
130 return 1;
131
132 return 0;
133}
134
102/* Check a directory tree of mount points for busyness 135/* Check a directory tree of mount points for busyness
103 * The tree is not busy iff no mountpoints are busy 136 * The tree is not busy iff no mountpoints are busy
104 */ 137 */
@@ -208,16 +241,48 @@ cont:
208 return NULL; 241 return NULL;
209} 242}
210 243
244/* Check if we can expire a direct mount (possibly a tree) */
245static struct dentry *autofs4_expire_direct(struct super_block *sb,
246 struct vfsmount *mnt,
247 struct autofs_sb_info *sbi,
248 int how)
249{
250 unsigned long timeout;
251 struct dentry *root = dget(sb->s_root);
252 int do_now = how & AUTOFS_EXP_IMMEDIATE;
253
254 if (!sbi->exp_timeout || !root)
255 return NULL;
256
257 now = jiffies;
258 timeout = sbi->exp_timeout;
259
260 /* Lock the tree as we must expire as a whole */
261 spin_lock(&sbi->fs_lock);
262 if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
263 struct autofs_info *ino = autofs4_dentry_ino(root);
264
265 /* Set this flag early to catch sys_chdir and the like */
266 ino->flags |= AUTOFS_INF_EXPIRING;
267 spin_unlock(&sbi->fs_lock);
268 return root;
269 }
270 spin_unlock(&sbi->fs_lock);
271 dput(root);
272
273 return NULL;
274}
275
211/* 276/*
212 * Find an eligible tree to time-out 277 * Find an eligible tree to time-out
213 * A tree is eligible if :- 278 * A tree is eligible if :-
214 * - it is unused by any user process 279 * - it is unused by any user process
215 * - it has been unused for exp_timeout time 280 * - it has been unused for exp_timeout time
216 */ 281 */
217static struct dentry *autofs4_expire(struct super_block *sb, 282static struct dentry *autofs4_expire_indirect(struct super_block *sb,
218 struct vfsmount *mnt, 283 struct vfsmount *mnt,
219 struct autofs_sb_info *sbi, 284 struct autofs_sb_info *sbi,
220 int how) 285 int how)
221{ 286{
222 unsigned long timeout; 287 unsigned long timeout;
223 struct dentry *root = sb->s_root; 288 struct dentry *root = sb->s_root;
@@ -249,7 +314,12 @@ static struct dentry *autofs4_expire(struct super_block *sb,
249 dentry = dget(dentry); 314 dentry = dget(dentry);
250 spin_unlock(&dcache_lock); 315 spin_unlock(&dcache_lock);
251 316
252 /* Case 1: indirect mount or top level direct mount */ 317 /*
318 * Case 1: (i) indirect mount or top level pseudo direct mount
319 * (autofs-4.1).
320 * (ii) indirect mount with offset mount, check the "/"
321 * offset (autofs-5.0+).
322 */
253 if (d_mountpoint(dentry)) { 323 if (d_mountpoint(dentry)) {
254 DPRINTK("checking mountpoint %p %.*s", 324 DPRINTK("checking mountpoint %p %.*s",
255 dentry, (int)dentry->d_name.len, dentry->d_name.name); 325 dentry, (int)dentry->d_name.len, dentry->d_name.name);
@@ -283,7 +353,10 @@ static struct dentry *autofs4_expire(struct super_block *sb,
283 break; 353 break;
284 } 354 }
285 spin_unlock(&sbi->fs_lock); 355 spin_unlock(&sbi->fs_lock);
286 /* Case 3: direct mount, expire individual leaves */ 356 /*
357 * Case 3: pseudo direct mount, expire individual leaves
358 * (autofs-4.1).
359 */
287 } else { 360 } else {
288 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); 361 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
289 if (expired) { 362 if (expired) {
@@ -325,7 +398,7 @@ int autofs4_expire_run(struct super_block *sb,
325 pkt.hdr.proto_version = sbi->version; 398 pkt.hdr.proto_version = sbi->version;
326 pkt.hdr.type = autofs_ptype_expire; 399 pkt.hdr.type = autofs_ptype_expire;
327 400
328 if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL) 401 if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
329 return -EAGAIN; 402 return -EAGAIN;
330 403
331 pkt.len = dentry->d_name.len; 404 pkt.len = dentry->d_name.len;
@@ -351,7 +424,12 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
351 if (arg && get_user(do_now, arg)) 424 if (arg && get_user(do_now, arg))
352 return -EFAULT; 425 return -EFAULT;
353 426
354 if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) { 427 if (sbi->type & AUTOFS_TYP_DIRECT)
428 dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
429 else
430 dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);
431
432 if (dentry) {
355 struct autofs_info *ino = autofs4_dentry_ino(dentry); 433 struct autofs_info *ino = autofs4_dentry_ino(dentry);
356 434
357 /* This is synchronous because it makes the daemon a 435 /* This is synchronous because it makes the daemon a