diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 2 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 26 | ||||
-rw-r--r-- | fs/autofs4/root.c | 40 | ||||
-rw-r--r-- | fs/autofs4/waitq.c | 2 |
4 files changed, 45 insertions, 25 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 2d4ae40718d9..c3d352d7fa93 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -35,7 +35,7 @@ | |||
35 | /* #define DEBUG */ | 35 | /* #define DEBUG */ |
36 | 36 | ||
37 | #ifdef DEBUG | 37 | #ifdef DEBUG |
38 | #define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __FUNCTION__ , ##args); } while(0) | 38 | #define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __func__ , ##args); } while(0) |
39 | #else | 39 | #else |
40 | #define DPRINTK(fmt,args...) do {} while(0) | 40 | #define DPRINTK(fmt,args...) do {} while(0) |
41 | #endif | 41 | #endif |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index d96e5c14a9ca..894fee54d4d8 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -73,8 +73,8 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) | |||
73 | status = 0; | 73 | status = 0; |
74 | done: | 74 | done: |
75 | DPRINTK("returning = %d", status); | 75 | DPRINTK("returning = %d", status); |
76 | mntput(mnt); | ||
77 | dput(dentry); | 76 | dput(dentry); |
77 | mntput(mnt); | ||
78 | return status; | 78 | return status; |
79 | } | 79 | } |
80 | 80 | ||
@@ -333,7 +333,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
333 | /* Can we expire this guy */ | 333 | /* Can we expire this guy */ |
334 | if (autofs4_can_expire(dentry, timeout, do_now)) { | 334 | if (autofs4_can_expire(dentry, timeout, do_now)) { |
335 | expired = dentry; | 335 | expired = dentry; |
336 | break; | 336 | goto found; |
337 | } | 337 | } |
338 | goto next; | 338 | goto next; |
339 | } | 339 | } |
@@ -352,7 +352,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
352 | inf->flags |= AUTOFS_INF_EXPIRING; | 352 | inf->flags |= AUTOFS_INF_EXPIRING; |
353 | spin_unlock(&sbi->fs_lock); | 353 | spin_unlock(&sbi->fs_lock); |
354 | expired = dentry; | 354 | expired = dentry; |
355 | break; | 355 | goto found; |
356 | } | 356 | } |
357 | spin_unlock(&sbi->fs_lock); | 357 | spin_unlock(&sbi->fs_lock); |
358 | /* | 358 | /* |
@@ -363,7 +363,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
363 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); | 363 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); |
364 | if (expired) { | 364 | if (expired) { |
365 | dput(dentry); | 365 | dput(dentry); |
366 | break; | 366 | goto found; |
367 | } | 367 | } |
368 | } | 368 | } |
369 | next: | 369 | next: |
@@ -371,18 +371,16 @@ next: | |||
371 | spin_lock(&dcache_lock); | 371 | spin_lock(&dcache_lock); |
372 | next = next->next; | 372 | next = next->next; |
373 | } | 373 | } |
374 | |||
375 | if (expired) { | ||
376 | DPRINTK("returning %p %.*s", | ||
377 | expired, (int)expired->d_name.len, expired->d_name.name); | ||
378 | spin_lock(&dcache_lock); | ||
379 | list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); | ||
380 | spin_unlock(&dcache_lock); | ||
381 | return expired; | ||
382 | } | ||
383 | spin_unlock(&dcache_lock); | 374 | spin_unlock(&dcache_lock); |
384 | |||
385 | return NULL; | 375 | return NULL; |
376 | |||
377 | found: | ||
378 | DPRINTK("returning %p %.*s", | ||
379 | expired, (int)expired->d_name.len, expired->d_name.name); | ||
380 | spin_lock(&dcache_lock); | ||
381 | list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); | ||
382 | spin_unlock(&dcache_lock); | ||
383 | return expired; | ||
386 | } | 384 | } |
387 | 385 | ||
388 | /* Perform an expiry operation */ | 386 | /* Perform an expiry operation */ |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index a54a946a50ae..edf5b6bddb52 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -146,17 +146,17 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
146 | 146 | ||
147 | if (d_mountpoint(dentry)) { | 147 | if (d_mountpoint(dentry)) { |
148 | struct file *fp = NULL; | 148 | struct file *fp = NULL; |
149 | struct vfsmount *fp_mnt = mntget(mnt); | 149 | struct path fp_path = { .dentry = dentry, .mnt = mnt }; |
150 | struct dentry *fp_dentry = dget(dentry); | ||
151 | 150 | ||
152 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { | 151 | path_get(&fp_path); |
153 | dput(fp_dentry); | 152 | |
154 | mntput(fp_mnt); | 153 | if (!autofs4_follow_mount(&fp_path.mnt, &fp_path.dentry)) { |
154 | path_put(&fp_path); | ||
155 | dcache_dir_close(inode, file); | 155 | dcache_dir_close(inode, file); |
156 | goto out; | 156 | goto out; |
157 | } | 157 | } |
158 | 158 | ||
159 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); | 159 | fp = dentry_open(fp_path.dentry, fp_path.mnt, file->f_flags); |
160 | status = PTR_ERR(fp); | 160 | status = PTR_ERR(fp); |
161 | if (IS_ERR(fp)) { | 161 | if (IS_ERR(fp)) { |
162 | dcache_dir_close(inode, file); | 162 | dcache_dir_close(inode, file); |
@@ -242,7 +242,8 @@ 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 | int status = 0; | 245 | struct dentry *new; |
246 | int status; | ||
246 | 247 | ||
247 | /* Block on any pending expiry here; invalidate the dentry | 248 | /* Block on any pending expiry here; invalidate the dentry |
248 | when expiration is done to trigger mount request with a new | 249 | when expiration is done to trigger mount request with a new |
@@ -318,7 +319,28 @@ 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); |
321 | return status; | 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 | |||
343 | return 0; | ||
322 | } | 344 | } |
323 | 345 | ||
324 | /* For autofs direct mounts the follow link triggers the mount */ | 346 | /* For autofs direct mounts the follow link triggers the mount */ |
@@ -533,9 +555,9 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct | |||
533 | goto next; | 555 | goto next; |
534 | 556 | ||
535 | if (d_unhashed(dentry)) { | 557 | if (d_unhashed(dentry)) { |
536 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
537 | struct inode *inode = dentry->d_inode; | 558 | struct inode *inode = dentry->d_inode; |
538 | 559 | ||
560 | ino = autofs4_dentry_ino(dentry); | ||
539 | list_del_init(&ino->rehash); | 561 | list_del_init(&ino->rehash); |
540 | dget(dentry); | 562 | dget(dentry); |
541 | /* | 563 | /* |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 1fe28e4754c2..75e5955c3f6d 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -171,7 +171,7 @@ static int autofs4_getpath(struct autofs_sb_info *sbi, | |||
171 | for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) | 171 | for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) |
172 | len += tmp->d_name.len + 1; | 172 | len += tmp->d_name.len + 1; |
173 | 173 | ||
174 | if (--len > NAME_MAX) { | 174 | if (!len || --len > NAME_MAX) { |
175 | spin_unlock(&dcache_lock); | 175 | spin_unlock(&dcache_lock); |
176 | return 0; | 176 | return 0; |
177 | } | 177 | } |