Received: by 2002:a05:6a10:d5a5:0:0:0:0 with SMTP id gn37csp670583pxb; Thu, 30 Sep 2021 14:36:57 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzDL8YSqbmVkn4K92pOVhWsmeEwRshNflvGfsvUytOezBDNBEJDjrOPFMac6AhhR3KisWlg X-Received: by 2002:a17:907:7ba8:: with SMTP id ne40mr1797626ejc.517.1633037817548; Thu, 30 Sep 2021 14:36:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1633037817; cv=none; d=google.com; s=arc-20160816; b=f+lPY24W5rRh+WErqRWsO7BicrMA9TCSxofjIa4sFkfLt8+XEGVa14q/aTVWU8+9nG t2Of+gYdu/XDllEUYQjjP0buJ1DDHtIFc5TXl1BQfC9kfNjf+ob5Aq9VxA9+PasdxYY6 zr8E0Pvicij/Eij0uwglRM/rv7x2Qs570bcBdT7W8LOXZgrczVdvTvlwkJ/HZBEBMhHB 1i6EMxDhKYtjUOg6dKystZk0qXNf6WKLgFTPGWO7QcMP2yQrkccF7t9OrakwqDjUxEV+ UmZXHv5JzZzhIqhQdFMiSADufgrjRqafJHqH2rVud8obsQZl8zMNyTUZx0xZ0emKYHhh K61Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject; bh=ciIegS2iyOw3qwNzg3YVUssCUgLkqHGh8vw+NP6mTDQ=; b=FoozKGb3AioZQCs24TkbFKeNLQDtdF+dbjafuQpUuN4Pexhl3UD1dMMsJfZVBPnbZa EoWxhf3wzFlRy0xXb+xb3ajUu3VG7Pb/66kp0UXo8F25TI/M/XUAW8Cu6yvc859EIToc Q1bYVn5Wvd5q5JEeLsL81PSFE/pjClBwa2/6CI+SgWUUAcnaEw6C3YuMxmODFZpWLKxp zlgPezu9gcr3OVeJcFk6MCQHlFadM0BREaPZKwUmQwr6p5olsjBlwVp1npI9lD/LVhrB liTfLDt5y53tIQxnN2KmB69oa1LRY0aK2AXr+R/o2dsG1RQ1zrd87tTO+nrvMhEiBDNR s65Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b12si6777323edd.196.2021.09.30.14.36.32; Thu, 30 Sep 2021 14:36:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348582AbhI3VH7 (ORCPT + 99 others); Thu, 30 Sep 2021 17:07:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:55666 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229957AbhI3VH7 (ORCPT ); Thu, 30 Sep 2021 17:07:59 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 4E4306135E; Thu, 30 Sep 2021 21:06:16 +0000 (UTC) Subject: [PATCH v1 1/2] SUNRPC: xdr_stream_subsegment() must handle non-zero page_bases From: Chuck Lever To: bfields@fieldses.org Cc: linux-nfs@vger.kernel.org Date: Thu, 30 Sep 2021 17:06:15 -0400 Message-ID: <163303597560.5125.8905823373792865984.stgit@klimt.1015granger.net> In-Reply-To: <163303585936.5125.6042907247616993649.stgit@klimt.1015granger.net> References: <163303585936.5125.6042907247616993649.stgit@klimt.1015granger.net> User-Agent: StGit/1.3 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org xdr_stream_subsegment() was introduced in commit c1346a1216ab ("NFSD: Replace the internals of the READ_BUF() macro"). There are two call sites for xdr_stream_subsegment(). One is nfsd4_decode_write(), and the other is nfsd4_decode_setxattr(). Currently neither of these call sites calls this API when xdr_buf::page_base is a non-zero value. However, I'm about to add a case where page_base will sometimes not be zero when nfsd4_decode_write() invokes this API. Replace the logic in xdr_stream_subsegment() that advances to the next data item in the xdr_stream with something more generic in order to handle this new use case. Signed-off-by: Chuck Lever --- net/sunrpc/xdr.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index ca10ba2626f2..df194cc07035 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1633,7 +1633,7 @@ EXPORT_SYMBOL_GPL(xdr_buf_subsegment); * Sets up @subbuf to represent a portion of @xdr. The portion * starts at the current offset in @xdr, and extends for a length * of @nbytes. If this is successful, @xdr is advanced to the next - * position following that portion. + * XDR data item following that portion. * * Return values: * %true: @subbuf has been initialized, and @xdr has been advanced. @@ -1642,29 +1642,31 @@ EXPORT_SYMBOL_GPL(xdr_buf_subsegment); bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, unsigned int nbytes) { - unsigned int remaining, offset, len; + unsigned int start = xdr_stream_pos(xdr); + unsigned int remaining, len; - if (xdr_buf_subsegment(xdr->buf, subbuf, xdr_stream_pos(xdr), nbytes)) + /* Extract @subbuf and bounds-check the fn arguments */ + if (xdr_buf_subsegment(xdr->buf, subbuf, start, nbytes)) return false; - if (subbuf->head[0].iov_len) - if (!__xdr_inline_decode(xdr, subbuf->head[0].iov_len)) - return false; - - remaining = subbuf->page_len; - offset = subbuf->page_base; - while (remaining) { - len = min_t(unsigned int, remaining, PAGE_SIZE) - offset; - + /* Advance @xdr by @nbytes */ + for (remaining = nbytes; remaining;) { if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr)) return false; - if (!__xdr_inline_decode(xdr, len)) - return false; + len = (char *)xdr->end - (char *)xdr->p; + if (remaining <= len) { + xdr->p = (__be32 *)((char *)xdr->p + + (remaining + xdr_pad_size(nbytes))); + break; + } + + xdr->p = (__be32 *)((char *)xdr->p + len); + xdr->end = xdr->p; remaining -= len; - offset = 0; } + xdr_stream_set_pos(xdr, start + nbytes); return true; } EXPORT_SYMBOL_GPL(xdr_stream_subsegment);