aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-17 10:56:50 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-17 10:56:50 -0400
commitcd9a1c0e5ac681871d64804f82291649e2a0accb (patch)
tree900c2bf6ba75c2a02af07091afcf4ba4cfdb2396 /fs/nfs
parent859d5024f450686ad0a42ed3c06f2fa20295c9e6 (diff)
NFSv4: Clean up nfs4_atomic_open
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>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c77
-rw-r--r--fs/nfs/inode.c8
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c40
4 files changed, 91 insertions, 36 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e257172d438c..17529b5bc551 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -38,6 +38,7 @@
38#include "delegation.h" 38#include "delegation.h"
39#include "iostat.h" 39#include "iostat.h"
40#include "internal.h" 40#include "internal.h"
41#include "fscache.h"
41 42
42/* #define NFS_DEBUG_VERBOSE 1 */ 43/* #define NFS_DEBUG_VERBOSE 1 */
43 44
@@ -1029,9 +1030,61 @@ static int is_atomic_open(struct nameidata *nd)
1029 return 1; 1030 return 1;
1030} 1031}
1031 1032
1033static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
1034{
1035 struct path path = {
1036 .mnt = nd->path.mnt,
1037 .dentry = dentry,
1038 };
1039 struct nfs_open_context *ctx;
1040 struct rpc_cred *cred;
1041 fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
1042
1043 cred = rpc_lookup_cred();
1044 if (IS_ERR(cred))
1045 return ERR_CAST(cred);
1046 ctx = alloc_nfs_open_context(&path, cred, fmode);
1047 put_rpccred(cred);
1048 if (ctx == NULL)
1049 return ERR_PTR(-ENOMEM);
1050 return ctx;
1051}
1052
1053static int do_open(struct inode *inode, struct file *filp)
1054{
1055 nfs_fscache_set_inode_cookie(inode, filp);
1056 return 0;
1057}
1058
1059static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
1060{
1061 struct file *filp;
1062 int ret = 0;
1063
1064 /* If the open_intent is for execute, we have an extra check to make */
1065 if (ctx->mode & FMODE_EXEC) {
1066 ret = nfs_may_open(ctx->path.dentry->d_inode,
1067 ctx->cred,
1068 nd->intent.open.flags);
1069 if (ret < 0)
1070 goto out;
1071 }
1072 filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
1073 if (IS_ERR(filp))
1074 ret = PTR_ERR(filp);
1075 else
1076 nfs_file_set_open_context(filp, ctx);
1077out:
1078 put_nfs_open_context(ctx);
1079 return ret;
1080}
1081
1032static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 1082static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1033{ 1083{
1084 struct nfs_open_context *ctx;
1085 struct iattr attr;
1034 struct dentry *res = NULL; 1086 struct dentry *res = NULL;
1087 int open_flags;
1035 int error; 1088 int error;
1036 1089
1037 dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", 1090 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
1054 goto out; 1107 goto out;
1055 } 1108 }
1056 1109
1110 ctx = nameidata_to_nfs_open_context(dentry, nd);
1111 res = ERR_CAST(ctx);
1112 if (IS_ERR(ctx))
1113 goto out;
1114
1115 open_flags = nd->intent.open.flags;
1116 if (nd->flags & LOOKUP_CREATE) {
1117 attr.ia_mode = nd->intent.open.create_mode;
1118 attr.ia_valid = ATTR_MODE;
1119 if (!IS_POSIXACL(dir))
1120 attr.ia_mode &= ~current_umask();
1121 } else {
1122 open_flags &= ~O_EXCL;
1123 attr.ia_valid = 0;
1124 BUG_ON(open_flags & O_CREAT);
1125 }
1126
1057 /* Open the file on the server */ 1127 /* Open the file on the server */
1058 res = nfs4_atomic_open(dir, dentry, nd); 1128 res = nfs4_atomic_open(dir, ctx, open_flags, &attr);
1059 if (IS_ERR(res)) { 1129 if (IS_ERR(res)) {
1130 put_nfs_open_context(ctx);
1060 error = PTR_ERR(res); 1131 error = PTR_ERR(res);
1061 switch (error) { 1132 switch (error) {
1062 /* Make a negative dentry */ 1133 /* Make a negative dentry */
@@ -1074,8 +1145,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
1074 default: 1145 default:
1075 goto out; 1146 goto out;
1076 } 1147 }
1077 } else if (res != NULL) 1148 }
1149 if (res != NULL)
1078 dentry = res; 1150 dentry = res;
1151 nfs_intent_set_file(nd, ctx);
1079out: 1152out:
1080 return res; 1153 return res;
1081no_open: 1154no_open:
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7d2d6c72aa78..2f9266406afc 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)
623 nfs_revalidate_inode(server, inode); 623 nfs_revalidate_inode(server, inode);
624} 624}
625 625
626static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred) 626struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
627{ 627{
628 struct nfs_open_context *ctx; 628 struct nfs_open_context *ctx;
629 629
@@ -633,6 +633,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
633 path_get(&ctx->path); 633 path_get(&ctx->path);
634 ctx->cred = get_rpccred(cred); 634 ctx->cred = get_rpccred(cred);
635 ctx->state = NULL; 635 ctx->state = NULL;
636 ctx->mode = f_mode;
636 ctx->flags = 0; 637 ctx->flags = 0;
637 ctx->error = 0; 638 ctx->error = 0;
638 ctx->dir_cookie = 0; 639 ctx->dir_cookie = 0;
@@ -673,7 +674,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
673 * Ensure that mmap has a recent RPC credential for use when writing out 674 * Ensure that mmap has a recent RPC credential for use when writing out
674 * shared pages 675 * shared pages
675 */ 676 */
676static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) 677void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
677{ 678{
678 struct inode *inode = filp->f_path.dentry->d_inode; 679 struct inode *inode = filp->f_path.dentry->d_inode;
679 struct nfs_inode *nfsi = NFS_I(inode); 680 struct nfs_inode *nfsi = NFS_I(inode);
@@ -730,11 +731,10 @@ int nfs_open(struct inode *inode, struct file *filp)
730 cred = rpc_lookup_cred(); 731 cred = rpc_lookup_cred();
731 if (IS_ERR(cred)) 732 if (IS_ERR(cred))
732 return PTR_ERR(cred); 733 return PTR_ERR(cred);
733 ctx = alloc_nfs_open_context(&filp->f_path, cred); 734 ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
734 put_rpccred(cred); 735 put_rpccred(cred);
735 if (ctx == NULL) 736 if (ctx == NULL)
736 return -ENOMEM; 737 return -ENOMEM;
737 ctx->mode = filp->f_mode;
738 nfs_file_set_open_context(filp, ctx); 738 nfs_file_set_open_context(filp, ctx);
739 put_nfs_open_context(ctx); 739 put_nfs_open_context(ctx);
740 nfs_fscache_set_inode_cookie(inode, filp); 740 nfs_fscache_set_inode_cookie(inode, filp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 311e15cc8af0..c5cc2a6aceb0 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 *);
242extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); 242extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
243extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); 243extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
244extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait); 244extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
245extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); 245extern struct dentry *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
246extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 246extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
247extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); 247extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
248extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, 248extern 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 089da5b5d20a..38c3bed2240d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2025,39 +2025,17 @@ out_close:
2025} 2025}
2026 2026
2027struct dentry * 2027struct dentry *
2028nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 2028nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
2029{ 2029{
2030 struct path path = { 2030 struct dentry *dentry = ctx->path.dentry;
2031 .mnt = nd->path.mnt,
2032 .dentry = dentry,
2033 };
2034 struct dentry *parent; 2031 struct dentry *parent;
2035 struct iattr attr;
2036 struct rpc_cred *cred;
2037 struct nfs4_state *state; 2032 struct nfs4_state *state;
2038 struct dentry *res; 2033 struct dentry *res;
2039 int open_flags = nd->intent.open.flags;
2040 fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
2041
2042 if (nd->flags & LOOKUP_CREATE) {
2043 attr.ia_mode = nd->intent.open.create_mode;
2044 attr.ia_valid = ATTR_MODE;
2045 if (!IS_POSIXACL(dir))
2046 attr.ia_mode &= ~current_umask();
2047 } else {
2048 open_flags &= ~O_EXCL;
2049 attr.ia_valid = 0;
2050 BUG_ON(open_flags & O_CREAT);
2051 }
2052 2034
2053 cred = rpc_lookup_cred();
2054 if (IS_ERR(cred))
2055 return (struct dentry *)cred;
2056 parent = dentry->d_parent; 2035 parent = dentry->d_parent;
2057 /* Protect against concurrent sillydeletes */ 2036 /* Protect against concurrent sillydeletes */
2058 nfs_block_sillyrename(parent); 2037 nfs_block_sillyrename(parent);
2059 state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred); 2038 state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
2060 put_rpccred(cred);
2061 if (IS_ERR(state)) { 2039 if (IS_ERR(state)) {
2062 if (PTR_ERR(state) == -ENOENT) { 2040 if (PTR_ERR(state) == -ENOENT) {
2063 d_add(dentry, NULL); 2041 d_add(dentry, NULL);
@@ -2067,11 +2045,15 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
2067 return (struct dentry *)state; 2045 return (struct dentry *)state;
2068 } 2046 }
2069 res = d_add_unique(dentry, igrab(state->inode)); 2047 res = d_add_unique(dentry, igrab(state->inode));
2070 if (res != NULL) 2048 if (res != NULL) {
2071 path.dentry = res; 2049 struct dentry *dummy = ctx->path.dentry;
2072 nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); 2050
2051 ctx->path.dentry = dget(res);
2052 dput(dummy);
2053 }
2054 ctx->state = state;
2055 nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
2073 nfs_unblock_sillyrename(parent); 2056 nfs_unblock_sillyrename(parent);
2074 nfs4_intent_set_file(nd, &path, state, fmode);
2075 return res; 2057 return res;
2076} 2058}
2077 2059