diff options
author | Ian Kent <raven@themaw.net> | 2006-03-27 04:14:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-27 11:44:40 -0500 |
commit | 3a15e2ab5d6e79a79291734ac24f33d51c0ae389 (patch) | |
tree | c195237286cab27521be8bc266a6f879e7e72e34 /fs/autofs4 | |
parent | 34ca959cfc15cf09ad4da4f31ab034691e51af78 (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')
-rw-r--r-- | fs/autofs4/expire.c | 96 |
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 | */ | ||
108 | static 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) */ | ||
245 | static 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 | */ |
217 | static struct dentry *autofs4_expire(struct super_block *sb, | 282 | static 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 |