aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2005-05-01 11:59:16 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 11:59:16 -0400
commit4dcd00b18118d174c4b8d838c11f437f0af3c20c (patch)
tree0e7497aa50c383e64f34616819066fc0bfe3c56d /fs/autofs4
parent945b092011c6af71a0107be96e119c8c08776f3f (diff)
[PATCH] autofs4: wait order fix
It's possible for an event wait request to arive before the event requestor. If this happens the daemon never gets notified and autofs hangs. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/autofs_i.h1
-rw-r--r--fs/autofs4/waitq.c22
2 files changed, 13 insertions, 10 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index f5a52c871726..978987735252 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -84,6 +84,7 @@ struct autofs_wait_queue {
84 char *name; 84 char *name;
85 /* This is for status reporting upon return */ 85 /* This is for status reporting upon return */
86 int status; 86 int status;
87 atomic_t notified;
87 atomic_t wait_ctr; 88 atomic_t wait_ctr;
88}; 89};
89 90
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 1ab24a662e09..5a40d36e5a51 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -210,17 +210,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
210 wq->len = len; 210 wq->len = len;
211 wq->status = -EINTR; /* Status return if interrupted */ 211 wq->status = -EINTR; /* Status return if interrupted */
212 atomic_set(&wq->wait_ctr, 2); 212 atomic_set(&wq->wait_ctr, 2);
213 atomic_set(&wq->notified, 1);
213 up(&sbi->wq_sem); 214 up(&sbi->wq_sem);
214
215 DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d",
216 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
217 /* autofs4_notify_daemon() may block */
218 if (notify != NFY_NONE) {
219 autofs4_notify_daemon(sbi,wq,
220 notify == NFY_MOUNT ?
221 autofs_ptype_missing :
222 autofs_ptype_expire_multi);
223 }
224 } else { 215 } else {
225 atomic_inc(&wq->wait_ctr); 216 atomic_inc(&wq->wait_ctr);
226 up(&sbi->wq_sem); 217 up(&sbi->wq_sem);
@@ -229,6 +220,17 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
229 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); 220 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
230 } 221 }
231 222
223 if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) {
224 int type = (notify == NFY_MOUNT ?
225 autofs_ptype_missing : autofs_ptype_expire_multi);
226
227 DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
228 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify));
229
230 /* autofs4_notify_daemon() may block */
231 autofs4_notify_daemon(sbi, wq, type);
232 }
233
232 /* wq->name is NULL if and only if the lock is already released */ 234 /* wq->name is NULL if and only if the lock is already released */
233 235
234 if ( sbi->catatonic ) { 236 if ( sbi->catatonic ) {