diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 114 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 2 |
2 files changed, 89 insertions, 27 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 68438aa4f08e..2b62e3f79c91 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -152,6 +152,12 @@ static const u32 nfs4_pnfs_open_bitmap[3] = { | |||
152 | FATTR4_WORD2_MDSTHRESHOLD | 152 | FATTR4_WORD2_MDSTHRESHOLD |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static const u32 nfs4_open_noattr_bitmap[3] = { | ||
156 | FATTR4_WORD0_TYPE | ||
157 | | FATTR4_WORD0_CHANGE | ||
158 | | FATTR4_WORD0_FILEID, | ||
159 | }; | ||
160 | |||
155 | const u32 nfs4_statfs_bitmap[2] = { | 161 | const u32 nfs4_statfs_bitmap[2] = { |
156 | FATTR4_WORD0_FILES_AVAIL | 162 | FATTR4_WORD0_FILES_AVAIL |
157 | | FATTR4_WORD0_FILES_FREE | 163 | | FATTR4_WORD0_FILES_FREE |
@@ -1126,11 +1132,80 @@ out_return_state: | |||
1126 | return state; | 1132 | return state; |
1127 | } | 1133 | } |
1128 | 1134 | ||
1129 | static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | 1135 | static void |
1136 | nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state) | ||
1137 | { | ||
1138 | struct nfs_client *clp = NFS_SERVER(state->inode)->nfs_client; | ||
1139 | struct nfs_delegation *delegation; | ||
1140 | int delegation_flags = 0; | ||
1141 | |||
1142 | rcu_read_lock(); | ||
1143 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | ||
1144 | if (delegation) | ||
1145 | delegation_flags = delegation->flags; | ||
1146 | rcu_read_unlock(); | ||
1147 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) { | ||
1148 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " | ||
1149 | "returning a delegation for " | ||
1150 | "OPEN(CLAIM_DELEGATE_CUR)\n", | ||
1151 | clp->cl_hostname); | ||
1152 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | ||
1153 | nfs_inode_set_delegation(state->inode, | ||
1154 | data->owner->so_cred, | ||
1155 | &data->o_res); | ||
1156 | else | ||
1157 | nfs_inode_reclaim_delegation(state->inode, | ||
1158 | data->owner->so_cred, | ||
1159 | &data->o_res); | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
1163 | * Check the inode attributes against the CLAIM_PREVIOUS returned attributes | ||
1164 | * and update the nfs4_state. | ||
1165 | */ | ||
1166 | static struct nfs4_state * | ||
1167 | _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) | ||
1168 | { | ||
1169 | struct inode *inode = data->state->inode; | ||
1170 | struct nfs4_state *state = data->state; | ||
1171 | int ret; | ||
1172 | |||
1173 | if (!data->rpc_done) { | ||
1174 | ret = data->rpc_status; | ||
1175 | goto err; | ||
1176 | } | ||
1177 | |||
1178 | ret = -ESTALE; | ||
1179 | if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) || | ||
1180 | !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) || | ||
1181 | !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE)) | ||
1182 | goto err; | ||
1183 | |||
1184 | ret = -ENOMEM; | ||
1185 | state = nfs4_get_open_state(inode, data->owner); | ||
1186 | if (state == NULL) | ||
1187 | goto err; | ||
1188 | |||
1189 | ret = nfs_refresh_inode(inode, &data->f_attr); | ||
1190 | if (ret) | ||
1191 | goto err; | ||
1192 | |||
1193 | if (data->o_res.delegation_type != 0) | ||
1194 | nfs4_opendata_check_deleg(data, state); | ||
1195 | update_open_stateid(state, &data->o_res.stateid, NULL, | ||
1196 | data->o_arg.fmode); | ||
1197 | |||
1198 | return state; | ||
1199 | err: | ||
1200 | return ERR_PTR(ret); | ||
1201 | |||
1202 | } | ||
1203 | |||
1204 | static struct nfs4_state * | ||
1205 | _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | ||
1130 | { | 1206 | { |
1131 | struct inode *inode; | 1207 | struct inode *inode; |
1132 | struct nfs4_state *state = NULL; | 1208 | struct nfs4_state *state = NULL; |
1133 | struct nfs_delegation *delegation; | ||
1134 | int ret; | 1209 | int ret; |
1135 | 1210 | ||
1136 | if (!data->rpc_done) { | 1211 | if (!data->rpc_done) { |
@@ -1149,30 +1224,8 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data | |||
1149 | state = nfs4_get_open_state(inode, data->owner); | 1224 | state = nfs4_get_open_state(inode, data->owner); |
1150 | if (state == NULL) | 1225 | if (state == NULL) |
1151 | goto err_put_inode; | 1226 | goto err_put_inode; |
1152 | if (data->o_res.delegation_type != 0) { | 1227 | if (data->o_res.delegation_type != 0) |
1153 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 1228 | nfs4_opendata_check_deleg(data, state); |
1154 | int delegation_flags = 0; | ||
1155 | |||
1156 | rcu_read_lock(); | ||
1157 | delegation = rcu_dereference(NFS_I(inode)->delegation); | ||
1158 | if (delegation) | ||
1159 | delegation_flags = delegation->flags; | ||
1160 | rcu_read_unlock(); | ||
1161 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) { | ||
1162 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " | ||
1163 | "returning a delegation for " | ||
1164 | "OPEN(CLAIM_DELEGATE_CUR)\n", | ||
1165 | clp->cl_hostname); | ||
1166 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | ||
1167 | nfs_inode_set_delegation(state->inode, | ||
1168 | data->owner->so_cred, | ||
1169 | &data->o_res); | ||
1170 | else | ||
1171 | nfs_inode_reclaim_delegation(state->inode, | ||
1172 | data->owner->so_cred, | ||
1173 | &data->o_res); | ||
1174 | } | ||
1175 | |||
1176 | update_open_stateid(state, &data->o_res.stateid, NULL, | 1229 | update_open_stateid(state, &data->o_res.stateid, NULL, |
1177 | data->o_arg.fmode); | 1230 | data->o_arg.fmode); |
1178 | iput(inode); | 1231 | iput(inode); |
@@ -1184,6 +1237,14 @@ err: | |||
1184 | return ERR_PTR(ret); | 1237 | return ERR_PTR(ret); |
1185 | } | 1238 | } |
1186 | 1239 | ||
1240 | static struct nfs4_state * | ||
1241 | nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | ||
1242 | { | ||
1243 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) | ||
1244 | return _nfs4_opendata_reclaim_to_nfs4_state(data); | ||
1245 | return _nfs4_opendata_to_nfs4_state(data); | ||
1246 | } | ||
1247 | |||
1187 | static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state) | 1248 | static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state) |
1188 | { | 1249 | { |
1189 | struct nfs_inode *nfsi = NFS_I(state->inode); | 1250 | struct nfs_inode *nfsi = NFS_I(state->inode); |
@@ -1505,6 +1566,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1505 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; | 1566 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; |
1506 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 1567 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
1507 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 1568 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
1569 | data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0]; | ||
1508 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | 1570 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); |
1509 | } | 1571 | } |
1510 | data->timestamp = jiffies; | 1572 | data->timestamp = jiffies; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 0d6030510fe2..40836ee5dc3a 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -2264,7 +2264,7 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, | |||
2264 | encode_open(xdr, args, &hdr); | 2264 | encode_open(xdr, args, &hdr); |
2265 | if (args->access) | 2265 | if (args->access) |
2266 | encode_access(xdr, args->access, &hdr); | 2266 | encode_access(xdr, args->access, &hdr); |
2267 | encode_getfattr(xdr, args->bitmask, &hdr); | 2267 | encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); |
2268 | encode_nops(&hdr); | 2268 | encode_nops(&hdr); |
2269 | } | 2269 | } |
2270 | 2270 | ||