summaryrefslogtreecommitdiff
path: root/fs/autofs4
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2005-05-01 08:59:16 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 08:59:16 -0700
commit4dcd00b18118d174c4b8d838c11f437f0af3c20c (patch)
tree0e7497aa50c383e64f34616819066fc0bfe3c56d /fs/autofs4
parent945b092011c6af71a0107be96e119c8c08776f3f (diff)
downloadlwn-4dcd00b18118d174c4b8d838c11f437f0af3c20c.tar.gz
lwn-4dcd00b18118d174c4b8d838c11f437f0af3c20c.zip
[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 {
char *name;
/* This is for status reporting upon return */
int status;
+ atomic_t notified;
atomic_t wait_ctr;
};
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,
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 ) {