Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142204
b: refs/heads/master
c: 496c262
h: refs/heads/master
v: v3
  • Loading branch information
Andy Adamson authored and J. Bruce Fields committed Apr 4, 2009
1 parent 92f905d commit 692ad71
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6668958fac1d05f55420de702f3678d46c1e93a5
refs/heads/master: 496c262cf01106a546ffb7df6fea84b8b881ee19
51 changes: 51 additions & 0 deletions trunk/fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3078,6 +3078,54 @@ static nfsd4_enc nfsd4_enc_ops[] = {
[OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
};

/*
* Calculate the total amount of memory that the compound response has taken
* after encoding the current operation.
*
* pad: add on 8 bytes for the next operation's op_code and status so that
* there is room to cache a failure on the next operation.
*
* Compare this length to the session se_fmaxresp_cached.
*
* Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so
* will be at least a page and will therefore hold the xdr_buf head.
*/
static int nfsd4_check_drc_limit(struct nfsd4_compoundres *resp)
{
int status = 0;
struct xdr_buf *xb = &resp->rqstp->rq_res;
struct nfsd4_compoundargs *args = resp->rqstp->rq_argp;
struct nfsd4_session *session = NULL;
struct nfsd4_slot *slot = resp->cstate.slot;
u32 length, tlen = 0, pad = 8;

if (!nfsd4_has_session(&resp->cstate))
return status;

session = resp->cstate.session;
if (session == NULL || slot->sl_cache_entry.ce_cachethis == 0)
return status;

if (resp->opcnt >= args->opcnt)
pad = 0; /* this is the last operation */

if (xb->page_len == 0) {
length = (char *)resp->p - (char *)xb->head[0].iov_base + pad;
} else {
if (xb->tail[0].iov_base && xb->tail[0].iov_len > 0)
tlen = (char *)resp->p - (char *)xb->tail[0].iov_base;

length = xb->head[0].iov_len + xb->page_len + tlen + pad;
}
dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__,
length, xb->page_len, tlen, pad);

if (length <= session->se_fmaxresp_cached)
return status;
else
return nfserr_rep_too_big_to_cache;
}

void
nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
{
Expand All @@ -3094,6 +3142,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
!nfsd4_enc_ops[op->opnum]);
op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
/* nfsd4_check_drc_limit guarantees enough room for error status */
if (!op->status && nfsd4_check_drc_limit(resp))
op->status = nfserr_rep_too_big_to_cache;
status:
/*
* Note: We write the status directly, instead of using WRITE32(),
Expand Down

0 comments on commit 692ad71

Please sign in to comment.