diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-09-17 10:56:50 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-09-17 10:56:50 -0400 |
commit | cd9a1c0e5ac681871d64804f82291649e2a0accb (patch) | |
tree | 900c2bf6ba75c2a02af07091afcf4ba4cfdb2396 /fs/nfs/dir.c | |
parent | 859d5024f450686ad0a42ed3c06f2fa20295c9e6 (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.c | 77 |
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 | ||
1033 | static 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 | |||
1053 | static int do_open(struct inode *inode, struct file *filp) | ||
1054 | { | ||
1055 | nfs_fscache_set_inode_cookie(inode, filp); | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | static 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); | ||
1077 | out: | ||
1078 | put_nfs_open_context(ctx); | ||
1079 | return ret; | ||
1080 | } | ||
1081 | |||
1032 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1082 | static 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); | ||
1079 | out: | 1152 | out: |
1080 | return res; | 1153 | return res; |
1081 | no_open: | 1154 | no_open: |