diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 3dbfc072ec70..39a7d507fba0 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -492,6 +492,27 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) | |||
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /* |
495 | * Clear dentry's mounted state if it has no remaining mounts. | ||
496 | * vfsmount_lock must be held for write. | ||
497 | */ | ||
498 | static void dentry_reset_mounted(struct vfsmount *mnt, struct dentry *dentry) | ||
499 | { | ||
500 | unsigned u; | ||
501 | |||
502 | for (u = 0; u < HASH_SIZE; u++) { | ||
503 | struct vfsmount *p; | ||
504 | |||
505 | list_for_each_entry(p, &mount_hashtable[u], mnt_hash) { | ||
506 | if (p->mnt_mountpoint == dentry) | ||
507 | return; | ||
508 | } | ||
509 | } | ||
510 | spin_lock(&dentry->d_lock); | ||
511 | dentry->d_flags &= ~DCACHE_MOUNTED; | ||
512 | spin_unlock(&dentry->d_lock); | ||
513 | } | ||
514 | |||
515 | /* | ||
495 | * vfsmount lock must be held for write | 516 | * vfsmount lock must be held for write |
496 | */ | 517 | */ |
497 | static void detach_mnt(struct vfsmount *mnt, struct path *old_path) | 518 | static void detach_mnt(struct vfsmount *mnt, struct path *old_path) |
@@ -502,7 +523,7 @@ static void detach_mnt(struct vfsmount *mnt, struct path *old_path) | |||
502 | mnt->mnt_mountpoint = mnt->mnt_root; | 523 | mnt->mnt_mountpoint = mnt->mnt_root; |
503 | list_del_init(&mnt->mnt_child); | 524 | list_del_init(&mnt->mnt_child); |
504 | list_del_init(&mnt->mnt_hash); | 525 | list_del_init(&mnt->mnt_hash); |
505 | old_path->dentry->d_mounted--; | 526 | dentry_reset_mounted(old_path->mnt, old_path->dentry); |
506 | } | 527 | } |
507 | 528 | ||
508 | /* | 529 | /* |
@@ -513,7 +534,9 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | |||
513 | { | 534 | { |
514 | child_mnt->mnt_parent = mntget(mnt); | 535 | child_mnt->mnt_parent = mntget(mnt); |
515 | child_mnt->mnt_mountpoint = dget(dentry); | 536 | child_mnt->mnt_mountpoint = dget(dentry); |
516 | dentry->d_mounted++; | 537 | spin_lock(&dentry->d_lock); |
538 | dentry->d_flags |= DCACHE_MOUNTED; | ||
539 | spin_unlock(&dentry->d_lock); | ||
517 | } | 540 | } |
518 | 541 | ||
519 | /* | 542 | /* |
@@ -1073,7 +1096,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) | |||
1073 | list_del_init(&p->mnt_child); | 1096 | list_del_init(&p->mnt_child); |
1074 | if (p->mnt_parent != p) { | 1097 | if (p->mnt_parent != p) { |
1075 | p->mnt_parent->mnt_ghosts++; | 1098 | p->mnt_parent->mnt_ghosts++; |
1076 | p->mnt_mountpoint->d_mounted--; | 1099 | dentry_reset_mounted(p->mnt_parent, p->mnt_mountpoint); |
1077 | } | 1100 | } |
1078 | change_mnt_propagation(p, MS_PRIVATE); | 1101 | change_mnt_propagation(p, MS_PRIVATE); |
1079 | } | 1102 | } |