diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/root.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index aa4c5ff8a40d..0533d37c73ae 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -242,6 +242,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
242 | { | 242 | { |
243 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 243 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
244 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 244 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
245 | struct dentry *new; | ||
245 | int status = 0; | 246 | int status = 0; |
246 | 247 | ||
247 | /* Block on any pending expiry here; invalidate the dentry | 248 | /* Block on any pending expiry here; invalidate the dentry |
@@ -318,6 +319,27 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
318 | spin_lock(&dentry->d_lock); | 319 | spin_lock(&dentry->d_lock); |
319 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 320 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
320 | spin_unlock(&dentry->d_lock); | 321 | spin_unlock(&dentry->d_lock); |
322 | |||
323 | /* | ||
324 | * The dentry that is passed in from lookup may not be the one | ||
325 | * we end up using, as mkdir can create a new one. If this | ||
326 | * happens, and another process tries the lookup at the same time, | ||
327 | * it will set the PENDING flag on this new dentry, but add itself | ||
328 | * to our waitq. Then, if after the lookup succeeds, the first | ||
329 | * process that requested the mount performs another lookup of the | ||
330 | * same directory, it will show up as still pending! So, we need | ||
331 | * to redo the lookup here and clear pending on that dentry. | ||
332 | */ | ||
333 | if (d_unhashed(dentry)) { | ||
334 | new = d_lookup(dentry->d_parent, &dentry->d_name); | ||
335 | if (new) { | ||
336 | spin_lock(&new->d_lock); | ||
337 | new->d_flags &= ~DCACHE_AUTOFS_PENDING; | ||
338 | spin_unlock(&new->d_lock); | ||
339 | dput(new); | ||
340 | } | ||
341 | } | ||
342 | |||
321 | return status; | 343 | return status; |
322 | } | 344 | } |
323 | 345 | ||