diff options
Diffstat (limited to 'fs/autofs4/expire.c')
-rw-r--r-- | fs/autofs4/expire.c | 27 |
1 files changed, 8 insertions, 19 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 9510d8d2e9cd..b493909e7492 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -316,19 +316,17 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, | |||
316 | if (ino->flags & AUTOFS_INF_PENDING) | 316 | if (ino->flags & AUTOFS_INF_PENDING) |
317 | goto out; | 317 | goto out; |
318 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | 318 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { |
319 | ino->flags |= AUTOFS_INF_NO_RCU; | 319 | ino->flags |= AUTOFS_INF_WANT_EXPIRE; |
320 | spin_unlock(&sbi->fs_lock); | 320 | spin_unlock(&sbi->fs_lock); |
321 | synchronize_rcu(); | 321 | synchronize_rcu(); |
322 | spin_lock(&sbi->fs_lock); | 322 | spin_lock(&sbi->fs_lock); |
323 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | 323 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { |
324 | ino->flags |= AUTOFS_INF_EXPIRING; | 324 | ino->flags |= AUTOFS_INF_EXPIRING; |
325 | smp_mb(); | ||
326 | ino->flags &= ~AUTOFS_INF_NO_RCU; | ||
327 | init_completion(&ino->expire_complete); | 325 | init_completion(&ino->expire_complete); |
328 | spin_unlock(&sbi->fs_lock); | 326 | spin_unlock(&sbi->fs_lock); |
329 | return root; | 327 | return root; |
330 | } | 328 | } |
331 | ino->flags &= ~AUTOFS_INF_NO_RCU; | 329 | ino->flags &= ~AUTOFS_INF_WANT_EXPIRE; |
332 | } | 330 | } |
333 | out: | 331 | out: |
334 | spin_unlock(&sbi->fs_lock); | 332 | spin_unlock(&sbi->fs_lock); |
@@ -446,7 +444,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
446 | while ((dentry = get_next_positive_subdir(dentry, root))) { | 444 | while ((dentry = get_next_positive_subdir(dentry, root))) { |
447 | spin_lock(&sbi->fs_lock); | 445 | spin_lock(&sbi->fs_lock); |
448 | ino = autofs4_dentry_ino(dentry); | 446 | ino = autofs4_dentry_ino(dentry); |
449 | if (ino->flags & AUTOFS_INF_NO_RCU) | 447 | if (ino->flags & AUTOFS_INF_WANT_EXPIRE) |
450 | expired = NULL; | 448 | expired = NULL; |
451 | else | 449 | else |
452 | expired = should_expire(dentry, mnt, timeout, how); | 450 | expired = should_expire(dentry, mnt, timeout, how); |
@@ -455,7 +453,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
455 | continue; | 453 | continue; |
456 | } | 454 | } |
457 | ino = autofs4_dentry_ino(expired); | 455 | ino = autofs4_dentry_ino(expired); |
458 | ino->flags |= AUTOFS_INF_NO_RCU; | 456 | ino->flags |= AUTOFS_INF_WANT_EXPIRE; |
459 | spin_unlock(&sbi->fs_lock); | 457 | spin_unlock(&sbi->fs_lock); |
460 | synchronize_rcu(); | 458 | synchronize_rcu(); |
461 | spin_lock(&sbi->fs_lock); | 459 | spin_lock(&sbi->fs_lock); |
@@ -465,7 +463,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
465 | goto found; | 463 | goto found; |
466 | } | 464 | } |
467 | 465 | ||
468 | ino->flags &= ~AUTOFS_INF_NO_RCU; | 466 | ino->flags &= ~AUTOFS_INF_WANT_EXPIRE; |
469 | if (expired != dentry) | 467 | if (expired != dentry) |
470 | dput(expired); | 468 | dput(expired); |
471 | spin_unlock(&sbi->fs_lock); | 469 | spin_unlock(&sbi->fs_lock); |
@@ -475,17 +473,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
475 | found: | 473 | found: |
476 | pr_debug("returning %p %pd\n", expired, expired); | 474 | pr_debug("returning %p %pd\n", expired, expired); |
477 | ino->flags |= AUTOFS_INF_EXPIRING; | 475 | ino->flags |= AUTOFS_INF_EXPIRING; |
478 | smp_mb(); | ||
479 | ino->flags &= ~AUTOFS_INF_NO_RCU; | ||
480 | init_completion(&ino->expire_complete); | 476 | init_completion(&ino->expire_complete); |
481 | spin_unlock(&sbi->fs_lock); | 477 | spin_unlock(&sbi->fs_lock); |
482 | spin_lock(&sbi->lookup_lock); | ||
483 | spin_lock(&expired->d_parent->d_lock); | ||
484 | spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED); | ||
485 | list_move(&expired->d_parent->d_subdirs, &expired->d_child); | ||
486 | spin_unlock(&expired->d_lock); | ||
487 | spin_unlock(&expired->d_parent->d_lock); | ||
488 | spin_unlock(&sbi->lookup_lock); | ||
489 | return expired; | 478 | return expired; |
490 | } | 479 | } |
491 | 480 | ||
@@ -496,7 +485,7 @@ int autofs4_expire_wait(struct dentry *dentry, int rcu_walk) | |||
496 | int status; | 485 | int status; |
497 | 486 | ||
498 | /* Block on any pending expire */ | 487 | /* Block on any pending expire */ |
499 | if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))) | 488 | if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE)) |
500 | return 0; | 489 | return 0; |
501 | if (rcu_walk) | 490 | if (rcu_walk) |
502 | return -ECHILD; | 491 | return -ECHILD; |
@@ -554,7 +543,7 @@ int autofs4_expire_run(struct super_block *sb, | |||
554 | ino = autofs4_dentry_ino(dentry); | 543 | ino = autofs4_dentry_ino(dentry); |
555 | /* avoid rapid-fire expire attempts if expiry fails */ | 544 | /* avoid rapid-fire expire attempts if expiry fails */ |
556 | ino->last_used = now; | 545 | ino->last_used = now; |
557 | ino->flags &= ~AUTOFS_INF_EXPIRING; | 546 | ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE); |
558 | complete_all(&ino->expire_complete); | 547 | complete_all(&ino->expire_complete); |
559 | spin_unlock(&sbi->fs_lock); | 548 | spin_unlock(&sbi->fs_lock); |
560 | 549 | ||
@@ -583,7 +572,7 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
583 | spin_lock(&sbi->fs_lock); | 572 | spin_lock(&sbi->fs_lock); |
584 | /* avoid rapid-fire expire attempts if expiry fails */ | 573 | /* avoid rapid-fire expire attempts if expiry fails */ |
585 | ino->last_used = now; | 574 | ino->last_used = now; |
586 | ino->flags &= ~AUTOFS_INF_EXPIRING; | 575 | ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE); |
587 | complete_all(&ino->expire_complete); | 576 | complete_all(&ino->expire_complete); |
588 | spin_unlock(&sbi->fs_lock); | 577 | spin_unlock(&sbi->fs_lock); |
589 | dput(dentry); | 578 | dput(dentry); |