diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 2 | ||||
-rw-r--r-- | fs/autofs4/dev-ioctl.c | 29 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 27 | ||||
-rw-r--r-- | fs/autofs4/inode.c | 2 | ||||
-rw-r--r-- | fs/autofs4/root.c | 45 |
5 files changed, 44 insertions, 61 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index a76803108d06..b7ff33c63101 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -186,6 +186,8 @@ int autofs4_expire_wait(struct dentry *dentry); | |||
186 | int autofs4_expire_run(struct super_block *, struct vfsmount *, | 186 | int autofs4_expire_run(struct super_block *, struct vfsmount *, |
187 | struct autofs_sb_info *, | 187 | struct autofs_sb_info *, |
188 | struct autofs_packet_expire __user *); | 188 | struct autofs_packet_expire __user *); |
189 | int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, | ||
190 | struct autofs_sb_info *sbi, int when); | ||
189 | int autofs4_expire_multi(struct super_block *, struct vfsmount *, | 191 | int autofs4_expire_multi(struct super_block *, struct vfsmount *, |
190 | struct autofs_sb_info *, int __user *); | 192 | struct autofs_sb_info *, int __user *); |
191 | struct dentry *autofs4_expire_direct(struct super_block *sb, | 193 | struct dentry *autofs4_expire_direct(struct super_block *sb, |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 025e105bffea..9e5ae8a4f5c8 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -525,40 +525,13 @@ static int autofs_dev_ioctl_expire(struct file *fp, | |||
525 | struct autofs_sb_info *sbi, | 525 | struct autofs_sb_info *sbi, |
526 | struct autofs_dev_ioctl *param) | 526 | struct autofs_dev_ioctl *param) |
527 | { | 527 | { |
528 | struct dentry *dentry; | ||
529 | struct vfsmount *mnt; | 528 | struct vfsmount *mnt; |
530 | int err = -EAGAIN; | ||
531 | int how; | 529 | int how; |
532 | 530 | ||
533 | how = param->expire.how; | 531 | how = param->expire.how; |
534 | mnt = fp->f_path.mnt; | 532 | mnt = fp->f_path.mnt; |
535 | 533 | ||
536 | if (autofs_type_trigger(sbi->type)) | 534 | return autofs4_do_expire_multi(sbi->sb, mnt, sbi, how); |
537 | dentry = autofs4_expire_direct(sbi->sb, mnt, sbi, how); | ||
538 | else | ||
539 | dentry = autofs4_expire_indirect(sbi->sb, mnt, sbi, how); | ||
540 | |||
541 | if (dentry) { | ||
542 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
543 | |||
544 | /* | ||
545 | * This is synchronous because it makes the daemon a | ||
546 | * little easier | ||
547 | */ | ||
548 | err = autofs4_wait(sbi, dentry, NFY_EXPIRE); | ||
549 | |||
550 | spin_lock(&sbi->fs_lock); | ||
551 | if (ino->flags & AUTOFS_INF_MOUNTPOINT) { | ||
552 | ino->flags &= ~AUTOFS_INF_MOUNTPOINT; | ||
553 | sbi->sb->s_root->d_mounted++; | ||
554 | } | ||
555 | ino->flags &= ~AUTOFS_INF_EXPIRING; | ||
556 | complete_all(&ino->expire_complete); | ||
557 | spin_unlock(&sbi->fs_lock); | ||
558 | dput(dentry); | ||
559 | } | ||
560 | |||
561 | return err; | ||
562 | } | 535 | } |
563 | 536 | ||
564 | /* Check if autofs mount point is in use */ | 537 | /* Check if autofs mount point is in use */ |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index e3bd50776f9e..75f7ddacf7d6 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -478,22 +478,16 @@ int autofs4_expire_run(struct super_block *sb, | |||
478 | return ret; | 478 | return ret; |
479 | } | 479 | } |
480 | 480 | ||
481 | /* Call repeatedly until it returns -EAGAIN, meaning there's nothing | 481 | int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, |
482 | more to be done */ | 482 | struct autofs_sb_info *sbi, int when) |
483 | int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | ||
484 | struct autofs_sb_info *sbi, int __user *arg) | ||
485 | { | 483 | { |
486 | struct dentry *dentry; | 484 | struct dentry *dentry; |
487 | int ret = -EAGAIN; | 485 | int ret = -EAGAIN; |
488 | int do_now = 0; | ||
489 | |||
490 | if (arg && get_user(do_now, arg)) | ||
491 | return -EFAULT; | ||
492 | 486 | ||
493 | if (autofs_type_trigger(sbi->type)) | 487 | if (autofs_type_trigger(sbi->type)) |
494 | dentry = autofs4_expire_direct(sb, mnt, sbi, do_now); | 488 | dentry = autofs4_expire_direct(sb, mnt, sbi, when); |
495 | else | 489 | else |
496 | dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now); | 490 | dentry = autofs4_expire_indirect(sb, mnt, sbi, when); |
497 | 491 | ||
498 | if (dentry) { | 492 | if (dentry) { |
499 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 493 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
@@ -516,3 +510,16 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
516 | return ret; | 510 | return ret; |
517 | } | 511 | } |
518 | 512 | ||
513 | /* Call repeatedly until it returns -EAGAIN, meaning there's nothing | ||
514 | more to be done */ | ||
515 | int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | ||
516 | struct autofs_sb_info *sbi, int __user *arg) | ||
517 | { | ||
518 | int do_now = 0; | ||
519 | |||
520 | if (arg && get_user(do_now, arg)) | ||
521 | return -EFAULT; | ||
522 | |||
523 | return autofs4_do_expire_multi(sb, mnt, sbi, do_now); | ||
524 | } | ||
525 | |||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 716e12b627b2..69c8142da838 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -310,7 +310,7 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) | |||
310 | return ino; | 310 | return ino; |
311 | } | 311 | } |
312 | 312 | ||
313 | static struct dentry_operations autofs4_sb_dentry_operations = { | 313 | static const struct dentry_operations autofs4_sb_dentry_operations = { |
314 | .d_release = autofs4_dentry_release, | 314 | .d_release = autofs4_dentry_release, |
315 | }; | 315 | }; |
316 | 316 | ||
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 2a41c2a7fc52..e383bf0334f1 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -349,13 +349,13 @@ void autofs4_dentry_release(struct dentry *de) | |||
349 | } | 349 | } |
350 | 350 | ||
351 | /* For dentries of directories in the root dir */ | 351 | /* For dentries of directories in the root dir */ |
352 | static struct dentry_operations autofs4_root_dentry_operations = { | 352 | static const struct dentry_operations autofs4_root_dentry_operations = { |
353 | .d_revalidate = autofs4_revalidate, | 353 | .d_revalidate = autofs4_revalidate, |
354 | .d_release = autofs4_dentry_release, | 354 | .d_release = autofs4_dentry_release, |
355 | }; | 355 | }; |
356 | 356 | ||
357 | /* For other dentries */ | 357 | /* For other dentries */ |
358 | static struct dentry_operations autofs4_dentry_operations = { | 358 | static const struct dentry_operations autofs4_dentry_operations = { |
359 | .d_revalidate = autofs4_revalidate, | 359 | .d_revalidate = autofs4_revalidate, |
360 | .d_release = autofs4_dentry_release, | 360 | .d_release = autofs4_dentry_release, |
361 | }; | 361 | }; |
@@ -485,22 +485,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
485 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 485 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
486 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 486 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
487 | 487 | ||
488 | expiring = autofs4_lookup_expiring(sbi, dentry->d_parent, &dentry->d_name); | ||
489 | if (expiring) { | ||
490 | /* | ||
491 | * If we are racing with expire the request might not | ||
492 | * be quite complete but the directory has been removed | ||
493 | * so it must have been successful, so just wait for it. | ||
494 | */ | ||
495 | ino = autofs4_dentry_ino(expiring); | ||
496 | autofs4_expire_wait(expiring); | ||
497 | spin_lock(&sbi->lookup_lock); | ||
498 | if (!list_empty(&ino->expiring)) | ||
499 | list_del_init(&ino->expiring); | ||
500 | spin_unlock(&sbi->lookup_lock); | ||
501 | dput(expiring); | ||
502 | } | ||
503 | |||
504 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); | 488 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); |
505 | if (unhashed) | 489 | if (unhashed) |
506 | dentry = unhashed; | 490 | dentry = unhashed; |
@@ -538,14 +522,31 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
538 | } | 522 | } |
539 | 523 | ||
540 | if (!oz_mode) { | 524 | if (!oz_mode) { |
525 | mutex_unlock(&dir->i_mutex); | ||
526 | expiring = autofs4_lookup_expiring(sbi, | ||
527 | dentry->d_parent, | ||
528 | &dentry->d_name); | ||
529 | if (expiring) { | ||
530 | /* | ||
531 | * If we are racing with expire the request might not | ||
532 | * be quite complete but the directory has been removed | ||
533 | * so it must have been successful, so just wait for it. | ||
534 | */ | ||
535 | ino = autofs4_dentry_ino(expiring); | ||
536 | autofs4_expire_wait(expiring); | ||
537 | spin_lock(&sbi->lookup_lock); | ||
538 | if (!list_empty(&ino->expiring)) | ||
539 | list_del_init(&ino->expiring); | ||
540 | spin_unlock(&sbi->lookup_lock); | ||
541 | dput(expiring); | ||
542 | } | ||
543 | |||
541 | spin_lock(&dentry->d_lock); | 544 | spin_lock(&dentry->d_lock); |
542 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 545 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; |
543 | spin_unlock(&dentry->d_lock); | 546 | spin_unlock(&dentry->d_lock); |
544 | if (dentry->d_op && dentry->d_op->d_revalidate) { | 547 | if (dentry->d_op && dentry->d_op->d_revalidate) |
545 | mutex_unlock(&dir->i_mutex); | ||
546 | (dentry->d_op->d_revalidate)(dentry, nd); | 548 | (dentry->d_op->d_revalidate)(dentry, nd); |
547 | mutex_lock(&dir->i_mutex); | 549 | mutex_lock(&dir->i_mutex); |
548 | } | ||
549 | } | 550 | } |
550 | 551 | ||
551 | /* | 552 | /* |