aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r--fs/nfsd/nfs4proc.c97
1 files changed, 57 insertions, 40 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index ae73175e6e68..8ae5abfe6ba2 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -191,9 +191,18 @@ static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
191 return nfserr_symlink; 191 return nfserr_symlink;
192} 192}
193 193
194static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh *resfh)
195{
196 if (nfsd4_has_session(cstate))
197 return;
198 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
199 &resfh->fh_handle);
200}
201
194static __be32 202static __be32
195do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 203do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
196{ 204{
205 struct svc_fh *current_fh = &cstate->current_fh;
197 struct svc_fh *resfh; 206 struct svc_fh *resfh;
198 int accmode; 207 int accmode;
199 __be32 status; 208 __be32 status;
@@ -252,9 +261,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
252 if (is_create_with_attrs(open) && open->op_acl != NULL) 261 if (is_create_with_attrs(open) && open->op_acl != NULL)
253 do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); 262 do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
254 263
255 /* set reply cache */ 264 nfsd4_set_open_owner_reply_cache(cstate, open, resfh);
256 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
257 &resfh->fh_handle);
258 accmode = NFSD_MAY_NOP; 265 accmode = NFSD_MAY_NOP;
259 if (open->op_created) 266 if (open->op_created)
260 accmode |= NFSD_MAY_OWNER_OVERRIDE; 267 accmode |= NFSD_MAY_OWNER_OVERRIDE;
@@ -268,8 +275,9 @@ out:
268} 275}
269 276
270static __be32 277static __be32
271do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 278do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
272{ 279{
280 struct svc_fh *current_fh = &cstate->current_fh;
273 __be32 status; 281 __be32 status;
274 282
275 /* We don't know the target directory, and therefore can not 283 /* We don't know the target directory, and therefore can not
@@ -278,9 +286,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
278 286
279 memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info)); 287 memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
280 288
281 /* set replay cache */ 289 nfsd4_set_open_owner_reply_cache(cstate, open, current_fh);
282 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
283 &current_fh->fh_handle);
284 290
285 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && 291 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
286 (open->op_iattr.ia_size == 0); 292 (open->op_iattr.ia_size == 0);
@@ -351,6 +357,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
351 } 357 }
352 if (status) 358 if (status)
353 goto out; 359 goto out;
360 if (open->op_xdr_error) {
361 status = open->op_xdr_error;
362 goto out;
363 }
354 364
355 status = nfsd4_check_open_attributes(rqstp, cstate, open); 365 status = nfsd4_check_open_attributes(rqstp, cstate, open);
356 if (status) 366 if (status)
@@ -368,8 +378,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
368 switch (open->op_claim_type) { 378 switch (open->op_claim_type) {
369 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 379 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
370 case NFS4_OPEN_CLAIM_NULL: 380 case NFS4_OPEN_CLAIM_NULL:
371 status = do_open_lookup(rqstp, &cstate->current_fh, 381 status = do_open_lookup(rqstp, cstate, open);
372 open);
373 if (status) 382 if (status)
374 goto out; 383 goto out;
375 break; 384 break;
@@ -382,8 +391,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
382 goto out; 391 goto out;
383 case NFS4_OPEN_CLAIM_FH: 392 case NFS4_OPEN_CLAIM_FH:
384 case NFS4_OPEN_CLAIM_DELEG_CUR_FH: 393 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
385 status = do_open_fhandle(rqstp, &cstate->current_fh, 394 status = do_open_fhandle(rqstp, cstate, open);
386 open);
387 if (status) 395 if (status)
388 goto out; 396 goto out;
389 break; 397 break;
@@ -409,14 +417,33 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
409 WARN_ON(status && open->op_created); 417 WARN_ON(status && open->op_created);
410out: 418out:
411 nfsd4_cleanup_open_state(open, status); 419 nfsd4_cleanup_open_state(open, status);
412 if (open->op_openowner) 420 if (open->op_openowner && !nfsd4_has_session(cstate))
413 cstate->replay_owner = &open->op_openowner->oo_owner; 421 cstate->replay_owner = &open->op_openowner->oo_owner;
414 else 422 nfsd4_bump_seqid(cstate, status);
423 if (!cstate->replay_owner)
415 nfs4_unlock_state(); 424 nfs4_unlock_state();
416 return status; 425 return status;
417} 426}
418 427
419/* 428/*
429 * OPEN is the only seqid-mutating operation whose decoding can fail
430 * with a seqid-mutating error (specifically, decoding of user names in
431 * the attributes). Therefore we have to do some processing to look up
432 * the stateowner so that we can bump the seqid.
433 */
434static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_op *op)
435{
436 struct nfsd4_open *open = (struct nfsd4_open *)&op->u;
437
438 if (!seqid_mutating_err(ntohl(op->status)))
439 return op->status;
440 if (nfsd4_has_session(cstate))
441 return op->status;
442 open->op_xdr_error = op->status;
443 return nfsd4_open(rqstp, cstate, open);
444}
445
446/*
420 * filehandle-manipulating ops. 447 * filehandle-manipulating ops.
421 */ 448 */
422static __be32 449static __be32
@@ -786,21 +813,11 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
786 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, 813 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
787 rename->rn_snamelen, &cstate->current_fh, 814 rename->rn_snamelen, &cstate->current_fh,
788 rename->rn_tname, rename->rn_tnamelen); 815 rename->rn_tname, rename->rn_tnamelen);
789 816 if (status)
790 /* the underlying filesystem returns different error's than required 817 return status;
791 * by NFSv4. both save_fh and current_fh have been verified.. */ 818 set_change_info(&rename->rn_sinfo, &cstate->current_fh);
792 if (status == nfserr_isdir) 819 set_change_info(&rename->rn_tinfo, &cstate->save_fh);
793 status = nfserr_exist; 820 return nfs_ok;
794 else if ((status == nfserr_notdir) &&
795 (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
796 S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
797 status = nfserr_exist;
798
799 if (!status) {
800 set_change_info(&rename->rn_sinfo, &cstate->current_fh);
801 set_change_info(&rename->rn_tinfo, &cstate->save_fh);
802 }
803 return status;
804} 821}
805 822
806static __be32 823static __be32
@@ -931,14 +948,14 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
931 nfs4_lock_state(); 948 nfs4_lock_state();
932 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 949 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
933 cstate, stateid, WR_STATE, &filp); 950 cstate, stateid, WR_STATE, &filp);
934 if (filp)
935 get_file(filp);
936 nfs4_unlock_state();
937
938 if (status) { 951 if (status) {
952 nfs4_unlock_state();
939 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 953 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
940 return status; 954 return status;
941 } 955 }
956 if (filp)
957 get_file(filp);
958 nfs4_unlock_state();
942 959
943 cnt = write->wr_buflen; 960 cnt = write->wr_buflen;
944 write->wr_how_written = write->wr_stable_how; 961 write->wr_how_written = write->wr_stable_how;
@@ -1244,8 +1261,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1244 * for example, if there is a miscellaneous XDR error 1261 * for example, if there is a miscellaneous XDR error
1245 * it will be set to nfserr_bad_xdr. 1262 * it will be set to nfserr_bad_xdr.
1246 */ 1263 */
1247 if (op->status) 1264 if (op->status) {
1265 if (op->opnum == OP_OPEN)
1266 op->status = nfsd4_open_omfg(rqstp, cstate, op);
1248 goto encode_op; 1267 goto encode_op;
1268 }
1249 1269
1250 /* We must be able to encode a successful response to 1270 /* We must be able to encode a successful response to
1251 * this operation, with enough room left over to encode a 1271 * this operation, with enough room left over to encode a
@@ -1282,12 +1302,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1282 if (op->status) 1302 if (op->status)
1283 goto encode_op; 1303 goto encode_op;
1284 1304
1285 if (opdesc->op_func) { 1305 if (opdesc->op_get_currentstateid)
1286 if (opdesc->op_get_currentstateid) 1306 opdesc->op_get_currentstateid(cstate, &op->u);
1287 opdesc->op_get_currentstateid(cstate, &op->u); 1307 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1288 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1289 } else
1290 BUG_ON(op->status == nfs_ok);
1291 1308
1292 if (!op->status) { 1309 if (!op->status) {
1293 if (opdesc->op_set_currentstateid) 1310 if (opdesc->op_set_currentstateid)