Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp2205333pxa; Mon, 3 Aug 2020 10:00:43 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz6kXKPLvnh6L2Xnd8Mzo8GsZmYW+f0xLF4J3oBx14RGvuBBjcXyWaymIaG+gc8sxm/bMh1 X-Received: by 2002:a17:906:817:: with SMTP id e23mr17313230ejd.203.1596474043733; Mon, 03 Aug 2020 10:00:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1596474043; cv=none; d=google.com; s=arc-20160816; b=MAsRVeueMSSUbKOcs292RAfjMSbhcwsx4sDeow4rG7zNIOYrc4lRuKGKJKWxtLkw5m X3W96JQYIKcVL542F+QX6vOFnRnCrvtHXqNUctReXVsMYAy57M3xOQO+OCvK9oSwegcY Z3e2atyodsTrH/Tsy4nRsCFpMtr7O8A98xzfdZLrwTQt8tRpHzaFKcY1xGu6mBa5Rvmj vj4PxVWZAuGjDAG6dRFlscCePw6ahU7Zq0pAL7kU4r3Ip7oRhn/14g5rxduIMRE1xAZT zCdqdi3FCmgLNymjuSuBXHuKdUW/rOWriSSvvdeYzNVVxOk/jcAZYVNO/SEageikDQ1x qTpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=sQ5eL1nmuUmkLTUxFw+0Fbr3N0wgB3Xm8iWP31hLmAs=; b=CLGrHf3AFSSPEqW0BDC6z47eovSvmR3jWhj8zOBXsIqQ9Z+erWDg8XLV4uGspTx3SM LoeqYe9drP15kVx25dUJKdmgkqFXWkd2dk9VWX5wI4o1yKQpWBcswHCYlUzlMvRtxUPC qiotBqOfyqCu8PYk3BpJesQ4Oxq5pyUoggqz7IPLS8rZOJsZnmA9S8mewVhP6shQpmE7 sg04Y2KA3ZTXwtFJ8OEG+0jCyiKrwbeQDNpgwexzxbSFKT1235sqXO8tXUtpz34/1vlM EdxluPmV8rmKY/jTuJdQdL+AoWI2T3xfTJY5LMHec6icxxQA9PDEEuOqelHQUM4+4kU7 B4YA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=aRlzH1hr; 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=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id nv5si10511536ejb.144.2020.08.03.10.00.07; Mon, 03 Aug 2020 10:00:43 -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; dkim=fail header.i=@gmail.com header.s=20161025 header.b=aRlzH1hr; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728081AbgHCQ76 (ORCPT + 99 others); Mon, 3 Aug 2020 12:59:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726356AbgHCQ76 (ORCPT ); Mon, 3 Aug 2020 12:59:58 -0400 Received: from mail-il1-x143.google.com (mail-il1-x143.google.com [IPv6:2607:f8b0:4864:20::143]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 54049C06174A for ; Mon, 3 Aug 2020 09:59:58 -0700 (PDT) Received: by mail-il1-x143.google.com with SMTP id p13so3238600ilh.4 for ; Mon, 03 Aug 2020 09:59:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sQ5eL1nmuUmkLTUxFw+0Fbr3N0wgB3Xm8iWP31hLmAs=; b=aRlzH1hr2wHpPP58ZC5qwWvavEZv8k/Ei3Q6PFmZqRIC7CeaISNUyKy6mdzBfVyCHh LZSMt08Z5bTnGyQUWBNVYleQ0DxCX7u3DZjinq4Pa2dbZp7PITVw5RoG/EZRsauk2H1i C5zYwPhTPzrI8BhrJJgkCTGaIx9Jz4WsreCn9d2rjzWKZoBvnsci3oBcr4OtUGl57uBd TaTHvBB1GvMCwVR9uN9+FYZpk/b78unDtcvIYMg7Jo8kW7kntIqESzJcT2jR0pbOChYB MT8bODzpjBeFjupVzsEy7HwyUF5GQsc96jNDK6RGDoJcxxc11+o0opTtppior2FmFiSw mMwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=sQ5eL1nmuUmkLTUxFw+0Fbr3N0wgB3Xm8iWP31hLmAs=; b=i6TBv47VN5v0nbwZqOz1DG9DvXnYyWYZhVaXIEw0GLhfBZlr3cKWGkz8fiUTrJzuaM pIu/mrcwHz8EKfYOWzFT9ANcIDqHljxilOTz9lRZFfK0aUPEFAH/7y1dMGLUxmGmJz+8 kcZde9vbeKvvOX91bwYDpf8pZBteC2cuE4Fd45mREzhdVU/OqEBkfWWR2n0u7LlLRhSS ByB5kZQgN5s0Z+Bc/ECA4woklwzPrRze86LIR4Ksy31xEjF4FBFpDTfpQLRFnrQr61ex DNNx5wBjMX/CHaDxabiULWwJPzuCX2uibREPvQ9aVFRp5x+wYjn5OKqoVF/XrYhrneYG aUHw== X-Gm-Message-State: AOAM53078QxIkIoEe+8lNslIZaDfsKnEzdtQbBLla29z3cqiCsj41zhr gOhbtnalINhnNXQsrTuVftDp1i3C X-Received: by 2002:a92:d781:: with SMTP id d1mr302536iln.68.1596473997682; Mon, 03 Aug 2020 09:59:57 -0700 (PDT) Received: from gouda.nowheycreamery.com (c-68-32-74-190.hsd1.mi.comcast.net. [68.32.74.190]) by smtp.gmail.com with ESMTPSA id f20sm10794639ilj.62.2020.08.03.09.59.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2020 09:59:57 -0700 (PDT) From: schumaker.anna@gmail.com X-Google-Original-From: Anna.Schumaker@Netapp.com To: bfields@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v3 1/6] SUNRPC: Implement xdr_reserve_space_vec() Date: Mon, 3 Aug 2020 12:59:49 -0400 Message-Id: <20200803165954.1348263-2-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200803165954.1348263-1-Anna.Schumaker@Netapp.com> References: <20200803165954.1348263-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker Reserving space for a large READ payload requires special handling when reserving space in the xdr buffer pages. One problem we can have is use of the scratch buffer, which is used to get a pointer to a contiguous region of data up to PAGE_SIZE. When using the scratch buffer, calls to xdr_commit_encode() shift the data to it's proper alignment in the xdr buffer. If we've reserved several pages in a vector, then this could potentially invalidate earlier pointers and result in incorrect READ data being sent to the client. I get around this by looking at the amount of space left in the current page, and never reserve more than that for each entry in the read vector. This lets us place data directly where it needs to go in the buffer pages. Signed-off-by: Anna Schumaker --- include/linux/sunrpc/xdr.h | 2 ++ net/sunrpc/xdr.c | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 22c207b2425f..bac459584dd0 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -234,6 +234,8 @@ typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, struct rpc_rqst *rqst); extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); +extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, + size_t nbytes); extern void xdr_commit_encode(struct xdr_stream *xdr); extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index be11d672b5b9..6dfe5dc8b35f 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -648,6 +648,51 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) } EXPORT_SYMBOL_GPL(xdr_reserve_space); + +/** + * xdr_reserve_space_vec - Reserves a large amount of buffer space for sending + * @xdr: pointer to xdr_stream + * @vec: pointer to a kvec array + * @nbytes: number of bytes to reserve + * + * Reserves enough buffer space to encode 'nbytes' of data and stores the + * pointers in 'vec'. The size argument passed to xdr_reserve_space() is + * determined based on the number of bytes remaining in the current page to + * avoid invalidating iov_base pointers when xdr_commit_encode() is called. + */ +int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, size_t nbytes) +{ + int thislen; + int v = 0; + __be32 *p; + + /* + * svcrdma requires every READ payload to start somewhere + * in xdr->pages. + */ + if (xdr->iov == xdr->buf->head) { + xdr->iov = NULL; + xdr->end = xdr->p; + } + + while (nbytes) { + thislen = xdr->buf->page_len % PAGE_SIZE; + thislen = min_t(size_t, nbytes, PAGE_SIZE - thislen); + + p = xdr_reserve_space(xdr, thislen); + if (!p) + return -EIO; + + vec[v].iov_base = p; + vec[v].iov_len = thislen; + v++; + nbytes -= thislen; + } + + return v; +} +EXPORT_SYMBOL_GPL(xdr_reserve_space_vec); + /** * xdr_truncate_encode - truncate an encode buffer * @xdr: pointer to xdr_stream -- 2.27.0