Commit 4dcd00b1 authored by Ian Kent's avatar Ian Kent Committed by Linus Torvalds

[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: default avatarIan Kent <raven@themaw.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 945b0920
...@@ -84,6 +84,7 @@ struct autofs_wait_queue { ...@@ -84,6 +84,7 @@ struct autofs_wait_queue {
char *name; char *name;
/* This is for status reporting upon return */ /* This is for status reporting upon return */
int status; int status;
atomic_t notified;
atomic_t wait_ctr; atomic_t wait_ctr;
}; };
......
...@@ -210,17 +210,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, ...@@ -210,17 +210,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->len = len; wq->len = len;
wq->status = -EINTR; /* Status return if interrupted */ wq->status = -EINTR; /* Status return if interrupted */
atomic_set(&wq->wait_ctr, 2); atomic_set(&wq->wait_ctr, 2);
atomic_set(&wq->notified, 1);
up(&sbi->wq_sem); 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 { } else {
atomic_inc(&wq->wait_ctr); atomic_inc(&wq->wait_ctr);
up(&sbi->wq_sem); up(&sbi->wq_sem);
...@@ -229,6 +220,17 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, ...@@ -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); (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 */ /* wq->name is NULL if and only if the lock is already released */
if ( sbi->catatonic ) { if ( sbi->catatonic ) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment