aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
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/dir.c
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/dir.c')
-rw-r--r--fs/nfs/dir.c77
1 files changed, 75 insertions, 2 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: