diff options
author | J. Bruce Fields <bfields@redhat.com> | 2013-09-09 16:15:13 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-09 00:16:36 -0500 |
commit | 0dbc018a490ed482a1236aad77ac12e20742b322 (patch) | |
tree | 22ea922d1d9d68bf7d9d1f82e256380e87190f5c | |
parent | 78cee9a8e4b42b3f585ea3bd1c076f5a76fee722 (diff) |
exportfs: clear DISCONNECTED on all parents sooner
Once we've found any connected parent, we know all our parents are
connected--that's true even if there's a concurrent rename. May as well
clear them all at once and be done with it.
Reviewed-by: Cristoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/exportfs/expfs.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 87e6dca69e43..c65b748688ff 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -90,6 +90,24 @@ find_disconnected_root(struct dentry *dentry) | |||
90 | return dentry; | 90 | return dentry; |
91 | } | 91 | } |
92 | 92 | ||
93 | static void clear_disconnected(struct dentry *dentry) | ||
94 | { | ||
95 | dget(dentry); | ||
96 | while (dentry->d_flags & DCACHE_DISCONNECTED) { | ||
97 | struct dentry *parent = dget_parent(dentry); | ||
98 | |||
99 | WARN_ON_ONCE(IS_ROOT(dentry)); | ||
100 | |||
101 | spin_lock(&dentry->d_lock); | ||
102 | dentry->d_flags &= ~DCACHE_DISCONNECTED; | ||
103 | spin_unlock(&dentry->d_lock); | ||
104 | |||
105 | dput(dentry); | ||
106 | dentry = parent; | ||
107 | } | ||
108 | dput(dentry); | ||
109 | } | ||
110 | |||
93 | /* | 111 | /* |
94 | * Make sure target_dir is fully connected to the dentry tree. | 112 | * Make sure target_dir is fully connected to the dentry tree. |
95 | * | 113 | * |
@@ -128,10 +146,9 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf) | |||
128 | 146 | ||
129 | if (!IS_ROOT(pd)) { | 147 | if (!IS_ROOT(pd)) { |
130 | /* must have found a connected parent - great */ | 148 | /* must have found a connected parent - great */ |
131 | spin_lock(&pd->d_lock); | 149 | clear_disconnected(target_dir); |
132 | pd->d_flags &= ~DCACHE_DISCONNECTED; | 150 | dput(pd); |
133 | spin_unlock(&pd->d_lock); | 151 | break; |
134 | noprogress = 0; | ||
135 | } else { | 152 | } else { |
136 | /* | 153 | /* |
137 | * We have hit the top of a disconnected path, try to | 154 | * We have hit the top of a disconnected path, try to |