When inserting a DRC-cached response into the reply buffer, ensure that the reply buffer's xdr_stream is updated properly. Otherwise the server will send a garbage response.
Unified · Split
| @@ -640,24 +640,17 @@ void nfsd_cache_update(struct svc_rqst *rqstp, struct nfsd_cacherep *rp, · 639 unmodified lines | ||
| 640 | 640 | return; |
| 641 | 641 | } |
| 642 | 642 | |
| 643 | −/* | |
| 644 | − * Copy cached reply to current reply buffer. Should always fit. | |
| 645 | − * FIXME as reply is in a page, we should just attach the page, and | |
| 646 | − * keep a refcount.... | |
| 647 | − */ | |
| 648 | 643 | static int |
| 649 | 644 | nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data) |
| 650 | 645 | { |
| 651 | − struct kvec *vec = &rqstp->rq_res.head[0]; | |
| 652 | − | |
| 653 | − if (vec->iov_len + data->iov_len > PAGE_SIZE) { | |
| 654 | − printk(KERN_WARNING "nfsd: cached reply too large (%zd).\n", | |
| 655 | − data->iov_len); | |
| 656 | − return 0; | |
| 657 | − } | |
| 658 | − memcpy((char*)vec->iov_base + vec->iov_len, data->iov_base, data->iov_len); | |
| 659 | − vec->iov_len += data->iov_len; | |
| 660 | − return 1; | |
| 646 | + __be32 *p; | |
| 647 | + | |
| 648 | + p = xdr_reserve_space(&rqstp->rq_res_stream, data->iov_len); | |
| 649 | + if (unlikely(!p)) | |
| 650 | + return false; | |
| 651 | + memcpy(p, data->iov_base, data->iov_len); | |
| 652 | + xdr_commit_encode(&rqstp->rq_res_stream); | |
| 653 | + return true; | |
| 661 | 654 | } |
| 662 | 655 | |
| 663 | 656 | /* |