diff -Nurp linux-2.6.9.orig/fs/autofs4/autofs_i.h linux-2.6.9/fs/autofs4/autofs_i.h
--- linux-2.6.9.orig/fs/autofs4/autofs_i.h	2004-10-19 05:54:38.000000000 +0800
+++ linux-2.6.9/fs/autofs4/autofs_i.h	2005-04-04 23:49:08.000000000 +0800
@@ -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;
 };
 
@@ -101,6 +102,7 @@ struct autofs_sb_info {
 	int needs_reghost;
 	struct super_block *sb;
 	struct semaphore wq_sem;
+	spinlock_t fs_lock;
 	struct autofs_wait_queue *queues; /* Wait queue pointer */
 };
 
@@ -126,9 +128,18 @@ static inline int autofs4_oz_mode(struct
 static inline int autofs4_ispending(struct dentry *dentry)
 {
 	struct autofs_info *inf = autofs4_dentry_ino(dentry);
+	int pending = 0;
 
-	return (dentry->d_flags & DCACHE_AUTOFS_PENDING) ||
-		(inf != NULL && inf->flags & AUTOFS_INF_EXPIRING);
+	if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
+		return 1;
+
+	if (inf) {
+		spin_lock(&inf->sbi->fs_lock);
+		pending = inf->flags & AUTOFS_INF_EXPIRING;
+		spin_unlock(&inf->sbi->fs_lock);
+	}
+
+	return pending;
 }
 
 static inline void autofs4_copy_atime(struct file *src, struct file *dst)
diff -Nurp linux-2.6.9.orig/fs/autofs4/expire.c linux-2.6.9/fs/autofs4/expire.c
--- linux-2.6.9.orig/fs/autofs4/expire.c	2004-10-19 05:54:39.000000000 +0800
+++ linux-2.6.9/fs/autofs4/expire.c	2005-04-04 23:49:08.000000000 +0800
@@ -99,6 +99,10 @@ static int autofs4_check_tree(struct vfs
 	if (!autofs4_can_expire(top, timeout, do_now))
 		return 0;
 
+	/* Is someone visiting anywhere in the tree ? */
+	if (may_umount_tree(mnt))
+		return 0;
+
 	spin_lock(&dcache_lock);
 repeat:
 	next = this_parent->d_subdirs.next;
@@ -270,10 +274,18 @@ static struct dentry *autofs4_expire(str
 
 		/* Case 2: tree mount, expire iff entire tree is not busy */
 		if (!exp_leaves) {
+			/* Lock the tree as we must expire as a whole */
+			spin_lock(&sbi->fs_lock);
 			if (autofs4_check_tree(mnt, dentry, timeout, do_now)) {
-			expired = dentry;
-			break;
+				struct autofs_info *inf = autofs4_dentry_ino(dentry);
+
+				/* Set this flag early to catch sys_chdir and the like */
+				inf->flags |= AUTOFS_INF_EXPIRING;
+				spin_unlock(&sbi->fs_lock);
+				expired = dentry;
+				break;
 			}
+			spin_unlock(&sbi->fs_lock);
 		/* Case 3: direct mount, expire individual leaves */
 		} else {
 			expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
diff -Nurp linux-2.6.9.orig/fs/autofs4/inode.c linux-2.6.9/fs/autofs4/inode.c
--- linux-2.6.9.orig/fs/autofs4/inode.c	2004-10-19 05:54:40.000000000 +0800
+++ linux-2.6.9/fs/autofs4/inode.c	2005-04-04 23:49:08.000000000 +0800
@@ -206,6 +206,7 @@ int autofs4_fill_super(struct super_bloc
 	sbi->version = 0;
 	sbi->sub_version = 0;
 	init_MUTEX(&sbi->wq_sem);
+	spin_lock_init(&sbi->fs_lock);
 	sbi->queues = NULL;
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
diff -Nurp linux-2.6.9.orig/fs/autofs4/root.c linux-2.6.9/fs/autofs4/root.c
--- linux-2.6.9.orig/fs/autofs4/root.c	2004-10-19 05:53:06.000000000 +0800
+++ linux-2.6.9/fs/autofs4/root.c	2005-04-04 23:48:23.000000000 +0800
@@ -19,7 +19,6 @@
 #include <linux/smp_lock.h>
 #include "autofs_i.h"
 
-static struct dentry *autofs4_dir_lookup(struct inode *,struct dentry *, struct nameidata *);
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
@@ -29,7 +28,7 @@ static int autofs4_dir_open(struct inode
 static int autofs4_dir_close(struct inode *inode, struct file *file);
 static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
 static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
-static struct dentry *autofs4_root_lookup(struct inode *,struct dentry *, struct nameidata *);
+static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
 static int autofs4_dcache_readdir(struct file *, void *, filldir_t);
 
 struct file_operations autofs4_root_operations = {
@@ -48,7 +47,7 @@ struct file_operations autofs4_dir_opera
 };
 
 struct inode_operations autofs4_root_inode_operations = {
-	.lookup		= autofs4_root_lookup,
+	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.symlink	= autofs4_dir_symlink,
 	.mkdir		= autofs4_dir_mkdir,
@@ -56,7 +55,7 @@ struct inode_operations autofs4_root_ino
 };
 
 struct inode_operations autofs4_dir_inode_operations = {
-	.lookup		= autofs4_dir_lookup,
+	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.symlink	= autofs4_dir_symlink,
 	.mkdir		= autofs4_dir_mkdir,
@@ -361,6 +360,7 @@ static int try_to_fill_dentry(struct den
 	spin_lock(&dentry->d_lock);
 	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
 	spin_unlock(&dentry->d_lock);
+
 	return 1;
 }
 
@@ -439,23 +439,8 @@ static struct dentry_operations autofs4_
 	.d_release	= autofs4_dentry_release,
 };
 
-/* Lookups in non-root dirs never find anything - if it's there, it's
-   already in the dcache */
-static struct dentry *autofs4_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-#if 0
-	DPRINTK("ignoring lookup of %.*s/%.*s",
-		 dentry->d_parent->d_name.len, dentry->d_parent->d_name.name,
-		 dentry->d_name.len, dentry->d_name.name);
-#endif
-
-	dentry->d_fsdata = NULL;
-	d_add(dentry, NULL);
-	return NULL;
-}
-
 /* Lookups in the root directory */
-static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi;
 	int oz_mode;
diff -Nurp linux-2.6.9.orig/fs/autofs4/waitq.c linux-2.6.9/fs/autofs4/waitq.c
--- linux-2.6.9.orig/fs/autofs4/waitq.c	2004-10-19 05:55:27.000000000 +0800
+++ linux-2.6.9/fs/autofs4/waitq.c	2005-04-04 23:52:53.000000000 +0800
@@ -210,24 +210,27 @@ int autofs4_wait(struct autofs_sb_info *
 		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 ) {
diff -Nurp linux-2.6.9.orig/include/linux/auto_fs4.h linux-2.6.9/include/linux/auto_fs4.h
--- linux-2.6.9.orig/include/linux/auto_fs4.h	2004-10-19 05:53:08.000000000 +0800
+++ linux-2.6.9/include/linux/auto_fs4.h	2005-04-04 23:49:14.000000000 +0800
@@ -23,7 +23,7 @@
 #define AUTOFS_MIN_PROTO_VERSION	3
 #define AUTOFS_MAX_PROTO_VERSION	4
 
-#define AUTOFS_PROTO_SUBVERSION         5
+#define AUTOFS_PROTO_SUBVERSION		6
 
 /* Mask for expire behaviour */
 #define AUTOFS_EXP_IMMEDIATE		1
