aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/autofs4/expire.c13
-rw-r--r--fs/dcache.c1
-rw-r--r--fs/namespace.c29
-rw-r--r--include/linux/dcache.h42
4 files changed, 58 insertions, 27 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 */
498static 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 */
497static void detach_mnt(struct vfsmount *mnt, struct path *old_path) 518static 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 }
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index c2e7390289cc..e4414693065e 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -92,7 +92,6 @@ struct dentry {
92 unsigned int d_flags; /* protected by d_lock */ 92 unsigned int d_flags; /* protected by d_lock */
93 spinlock_t d_lock; /* per dentry lock */ 93 spinlock_t d_lock; /* per dentry lock */
94 seqcount_t d_seq; /* per dentry seqlock */ 94 seqcount_t d_seq; /* per dentry seqlock */
95 int d_mounted;
96 struct inode *d_inode; /* Where the name belongs to - NULL is 95 struct inode *d_inode; /* Where the name belongs to - NULL is
97 * negative */ 96 * negative */
98 /* 97 /*
@@ -156,33 +155,34 @@ struct dentry_operations {
156 155
157/* d_flags entries */ 156/* d_flags entries */
158#define DCACHE_AUTOFS_PENDING 0x0001 /* autofs: "under construction" */ 157#define DCACHE_AUTOFS_PENDING 0x0001 /* autofs: "under construction" */
159#define DCACHE_NFSFS_RENAMED 0x0002 /* this dentry has been "silly 158#define DCACHE_NFSFS_RENAMED 0x0002
160 * renamed" and has to be 159 /* this dentry has been "silly renamed" and has to be deleted on the last
161 * deleted on the last dput() 160 * dput() */
162 */ 161
163#define DCACHE_DISCONNECTED 0x0004 162#define DCACHE_DISCONNECTED 0x0004
164 /* This dentry is possibly not currently connected to the dcache tree, 163 /* This dentry is possibly not currently connected to the dcache tree, in
165 * in which case its parent will either be itself, or will have this 164 * which case its parent will either be itself, or will have this flag as
166 * flag as well. nfsd will not use a dentry with this bit set, but will 165 * well. nfsd will not use a dentry with this bit set, but will first
167 * first endeavour to clear the bit either by discovering that it is 166 * endeavour to clear the bit either by discovering that it is connected,
168 * connected, or by performing lookup operations. Any filesystem which 167 * or by performing lookup operations. Any filesystem which supports
169 * supports nfsd_operations MUST have a lookup function which, if it finds 168 * nfsd_operations MUST have a lookup function which, if it finds a
170 * a directory inode with a DCACHE_DISCONNECTED dentry, will d_move 169 * directory inode with a DCACHE_DISCONNECTED dentry, will d_move that
171 * that dentry into place and return that dentry rather than the passed one, 170 * dentry into place and return that dentry rather than the passed one,
172 * typically using d_splice_alias. 171 * typically using d_splice_alias. */
173 */
174 172
175#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ 173#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
176#define DCACHE_UNHASHED 0x0010 174#define DCACHE_UNHASHED 0x0010
177 175#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
178#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched by inotify */ 176 /* Parent inode is watched by inotify */
179 177
180#define DCACHE_COOKIE 0x0040 /* For use by dcookie subsystem */ 178#define DCACHE_COOKIE 0x0040 /* For use by dcookie subsystem */
181 179#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080
182#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ 180 /* Parent inode is watched by some fsnotify listener */
183 181
184#define DCACHE_CANT_MOUNT 0x0100 182#define DCACHE_CANT_MOUNT 0x0100
185#define DCACHE_GENOCIDE 0x0200 183#define DCACHE_GENOCIDE 0x0200
184#define DCACHE_MOUNTED 0x0400 /* is a mountpoint */
185
186 186
187extern spinlock_t dcache_inode_lock; 187extern spinlock_t dcache_inode_lock;
188extern seqlock_t rename_lock; 188extern seqlock_t rename_lock;
@@ -372,7 +372,7 @@ extern void dput(struct dentry *);
372 372
373static inline int d_mountpoint(struct dentry *dentry) 373static inline int d_mountpoint(struct dentry *dentry)
374{ 374{
375 return dentry->d_mounted; 375 return dentry->d_flags & DCACHE_MOUNTED;
376} 376}
377 377
378extern struct vfsmount *lookup_mnt(struct path *); 378extern struct vfsmount *lookup_mnt(struct path *);