From patchwork Mon May 16 16:23:47 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benny Halevy X-Patchwork-Id: 788772 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4GGKjCL018574 for ; Mon, 16 May 2011 16:23:51 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752740Ab1EPQXu (ORCPT ); Mon, 16 May 2011 12:23:50 -0400 Received: from daytona.panasas.com ([67.152.220.89]:34797 "EHLO daytona.panasas.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752379Ab1EPQXu (ORCPT ); Mon, 16 May 2011 12:23:50 -0400 Received: from lt.bhalevy.com.com ([172.17.142.149]) by daytona.panasas.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 16 May 2011 12:23:49 -0400 From: Benny Halevy To: Trond Myklebust Cc: linux-nfs@vger.kernel.org, bharrosh@panasas.com Subject: [PATCH v3 23/29] sunrpc: xdr_rewind_stream() Date: Mon, 16 May 2011 09:23:47 -0700 Message-Id: <1305563027-8136-1-git-send-email-bhalevy@panasas.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <4DD14D8E.1070701@panasas.com> References: <4DD14D8E.1070701@panasas.com> X-OriginalArrivalTime: 16 May 2011 16:23:49.0878 (UTC) FILETIME=[A3859160:01CC13E5] Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 16 May 2011 16:23:51 +0000 (UTC) In a long encoded xdr stream, we might run out of allocated xdr space. In some situations it is possibly to reset the xdr buffer to a previuos good state and send a parial list, which is better then just BUGing as today or completely failing the xdr. * define such API that can move the xdr pointer to a good known state before the failed encoding. Signed-off-by: Boaz Harrosh Signed-off-by: Benny Halevy --- include/linux/sunrpc/xdr.h | 1 + net/sunrpc/xdr.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 0 deletions(-) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index fc84b7a..bf17e38 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -213,6 +213,7 @@ typedef int (*kxdrdproc_t)(void *rqstp, struct xdr_stream *xdr, void *obj); extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p); extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); +extern __be32 *xdr_rewind_stream(struct xdr_stream *xdr, __be32 *q); extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, unsigned int base, unsigned int len); extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p); diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 679cd67..3e0d79e 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -518,6 +518,27 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) EXPORT_SYMBOL_GPL(xdr_reserve_space); /** + * xdr_rewind_stream - rewind a stream back to some checkpoint + * @xdr: pointer to xdr_stream + * @q: some checkpoint at historical place of @xdr + * + * Restors an xdr stream to some historical point. @q must be + * a logical xdr point in the past that was sampled by @q = @xdr->p. + */ +__be32 *xdr_rewind_stream(struct xdr_stream *xdr, __be32 *q) +{ + size_t nbytes = (xdr->p - q) << 2; + + BUG_ON(xdr->p < q); + BUG_ON(nbytes > xdr->iov->iov_len || nbytes > xdr->buf->len); + xdr->p = q; + xdr->iov->iov_len -= nbytes; + xdr->buf->len -= nbytes; + return q; +} +EXPORT_SYMBOL_GPL(xdr_rewind_stream); + +/** * xdr_write_pages - Insert a list of pages into an XDR buffer for sending * @xdr: pointer to xdr_stream * @pages: list of pages