[PATCH] autofs4: wait order fix
authorIan Kent <raven@themaw.net>
Sun, 1 May 2005 15:59:16 +0000 (08:59 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sun, 1 May 2005 15:59:16 +0000 (08:59 -0700)
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>
fs/autofs4/autofs_i.h
fs/autofs4/waitq.c

index f5a52c87172621b135eaaf044ed248892711abe2..9789877352522440d723186002c32d8ddc6d5d20 100644 (file)
@@ -84,6 +84,7 @@ struct autofs_wait_queue {
        char *name;
        /* This is for status reporting upon return */
        int status;
+       atomic_t notified;
        atomic_t wait_ctr;
 };
 
index 1ab24a662e09f22743ae1ef44287cf54b0b94224..5a40d36e5a5101f178a92703b818487925db882d 100644 (file)
@@ -210,17 +210,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                wq->len = len;
                wq->status = -EINTR; /* Status return if interrupted */
                atomic_set(&wq->wait_ctr, 2);
+               atomic_set(&wq->notified, 1);
                up(&sbi->wq_sem);
-
-               DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d",
-                       (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
-               /* autofs4_notify_daemon() may block */
-               if (notify != NFY_NONE) {
-                       autofs4_notify_daemon(sbi,wq, 
-                                       notify == NFY_MOUNT ?
-                                                 autofs_ptype_missing :
-                                                 autofs_ptype_expire_multi);
-               }
        } else {
                atomic_inc(&wq->wait_ctr);
                up(&sbi->wq_sem);
@@ -229,6 +220,17 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                        (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
        }
 
+       if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) {
+               int type = (notify == NFY_MOUNT ?
+                       autofs_ptype_missing : autofs_ptype_expire_multi);
+
+               DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
+                       (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify));
+
+               /* autofs4_notify_daemon() may block */
+               autofs4_notify_daemon(sbi, wq, type);
+       }
+
        /* wq->name is NULL if and only if the lock is already released */
 
        if ( sbi->catatonic ) {