This patch adds the ability to "read a hole" into a set of XDR data pages attached to a specific request. Signed-off-by: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> --- include/linux/sunrpc/xdr.h | 1 + net/sunrpc/xdr.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 70c6b92..3ec52d2 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -229,6 +229,7 @@ extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes); extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len); extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len); extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data); +extern uint64_t xdr_read_hole(struct xdr_stream *, uint64_t); #endif /* __KERNEL__ */ diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 290af97..722f526 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -220,6 +220,38 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base, } /** + * _zero_data_pages + * @pages: array of pages + * @pgbase: beginning page vector address + * @len: length + */ +static void +_zero_data_pages(struct page **pages, size_t pgbase, size_t len) +{ + struct page **page; + char *vpage; + size_t zero; + + page = pages + (pgbase >> PAGE_CACHE_SHIFT); + pgbase &= ~PAGE_CACHE_MASK; + + do { + zero = len; + if (pgbase + zero > PAGE_SIZE) + zero = PAGE_SIZE - pgbase; + + vpage = kmap_atomic(*page); + memset(vpage + pgbase, 0, zero); + flush_dcache_page(*page); + kunmap_atomic(vpage); + + page++; + pgbase = 0; + + } while ((len -= zero) != 0); +} + +/** * _copy_to_pages * @pages: array of pages * @pgbase: page vector address of destination @@ -970,6 +1002,19 @@ unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len) } EXPORT_SYMBOL_GPL(xdr_read_pages); +uint64_t xdr_read_hole(struct xdr_stream *xdr, uint64_t length) +{ + struct xdr_buf *buf = xdr->buf; + + if (length > buf->page_len) + length = buf->page_len; + + xdr_align_pages(xdr, length); + _zero_data_pages(buf->pages, buf->page_base, length); + return length; +} +EXPORT_SYMBOL_GPL(xdr_read_hole); + /** * xdr_enter_page - decode data from the XDR page * @xdr: pointer to xdr_stream struct -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html