From: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> For getting a pointer to the memory address represented by the nth page, along with the length of the data on that page. Signed-off-by: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> --- include/linux/sunrpc/xdr.h | 2 ++ net/sunrpc/xdr.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index bdaf048edde0..79824fea4529 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -137,6 +137,8 @@ void xdr_inline_pages(struct xdr_buf *, unsigned int, struct page **, unsigned int, unsigned int); void xdr_terminate_string(const struct xdr_buf *, const u32); size_t xdr_buf_pagecount(const struct xdr_buf *buf); +char *xdr_buf_nth_page_address(const struct xdr_buf *buf, unsigned int n, + unsigned int *len); int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp); void xdr_free_bvec(struct xdr_buf *buf); diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 37956a274f81..88b28656a05d 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -140,6 +140,23 @@ size_t xdr_buf_pagecount(const struct xdr_buf *buf) return (buf->page_base + buf->page_len + PAGE_SIZE - 1) >> PAGE_SHIFT; } +char *xdr_buf_nth_page_address(const struct xdr_buf *buf, unsigned int n, + unsigned int *len) +{ + unsigned int pgbase = buf->page_base + (n * PAGE_SIZE); + struct page **pages = buf->pages; + struct page **page; + + if (n >= xdr_buf_pagecount(buf)) + return NULL; + + page = pages + (pgbase >> PAGE_SHIFT); + pgbase &= ~PAGE_MASK; + *len = min_t(size_t, PAGE_SIZE, buf->page_len - (n * PAGE_SIZE)); + return page_address(*page) + pgbase; +} +EXPORT_SYMBOL_GPL(xdr_buf_nth_page_address); + int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp) { -- 2.37.1