aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/autofs4/autofs_i.h1
-rw-r--r--fs/autofs4/expire.c29
-rw-r--r--fs/autofs4/root.c75
3 files changed, 40 insertions, 65 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 4b40cbc71e9b..69a2f5c92319 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -163,6 +163,7 @@ void autofs4_free_ino(struct autofs_info *);
163 163
164/* Expiration */ 164/* Expiration */
165int is_autofs4_dentry(struct dentry *); 165int is_autofs4_dentry(struct dentry *);
166int autofs4_expire_wait(struct dentry *dentry);
166int autofs4_expire_run(struct super_block *, struct vfsmount *, 167int autofs4_expire_run(struct super_block *, struct vfsmount *,
167 struct autofs_sb_info *, 168 struct autofs_sb_info *,
168 struct autofs_packet_expire __user *); 169 struct autofs_packet_expire __user *);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 705b9f057fb3..cdabb796ff01 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -402,6 +402,35 @@ found:
402 return expired; 402 return expired;
403} 403}
404 404
405int autofs4_expire_wait(struct dentry *dentry)
406{
407 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
408 struct autofs_info *ino = autofs4_dentry_ino(dentry);
409 int status;
410
411 /* Block on any pending expire */
412 spin_lock(&sbi->fs_lock);
413 if (ino->flags & AUTOFS_INF_EXPIRING) {
414 spin_unlock(&sbi->fs_lock);
415
416 DPRINTK("waiting for expire %p name=%.*s",
417 dentry, dentry->d_name.len, dentry->d_name.name);
418
419 status = autofs4_wait(sbi, dentry, NFY_NONE);
420 wait_for_completion(&ino->expire_complete);
421
422 DPRINTK("expire done status=%d", status);
423
424 if (d_unhashed(dentry))
425 return -EAGAIN;
426
427 return status;
428 }
429 spin_unlock(&sbi->fs_lock);
430
431 return 0;
432}
433
405/* Perform an expiry operation */ 434/* Perform an expiry operation */
406int autofs4_expire_run(struct super_block *sb, 435int autofs4_expire_run(struct super_block *sb,
407 struct vfsmount *mnt, 436 struct vfsmount *mnt,
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index e062ee5a3ed5..ae22bde0bbd7 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -130,34 +130,6 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
130 struct autofs_info *ino = autofs4_dentry_ino(dentry); 130 struct autofs_info *ino = autofs4_dentry_ino(dentry);
131 int status; 131 int status;
132 132
133 /* Block on any pending expiry here; invalidate the dentry
134 when expiration is done to trigger mount request with a new
135 dentry */
136 spin_lock(&sbi->fs_lock);
137 if (ino->flags & AUTOFS_INF_EXPIRING) {
138 spin_unlock(&sbi->fs_lock);
139
140 DPRINTK("waiting for expire %p name=%.*s",
141 dentry, dentry->d_name.len, dentry->d_name.name);
142
143 status = autofs4_wait(sbi, dentry, NFY_NONE);
144 wait_for_completion(&ino->expire_complete);
145
146 DPRINTK("expire done status=%d", status);
147
148 /*
149 * If the directory still exists the mount request must
150 * continue otherwise it can't be followed at the right
151 * time during the walk.
152 */
153 status = d_invalidate(dentry);
154 if (status != -EBUSY)
155 return -EAGAIN;
156
157 goto cont;
158 }
159 spin_unlock(&sbi->fs_lock);
160cont:
161 DPRINTK("dentry=%p %.*s ino=%p", 133 DPRINTK("dentry=%p %.*s ino=%p",
162 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); 134 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
163 135
@@ -248,22 +220,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
248 } 220 }
249 221
250 /* If an expire request is pending everyone must wait. */ 222 /* If an expire request is pending everyone must wait. */
251 spin_lock(&sbi->fs_lock); 223 autofs4_expire_wait(dentry);
252 if (ino->flags & AUTOFS_INF_EXPIRING) {
253 spin_unlock(&sbi->fs_lock);
254
255 DPRINTK("waiting for active request %p name=%.*s",
256 dentry, dentry->d_name.len, dentry->d_name.name);
257
258 status = autofs4_wait(sbi, dentry, NFY_NONE);
259 wait_for_completion(&ino->expire_complete);
260 224
261 DPRINTK("request done status=%d", status);
262
263 goto cont;
264 }
265 spin_unlock(&sbi->fs_lock);
266cont:
267 /* We trigger a mount for almost all flags */ 225 /* We trigger a mount for almost all flags */
268 lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS); 226 lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
269 if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING)) 227 if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
@@ -332,6 +290,14 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
332 return 1; 290 return 1;
333 291
334 /* 292 /*
293 * If the directory has gone away due to an expire
294 * we have been called as ->d_revalidate() and so
295 * we need to return false and proceed to ->lookup().
296 */
297 if (autofs4_expire_wait(dentry) == -EAGAIN)
298 return 0;
299
300 /*
335 * A zero status is success otherwise we have a 301 * A zero status is success otherwise we have a
336 * negative error code. 302 * negative error code.
337 */ 303 */
@@ -339,15 +305,6 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
339 if (status == 0) 305 if (status == 0)
340 return 1; 306 return 1;
341 307
342 /*
343 * A status of EAGAIN here means that the dentry has gone
344 * away while waiting for an expire to complete. If we are
345 * racing with expire lookup will wait for it so this must
346 * be a revalidate and we need to send it to lookup.
347 */
348 if (status == -EAGAIN)
349 return 0;
350
351 return status; 308 return status;
352 } 309 }
353 spin_unlock(&sbi->fs_lock); 310 spin_unlock(&sbi->fs_lock);
@@ -557,19 +514,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
557 * so it must have been successful, so just wait for it. 514 * so it must have been successful, so just wait for it.
558 */ 515 */
559 ino = autofs4_dentry_ino(expiring); 516 ino = autofs4_dentry_ino(expiring);
560 spin_lock(&sbi->fs_lock); 517 autofs4_expire_wait(expiring);
561 if (ino->flags & AUTOFS_INF_EXPIRING) {
562 spin_unlock(&sbi->fs_lock);
563 DPRINTK("wait for incomplete expire %p name=%.*s",
564 expiring, expiring->d_name.len,
565 expiring->d_name.name);
566 autofs4_wait(sbi, expiring, NFY_NONE);
567 wait_for_completion(&ino->expire_complete);
568 DPRINTK("request completed");
569 goto cont;
570 }
571 spin_unlock(&sbi->fs_lock);
572cont:
573 spin_lock(&sbi->lookup_lock); 518 spin_lock(&sbi->lookup_lock);
574 if (!list_empty(&ino->expiring)) 519 if (!list_empty(&ino->expiring))
575 list_del_init(&ino->expiring); 520 list_del_init(&ino->expiring);