linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Miklos Szeredi <miklos@szeredi.hu>
To: viro@ZenIV.linux.org.uk
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	hch@infradead.org, torvalds@linux-foundation.org,
	mszeredi@suse.cz
Subject: [PATCH 15/16] vfs: retry last component if opening stale dentry
Date: Mon, 21 May 2012 17:30:19 +0200	[thread overview]
Message-ID: <1337614220-6174-16-git-send-email-miklos@szeredi.hu> (raw)
In-Reply-To: <1337614220-6174-1-git-send-email-miklos@szeredi.hu>

From: Miklos Szeredi <mszeredi@suse.cz>

NFS optimizes away d_revalidates for last component of open.  This means that
open itself can find the dentry stale.

This patch allows the filesystem to return EOPENSTALE and the VFS will retry the
lookup on just the last component if possible.

If the lookup was done using RCU mode, including the last component, then this
is not possible since the parent dentry is lost.  In this case fall back to
non-RCU lookup.  Currently this is not used since NFS will always leave RCU
mode.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
 fs/namei.c            |   37 +++++++++++++++++++++++++++++++++++--
 include/linux/errno.h |    1 +
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index cdc2c05..fdab199 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2204,6 +2204,8 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
 	struct file *filp;
 	struct inode *inode;
 	int symlink_ok = 0;
+	struct path save_parent = { .dentry = NULL, .mnt = NULL };
+	bool retried = false;
 	int error;
 
 	nd->flags &= ~LOOKUP_PARENT;
@@ -2269,6 +2271,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
 	if (nd->last.name[nd->last.len])
 		goto exit;
 
+retry_lookup:
 	mutex_lock(&dir->d_inode->i_mutex);
 
 	dentry = lookup_hash(nd);
@@ -2351,12 +2354,21 @@ finish_lookup:
 		return NULL;
 	}
 
-	path_to_nameidata(path, nd);
+	if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
+		path_to_nameidata(path, nd);
+	} else {
+		save_parent.dentry = nd->path.dentry;
+		save_parent.mnt = mntget(path->mnt);
+		nd->path.dentry = path->dentry;
+
+	}
 	nd->inode = inode;
 	/* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
 	error = complete_walk(nd);
-	if (error)
+	if (error) {
+		path_put(&save_parent);
 		return ERR_PTR(error);
+	}
 	error = -EISDIR;
 	if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
 		goto exit;
@@ -2379,6 +2391,20 @@ common:
 	if (error)
 		goto exit;
 	filp = nameidata_to_filp(nd);
+	if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
+		BUG_ON(save_parent.dentry != dir);
+		path_put(&nd->path);
+		nd->path = save_parent;
+		nd->inode = dir->d_inode;
+		save_parent.mnt = NULL;
+		save_parent.dentry = NULL;
+		if (want_write) {
+			mnt_drop_write(nd->path.mnt);
+			want_write = 0;
+		}
+		retried = true;
+		goto retry_lookup;
+	}
 	if (!IS_ERR(filp)) {
 		error = ima_file_check(filp, op->acc_mode);
 		if (error) {
@@ -2398,6 +2424,7 @@ common:
 out:
 	if (want_write)
 		mnt_drop_write(nd->path.mnt);
+	path_put(&save_parent);
 	terminate_walk(nd);
 	return filp;
 
@@ -2461,6 +2488,12 @@ out:
 	if (base)
 		fput(base);
 	release_open_intent(nd);
+	if (filp == ERR_PTR(-EOPENSTALE)) {
+		if (flags & LOOKUP_RCU)
+			filp = ERR_PTR(-ECHILD);
+		else
+			filp = ERR_PTR(-ESTALE);
+	}
 	return filp;
 
 out_filp:
diff --git a/include/linux/errno.h b/include/linux/errno.h
index 2d09bfa..e0de516 100644
--- a/include/linux/errno.h
+++ b/include/linux/errno.h
@@ -17,6 +17,7 @@
 #define ENOIOCTLCMD	515	/* No ioctl command */
 #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
 #define EPROBE_DEFER	517	/* Driver requests probe retry */
+#define EOPENSTALE	518	/* open found a stale dentry */
 
 /* Defined for the NFSv3 protocol */
 #define EBADHANDLE	521	/* Illegal NFS file handle */
-- 
1.7.7

  parent reply	other threads:[~2012-05-21 15:30 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-21 15:30 [PATCH 00/16] vfs: atomic open v5 (part 1) Miklos Szeredi
2012-05-21 15:30 ` [PATCH 01/16] vfs: split do_lookup() Miklos Szeredi
2012-05-21 15:30 ` [PATCH 02/16] vfs: do_last(): make exit RCU safe Miklos Szeredi
2012-05-21 15:30 ` [PATCH 03/16] vfs: do_last(): inline walk_component() Miklos Szeredi
2012-05-21 15:30 ` [PATCH 04/16] vfs: do_last(): use inode variable Miklos Szeredi
2012-05-21 15:30 ` [PATCH 05/16] vfs: make follow_link check RCU safe Miklos Szeredi
2012-05-21 15:30 ` [PATCH 06/16] vfs: do_last(): make ENOENT exit " Miklos Szeredi
2012-05-21 15:30 ` [PATCH 07/16] vfs: do_last(): check LOOKUP_DIRECTORY Miklos Szeredi
2012-05-21 15:30 ` [PATCH 08/16] vfs: do_last(): only return EISDIR for O_CREAT Miklos Szeredi
2012-05-21 15:30 ` [PATCH 09/16] vfs: do_last(): add audit_inode before open Miklos Szeredi
2012-05-21 15:30 ` [PATCH 10/16] vfs: do_last() common post lookup Miklos Szeredi
2012-05-21 15:30 ` [PATCH 11/16] vfs: split __dentry_open() Miklos Szeredi
2012-05-21 15:30 ` [PATCH 12/16] vfs: do_dentry_open(): don't put filp Miklos Szeredi
2012-05-21 15:30 ` [PATCH 13/16] vfs: nameidata_to_filp(): inline __dentry_open() Miklos Szeredi
2012-05-21 15:30 ` [PATCH 14/16] vfs: nameidata_to_filp(): don't throw away file on error Miklos Szeredi
2012-05-21 15:30 ` Miklos Szeredi [this message]
2012-05-21 15:30 ` [PATCH 16/16] nfs: don't open in ->d_revalidate Miklos Szeredi
2012-05-21 16:27 ` [PATCH 00/16] vfs: atomic open v5 (part 1) Linus Torvalds
2012-05-21 20:39   ` Miklos Szeredi
  -- strict thread matches above, loose matches on Subject: below --
2012-04-25 12:44 [PATCH 00/16] vfs: atomic open v4 " Miklos Szeredi
2012-04-25 12:44 ` [PATCH 15/16] vfs: retry last component if opening stale dentry Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1337614220-6174-16-git-send-email-miklos@szeredi.hu \
    --to=miklos@szeredi.hu \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mszeredi@suse.cz \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).