linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / autofs4 / waitq.c
index caae47f..394ff36 100644 (file)
@@ -191,6 +191,13 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
        }
 
        if ( !wq ) {
+               /* Can't wait for an expire if there's no mount */
+               if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+                       kfree(name);
+                       up(&sbi->wq_sem);
+                       return -ENOENT;
+               }
+
                /* Create a new wait queue */
                wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
                if ( !wq ) {
@@ -210,33 +217,34 @@ 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);
+               kfree(name);
                DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
                        (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 ) {
                /* We might have slept, so check again for catatonic mode */
                wq->status = -ENOENT;
-               if ( wq->name ) {
-                       kfree(wq->name);
-                       wq->name = NULL;
-               }
+               kfree(wq->name);
+               wq->name = NULL;
        }
 
        if ( wq->name ) {
@@ -275,7 +283,7 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
        struct autofs_wait_queue *wq, **wql;
 
        down(&sbi->wq_sem);
-       for ( wql = &sbi->queues ; (wq = *wql) ; wql = &wq->next ) {
+       for ( wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next ) {
                if ( wq->wait_queue_token == wait_queue_token )
                        break;
        }