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 | return; | 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 | static int | 643 | static int |
| 649 | nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data) | 644 | nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data) |
| 650 | { | 645 | { |
| 651 | struct kvec *vec = &rqstp->rq_res.head[0]; | 646 | __be32 *p; |
| 652 | 647 | ||
| 653 | if (vec->iov_len + data->iov_len > PAGE_SIZE) { | 648 | p = xdr_reserve_space(&rqstp->rq_res_stream, data->iov_len); |
| 654 | printk(KERN_WARNING "nfsd: cached reply too large (%zd).\n", | 649 | if (unlikely(!p)) |
| 655 | data->iov_len); | 650 | return false; |
| 656 | return 0; | 651 | memcpy(p, data->iov_base, data->iov_len); |
| 657 | } | 652 | xdr_commit_encode(&rqstp->rq_res_stream); |
| 658 | memcpy((char*)vec->iov_base + vec->iov_len, data->iov_base, data->iov_len); | 653 | return true; |
| 659 | vec->iov_len += data->iov_len; | ||
| 660 | return 1; | ||
| 661 | } | 654 | } |
| 662 | 655 | ||
| 663 | /* | 656 | /* |