diff options
author | NeilBrown <neilb@suse.de> | 2014-10-13 18:52:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 20:18:16 -0400 |
commit | a5d1dba1430f059d5bb4bf1d95274ff01ccad3d9 (patch) | |
tree | 44a1ab49022175e85b81e9674059230124c62713 /fs/autofs4 | |
parent | 23bfc2a24ea3d993cc5cc90c9970654e7232502e (diff) |
autofs4: factor should_expire() out of autofs4_expire_indirect.
Future patch will potentially call this twice, so make it separate.
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Ian Kent <raven@themaw.net>
Tested-by: Ian Kent <raven@themaw.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/expire.c | 162 |
1 files changed, 88 insertions, 74 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 1695eda8ac18..d03bedc7369f 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -339,6 +339,89 @@ out: | |||
339 | return NULL; | 339 | return NULL; |
340 | } | 340 | } |
341 | 341 | ||
342 | /* Check if 'dentry' should expire, or return a nearby | ||
343 | * dentry that is suitable. | ||
344 | * If returned dentry is different from arg dentry, | ||
345 | * then a dget() reference was taken, else not. | ||
346 | */ | ||
347 | static struct dentry *should_expire(struct dentry *dentry, | ||
348 | struct vfsmount *mnt, | ||
349 | unsigned long timeout, | ||
350 | int how) | ||
351 | { | ||
352 | int do_now = how & AUTOFS_EXP_IMMEDIATE; | ||
353 | int exp_leaves = how & AUTOFS_EXP_LEAVES; | ||
354 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
355 | unsigned int ino_count; | ||
356 | |||
357 | /* No point expiring a pending mount */ | ||
358 | if (ino->flags & AUTOFS_INF_PENDING) | ||
359 | return NULL; | ||
360 | |||
361 | /* | ||
362 | * Case 1: (i) indirect mount or top level pseudo direct mount | ||
363 | * (autofs-4.1). | ||
364 | * (ii) indirect mount with offset mount, check the "/" | ||
365 | * offset (autofs-5.0+). | ||
366 | */ | ||
367 | if (d_mountpoint(dentry)) { | ||
368 | DPRINTK("checking mountpoint %p %.*s", | ||
369 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
370 | |||
371 | /* Can we umount this guy */ | ||
372 | if (autofs4_mount_busy(mnt, dentry)) | ||
373 | return NULL; | ||
374 | |||
375 | /* Can we expire this guy */ | ||
376 | if (autofs4_can_expire(dentry, timeout, do_now)) | ||
377 | return dentry; | ||
378 | return NULL; | ||
379 | } | ||
380 | |||
381 | if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) { | ||
382 | DPRINTK("checking symlink %p %.*s", | ||
383 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
384 | /* | ||
385 | * A symlink can't be "busy" in the usual sense so | ||
386 | * just check last used for expire timeout. | ||
387 | */ | ||
388 | if (autofs4_can_expire(dentry, timeout, do_now)) | ||
389 | return dentry; | ||
390 | return NULL; | ||
391 | } | ||
392 | |||
393 | if (simple_empty(dentry)) | ||
394 | return NULL; | ||
395 | |||
396 | /* Case 2: tree mount, expire iff entire tree is not busy */ | ||
397 | if (!exp_leaves) { | ||
398 | /* Path walk currently on this dentry? */ | ||
399 | ino_count = atomic_read(&ino->count) + 1; | ||
400 | if (d_count(dentry) > ino_count) | ||
401 | return NULL; | ||
402 | |||
403 | if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) | ||
404 | return dentry; | ||
405 | /* | ||
406 | * Case 3: pseudo direct mount, expire individual leaves | ||
407 | * (autofs-4.1). | ||
408 | */ | ||
409 | } else { | ||
410 | /* Path walk currently on this dentry? */ | ||
411 | struct dentry *expired; | ||
412 | ino_count = atomic_read(&ino->count) + 1; | ||
413 | if (d_count(dentry) > ino_count) | ||
414 | return NULL; | ||
415 | |||
416 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); | ||
417 | if (expired) { | ||
418 | if (expired == dentry) | ||
419 | dput(dentry); | ||
420 | return expired; | ||
421 | } | ||
422 | } | ||
423 | return NULL; | ||
424 | } | ||
342 | /* | 425 | /* |
343 | * Find an eligible tree to time-out | 426 | * Find an eligible tree to time-out |
344 | * A tree is eligible if :- | 427 | * A tree is eligible if :- |
@@ -353,11 +436,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
353 | unsigned long timeout; | 436 | unsigned long timeout; |
354 | struct dentry *root = sb->s_root; | 437 | struct dentry *root = sb->s_root; |
355 | struct dentry *dentry; | 438 | struct dentry *dentry; |
356 | struct dentry *expired = NULL; | 439 | struct dentry *expired; |
357 | int do_now = how & AUTOFS_EXP_IMMEDIATE; | ||
358 | int exp_leaves = how & AUTOFS_EXP_LEAVES; | ||
359 | struct autofs_info *ino; | 440 | struct autofs_info *ino; |
360 | unsigned int ino_count; | ||
361 | 441 | ||
362 | if (!root) | 442 | if (!root) |
363 | return NULL; | 443 | return NULL; |
@@ -368,78 +448,12 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
368 | dentry = NULL; | 448 | dentry = NULL; |
369 | while ((dentry = get_next_positive_subdir(dentry, root))) { | 449 | while ((dentry = get_next_positive_subdir(dentry, root))) { |
370 | spin_lock(&sbi->fs_lock); | 450 | spin_lock(&sbi->fs_lock); |
371 | ino = autofs4_dentry_ino(dentry); | 451 | expired = should_expire(dentry, mnt, timeout, how); |
372 | /* No point expiring a pending mount */ | 452 | if (expired) { |
373 | if (ino->flags & AUTOFS_INF_PENDING) | 453 | if (expired != dentry) |
374 | goto next; | ||
375 | |||
376 | /* | ||
377 | * Case 1: (i) indirect mount or top level pseudo direct mount | ||
378 | * (autofs-4.1). | ||
379 | * (ii) indirect mount with offset mount, check the "/" | ||
380 | * offset (autofs-5.0+). | ||
381 | */ | ||
382 | if (d_mountpoint(dentry)) { | ||
383 | DPRINTK("checking mountpoint %p %.*s", | ||
384 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
385 | |||
386 | /* Can we umount this guy */ | ||
387 | if (autofs4_mount_busy(mnt, dentry)) | ||
388 | goto next; | ||
389 | |||
390 | /* Can we expire this guy */ | ||
391 | if (autofs4_can_expire(dentry, timeout, do_now)) { | ||
392 | expired = dentry; | ||
393 | goto found; | ||
394 | } | ||
395 | goto next; | ||
396 | } | ||
397 | |||
398 | if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) { | ||
399 | DPRINTK("checking symlink %p %.*s", | ||
400 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
401 | /* | ||
402 | * A symlink can't be "busy" in the usual sense so | ||
403 | * just check last used for expire timeout. | ||
404 | */ | ||
405 | if (autofs4_can_expire(dentry, timeout, do_now)) { | ||
406 | expired = dentry; | ||
407 | goto found; | ||
408 | } | ||
409 | goto next; | ||
410 | } | ||
411 | |||
412 | if (simple_empty(dentry)) | ||
413 | goto next; | ||
414 | |||
415 | /* Case 2: tree mount, expire iff entire tree is not busy */ | ||
416 | if (!exp_leaves) { | ||
417 | /* Path walk currently on this dentry? */ | ||
418 | ino_count = atomic_read(&ino->count) + 1; | ||
419 | if (d_count(dentry) > ino_count) | ||
420 | goto next; | ||
421 | |||
422 | if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { | ||
423 | expired = dentry; | ||
424 | goto found; | ||
425 | } | ||
426 | /* | ||
427 | * Case 3: pseudo direct mount, expire individual leaves | ||
428 | * (autofs-4.1). | ||
429 | */ | ||
430 | } else { | ||
431 | /* Path walk currently on this dentry? */ | ||
432 | ino_count = atomic_read(&ino->count) + 1; | ||
433 | if (d_count(dentry) > ino_count) | ||
434 | goto next; | ||
435 | |||
436 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); | ||
437 | if (expired) { | ||
438 | dput(dentry); | 454 | dput(dentry); |
439 | goto found; | 455 | goto found; |
440 | } | ||
441 | } | 456 | } |
442 | next: | ||
443 | spin_unlock(&sbi->fs_lock); | 457 | spin_unlock(&sbi->fs_lock); |
444 | } | 458 | } |
445 | return NULL; | 459 | return NULL; |