+ autofs4-needs-to-force-fail-return-revalidate.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled

     autofs4 needs to force fail return revalidate

has been added to the -mm tree.  Its filename is

     autofs4-needs-to-force-fail-return-revalidate.patch

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: autofs4 needs to force fail return revalidate
From: Ian Kent <raven@xxxxxxxxxx>


For a long time now I have had a problem with not being able to return a
lookup failure on an existsing directory.  In autofs this corresponds to a
mount failure on a autofs managed mount entry that is browsable (and so the
mount point directory exists).

While this problem has been present for a long time I've avoided resolving
it because it was not very visible.  But now that autofs v5 has "mount and
expire on demand" of nested multiple mounts, such as is found when mounting
an export list from a server, solving the problem cannot be avoided any
longer.

I've tried very hard to find a way to do this entirely within the autofs4
module but have not been able to find a satisfactory way to achieve it.

So, I need to propose a change to the VFS.

Signed-off-by: Ian Kent <raven@xxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 fs/autofs4/root.c      |    9 +++++-
 fs/namei.c             |   57 ++++++++++++++++++++++++++++++++++-----
 include/linux/dcache.h |    1 
 3 files changed, 59 insertions(+), 8 deletions(-)

diff -puN fs/autofs4/root.c~autofs4-needs-to-force-fail-return-revalidate fs/autofs4/root.c
--- a/fs/autofs4/root.c~autofs4-needs-to-force-fail-return-revalidate
+++ a/fs/autofs4/root.c
@@ -421,8 +421,15 @@ 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)
+		if (!oz_mode) {
 			status = try_to_fill_dentry(dentry, flags);
+			if (status) {
+				spin_lock(&dentry->d_lock);
+				dentry->d_flags |= DCACHE_REVAL_FORCE_FAIL;
+				spin_unlock(&dentry->d_lock);
+				return 0;
+			}
+		}
 		return !status;
 	}
 	spin_unlock(&dcache_lock);
diff -puN fs/namei.c~autofs4-needs-to-force-fail-return-revalidate fs/namei.c
--- a/fs/namei.c~autofs4-needs-to-force-fail-return-revalidate
+++ a/fs/namei.c
@@ -380,9 +380,24 @@ static struct dentry * cached_lookup(str
 		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->d_op->d_revalidate(dentry, nd)) {
+			if (!d_invalidate(dentry)) {
+				dput(dentry);
+				return NULL;
+			}
+			/*
+			 * As well as the normal validation, check if we need
+			 * to force a fail on a valid dentry (autofs4 browsable
+			 * mounts).
+			 */
+			spin_lock(&dentry->d_lock);
+			if (dentry->d_flags & DCACHE_REVAL_FORCE_FAIL) {
+				dentry->d_flags &= ~DCACHE_REVAL_FORCE_FAIL;
+				spin_unlock(&dentry->d_lock);
+				dput(dentry);
+				return ERR_PTR(-ENOENT);
+			}
+			spin_unlock(&dentry->d_lock);
 		}
 	}
 	return dentry;
@@ -477,9 +492,24 @@ 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 = ERR_PTR(-ENOENT);
+		if (!result->d_op->d_revalidate(result, nd)) {
+			if (!d_invalidate(result)) {
+				dput(result);
+				return ERR_PTR(-ENOENT);
+			}
+			/*
+		 	* d_revalidate failed but the dentry is still valid so
+			* check if we need to force a fail on the dentry (autofs4
+			* browsable mounts).
+		 	*/
+			spin_lock(&result->d_lock);
+		    	if (result->d_flags & DCACHE_REVAL_FORCE_FAIL) {
+				result->d_flags &= ~DCACHE_REVAL_FORCE_FAIL;
+				spin_unlock(&result->d_lock);
+				dput(result);
+				return ERR_PTR(-ENOENT);
+			}
+			spin_unlock(&result->d_lock);
 		}
 	}
 	return result;
@@ -762,8 +792,21 @@ need_lookup:
 need_revalidate:
 	if (dentry->d_op->d_revalidate(dentry, nd))
 		goto done;
-	if (d_invalidate(dentry))
+	if (d_invalidate(dentry)) {
+		/*
+		 * d_revalidate failed but the dentry is still valid so check
+		 * if we need to return a fail (autofs4 browsable mounts).
+		 */
+		spin_lock(&dentry->d_lock);
+		if (dentry->d_flags & DCACHE_REVAL_FORCE_FAIL) {
+			dentry->d_flags &= ~DCACHE_REVAL_FORCE_FAIL;
+			spin_unlock(&dentry->d_lock);
+			dput(dentry);
+			return -ENOENT;
+		}
+		spin_unlock(&dentry->d_lock);
 		goto done;
+	}
 	dput(dentry);
 	goto need_lookup;
 
diff -puN include/linux/dcache.h~autofs4-needs-to-force-fail-return-revalidate include/linux/dcache.h
--- a/include/linux/dcache.h~autofs4-needs-to-force-fail-return-revalidate
+++ a/include/linux/dcache.h
@@ -163,6 +163,7 @@ d_iput:		no		no		no       yes
 #define DCACHE_UNHASHED		0x0010	
 
 #define DCACHE_INOTIFY_PARENT_WATCHED	0x0020 /* Parent inode is watched */
+#define DCACHE_REVAL_FORCE_FAIL 0x0040	/* Force revalidate fail on valid dentry */
 
 extern spinlock_t dcache_lock;
 
_

Patches currently in -mm which might be from raven@xxxxxxxxxx are

autofs4-need-to-invalidate-children-on-tree-mount-expire.patch
autofs4-needs-to-force-fail-return-revalidate.patch
fs-use-list_move.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux