xprtrdma: rpcrdma_inline_fixup() overruns the receive page list
When the remaining length of an incoming reply is longer than the XDR buf's page_len, switch over to the tail iovec instead of copying more than page_len bytes into the page list. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
5ab8142839
commit
80414abc28
|
@ -773,12 +773,17 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
|
|||
page_base &= ~PAGE_MASK;
|
||||
|
||||
if (copy_len && rqst->rq_rcv_buf.page_len) {
|
||||
npages = PAGE_ALIGN(page_base +
|
||||
rqst->rq_rcv_buf.page_len) >> PAGE_SHIFT;
|
||||
int pagelist_len;
|
||||
|
||||
pagelist_len = rqst->rq_rcv_buf.page_len;
|
||||
if (pagelist_len > copy_len)
|
||||
pagelist_len = copy_len;
|
||||
npages = PAGE_ALIGN(page_base + pagelist_len) >> PAGE_SHIFT;
|
||||
for (; i < npages; i++) {
|
||||
curlen = PAGE_SIZE - page_base;
|
||||
if (curlen > copy_len)
|
||||
curlen = copy_len;
|
||||
if (curlen > pagelist_len)
|
||||
curlen = pagelist_len;
|
||||
|
||||
dprintk("RPC: %s: page %d"
|
||||
" srcp 0x%p len %d curlen %d\n",
|
||||
__func__, i, srcp, copy_len, curlen);
|
||||
|
@ -788,7 +793,8 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
|
|||
kunmap_atomic(destp);
|
||||
srcp += curlen;
|
||||
copy_len -= curlen;
|
||||
if (copy_len == 0)
|
||||
pagelist_len -= curlen;
|
||||
if (!pagelist_len)
|
||||
break;
|
||||
page_base = 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue