aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c37
1 files changed, 18 insertions, 19 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5252d6681960..f4116cf16595 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3387,34 +3387,29 @@ static nfsd4_enc nfsd4_enc_ops[] = {
3387 3387
3388/* 3388/*
3389 * Calculate the total amount of memory that the compound response has taken 3389 * Calculate the total amount of memory that the compound response has taken
3390 * after encoding the current operation. 3390 * after encoding the current operation with pad.
3391 * 3391 *
3392 * pad: add on 8 bytes for the next operation's op_code and status so that 3392 * pad: if operation is non-idempotent, pad was calculate by op_rsize_bop()
3393 * there is room to cache a failure on the next operation. 3393 * which was specified at nfsd4_operation, else pad is zero.
3394 * 3394 *
3395 * Compare this length to the session se_fmaxresp_cached. 3395 * Compare this length to the session se_fmaxresp_sz and se_fmaxresp_cached.
3396 * 3396 *
3397 * Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so 3397 * Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so
3398 * will be at least a page and will therefore hold the xdr_buf head. 3398 * will be at least a page and will therefore hold the xdr_buf head.
3399 */ 3399 */
3400static int nfsd4_check_drc_limit(struct nfsd4_compoundres *resp) 3400int nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
3401{ 3401{
3402 int status = 0;
3403 struct xdr_buf *xb = &resp->rqstp->rq_res; 3402 struct xdr_buf *xb = &resp->rqstp->rq_res;
3404 struct nfsd4_compoundargs *args = resp->rqstp->rq_argp;
3405 struct nfsd4_session *session = NULL; 3403 struct nfsd4_session *session = NULL;
3406 struct nfsd4_slot *slot = resp->cstate.slot; 3404 struct nfsd4_slot *slot = resp->cstate.slot;
3407 u32 length, tlen = 0, pad = 8; 3405 u32 length, tlen = 0;
3408 3406
3409 if (!nfsd4_has_session(&resp->cstate)) 3407 if (!nfsd4_has_session(&resp->cstate))
3410 return status; 3408 return 0;
3411 3409
3412 session = resp->cstate.session; 3410 session = resp->cstate.session;
3413 if (session == NULL || slot->sl_cachethis == 0) 3411 if (session == NULL)
3414 return status; 3412 return 0;
3415
3416 if (resp->opcnt >= args->opcnt)
3417 pad = 0; /* this is the last operation */
3418 3413
3419 if (xb->page_len == 0) { 3414 if (xb->page_len == 0) {
3420 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; 3415 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad;
@@ -3427,10 +3422,14 @@ static int nfsd4_check_drc_limit(struct nfsd4_compoundres *resp)
3427 dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__, 3422 dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__,
3428 length, xb->page_len, tlen, pad); 3423 length, xb->page_len, tlen, pad);
3429 3424
3430 if (length <= session->se_fchannel.maxresp_cached) 3425 if (length > session->se_fchannel.maxresp_sz)
3431 return status; 3426 return nfserr_rep_too_big;
3432 else 3427
3428 if (slot->sl_cachethis == 1 &&
3429 length > session->se_fchannel.maxresp_cached)
3433 return nfserr_rep_too_big_to_cache; 3430 return nfserr_rep_too_big_to_cache;
3431
3432 return 0;
3434} 3433}
3435 3434
3436void 3435void
@@ -3450,8 +3449,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3450 !nfsd4_enc_ops[op->opnum]); 3449 !nfsd4_enc_ops[op->opnum]);
3451 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); 3450 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
3452 /* nfsd4_check_drc_limit guarantees enough room for error status */ 3451 /* nfsd4_check_drc_limit guarantees enough room for error status */
3453 if (!op->status && nfsd4_check_drc_limit(resp)) 3452 if (!op->status)
3454 op->status = nfserr_rep_too_big_to_cache; 3453 op->status = nfsd4_check_resp_size(resp, 0);
3455status: 3454status:
3456 /* 3455 /*
3457 * Note: We write the status directly, instead of using WRITE32(), 3456 * Note: We write the status directly, instead of using WRITE32(),