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.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 82189b208af3..d543222babf3 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1273,6 +1273,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1273 struct nfsd4_op *op; 1273 struct nfsd4_op *op;
1274 struct nfsd4_operation *opdesc; 1274 struct nfsd4_operation *opdesc;
1275 struct nfsd4_compound_state *cstate = &resp->cstate; 1275 struct nfsd4_compound_state *cstate = &resp->cstate;
1276 struct svc_fh *current_fh = &cstate->current_fh;
1277 struct svc_fh *save_fh = &cstate->save_fh;
1276 int slack_bytes; 1278 int slack_bytes;
1277 u32 plen = 0; 1279 u32 plen = 0;
1278 __be32 status; 1280 __be32 status;
@@ -1288,11 +1290,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1288 resp->tag = args->tag; 1290 resp->tag = args->tag;
1289 resp->opcnt = 0; 1291 resp->opcnt = 0;
1290 resp->rqstp = rqstp; 1292 resp->rqstp = rqstp;
1291 resp->cstate.minorversion = args->minorversion; 1293 cstate->minorversion = args->minorversion;
1292 resp->cstate.replay_owner = NULL; 1294 cstate->replay_owner = NULL;
1293 resp->cstate.session = NULL; 1295 cstate->session = NULL;
1294 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE); 1296 fh_init(current_fh, NFS4_FHSIZE);
1295 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE); 1297 fh_init(save_fh, NFS4_FHSIZE);
1296 /* 1298 /*
1297 * Don't use the deferral mechanism for NFSv4; compounds make it 1299 * Don't use the deferral mechanism for NFSv4; compounds make it
1298 * too hard to avoid non-idempotency problems. 1300 * too hard to avoid non-idempotency problems.
@@ -1345,20 +1347,28 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1345 1347
1346 opdesc = OPDESC(op); 1348 opdesc = OPDESC(op);
1347 1349
1348 if (!cstate->current_fh.fh_dentry) { 1350 if (!current_fh->fh_dentry) {
1349 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { 1351 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
1350 op->status = nfserr_nofilehandle; 1352 op->status = nfserr_nofilehandle;
1351 goto encode_op; 1353 goto encode_op;
1352 } 1354 }
1353 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated && 1355 } else if (current_fh->fh_export->ex_fslocs.migrated &&
1354 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) { 1356 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
1355 op->status = nfserr_moved; 1357 op->status = nfserr_moved;
1356 goto encode_op; 1358 goto encode_op;
1357 } 1359 }
1358 1360
1361 fh_clear_wcc(current_fh);
1362
1359 /* If op is non-idempotent */ 1363 /* If op is non-idempotent */
1360 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { 1364 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) {
1361 plen = opdesc->op_rsize_bop(rqstp, op); 1365 plen = opdesc->op_rsize_bop(rqstp, op);
1366 /*
1367 * If there's still another operation, make sure
1368 * we'll have space to at least encode an error:
1369 */
1370 if (resp->opcnt < args->opcnt)
1371 plen += COMPOUND_ERR_SLACK_SPACE;
1362 op->status = nfsd4_check_resp_size(resp, plen); 1372 op->status = nfsd4_check_resp_size(resp, plen);
1363 } 1373 }
1364 1374
@@ -1377,12 +1387,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1377 clear_current_stateid(cstate); 1387 clear_current_stateid(cstate);
1378 1388
1379 if (need_wrongsec_check(rqstp)) 1389 if (need_wrongsec_check(rqstp))
1380 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); 1390 op->status = check_nfsd_access(current_fh->fh_export, rqstp);
1381 } 1391 }
1382 1392
1383encode_op: 1393encode_op:
1384 /* Only from SEQUENCE */ 1394 /* Only from SEQUENCE */
1385 if (resp->cstate.status == nfserr_replay_cache) { 1395 if (cstate->status == nfserr_replay_cache) {
1386 dprintk("%s NFS4.1 replay from cache\n", __func__); 1396 dprintk("%s NFS4.1 replay from cache\n", __func__);
1387 status = op->status; 1397 status = op->status;
1388 goto out; 1398 goto out;
@@ -1411,10 +1421,10 @@ encode_op:
1411 nfsd4_increment_op_stats(op->opnum); 1421 nfsd4_increment_op_stats(op->opnum);
1412 } 1422 }
1413 1423
1414 resp->cstate.status = status; 1424 cstate->status = status;
1415 fh_put(&resp->cstate.current_fh); 1425 fh_put(current_fh);
1416 fh_put(&resp->cstate.save_fh); 1426 fh_put(save_fh);
1417 BUG_ON(resp->cstate.replay_owner); 1427 BUG_ON(cstate->replay_owner);
1418out: 1428out:
1419 /* Reset deferral mechanism for RPC deferrals */ 1429 /* Reset deferral mechanism for RPC deferrals */
1420 rqstp->rq_usedeferral = 1; 1430 rqstp->rq_usedeferral = 1;
@@ -1523,7 +1533,8 @@ static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o
1523 1533
1524static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1534static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1525{ 1535{
1526 return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32); 1536 return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) *
1537 sizeof(__be32);
1527} 1538}
1528 1539
1529static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1540static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)