From patchwork Tue Sep 8 16:25:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anna Schumaker X-Patchwork-Id: 11763577 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 23054618 for ; Tue, 8 Sep 2020 16:27:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 00BE4206E7 for ; Tue, 8 Sep 2020 16:27:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HLmckf9B" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731908AbgIHQ1L (ORCPT ); Tue, 8 Sep 2020 12:27:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731046AbgIHQ0T (ORCPT ); Tue, 8 Sep 2020 12:26:19 -0400 Received: from mail-io1-xd42.google.com (mail-io1-xd42.google.com [IPv6:2607:f8b0:4864:20::d42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A088C061756 for ; Tue, 8 Sep 2020 09:26:03 -0700 (PDT) Received: by mail-io1-xd42.google.com with SMTP id r9so17776924ioa.2 for ; Tue, 08 Sep 2020 09:26:03 -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=FRSuIdkk6ALMTWDJIFlzdvg+Fc3EiYObmZAafS+1zAY=; b=HLmckf9BB/soOGh8cc+6du8DkgJ8974kIPJ0vmem3+oAtVoiBsxZJNRUmLbO/6QVtk m5EMfR4OwBBgWdC8OZD5mJCXetgxVXpblwEBuF8COyZQp/mn0fz+mA8SBdUOxn45S1VG 9Zo84ZphtdZ9XuSiR4GJV9SW/9lX/uaPweS6KShGf0pY/kzaIRJlVc1r6S5/k9sBNYM+ r1LPE0CNcIRpvhX/VzHx27t0qxRrzIjNM7yOJIyo0t+vassBUcZoX3wHT69LbEXNeJ77 fq0QkZSdQa4IAkjBg3TCrG5pyd/pqki4mceBcXYn9ds4z0K8OGBJIVeX6tXgKiSdZE/t ighw== 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=FRSuIdkk6ALMTWDJIFlzdvg+Fc3EiYObmZAafS+1zAY=; b=mtcPNhymJKTW8Myo7Vjbc0LoAvNXl22F8uxicJGF32JxvoDhYIopM39eqNaIUcxTYQ NuqV+9ZyZKZD7JI2zIFYV3W1Gs4SaLEN0uver+v6t7AkIvqln2jY6SewSNWXGGUwqjn8 w/GMsWrRr+fvrxczp2+ROpxyk2xUL2FYb/MujWhCptCkpoZ4IcRNjDhBHXKiuuD+c75c b5c2dfkCiz78pfs9S3TF4cmbZIsWTahM6DeNVTHRcjRusm2/wgGyVkVHZ5IKTqSfPIHU 1j8w+7l1jhZSB/Jl2Ninh/g6pFNqhwfGOJFRrFBpIkFT2ZZ5HpyRogey+jPqu09a+TGL poZA== X-Gm-Message-State: AOAM530ZeXouegiX6Ydhmy/s9LaJI/kHcLwSNvtim9lTQKwMT0JBNfbO 4Gh94yU/OZszAHO4pScoYWJRnRzoMNk= X-Google-Smtp-Source: ABdhPJyMKphX1omDaM0mQrqWTuZluMQqNg3JgsM8YuhPO4pMWTkdbLidzWA0Pj2ULyc4zqmIbV7vcA== X-Received: by 2002:a6b:d214:: with SMTP id q20mr11207687iob.23.1599582362001; Tue, 08 Sep 2020 09:26:02 -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 v7sm10269657ilg.83.2020.09.08.09.26.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 09:26:01 -0700 (PDT) From: schumaker.anna@gmail.com X-Google-Original-From: Anna.Schumaker@Netapp.com To: bfields@redhat.com, chuck.lever@oracle.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v5 1/5] SUNRPC/NFSD: Implement xdr_reserve_space_vec() Date: Tue, 8 Sep 2020 12:25:55 -0400 Message-Id: <20200908162559.509113-2-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> References: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 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 --- fs/nfsd/nfs4xdr.c | 28 +++--------------------- include/linux/sunrpc/xdr.h | 2 ++ net/sunrpc/xdr.c | 45 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 259d5ad0e3f4..0be194de4888 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3814,36 +3814,14 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, { struct xdr_stream *xdr = &resp->xdr; u32 eof; - int v; int starting_len = xdr->buf->len - 8; - long len; - int thislen; __be32 nfserr; __be32 tmp; - __be32 *p; int pad; - /* - * svcrdma requires every READ payload to start somewhere - * in xdr->pages. - */ - if (xdr->iov == xdr->buf->head) { - xdr->iov = NULL; - xdr->end = xdr->p; - } - - len = maxcount; - v = 0; - while (len) { - thislen = min_t(long, len, PAGE_SIZE); - p = xdr_reserve_space(xdr, thislen); - WARN_ON_ONCE(!p); - resp->rqstp->rq_vec[v].iov_base = p; - resp->rqstp->rq_vec[v].iov_len = thislen; - v++; - len -= thislen; - } - read->rd_vlen = v; + read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount); + if (read->rd_vlen < 0) + return nfserr_resource; nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, &maxcount, diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 5a6a81b7cd9f..6613d96a3029 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 From patchwork Tue Sep 8 16:25:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anna Schumaker X-Patchwork-Id: 11763631 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9DE4413B1 for ; Tue, 8 Sep 2020 16:47:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 761AA207DE for ; Tue, 8 Sep 2020 16:47:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rClrCUR7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731514AbgIHQrI (ORCPT ); Tue, 8 Sep 2020 12:47:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58856 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731920AbgIHQ0T (ORCPT ); Tue, 8 Sep 2020 12:26:19 -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 3666CC06179B for ; Tue, 8 Sep 2020 09:26:04 -0700 (PDT) Received: by mail-il1-x143.google.com with SMTP id w8so15980268ilj.8 for ; Tue, 08 Sep 2020 09:26:04 -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=Oed030nq5SBvqYHM9ReFakSIqfjHoKnXwhpHolYoM1Q=; b=rClrCUR7XX92MHQShouRzPWBRpR0IQz9ne4hmT3MjiMOlBWmnbIpYV2uJWCkwQLJk3 0BuCH5lFj1DTA1R+1Z5Wgn7SPGazSXSY+KpwFlLnUZbwnJesLZeSlwfCb0xbfBv2cicC HxHPgVFoqC18pj8cdBoGsjC42uJWnCHhqWdLEKA0xLb4zlDrXsvqA2PPyfkibbu34AiU 0i5Y6Puh/mxIBZXly8mfyvAnfge0FOSwOzdDZXb37c/0gy+NFSUCeQHkVgdqyH9PfgLx ANQMRP0tNzT90KAPAcGi3ZhjXbOvzjIQKVlNovzYjOYflQ+is0QnW9c4Ie+cRskDoaud BsHw== 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=Oed030nq5SBvqYHM9ReFakSIqfjHoKnXwhpHolYoM1Q=; b=CG2jSNklQpQk7PBonYy04ZshvXcCLwBlrMML3yv3OA5D9VrFAad+M1a2ZvIGPvsh2d lf+ULJtWZF/Dx+UWqPUdxGJh1VV5pfQJaToP+KHVsPbB5GuQAYlAjZE68b3DayLjoEFJ OiwFYq9E2G1Wkxk3DDoXyLUbKK2lc/sa2jDDPv+qSY1aNshRegkaTHGnvAqjPqfjMQbJ DueTKINEGngdDa/RK79An7aeGr9XRBj+l7el2xLZDl9MEAT+rNHrKeDUKrUMjRzy65OE 39aXhrUH34KXcN2HrRMu4pLdQKzsZ5b+SdKr8s+EKue36FtuEoC/ujChq/3gcwhARe3I 5Ixw== X-Gm-Message-State: AOAM531ygym7EOYeoIaXutb2coueQOUkGVpNzN+YIkrE9V9rCcX5Rg4F d+ABPQnhfZ0+tUuTzlCebPE= X-Google-Smtp-Source: ABdhPJyIAlfYWIpdv/teDgcesuTdiLJDhSzctD8A/OX+PQXvvZPq7AOrCHA6uloxmplLNvG/uGGT1Q== X-Received: by 2002:a92:906:: with SMTP id y6mr22441181ilg.106.1599582363522; Tue, 08 Sep 2020 09:26:03 -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 v7sm10269657ilg.83.2020.09.08.09.26.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 09:26:02 -0700 (PDT) From: schumaker.anna@gmail.com X-Google-Original-From: Anna.Schumaker@Netapp.com To: bfields@redhat.com, chuck.lever@oracle.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v5 2/5] NFSD: Add READ_PLUS data support Date: Tue, 8 Sep 2020 12:25:56 -0400 Message-Id: <20200908162559.509113-3-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> References: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker This patch adds READ_PLUS support for returning a single NFS4_CONTENT_DATA segment to the client. This is basically the same as the READ operation, only with the extra information about data segments. Signed-off-by: Anna Schumaker --- v5: Fix up nfsd4_read_plus_rsize() calculation --- fs/nfsd/nfs4proc.c | 20 +++++++++++ fs/nfsd/nfs4xdr.c | 83 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index eaf50eafa935..0a3df5f10501 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2591,6 +2591,19 @@ static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32); } +static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) +{ + u32 maxcount = svc_max_payload(rqstp); + u32 rlen = min(op->u.read.rd_length, maxcount); + /* + * Worst case is a single large data segment, so make + * sure we have enough room to encode that + */ + u32 seg_len = 1 + 2 + 1; + + return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32); +} + static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) { u32 maxcount = 0, rlen = 0; @@ -3163,6 +3176,13 @@ static const struct nfsd4_operation nfsd4_ops[] = { .op_name = "OP_COPY", .op_rsize_bop = nfsd4_copy_rsize, }, + [OP_READ_PLUS] = { + .op_func = nfsd4_read, + .op_release = nfsd4_read_release, + .op_name = "OP_READ_PLUS", + .op_rsize_bop = nfsd4_read_plus_rsize, + .op_get_currentstateid = nfsd4_get_readstateid, + }, [OP_SEEK] = { .op_func = nfsd4_seek, .op_name = "OP_SEEK", diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0be194de4888..26d12e3edf33 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2173,7 +2173,7 @@ static const nfsd4_dec nfsd4_dec_ops[] = { [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp, [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_offload_status, [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_offload_status, - [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp, + [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_read, [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek, [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp, [OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone, @@ -4597,6 +4597,85 @@ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr, return nfserr_resource; p = xdr_encode_hyper(p, os->count); *p++ = cpu_to_be32(0); + return nfserr; +} + +static __be32 +nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, + struct nfsd4_read *read, + unsigned long maxcount, u32 *eof) +{ + struct xdr_stream *xdr = &resp->xdr; + struct file *file = read->rd_nf->nf_file; + int starting_len = xdr->buf->len; + __be32 nfserr; + __be32 *p, tmp; + __be64 tmp64; + + /* Content type, offset, byte count */ + p = xdr_reserve_space(xdr, 4 + 8 + 4); + if (!p) + return nfserr_resource; + + read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount); + if (read->rd_vlen < 0) + return nfserr_resource; + + nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, + resp->rqstp->rq_vec, read->rd_vlen, &maxcount, eof); + if (nfserr) + return nfserr; + + tmp = htonl(NFS4_CONTENT_DATA); + write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); + tmp64 = cpu_to_be64(read->rd_offset); + write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp64, 8); + tmp = htonl(maxcount); + write_bytes_to_xdr_buf(xdr->buf, starting_len + 12, &tmp, 4); + return nfs_ok; +} + +static __be32 +nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, + struct nfsd4_read *read) +{ + unsigned long maxcount; + struct xdr_stream *xdr = &resp->xdr; + struct file *file; + int starting_len = xdr->buf->len; + int segments = 0; + __be32 *p, tmp; + u32 eof; + + if (nfserr) + return nfserr; + file = read->rd_nf->nf_file; + + /* eof flag, segment count */ + p = xdr_reserve_space(xdr, 4 + 4); + if (!p) + return nfserr_resource; + xdr_commit_encode(xdr); + + maxcount = svc_max_payload(resp->rqstp); + maxcount = min_t(unsigned long, maxcount, + (xdr->buf->buflen - xdr->buf->len)); + maxcount = min_t(unsigned long, maxcount, read->rd_length); + + eof = read->rd_offset >= i_size_read(file_inode(file)); + if (!eof) { + nfserr = nfsd4_encode_read_plus_data(resp, read, maxcount, &eof); + segments++; + } + + if (nfserr) + xdr_truncate_encode(xdr, starting_len); + else { + tmp = htonl(eof); + write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); + tmp = htonl(segments); + write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4); + } return nfserr; } @@ -4974,7 +5053,7 @@ static const nfsd4_enc nfsd4_enc_ops[] = { [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop, [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop, [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_offload_status, - [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop, + [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_read_plus, [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek, [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop, [OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop, From patchwork Tue Sep 8 16:25:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anna Schumaker X-Patchwork-Id: 11763635 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D7F41618 for ; Tue, 8 Sep 2020 16:47:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BA002206E6 for ; Tue, 8 Sep 2020 16:47:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dh72JQuR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731951AbgIHQrK (ORCPT ); Tue, 8 Sep 2020 12:47:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58748 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731957AbgIHQ0T (ORCPT ); Tue, 8 Sep 2020 12:26:19 -0400 Received: from mail-io1-xd44.google.com (mail-io1-xd44.google.com [IPv6:2607:f8b0:4864:20::d44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 446DAC06179E for ; Tue, 8 Sep 2020 09:26:05 -0700 (PDT) Received: by mail-io1-xd44.google.com with SMTP id d18so17678351iop.13 for ; Tue, 08 Sep 2020 09:26:05 -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=n/2fiuBOtKrY5YnAqes3SdT/3HFoEVtpaKzKG372BbY=; b=dh72JQuRNA/fcn4CQ1VLre56pTxeUVlb0dZGK0prahVv0QKkAjPGmRu9I90MadFShP wQIia9HHM3oP3djg3IgviRNIpML0EV3kRvAJfcdlfrfPS73KcopCwuHfTo34LQ7RaFv6 F2MqrpWIPNdJUTYLeQp37lrEaGCqndj25LWQI3V9a8M+lE/rocxXiXYSQQc55cqJO0oA 8x8vc8Z7gLKwEU9FF6zyheERlo9tlf3AFhs9/AHItBs+cMOqV6U16lZmYr2C7AJEVv57 4/9Tt/tMEod6rhvbDNCzn9Ix+nVsY5l5w33QBse1PQ0gIfDhhS7WpRu+cY2iVJrUyIIx ZH6A== 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=n/2fiuBOtKrY5YnAqes3SdT/3HFoEVtpaKzKG372BbY=; b=HHc66eKFJOFbe16GbLPtzEEIsPwW4Z0xo+bQZb/M/qDwcn+nUi+HPJ0AChOZ4r7+fU eT/QIQlrxr/Z9bIDFNCyRHYkuGTZGgjrGtSgTn7QfmZM6yi+R6teDFz65uaLIUUzhoki BrFsiE0Chnx+9eK034DFaYU3JBtwWFQN0JPEekFw+c2o8h3V9d/yphsU7wuWJKSvsojK m7XiehnQZq84X8Mvoz9jgzBb/kuvNOFfX8LycTonguidTUz3PqZ/p4NWK/QZLKr8eUgF 6r0U95JIlSnnyeMNdjBZl7JoguwrkAuyPAMNG/JtMc7RUG/q1NDHAZHkfCI68FfWJbCu 7z4A== X-Gm-Message-State: AOAM531bWlEzvonYeSzGTYv093e3oZ3Y3BzqHqxXAOtK/IGPpDOWsDne WaiUY6RgnDKnKoUzLcWn6/8= X-Google-Smtp-Source: ABdhPJzmhBVuogiQ/FXzSfjC4JKWZr5Szi/98D7+VXvoZ0xOQOV7LcAKVNPTiirGQ7VnNAnCJNpDCQ== X-Received: by 2002:a5d:8b4a:: with SMTP id c10mr21926653iot.143.1599582364551; Tue, 08 Sep 2020 09:26:04 -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 v7sm10269657ilg.83.2020.09.08.09.26.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 09:26:03 -0700 (PDT) From: schumaker.anna@gmail.com X-Google-Original-From: Anna.Schumaker@Netapp.com To: bfields@redhat.com, chuck.lever@oracle.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v5 3/5] NFSD: Add READ_PLUS hole segment encoding Date: Tue, 8 Sep 2020 12:25:57 -0400 Message-Id: <20200908162559.509113-4-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> References: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker However, we still only reply to the READ_PLUS call with a single segment at this time. Signed-off-by: Anna Schumaker --- fs/nfsd/nfs4xdr.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 26d12e3edf33..45159bd9e9a4 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4608,10 +4608,14 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct xdr_stream *xdr = &resp->xdr; struct file *file = read->rd_nf->nf_file; int starting_len = xdr->buf->len; + loff_t hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE); __be32 nfserr; __be32 *p, tmp; __be64 tmp64; + if (hole_pos > read->rd_offset) + maxcount = min_t(unsigned long, maxcount, hole_pos - read->rd_offset); + /* Content type, offset, byte count */ p = xdr_reserve_space(xdr, 4 + 8 + 4); if (!p) @@ -4635,6 +4639,27 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, return nfs_ok; } +static __be32 +nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, + struct nfsd4_read *read, + unsigned long maxcount, u32 *eof) +{ + struct file *file = read->rd_nf->nf_file; + __be32 *p; + + /* Content type, offset, byte count */ + p = xdr_reserve_space(&resp->xdr, 4 + 8 + 8); + if (!p) + return nfserr_resource; + + *p++ = htonl(NFS4_CONTENT_HOLE); + p = xdr_encode_hyper(p, read->rd_offset); + p = xdr_encode_hyper(p, maxcount); + + *eof = (read->rd_offset + maxcount) >= i_size_read(file_inode(file)); + return nfs_ok; +} + static __be32 nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_read *read) @@ -4645,6 +4670,7 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, int starting_len = xdr->buf->len; int segments = 0; __be32 *p, tmp; + loff_t pos; u32 eof; if (nfserr) @@ -4663,11 +4689,23 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, maxcount = min_t(unsigned long, maxcount, read->rd_length); eof = read->rd_offset >= i_size_read(file_inode(file)); - if (!eof) { + if (eof) + goto out; + + pos = vfs_llseek(file, read->rd_offset, SEEK_DATA); + if (pos == -ENXIO) + pos = i_size_read(file_inode(file)); + + if (pos > read->rd_offset) { + maxcount = pos - read->rd_offset; + nfserr = nfsd4_encode_read_plus_hole(resp, read, maxcount, &eof); + segments++; + } else { nfserr = nfsd4_encode_read_plus_data(resp, read, maxcount, &eof); segments++; } +out: if (nfserr) xdr_truncate_encode(xdr, starting_len); else { From patchwork Tue Sep 8 16:25:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anna Schumaker X-Patchwork-Id: 11763637 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 531A613B1 for ; Tue, 8 Sep 2020 16:47:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3155620708 for ; Tue, 8 Sep 2020 16:47:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CsVxCIKT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731957AbgIHQrK (ORCPT ); Tue, 8 Sep 2020 12:47:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58746 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731956AbgIHQ0T (ORCPT ); Tue, 8 Sep 2020 12:26:19 -0400 Received: from mail-io1-xd43.google.com (mail-io1-xd43.google.com [IPv6:2607:f8b0:4864:20::d43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E399C06179F for ; Tue, 8 Sep 2020 09:26:06 -0700 (PDT) Received: by mail-io1-xd43.google.com with SMTP id d190so17757244iof.3 for ; Tue, 08 Sep 2020 09:26:06 -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=gF4PFGeOCBPbyVDX2yvL+porZgljePXBrb0QVyft2vc=; b=CsVxCIKT5dFNSCN2oTW/KY2IS/GvnAfgbkFLzCt+gH6CSSWwsN9ViMR5NHmD1vkxTq SJubjv4bdvg+NbnBvA+JXDj//oU7KFk1vrdHEvf8nAS79s9H1w1uRditovAwVywQnDRN zk3YKD0ffZJHYpj7oR1gMT/DUPAyhKNw0J4fkFDXpzibosqfs+vyS1D7yprYddcSKsnD cEF1BPHhGgjiZ5VJONWSZbFtPIdyrLKDd0ACYwEKon4QfPGH+F6MlGvedxVN7llIXfOW Si2dAxeCbFQ32D28Wuw5QHdJERIZfUVIMUkEBacm7BlgfYEz+w36pQR+zOmW8Q3m9+9s O5BA== 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=gF4PFGeOCBPbyVDX2yvL+porZgljePXBrb0QVyft2vc=; b=o8/5kWZXvWDfGG0DcH05fMZ14NB/CoArxaZXZxGSvQflyMeW7QJ0Mj4t3J3Hwt7m0b TlPnkpCfaVPg+WFq32uaeUhW7ggIRB51GzoQJEmjE7oP0WswSFORGZ3ARGV1enKmPUFi m8e9ni6u5T2F9h5XR0oTlvpg1ye3kK+POMgmMR82Rn02lTcdN2VNsbHa9+6Hai5RsJh6 c4uq43KNRAqR1XXUfJELU+jjJ3hEG5XVARRyTNajeHWhvEO0K9OH1cQlN/SttG0uPHs0 xhxi8yhccEzquS1XpphlzSFPd95Rzkhz8Qkketxkjnl8/Gg3ytHeFcMz2ORAxO0sj4rU oKhw== X-Gm-Message-State: AOAM531zLrXomcNOkFHB6G8kzDOqvednmSMX25UmR9hkP+37ZAF64m15 5Tqix2BQtxBTuCP4nOZpuHo= X-Google-Smtp-Source: ABdhPJxNSuiV+YvEVUpTjO4FbpA1xAMjGcVGXZemMMPVqWm4SgrI++enm2aLr5jJiKhnIEYrBCJuIw== X-Received: by 2002:a6b:f919:: with SMTP id j25mr22013078iog.113.1599582365573; Tue, 08 Sep 2020 09:26:05 -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 v7sm10269657ilg.83.2020.09.08.09.26.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 09:26:04 -0700 (PDT) From: schumaker.anna@gmail.com X-Google-Original-From: Anna.Schumaker@Netapp.com To: bfields@redhat.com, chuck.lever@oracle.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v5 4/5] NFSD: Return both a hole and a data segment Date: Tue, 8 Sep 2020 12:25:58 -0400 Message-Id: <20200908162559.509113-5-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> References: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker But only one of each right now. We'll expand on this in the next patch. Signed-off-by: Anna Schumaker --- v5: If we've already encoded a segment, then return a short read if later segments return an error for some reason. --- fs/nfsd/nfs4xdr.c | 54 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 45159bd9e9a4..856606263c1d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4603,7 +4603,7 @@ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr, static __be32 nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct nfsd4_read *read, - unsigned long maxcount, u32 *eof) + unsigned long *maxcount, u32 *eof) { struct xdr_stream *xdr = &resp->xdr; struct file *file = read->rd_nf->nf_file; @@ -4614,19 +4614,19 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, __be64 tmp64; if (hole_pos > read->rd_offset) - maxcount = min_t(unsigned long, maxcount, hole_pos - read->rd_offset); + *maxcount = min_t(unsigned long, *maxcount, hole_pos - read->rd_offset); /* Content type, offset, byte count */ p = xdr_reserve_space(xdr, 4 + 8 + 4); if (!p) return nfserr_resource; - read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount); + read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, *maxcount); if (read->rd_vlen < 0) return nfserr_resource; nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, - resp->rqstp->rq_vec, read->rd_vlen, &maxcount, eof); + resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof); if (nfserr) return nfserr; @@ -4634,7 +4634,7 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); tmp64 = cpu_to_be64(read->rd_offset); write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp64, 8); - tmp = htonl(maxcount); + tmp = htonl(*maxcount); write_bytes_to_xdr_buf(xdr->buf, starting_len + 12, &tmp, 4); return nfs_ok; } @@ -4642,11 +4642,19 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, static __be32 nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, struct nfsd4_read *read, - unsigned long maxcount, u32 *eof) + unsigned long *maxcount, u32 *eof) { struct file *file = read->rd_nf->nf_file; + loff_t data_pos = vfs_llseek(file, read->rd_offset, SEEK_DATA); + unsigned long count; __be32 *p; + if (data_pos == -ENXIO) + data_pos = i_size_read(file_inode(file)); + else if (data_pos <= read->rd_offset) + return nfserr_resource; + count = data_pos - read->rd_offset; + /* Content type, offset, byte count */ p = xdr_reserve_space(&resp->xdr, 4 + 8 + 8); if (!p) @@ -4654,9 +4662,10 @@ nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, *p++ = htonl(NFS4_CONTENT_HOLE); p = xdr_encode_hyper(p, read->rd_offset); - p = xdr_encode_hyper(p, maxcount); + p = xdr_encode_hyper(p, count); - *eof = (read->rd_offset + maxcount) >= i_size_read(file_inode(file)); + *eof = (read->rd_offset + count) >= i_size_read(file_inode(file)); + *maxcount = min_t(unsigned long, count, *maxcount); return nfs_ok; } @@ -4664,7 +4673,7 @@ static __be32 nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_read *read) { - unsigned long maxcount; + unsigned long maxcount, count; struct xdr_stream *xdr = &resp->xdr; struct file *file; int starting_len = xdr->buf->len; @@ -4687,6 +4696,7 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, maxcount = min_t(unsigned long, maxcount, (xdr->buf->buflen - xdr->buf->len)); maxcount = min_t(unsigned long, maxcount, read->rd_length); + count = maxcount; eof = read->rd_offset >= i_size_read(file_inode(file)); if (eof) @@ -4695,24 +4705,38 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, pos = vfs_llseek(file, read->rd_offset, SEEK_DATA); if (pos == -ENXIO) pos = i_size_read(file_inode(file)); + else if (pos < 0) + pos = read->rd_offset; - if (pos > read->rd_offset) { - maxcount = pos - read->rd_offset; - nfserr = nfsd4_encode_read_plus_hole(resp, read, maxcount, &eof); + if (pos == read->rd_offset) { + maxcount = count; + nfserr = nfsd4_encode_read_plus_data(resp, read, &maxcount, &eof); + if (nfserr) + goto out; + count -= maxcount; + read->rd_offset += maxcount; segments++; - } else { - nfserr = nfsd4_encode_read_plus_data(resp, read, maxcount, &eof); + } + + if (count > 0 && !eof) { + maxcount = count; + nfserr = nfsd4_encode_read_plus_hole(resp, read, &maxcount, &eof); + if (nfserr) + goto out; + count -= maxcount; + read->rd_offset += maxcount; segments++; } out: - if (nfserr) + if (nfserr && segments == 0) xdr_truncate_encode(xdr, starting_len); else { tmp = htonl(eof); write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); tmp = htonl(segments); write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4); + nfserr = nfs_ok; } return nfserr; From patchwork Tue Sep 8 16:25:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anna Schumaker X-Patchwork-Id: 11763633 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0FBBB618 for ; Tue, 8 Sep 2020 16:47:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E87C620708 for ; Tue, 8 Sep 2020 16:47:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="stx3mu5A" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731920AbgIHQrJ (ORCPT ); Tue, 8 Sep 2020 12:47:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58750 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731955AbgIHQ0T (ORCPT ); Tue, 8 Sep 2020 12:26:19 -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 77E8BC0617A0 for ; Tue, 8 Sep 2020 09:26:07 -0700 (PDT) Received: by mail-il1-x143.google.com with SMTP id a8so10267903ilk.1 for ; Tue, 08 Sep 2020 09:26:07 -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=U2S2Lxx0kQ3S0aFYVuRfdaPqpk3hF/pusSGQYcIaIQc=; b=stx3mu5AMbv4ZUqCMu+mtiYRRt4bMcwJQ/yBwP9AFGM+ofEYENYstgOPbkly7VVeMT 1PsqNgWhkBS+7UIWTyj+IbEOvnS5vSR6d/w00+Wzfq+x1L414CwbOm6/7WTYBC4pP02x IeMOmhcrpBQxFP/M483r1kngnqkaSSIfczwZxruUhhqhnUOTt6IHu+XdXeio4xwbX8DG POqpXhbcMY2d+3TAmnsQ8XNpf3d5h9srsvKHDwDdJ4ViEilEvuDVCKAiik843izgb5EI QHYnp/65q21RfLJwBB2YImxOtG5FSFL1yYj5QR3AHmJYnYJtHOyR9g9jf+2kHhLeE3Pv 8K5Q== 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=U2S2Lxx0kQ3S0aFYVuRfdaPqpk3hF/pusSGQYcIaIQc=; b=LKhnnCD49AyJelQIRaiVM6AT6p/T4ptSFUPn6nQ140zPoDuXrT5GplyQROOnCGnzJv UbkQkMtPSJ4vO5nutwkcBuLoAYdEM9hO7vUpxzMUj9Tbx81O/GJ+POC4FdkJIgg9nQyK lATu8KmVNeuaowGdTBkTcjWnEv/0NSnOMPS5JHvOsaSFjGVmSXgeGB/Lsu8dmxN0sbWn 5Qwxjwy149kF2jHU9s5cgOXu7L3oSH/RpYZ6S3NGUmO2Tj2KaVc5sWNKRvZ0O3ejWDOD qwS5ONwAh1Fv/oZ+Io7njPUxIBxR+CGI7eZOFaoAEkap9dV++JfQ2Nlrx9j+IYoYGkbt QQOQ== X-Gm-Message-State: AOAM532LcZqnfVV/tUzRaEmiRWjzy7GPtWILYM1Iuvl5Jo7ML4rtgV/U 5oBoz3c+2RD/y+kN4iSCz3Y= X-Google-Smtp-Source: ABdhPJy1l38phwlhZaF3x53OuF8dT4x0AL5v/9sQfAfzSUlFQVtRna3K9X5//LvQtYvS9zef9CE2jg== X-Received: by 2002:a92:d40d:: with SMTP id q13mr24880553ilm.45.1599582366694; Tue, 08 Sep 2020 09:26:06 -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 v7sm10269657ilg.83.2020.09.08.09.26.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 09:26:06 -0700 (PDT) From: schumaker.anna@gmail.com X-Google-Original-From: Anna.Schumaker@Netapp.com To: bfields@redhat.com, chuck.lever@oracle.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v5 5/5] NFSD: Encode a full READ_PLUS reply Date: Tue, 8 Sep 2020 12:25:59 -0400 Message-Id: <20200908162559.509113-6-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> References: <20200908162559.509113-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker Reply to the client with multiple hole and data segments. I use the result of the first vfs_llseek() call for encoding as an optimization so we don't have to immediately repeat the call. Signed-off-by: Anna Schumaker --- v5: Truncate the encode to the last segment length if we're returning a short read --- fs/nfsd/nfs4xdr.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 856606263c1d..eec23a7d5ca0 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4603,16 +4603,18 @@ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr, static __be32 nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct nfsd4_read *read, - unsigned long *maxcount, u32 *eof) + unsigned long *maxcount, u32 *eof, + loff_t *pos) { struct xdr_stream *xdr = &resp->xdr; struct file *file = read->rd_nf->nf_file; int starting_len = xdr->buf->len; - loff_t hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE); + loff_t hole_pos; __be32 nfserr; __be32 *p, tmp; __be64 tmp64; + hole_pos = pos ? *pos : vfs_llseek(file, read->rd_offset, SEEK_HOLE); if (hole_pos > read->rd_offset) *maxcount = min_t(unsigned long, *maxcount, hole_pos - read->rd_offset); @@ -4677,8 +4679,10 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, struct xdr_stream *xdr = &resp->xdr; struct file *file; int starting_len = xdr->buf->len; + int last_segment = xdr->buf->len; int segments = 0; __be32 *p, tmp; + bool is_data; loff_t pos; u32 eof; @@ -4702,29 +4706,22 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, if (eof) goto out; - pos = vfs_llseek(file, read->rd_offset, SEEK_DATA); - if (pos == -ENXIO) - pos = i_size_read(file_inode(file)); - else if (pos < 0) - pos = read->rd_offset; + pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE); + is_data = pos > read->rd_offset; - if (pos == read->rd_offset) { + while (count > 0 && !eof) { maxcount = count; - nfserr = nfsd4_encode_read_plus_data(resp, read, &maxcount, &eof); - if (nfserr) - goto out; - count -= maxcount; - read->rd_offset += maxcount; - segments++; - } - - if (count > 0 && !eof) { - maxcount = count; - nfserr = nfsd4_encode_read_plus_hole(resp, read, &maxcount, &eof); + if (is_data) + nfserr = nfsd4_encode_read_plus_data(resp, read, &maxcount, &eof, + segments == 0 ? &pos : NULL); + else + nfserr = nfsd4_encode_read_plus_hole(resp, read, &maxcount, &eof); if (nfserr) goto out; count -= maxcount; read->rd_offset += maxcount; + is_data = !is_data; + last_segment = xdr->buf->len; segments++; } @@ -4736,7 +4733,10 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); tmp = htonl(segments); write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4); - nfserr = nfs_ok; + if (nfserr) { + xdr_truncate_encode(xdr, last_segment); + nfserr = nfs_ok; + } } return nfserr;