Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp4742008pxb; Tue, 31 Aug 2021 12:09:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyhOz0RBDYJQw67/qN9VjVU5uld8Qs54K9kzwIs4ey+tvaI1LsWNlZwaaUiwre/UWrFHgog X-Received: by 2002:a50:8e42:: with SMTP id 2mr11936564edx.338.1630436963366; Tue, 31 Aug 2021 12:09:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630436963; cv=none; d=google.com; s=arc-20160816; b=V4lhYL08DBVBelATR/bQu0pGOPEvmwevKRof4kGGp0kMSPsVRumJXWgZwXuvcrTbvT cKha734utOcHBJBMMJpaXrChvF5CDsdk/nVQT6XzFJNFEmQmB1SxtMcLi9KzT8ZPBHqe EC0DBR8rgsn5Bp/26HS+LPzJC6pzx2VS9nwI32CpewMd0lCcTGOjZo9NlxDqIBqsPgdz jJ6nl1yblDNglfbgNTfOTuQCY/2/qUA3IEIEQhdLSvIJeRX/HG6A0mmRlWT1/I2O4mFP uyqQmsxNJNvYt72yDCR0BPo0NlOJ/pGClmoBaCgmccalySGAawI963zDUCEz8gV0oE5r dHdQ== 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=TP69bweNmcNsnSt3DfOfUvjwY3pil18bZxf+uAC2eGbfOtF3K6qWW+QhAjkgztxjYT dXdCzztHqV/YmF5SDAQxeMtYz8+vWbOJpPfe1xEr+f6phiffYsig+HKPSHAZ/VS4lbLv R7s4fTZ5XbNO0rIMMkJQt1EXAwFeXhIh/giFHWtwJwAOWUa8MAtUgSBcO5vCi5QdNDST 2yjnYXAjHB59NTmnOfFW1xCGOrMatTnUMN69jN6lf0lU4UD0nVB8WIhAyfxsoeWV/lV3 FFuwTJ29ynCZbFVOzJS42QNeBykqmoVkVb6g9aHJlKFPN6B1DfQN5Yi1pYL6iw+4Du1S 8Zmw== 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 u10si16975301ejc.522.2021.08.31.12.08.59; Tue, 31 Aug 2021 12:09:23 -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 S240031AbhHaTGX (ORCPT + 99 others); Tue, 31 Aug 2021 15:06:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:34666 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240163AbhHaTGS (ORCPT ); Tue, 31 Aug 2021 15:06:18 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id B157161041; Tue, 31 Aug 2021 19:05:22 +0000 (UTC) Subject: [PATCH RFC 2/6] SUNRPC: xdr_stream_subsegment() must handle non-zero page_bases From: Chuck Lever To: bfields@fieldses.org Cc: linux-nfs@vger.kernel.org, linux-rdma@vger.kernel.org Date: Tue, 31 Aug 2021 15:05:22 -0400 Message-ID: <163043672202.1415.7895822540426489041.stgit@klimt.1015granger.net> In-Reply-To: <163043485613.1415.4979286233971984855.stgit@klimt.1015granger.net> References: <163043485613.1415.4979286233971984855.stgit@klimt.1015granger.net> User-Agent: StGit/1.1 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);