File: //usr/share/doc/autofs-5.0.1/autofs4-2.6.17-v5-update.patch
diff -Nurp linux-2.6.17.orig/fs/autofs4/expire.c linux-2.6.17/fs/autofs4/expire.c
--- linux-2.6.17.orig/fs/autofs4/expire.c 2006-06-18 09:49:35.000000000 +0800
+++ linux-2.6.17/fs/autofs4/expire.c 2006-08-31 14:54:11.000000000 +0800
@@ -174,6 +174,12 @@ static int autofs4_tree_busy(struct vfsm
struct autofs_info *ino = autofs4_dentry_ino(p);
unsigned int ino_count = atomic_read(&ino->count);
+ /*
+ * Clean stale dentries below that have not been
+ * invalidated after a mount fail during lookup
+ */
+ d_invalidate(p);
+
/* allow for dget above and top is already dgot */
if (p == top)
ino_count += 2;
diff -Nurp linux-2.6.17.orig/fs/autofs4/root.c linux-2.6.17/fs/autofs4/root.c
--- linux-2.6.17.orig/fs/autofs4/root.c 2006-06-18 09:49:35.000000000 +0800
+++ linux-2.6.17/fs/autofs4/root.c 2006-08-31 14:54:11.000000000 +0800
@@ -137,7 +137,9 @@ static int autofs4_dir_open(struct inode
nd.flags = LOOKUP_DIRECTORY;
ret = (dentry->d_op->d_revalidate)(dentry, &nd);
- if (!ret) {
+ if (ret <= 0) {
+ if (ret < 0)
+ status = ret;
dcache_dir_close(inode, file);
goto out;
}
@@ -279,9 +281,6 @@ static int try_to_fill_dentry(struct den
DPRINTK("mount done status=%d", status);
- if (status && dentry->d_inode)
- return status; /* Try to get the kernel to invalidate this dentry */
-
/* Turn this into a real negative dentry? */
if (status == -ENOENT) {
spin_lock(&dentry->d_lock);
@@ -357,7 +356,7 @@ static void *autofs4_follow_link(struct
* don't try to mount it again.
*/
spin_lock(&dcache_lock);
- if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
+ if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
spin_unlock(&dcache_lock);
status = try_to_fill_dentry(dentry, 0);
@@ -400,13 +399,23 @@ static int autofs4_revalidate(struct den
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
int oz_mode = autofs4_oz_mode(sbi);
int flags = nd ? nd->flags : 0;
- int status = 0;
+ int status;
/* Pending dentry */
if (autofs4_ispending(dentry)) {
- if (!oz_mode)
- status = try_to_fill_dentry(dentry, flags);
- return !status;
+ /* The daemon never causes a mount to trigger */
+ if (oz_mode)
+ return 1;
+
+ /*
+ * A zero status is success otherwise we have a
+ * negative error code.
+ */
+ status = try_to_fill_dentry(dentry, flags);
+ if (status == 0)
+ return 1;
+
+ return status;
}
/* Negative dentry.. invalidate if "old" */
@@ -421,9 +430,19 @@ static int autofs4_revalidate(struct den
DPRINTK("dentry=%p %.*s, emptydir",
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dcache_lock);
- if (!oz_mode)
- status = try_to_fill_dentry(dentry, flags);
- return !status;
+ /* The daemon never causes a mount to trigger */
+ if (oz_mode)
+ return 1;
+
+ /*
+ * A zero status is success otherwise we have a
+ * negative error code.
+ */
+ status = try_to_fill_dentry(dentry, flags);
+ if (status == 0)
+ return 1;
+
+ return status;
}
spin_unlock(&dcache_lock);
@@ -518,6 +537,9 @@ static struct dentry *autofs4_lookup(str
return ERR_PTR(-ERESTARTNOINTR);
}
}
+ spin_lock(&dentry->d_lock);
+ dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
+ spin_unlock(&dentry->d_lock);
}
/*
diff -Nurp linux-2.6.17.orig/fs/namei.c linux-2.6.17/fs/namei.c
--- linux-2.6.17.orig/fs/namei.c 2006-06-18 09:49:35.000000000 +0800
+++ linux-2.6.17/fs/namei.c 2006-08-31 14:54:11.000000000 +0800
@@ -365,6 +365,29 @@ void release_open_intent(struct nameidat
fput(nd->intent.open.file);
}
+static inline struct dentry *do_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+ int status = dentry->d_op->d_revalidate(dentry, nd);
+ if (unlikely(status <= 0)) {
+ /*
+ * The dentry failed validation.
+ * If d_revalidate returned 0 attempt to invalidate
+ * the dentry otherwise d_revalidate is asking us
+ * to return a fail status.
+ */
+ if (!status) {
+ if (!d_invalidate(dentry)) {
+ dput(dentry);
+ dentry = NULL;
+ }
+ } else {
+ dput(dentry);
+ dentry = ERR_PTR(status);
+ }
+ }
+ return dentry;
+}
+
/*
* Internal lookup() using the new generic dcache.
* SMP-safe
@@ -379,12 +402,9 @@ static struct dentry * cached_lookup(str
if (!dentry)
dentry = d_lookup(parent, name);
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
- dput(dentry);
- dentry = NULL;
- }
- }
+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
+ dentry = do_revalidate(dentry, nd);
+
return dentry;
}
@@ -477,10 +497,9 @@ static struct dentry * real_lookup(struc
*/
mutex_unlock(&dir->i_mutex);
if (result->d_op && result->d_op->d_revalidate) {
- if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
- dput(result);
+ result = do_revalidate(result, nd);
+ if (!result)
result = ERR_PTR(-ENOENT);
- }
}
return result;
}
@@ -760,12 +779,12 @@ need_lookup:
goto done;
need_revalidate:
- if (dentry->d_op->d_revalidate(dentry, nd))
- goto done;
- if (d_invalidate(dentry))
- goto done;
- dput(dentry);
- goto need_lookup;
+ dentry = do_revalidate(dentry, nd);
+ if (!dentry)
+ goto need_lookup;
+ if (IS_ERR(dentry))
+ goto fail;
+ goto done;
fail:
return PTR_ERR(dentry);