linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Remove struct nameidata from lower level NFS code
@ 2010-09-16 21:01 Trond Myklebust
  2010-09-16 21:01 ` [PATCH 1/6] NFSv4: Clean up nfs4_atomic_open Trond Myklebust
  0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Hi,

The following patches attempt to clean up the atomic open code so that we
keep all the functions that depend on the struct nameidata in fs/nfs/dir.c.
Instead of passing down the struct nameidata, we have the lower layer NFSv4
code fill in the nfs_open_context, which can then be used by nfs_atomic_lookup
to fill in the struct file.

Cheers
  Trond

Trond Myklebust (6):
  NFSv4: Clean up nfs4_atomic_open
  NFSv4: Further minor cleanups for nfs4_atomic_open()
  NFSv4: Clean up nfs4_open_revalidate
  NFSv4: Further cleanups for nfs4_open_revalidate()
  NFS: Clean up nfs4_proc_create()
  NFS: Add an 'open_context' element to struct nfs_rpc_ops

 fs/nfs/dir.c            |  179 ++++++++++++++++++++++++++++++++++++++++++----
 fs/nfs/inode.c          |    8 +-
 fs/nfs/nfs3proc.c       |    2 +-
 fs/nfs/nfs4_fs.h        |    2 -
 fs/nfs/nfs4proc.c       |  148 ++++++---------------------------------
 fs/nfs/proc.c           |    2 +-
 include/linux/nfs_fs.h  |    2 +
 include/linux/nfs_xdr.h |    6 ++-
 8 files changed, 198 insertions(+), 151 deletions(-)

-- 
1.7.2.3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] NFSv4: Clean up nfs4_atomic_open
  2010-09-16 21:01 [PATCH 0/6] Remove struct nameidata from lower level NFS code Trond Myklebust
@ 2010-09-16 21:01 ` Trond Myklebust
  2010-09-16 21:01   ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() Trond Myklebust
  0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Start moving the 'struct nameidata' dependent code out of the lower level
NFS code in preparation for the removal of open intents.

Instead of the struct nameidata, we pass down a partially initialised
struct nfs_open_context that will be fully initialised by the atomic open
upon success.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/dir.c           |   77 ++++++++++++++++++++++++++++++++++++++++++++++-
 fs/nfs/inode.c         |    8 ++--
 fs/nfs/nfs4_fs.h       |    2 +-
 fs/nfs/nfs4proc.c      |   40 +++++++------------------
 include/linux/nfs_fs.h |    2 +
 5 files changed, 93 insertions(+), 36 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e257172..17529b5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -38,6 +38,7 @@
 #include "delegation.h"
 #include "iostat.h"
 #include "internal.h"
+#include "fscache.h"
 
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -1029,9 +1030,61 @@ static int is_atomic_open(struct nameidata *nd)
 	return 1;
 }
 
+static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
+{
+	struct path path = {
+		.mnt = nd->path.mnt,
+		.dentry = dentry,
+	};
+	struct nfs_open_context *ctx;
+	struct rpc_cred *cred;
+	fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+
+	cred = rpc_lookup_cred();
+	if (IS_ERR(cred))
+		return ERR_CAST(cred);
+	ctx = alloc_nfs_open_context(&path, cred, fmode);
+	put_rpccred(cred);
+	if (ctx == NULL)
+		return ERR_PTR(-ENOMEM);
+	return ctx;
+}
+
+static int do_open(struct inode *inode, struct file *filp)
+{
+	nfs_fscache_set_inode_cookie(inode, filp);
+	return 0;
+}
+
+static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+{
+	struct file *filp;
+	int ret = 0;
+
+	/* If the open_intent is for execute, we have an extra check to make */
+	if (ctx->mode & FMODE_EXEC) {
+		ret = nfs_may_open(ctx->path.dentry->d_inode,
+				ctx->cred,
+				nd->intent.open.flags);
+		if (ret < 0)
+			goto out;
+	}
+	filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
+	if (IS_ERR(filp))
+		ret = PTR_ERR(filp);
+	else
+		nfs_file_set_open_context(filp, ctx);
+out:
+	put_nfs_open_context(ctx);
+	return ret;
+}
+
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct nfs_open_context *ctx;
+	struct iattr attr;
 	struct dentry *res = NULL;
+	int open_flags;
 	int error;
 
 	dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
@@ -1054,9 +1107,27 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 		goto out;
 	}
 
+	ctx = nameidata_to_nfs_open_context(dentry, nd);
+	res = ERR_CAST(ctx);
+	if (IS_ERR(ctx))
+		goto out;
+
+	open_flags = nd->intent.open.flags;
+	if (nd->flags & LOOKUP_CREATE) {
+		attr.ia_mode = nd->intent.open.create_mode;
+		attr.ia_valid = ATTR_MODE;
+		if (!IS_POSIXACL(dir))
+			attr.ia_mode &= ~current_umask();
+	} else {
+		open_flags &= ~O_EXCL;
+		attr.ia_valid = 0;
+		BUG_ON(open_flags & O_CREAT);
+	}
+
 	/* Open the file on the server */
-	res = nfs4_atomic_open(dir, dentry, nd);
+	res = nfs4_atomic_open(dir, ctx, open_flags, &attr);
 	if (IS_ERR(res)) {
+		put_nfs_open_context(ctx);
 		error = PTR_ERR(res);
 		switch (error) {
 			/* Make a negative dentry */
@@ -1074,8 +1145,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 			default:
 				goto out;
 		}
-	} else if (res != NULL)
+	}
+	if (res != NULL)
 		dentry = res;
+	nfs_intent_set_file(nd, ctx);
 out:
 	return res;
 no_open:
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7d2d6c7..2f92664 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -623,7 +623,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
 	nfs_revalidate_inode(server, inode);
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
+struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
 {
 	struct nfs_open_context *ctx;
 
@@ -633,6 +633,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
 		path_get(&ctx->path);
 		ctx->cred = get_rpccred(cred);
 		ctx->state = NULL;
+		ctx->mode = f_mode;
 		ctx->flags = 0;
 		ctx->error = 0;
 		ctx->dir_cookie = 0;
@@ -673,7 +674,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
  */
-static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -730,11 +731,10 @@ int nfs_open(struct inode *inode, struct file *filp)
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	ctx = alloc_nfs_open_context(&filp->f_path, cred);
+	ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
 	put_rpccred(cred);
 	if (ctx == NULL)
 		return -ENOMEM;
-	ctx->mode = filp->f_mode;
 	nfs_file_set_open_context(filp, ctx);
 	put_nfs_open_context(ctx);
 	nfs_fscache_set_inode_cookie(inode, filp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 311e15c..c5cc2a6 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -242,7 +242,7 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
-extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 089da5b..38c3bed 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2025,39 +2025,17 @@ out_close:
 }
 
 struct dentry *
-nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
-	struct path path = {
-		.mnt = nd->path.mnt,
-		.dentry = dentry,
-	};
+	struct dentry *dentry = ctx->path.dentry;
 	struct dentry *parent;
-	struct iattr attr;
-	struct rpc_cred *cred;
 	struct nfs4_state *state;
 	struct dentry *res;
-	int open_flags = nd->intent.open.flags;
-	fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
-
-	if (nd->flags & LOOKUP_CREATE) {
-		attr.ia_mode = nd->intent.open.create_mode;
-		attr.ia_valid = ATTR_MODE;
-		if (!IS_POSIXACL(dir))
-			attr.ia_mode &= ~current_umask();
-	} else {
-		open_flags &= ~O_EXCL;
-		attr.ia_valid = 0;
-		BUG_ON(open_flags & O_CREAT);
-	}
 
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred))
-		return (struct dentry *)cred;
 	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
 	nfs_block_sillyrename(parent);
-	state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
-	put_rpccred(cred);
+	state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
 	if (IS_ERR(state)) {
 		if (PTR_ERR(state) == -ENOENT) {
 			d_add(dentry, NULL);
@@ -2067,11 +2045,15 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		return (struct dentry *)state;
 	}
 	res = d_add_unique(dentry, igrab(state->inode));
-	if (res != NULL)
-		path.dentry = res;
-	nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
+	if (res != NULL) {
+		struct dentry *dummy = ctx->path.dentry;
+
+		ctx->path.dentry = dget(res);
+		dput(dummy);
+	}
+	ctx->state = state;
+	nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
 	nfs_unblock_sillyrename(parent);
-	nfs4_intent_set_file(nd, &path, state, fmode);
 	return res;
 }
 
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 508f8cf..39cb70b 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -360,6 +360,8 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
+extern struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode);
+extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
 extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
 extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
 extern u64 nfs_compat_user_ino64(u64 fileid);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open()
  2010-09-16 21:01 ` [PATCH 1/6] NFSv4: Clean up nfs4_atomic_open Trond Myklebust
@ 2010-09-16 21:01   ` Trond Myklebust
  2010-09-16 21:01     ` [PATCH 3/6] NFSv4: Clean up nfs4_open_revalidate Trond Myklebust
  2010-09-17 17:23     ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() J. Bruce Fields
  0 siblings, 2 replies; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/dir.c      |   21 +++++++++++++++------
 fs/nfs/nfs4_fs.h  |    2 +-
 fs/nfs/nfs4proc.c |   28 ++++------------------------
 3 files changed, 20 insertions(+), 31 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 17529b5..194676c 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1084,8 +1084,8 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 	struct nfs_open_context *ctx;
 	struct iattr attr;
 	struct dentry *res = NULL;
+	struct inode *inode;
 	int open_flags;
-	int error;
 
 	dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1125,13 +1125,15 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 	}
 
 	/* Open the file on the server */
-	res = nfs4_atomic_open(dir, ctx, open_flags, &attr);
-	if (IS_ERR(res)) {
+	nfs_block_sillyrename(dentry->d_parent);
+	inode = nfs4_atomic_open(dir, ctx, open_flags, &attr);
+	if (IS_ERR(inode)) {
+		nfs_unblock_sillyrename(dentry->d_parent);
 		put_nfs_open_context(ctx);
-		error = PTR_ERR(res);
-		switch (error) {
+		switch (PTR_ERR(inode)) {
 			/* Make a negative dentry */
 			case -ENOENT:
+				d_add(dentry, NULL);
 				res = NULL;
 				goto out;
 			/* This turned out not to be a regular file */
@@ -1143,13 +1145,20 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 					goto no_open;
 			/* case -EINVAL: */
 			default:
+				res = ERR_CAST(inode);
 				goto out;
 		}
 	}
-	if (res != NULL)
+	res = d_add_unique(dentry, inode);
+	if (res != NULL) {
+		dput(ctx->path.dentry);
+		ctx->path.dentry = dget(res);
 		dentry = res;
+	}
 	nfs_intent_set_file(nd, ctx);
+	nfs_unblock_sillyrename(dentry->d_parent);
 out:
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	return res;
 no_open:
 	return nfs_lookup(dir, dentry, nd);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c5cc2a6..8e1f639 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -242,7 +242,7 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
-extern struct dentry *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
+extern struct inode *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 38c3bed..f8d41ee 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2024,37 +2024,17 @@ out_close:
 	return ret;
 }
 
-struct dentry *
+struct inode *
 nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
-	struct dentry *dentry = ctx->path.dentry;
-	struct dentry *parent;
 	struct nfs4_state *state;
-	struct dentry *res;
 
-	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
-	nfs_block_sillyrename(parent);
 	state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
-	if (IS_ERR(state)) {
-		if (PTR_ERR(state) == -ENOENT) {
-			d_add(dentry, NULL);
-			nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-		}
-		nfs_unblock_sillyrename(parent);
-		return (struct dentry *)state;
-	}
-	res = d_add_unique(dentry, igrab(state->inode));
-	if (res != NULL) {
-		struct dentry *dummy = ctx->path.dentry;
-
-		ctx->path.dentry = dget(res);
-		dput(dummy);
-	}
+	if (IS_ERR(state))
+		return ERR_CAST(state);
 	ctx->state = state;
-	nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
-	nfs_unblock_sillyrename(parent);
-	return res;
+	return igrab(state->inode);
 }
 
 int
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/6] NFSv4: Clean up nfs4_open_revalidate
  2010-09-16 21:01   ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() Trond Myklebust
@ 2010-09-16 21:01     ` Trond Myklebust
  2010-09-16 21:01       ` [PATCH 4/6] NFSv4: Further cleanups for nfs4_open_revalidate() Trond Myklebust
  2010-09-17 17:23     ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() J. Bruce Fields
  1 sibling, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Remove references to 'struct nameidata' from the low-level open_revalidate
code, and replace them with a struct nfs_open_context which will be
correctly initialised upon success.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/dir.c      |   11 ++++++++++-
 fs/nfs/nfs4_fs.h  |    2 +-
 fs/nfs/nfs4proc.c |   23 ++++++-----------------
 3 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 194676c..196775c 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1169,6 +1169,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	struct dentry *parent = NULL;
 	struct inode *inode = dentry->d_inode;
 	struct inode *dir;
+	struct nfs_open_context *ctx;
 	int openflags, ret = 0;
 
 	if (!is_atomic_open(nd) || d_mountpoint(dentry))
@@ -1194,12 +1195,20 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	/* We can't create new files, or truncate existing ones here */
 	openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
 
+	ctx = nameidata_to_nfs_open_context(dentry, nd);
+	ret = PTR_ERR(ctx);
+	if (IS_ERR(ctx))
+		goto out;
 	/*
 	 * Note: we're not holding inode->i_mutex and so may be racing with
 	 * operations that change the directory. We therefore save the
 	 * change attribute *before* we do the RPC call.
 	 */
-	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
+	ret = nfs4_open_revalidate(dir, ctx, openflags);
+	if (ret == 1)
+		nfs_intent_set_file(nd, ctx);
+	else
+		put_nfs_open_context(ctx);
 out:
 	dput(parent);
 	if (!ret)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 8e1f639..76ec1c6 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -243,7 +243,7 @@ extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
 extern struct inode *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
+extern int nfs4_open_revalidate(struct inode *, struct nfs_open_context *, int);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f8d41ee..b476246 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2038,21 +2038,11 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags
 }
 
 int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
+nfs4_open_revalidate(struct inode *dir, struct nfs_open_context *ctx, int openflags)
 {
-	struct path path = {
-		.mnt = nd->path.mnt,
-		.dentry = dentry,
-	};
-	struct rpc_cred *cred;
 	struct nfs4_state *state;
-	fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE);
 
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred))
-		return PTR_ERR(cred);
-	state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
-	put_rpccred(cred);
+	state = nfs4_do_open(dir, &ctx->path, ctx->mode, openflags, NULL, ctx->cred);
 	if (IS_ERR(state)) {
 		switch (PTR_ERR(state)) {
 			case -EPERM:
@@ -2065,14 +2055,13 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
 				goto out_drop;
 		}
 	}
-	if (state->inode == dentry->d_inode) {
-		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-		nfs4_intent_set_file(nd, &path, state, fmode);
+	ctx->state = state;
+	if (state->inode == ctx->path.dentry->d_inode) {
+		nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
 		return 1;
 	}
-	nfs4_close_sync(&path, state, fmode);
 out_drop:
-	d_drop(dentry);
+	d_drop(ctx->path.dentry);
 	return 0;
 }
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/6] NFSv4: Further cleanups for nfs4_open_revalidate()
  2010-09-16 21:01     ` [PATCH 3/6] NFSv4: Clean up nfs4_open_revalidate Trond Myklebust
@ 2010-09-16 21:01       ` Trond Myklebust
  2010-09-16 21:01         ` [PATCH 5/6] NFS: Clean up nfs4_proc_create() Trond Myklebust
  0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/dir.c      |   32 ++++++++++++++++++++++++++------
 fs/nfs/nfs4_fs.h  |    1 -
 fs/nfs/nfs4proc.c |   28 ----------------------------
 3 files changed, 26 insertions(+), 35 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 196775c..dc93d35 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1204,16 +1204,36 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	 * operations that change the directory. We therefore save the
 	 * change attribute *before* we do the RPC call.
 	 */
-	ret = nfs4_open_revalidate(dir, ctx, openflags);
-	if (ret == 1)
+	inode = nfs4_atomic_open(dir, ctx, openflags, NULL);
+	if (IS_ERR(inode)) {
+		ret = PTR_ERR(inode);
+		switch (ret) {
+		case -EPERM:
+		case -EACCES:
+		case -EDQUOT:
+		case -ENOSPC:
+		case -EROFS:
+			goto out_put_ctx;
+		default:
+			goto out_drop;
+		}
+	}
+	iput(inode);
+	if (inode == dentry->d_inode) {
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 		nfs_intent_set_file(nd, ctx);
-	else
-		put_nfs_open_context(ctx);
+	} else
+		goto out_drop;
 out:
 	dput(parent);
-	if (!ret)
-		d_drop(dentry);
 	return ret;
+out_drop:
+	d_drop(dentry);
+	ret = 0;
+out_put_ctx:
+	put_nfs_open_context(ctx);
+	goto out;
+
 no_open_dput:
 	dput(parent);
 no_open:
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 76ec1c6..6cf12ba 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -243,7 +243,6 @@ extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
 extern struct inode *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
-extern int nfs4_open_revalidate(struct inode *, struct nfs_open_context *, int);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b476246..83c5ef6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2037,34 +2037,6 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags
 	return igrab(state->inode);
 }
 
-int
-nfs4_open_revalidate(struct inode *dir, struct nfs_open_context *ctx, int openflags)
-{
-	struct nfs4_state *state;
-
-	state = nfs4_do_open(dir, &ctx->path, ctx->mode, openflags, NULL, ctx->cred);
-	if (IS_ERR(state)) {
-		switch (PTR_ERR(state)) {
-			case -EPERM:
-			case -EACCES:
-			case -EDQUOT:
-			case -ENOSPC:
-			case -EROFS:
-				return PTR_ERR(state);
-			default:
-				goto out_drop;
-		}
-	}
-	ctx->state = state;
-	if (state->inode == ctx->path.dentry->d_inode) {
-		nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
-		return 1;
-	}
-out_drop:
-	d_drop(ctx->path.dentry);
-	return 0;
-}
-
 static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
 {
 	if (ctx->state == NULL)
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/6] NFS: Clean up nfs4_proc_create()
  2010-09-16 21:01       ` [PATCH 4/6] NFSv4: Further cleanups for nfs4_open_revalidate() Trond Myklebust
@ 2010-09-16 21:01         ` Trond Myklebust
  2010-09-16 21:01           ` [PATCH 6/6] NFS: Add an 'open_context' element to struct nfs_rpc_ops Trond Myklebust
  0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Remove all remaining references to the struct nameidata from the low level
NFS layers. Again pass down a partially initialised struct nfs_open_context
when we want to do atomic open+create.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/dir.c            |   47 ++++++++++++++++++++++++++++++++++-----
 fs/nfs/nfs3proc.c       |    2 +-
 fs/nfs/nfs4proc.c       |   56 +++++++++++-----------------------------------
 fs/nfs/proc.c           |    2 +-
 include/linux/nfs_xdr.h |    2 +-
 5 files changed, 58 insertions(+), 51 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index dc93d35..e37ffdd 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -105,8 +105,9 @@ const struct inode_operations nfs3_dir_inode_operations = {
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
 const struct inode_operations nfs4_dir_inode_operations = {
-	.create		= nfs_create,
+	.create		= nfs_open_create,
 	.lookup		= nfs_atomic_lookup,
 	.link		= nfs_link,
 	.unlink		= nfs_unlink,
@@ -1239,6 +1240,44 @@ no_open_dput:
 no_open:
 	return nfs_lookup_revalidate(dentry, nd);
 }
+
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
+{
+	struct nfs_open_context *ctx = NULL;
+	struct iattr attr;
+	int error;
+	int open_flags = 0;
+
+	dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
+			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+
+	attr.ia_mode = mode;
+	attr.ia_valid = ATTR_MODE;
+
+	if ((nd->flags & LOOKUP_CREATE) != 0) {
+		open_flags = nd->intent.open.flags;
+
+		ctx = nameidata_to_nfs_open_context(dentry, nd);
+		error = PTR_ERR(ctx);
+		if (IS_ERR(ctx))
+			goto out_err;
+	}
+
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
+	if (error != 0)
+		goto out_put_ctx;
+	if (ctx != NULL)
+		nfs_intent_set_file(nd, ctx);
+	return 0;
+out_put_ctx:
+	if (ctx != NULL)
+		put_nfs_open_context(ctx);
+out_err:
+	d_drop(dentry);
+	return error;
+}
+
 #endif /* CONFIG_NFSV4 */
 
 static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
@@ -1369,7 +1408,6 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 {
 	struct iattr attr;
 	int error;
-	int open_flags = 0;
 
 	dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1377,10 +1415,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	attr.ia_mode = mode;
 	attr.ia_valid = ATTR_MODE;
 
-	if ((nd->flags & LOOKUP_CREATE) != 0)
-		open_flags = nd->intent.open.flags;
-
-	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, 0, NULL);
 	if (error != 0)
 		goto out_err;
 	return 0;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index fabb4f2..2be4a7f 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -313,7 +313,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		 int flags, struct nameidata *nd)
+		 int flags, struct nfs_open_context *ctx)
 {
 	struct nfs3_createdata *data;
 	mode_t mode = sattr->ia_mode;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 83c5ef6..617b149 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1998,32 +1998,6 @@ out:
 	return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode)
-{
-	struct file *filp;
-	int ret;
-
-	/* If the open_intent is for execute, we have an extra check to make */
-	if (fmode & FMODE_EXEC) {
-		ret = nfs_may_open(state->inode,
-				state->owner->so_cred,
-				nd->intent.open.flags);
-		if (ret < 0)
-			goto out_close;
-	}
-	filp = lookup_instantiate_filp(nd, path->dentry, NULL);
-	if (!IS_ERR(filp)) {
-		struct nfs_open_context *ctx;
-		ctx = nfs_file_open_context(filp);
-		ctx->state = state;
-		return 0;
-	}
-	ret = PTR_ERR(filp);
-out_close:
-	nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE));
-	return ret;
-}
-
 struct inode *
 nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
@@ -2491,36 +2465,34 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nameidata *nd)
+                 int flags, struct nfs_open_context *ctx)
 {
-	struct path path = {
-		.mnt = nd->path.mnt,
+	struct path my_path = {
 		.dentry = dentry,
 	};
+	struct path *path = &my_path;
 	struct nfs4_state *state;
-	struct rpc_cred *cred;
-	fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE);
+	struct rpc_cred *cred = NULL;
+	fmode_t fmode = 0;
 	int status = 0;
 
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred)) {
-		status = PTR_ERR(cred);
-		goto out;
+	if (ctx != NULL) {
+		cred = ctx->cred;
+		path = &ctx->path;
+		fmode = ctx->mode;
 	}
-	state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
+	state = nfs4_do_open(dir, path, fmode, flags, sattr, cred);
 	d_drop(dentry);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
-		goto out_putcred;
+		goto out;
 	}
 	d_add(dentry, igrab(state->inode));
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
-		status = nfs4_intent_set_file(nd, &path, state, fmode);
+	if (ctx != NULL)
+		ctx->state = state;
 	else
-		nfs4_close_sync(&path, state, fmode);
-out_putcred:
-	put_rpccred(cred);
+		nfs4_close_sync(path, state, fmode);
 out:
 	return status;
 }
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 611bec2..4ef39ae 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -258,7 +258,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		int flags, struct nameidata *nd)
+		int flags, struct nfs_open_context *ctx)
 {
 	struct nfs_createdata *data;
 	struct rpc_message msg = {
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index fc46192..b1484da 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1032,7 +1032,7 @@ struct nfs_rpc_ops {
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
 			    unsigned int);
 	int	(*create)  (struct inode *, struct dentry *,
-			    struct iattr *, int, struct nameidata *);
+			    struct iattr *, int, struct nfs_open_context *);
 	int	(*remove)  (struct inode *, struct qstr *);
 	void	(*unlink_setup)  (struct rpc_message *, struct inode *dir);
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6/6] NFS: Add an 'open_context' element to struct nfs_rpc_ops
  2010-09-16 21:01         ` [PATCH 5/6] NFS: Clean up nfs4_proc_create() Trond Myklebust
@ 2010-09-16 21:01           ` Trond Myklebust
  0 siblings, 0 replies; 8+ messages in thread
From: Trond Myklebust @ 2010-09-16 21:01 UTC (permalink / raw)
  To: linux-nfs; +Cc: viro, hch

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/dir.c            |    7 ++++---
 fs/nfs/nfs4_fs.h        |    1 -
 fs/nfs/nfs4proc.c       |    3 ++-
 include/linux/nfs_xdr.h |    4 ++++
 4 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e37ffdd..1e9e188 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -34,7 +34,6 @@
 #include <linux/mount.h>
 #include <linux/sched.h>
 
-#include "nfs4_fs.h"
 #include "delegation.h"
 #include "iostat.h"
 #include "internal.h"
@@ -1127,7 +1126,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 
 	/* Open the file on the server */
 	nfs_block_sillyrename(dentry->d_parent);
-	inode = nfs4_atomic_open(dir, ctx, open_flags, &attr);
+	inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
 	if (IS_ERR(inode)) {
 		nfs_unblock_sillyrename(dentry->d_parent);
 		put_nfs_open_context(ctx);
@@ -1175,8 +1174,10 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 
 	if (!is_atomic_open(nd) || d_mountpoint(dentry))
 		goto no_open;
+
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
+
 	/* We can't create new files in nfs_open_revalidate(), so we
 	 * optimize away revalidation of negative dentries.
 	 */
@@ -1205,7 +1206,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	 * operations that change the directory. We therefore save the
 	 * change attribute *before* we do the RPC call.
 	 */
-	inode = nfs4_atomic_open(dir, ctx, openflags, NULL);
+	inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
 	if (IS_ERR(inode)) {
 		ret = PTR_ERR(inode);
 		switch (ret) {
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 6cf12ba..d24a8e0 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -242,7 +242,6 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
-extern struct inode *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 617b149..643abd2 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1998,7 +1998,7 @@ out:
 	return status;
 }
 
-struct inode *
+static struct inode *
 nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
 	struct nfs4_state *state;
@@ -5358,6 +5358,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 	.lock		= nfs4_proc_lock,
 	.clear_acl_cache = nfs4_zap_acl_attr,
 	.close_context  = nfs4_close_context,
+	.open_context	= nfs4_atomic_open,
 };
 
 /*
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index b1484da..6f345f8 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1065,6 +1065,10 @@ struct nfs_rpc_ops {
 	int	(*lock_check_bounds)(const struct file_lock *);
 	void	(*clear_acl_cache)(struct inode *);
 	void	(*close_context)(struct nfs_open_context *ctx, int);
+	struct inode * (*open_context) (struct inode *dir,
+				struct nfs_open_context *ctx,
+				int open_flags,
+				struct iattr *iattr);
 };
 
 /*
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open()
  2010-09-16 21:01   ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() Trond Myklebust
  2010-09-16 21:01     ` [PATCH 3/6] NFSv4: Clean up nfs4_open_revalidate Trond Myklebust
@ 2010-09-17 17:23     ` J. Bruce Fields
  1 sibling, 0 replies; 8+ messages in thread
From: J. Bruce Fields @ 2010-09-17 17:23 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-nfs, viro, hch

On Thu, Sep 16, 2010 at 05:01:39PM -0400, Trond Myklebust wrote:
> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
> ---
>  fs/nfs/dir.c      |   21 +++++++++++++++------
>  fs/nfs/nfs4_fs.h  |    2 +-
>  fs/nfs/nfs4proc.c |   28 ++++------------------------
>  3 files changed, 20 insertions(+), 31 deletions(-)
> 
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 17529b5..194676c 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -1084,8 +1084,8 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
>  	struct nfs_open_context *ctx;
>  	struct iattr attr;
>  	struct dentry *res = NULL;
> +	struct inode *inode;
>  	int open_flags;
> -	int error;
>  
>  	dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
>  			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
> @@ -1125,13 +1125,15 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
>  	}
>  
>  	/* Open the file on the server */
> -	res = nfs4_atomic_open(dir, ctx, open_flags, &attr);
> -	if (IS_ERR(res)) {
> +	nfs_block_sillyrename(dentry->d_parent);

This looks like a bugfix, not just "minor cleanups"?

--b.

> +	inode = nfs4_atomic_open(dir, ctx, open_flags, &attr);
> +	if (IS_ERR(inode)) {
> +		nfs_unblock_sillyrename(dentry->d_parent);
>  		put_nfs_open_context(ctx);
> -		error = PTR_ERR(res);
> -		switch (error) {
> +		switch (PTR_ERR(inode)) {
>  			/* Make a negative dentry */
>  			case -ENOENT:
> +				d_add(dentry, NULL);
>  				res = NULL;
>  				goto out;
>  			/* This turned out not to be a regular file */
> @@ -1143,13 +1145,20 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
>  					goto no_open;
>  			/* case -EINVAL: */
>  			default:
> +				res = ERR_CAST(inode);
>  				goto out;
>  		}
>  	}
> -	if (res != NULL)
> +	res = d_add_unique(dentry, inode);
> +	if (res != NULL) {
> +		dput(ctx->path.dentry);
> +		ctx->path.dentry = dget(res);
>  		dentry = res;
> +	}
>  	nfs_intent_set_file(nd, ctx);
> +	nfs_unblock_sillyrename(dentry->d_parent);
>  out:
> +	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
>  	return res;
>  no_open:
>  	return nfs_lookup(dir, dentry, nd);
> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index c5cc2a6..8e1f639 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -242,7 +242,7 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
>  extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
>  extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
>  extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
> -extern struct dentry *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
> +extern struct inode *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
>  extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
>  extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
>  extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 38c3bed..f8d41ee 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -2024,37 +2024,17 @@ out_close:
>  	return ret;
>  }
>  
> -struct dentry *
> +struct inode *
>  nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
>  {
> -	struct dentry *dentry = ctx->path.dentry;
> -	struct dentry *parent;
>  	struct nfs4_state *state;
> -	struct dentry *res;
>  
> -	parent = dentry->d_parent;
>  	/* Protect against concurrent sillydeletes */
> -	nfs_block_sillyrename(parent);
>  	state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
> -	if (IS_ERR(state)) {
> -		if (PTR_ERR(state) == -ENOENT) {
> -			d_add(dentry, NULL);
> -			nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
> -		}
> -		nfs_unblock_sillyrename(parent);
> -		return (struct dentry *)state;
> -	}
> -	res = d_add_unique(dentry, igrab(state->inode));
> -	if (res != NULL) {
> -		struct dentry *dummy = ctx->path.dentry;
> -
> -		ctx->path.dentry = dget(res);
> -		dput(dummy);
> -	}
> +	if (IS_ERR(state))
> +		return ERR_CAST(state);
>  	ctx->state = state;
> -	nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
> -	nfs_unblock_sillyrename(parent);
> -	return res;
> +	return igrab(state->inode);
>  }
>  
>  int
> -- 
> 1.7.2.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-09-17 17:24 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-16 21:01 [PATCH 0/6] Remove struct nameidata from lower level NFS code Trond Myklebust
2010-09-16 21:01 ` [PATCH 1/6] NFSv4: Clean up nfs4_atomic_open Trond Myklebust
2010-09-16 21:01   ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() Trond Myklebust
2010-09-16 21:01     ` [PATCH 3/6] NFSv4: Clean up nfs4_open_revalidate Trond Myklebust
2010-09-16 21:01       ` [PATCH 4/6] NFSv4: Further cleanups for nfs4_open_revalidate() Trond Myklebust
2010-09-16 21:01         ` [PATCH 5/6] NFS: Clean up nfs4_proc_create() Trond Myklebust
2010-09-16 21:01           ` [PATCH 6/6] NFS: Add an 'open_context' element to struct nfs_rpc_ops Trond Myklebust
2010-09-17 17:23     ` [PATCH 2/6] NFSv4: Further minor cleanups for nfs4_atomic_open() J. Bruce Fields

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).