diff options
Diffstat (limited to 'fs/autofs4/waitq.c')
-rw-r--r-- | fs/autofs4/waitq.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 2341375386f8..4be8f778a418 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -186,16 +186,25 @@ static int autofs4_getpath(struct autofs_sb_info *sbi, | |||
186 | { | 186 | { |
187 | struct dentry *root = sbi->sb->s_root; | 187 | struct dentry *root = sbi->sb->s_root; |
188 | struct dentry *tmp; | 188 | struct dentry *tmp; |
189 | char *buf = *name; | 189 | char *buf; |
190 | char *p; | 190 | char *p; |
191 | int len = 0; | 191 | int len; |
192 | 192 | unsigned seq; | |
193 | |||
194 | rename_retry: | ||
195 | buf = *name; | ||
196 | len = 0; | ||
197 | seq = read_seqbegin(&rename_lock); | ||
198 | rcu_read_lock(); | ||
193 | spin_lock(&dcache_lock); | 199 | spin_lock(&dcache_lock); |
194 | for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) | 200 | for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) |
195 | len += tmp->d_name.len + 1; | 201 | len += tmp->d_name.len + 1; |
196 | 202 | ||
197 | if (!len || --len > NAME_MAX) { | 203 | if (!len || --len > NAME_MAX) { |
198 | spin_unlock(&dcache_lock); | 204 | spin_unlock(&dcache_lock); |
205 | rcu_read_unlock(); | ||
206 | if (read_seqretry(&rename_lock, seq)) | ||
207 | goto rename_retry; | ||
199 | return 0; | 208 | return 0; |
200 | } | 209 | } |
201 | 210 | ||
@@ -209,6 +218,9 @@ static int autofs4_getpath(struct autofs_sb_info *sbi, | |||
209 | strncpy(p, tmp->d_name.name, tmp->d_name.len); | 218 | strncpy(p, tmp->d_name.name, tmp->d_name.len); |
210 | } | 219 | } |
211 | spin_unlock(&dcache_lock); | 220 | spin_unlock(&dcache_lock); |
221 | rcu_read_unlock(); | ||
222 | if (read_seqretry(&rename_lock, seq)) | ||
223 | goto rename_retry; | ||
212 | 224 | ||
213 | return len; | 225 | return len; |
214 | } | 226 | } |