diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/autofs4/expire.c | 13 | ||||
-rw-r--r-- | fs/dcache.c | 1 | ||||
-rw-r--r-- | fs/namespace.c | 29 |
3 files changed, 37 insertions, 6 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 2f7951d67d16..cc1d01365905 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -295,7 +295,9 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, | |||
295 | struct autofs_info *ino = autofs4_dentry_ino(root); | 295 | struct autofs_info *ino = autofs4_dentry_ino(root); |
296 | if (d_mountpoint(root)) { | 296 | if (d_mountpoint(root)) { |
297 | ino->flags |= AUTOFS_INF_MOUNTPOINT; | 297 | ino->flags |= AUTOFS_INF_MOUNTPOINT; |
298 | root->d_mounted--; | 298 | spin_lock(&root->d_lock); |
299 | root->d_flags &= ~DCACHE_MOUNTED; | ||
300 | spin_unlock(&root->d_lock); | ||
299 | } | 301 | } |
300 | ino->flags |= AUTOFS_INF_EXPIRING; | 302 | ino->flags |= AUTOFS_INF_EXPIRING; |
301 | init_completion(&ino->expire_complete); | 303 | init_completion(&ino->expire_complete); |
@@ -503,7 +505,14 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
503 | 505 | ||
504 | spin_lock(&sbi->fs_lock); | 506 | spin_lock(&sbi->fs_lock); |
505 | if (ino->flags & AUTOFS_INF_MOUNTPOINT) { | 507 | if (ino->flags & AUTOFS_INF_MOUNTPOINT) { |
506 | sb->s_root->d_mounted++; | 508 | spin_lock(&sb->s_root->d_lock); |
509 | /* | ||
510 | * If we haven't been expired away, then reset | ||
511 | * mounted status. | ||
512 | */ | ||
513 | if (mnt->mnt_parent != mnt) | ||
514 | sb->s_root->d_flags |= DCACHE_MOUNTED; | ||
515 | spin_unlock(&sb->s_root->d_lock); | ||
507 | ino->flags &= ~AUTOFS_INF_MOUNTPOINT; | 516 | ino->flags &= ~AUTOFS_INF_MOUNTPOINT; |
508 | } | 517 | } |
509 | ino->flags &= ~AUTOFS_INF_EXPIRING; | 518 | ino->flags &= ~AUTOFS_INF_EXPIRING; |
diff --git a/fs/dcache.c b/fs/dcache.c index 187fea040108..1d5cf511e1c7 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1265,7 +1265,6 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1265 | dentry->d_sb = NULL; | 1265 | dentry->d_sb = NULL; |
1266 | dentry->d_op = NULL; | 1266 | dentry->d_op = NULL; |
1267 | dentry->d_fsdata = NULL; | 1267 | dentry->d_fsdata = NULL; |
1268 | dentry->d_mounted = 0; | ||
1269 | INIT_HLIST_NODE(&dentry->d_hash); | 1268 | INIT_HLIST_NODE(&dentry->d_hash); |
1270 | INIT_LIST_HEAD(&dentry->d_lru); | 1269 | INIT_LIST_HEAD(&dentry->d_lru); |
1271 | INIT_LIST_HEAD(&dentry->d_subdirs); | 1270 | INIT_LIST_HEAD(&dentry->d_subdirs); |
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 | } |