aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/waitq.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4/waitq.c')
-rw-r--r--fs/autofs4/waitq.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 2341375386f8..25435987d6ae 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -186,16 +186,26 @@ 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 unsigned seq;
192 193
193 spin_lock(&dcache_lock); 194rename_retry:
195 buf = *name;
196 len = 0;
197
198 seq = read_seqbegin(&rename_lock);
199 rcu_read_lock();
200 spin_lock(&sbi->fs_lock);
194 for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) 201 for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
195 len += tmp->d_name.len + 1; 202 len += tmp->d_name.len + 1;
196 203
197 if (!len || --len > NAME_MAX) { 204 if (!len || --len > NAME_MAX) {
198 spin_unlock(&dcache_lock); 205 spin_unlock(&sbi->fs_lock);
206 rcu_read_unlock();
207 if (read_seqretry(&rename_lock, seq))
208 goto rename_retry;
199 return 0; 209 return 0;
200 } 210 }
201 211
@@ -208,7 +218,10 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
208 p -= tmp->d_name.len; 218 p -= tmp->d_name.len;
209 strncpy(p, tmp->d_name.name, tmp->d_name.len); 219 strncpy(p, tmp->d_name.name, tmp->d_name.len);
210 } 220 }
211 spin_unlock(&dcache_lock); 221 spin_unlock(&sbi->fs_lock);
222 rcu_read_unlock();
223 if (read_seqretry(&rename_lock, seq))
224 goto rename_retry;
212 225
213 return len; 226 return len;
214} 227}
@@ -296,6 +309,9 @@ static int validate_request(struct autofs_wait_queue **wait,
296 * completed while we waited on the mutex ... 309 * completed while we waited on the mutex ...
297 */ 310 */
298 if (notify == NFY_MOUNT) { 311 if (notify == NFY_MOUNT) {
312 struct dentry *new = NULL;
313 int valid = 1;
314
299 /* 315 /*
300 * If the dentry was successfully mounted while we slept 316 * If the dentry was successfully mounted while we slept
301 * on the wait queue mutex we can return success. If it 317 * on the wait queue mutex we can return success. If it
@@ -303,8 +319,20 @@ static int validate_request(struct autofs_wait_queue **wait,
303 * a multi-mount with no mount at it's base) we can 319 * a multi-mount with no mount at it's base) we can
304 * continue on and create a new request. 320 * continue on and create a new request.
305 */ 321 */
322 if (!IS_ROOT(dentry)) {
323 if (dentry->d_inode && d_unhashed(dentry)) {
324 struct dentry *parent = dentry->d_parent;
325 new = d_lookup(parent, &dentry->d_name);
326 if (new)
327 dentry = new;
328 }
329 }
306 if (have_submounts(dentry)) 330 if (have_submounts(dentry))
307 return 0; 331 valid = 0;
332
333 if (new)
334 dput(new);
335 return valid;
308 } 336 }
309 337
310 return 1; 338 return 1;