Linux-NFS Archive on lore.kernel.org
 help / color / Atom feed
From: schumaker.anna@gmail.com
To: bfields@redhat.com, linux-nfs@vger.kernel.org
Cc: Anna.Schumaker@Netapp.com
Subject: [PATCH 4/4] NFSD: Encode a full READ_PLUS reply
Date: Fri, 10 Jan 2020 17:35:38 -0500
Message-ID: <20200110223538.528560-5-Anna.Schumaker@Netapp.com> (raw)
In-Reply-To: <20200110223538.528560-1-Anna.Schumaker@Netapp.com>

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

Reply to the client with multiple hole and data segments. This might
have performance issues due to the number of calls to vfs_llseek(),
depending on the underlying filesystem used on the server.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 fs/nfsd/nfs4xdr.c | 41 +++++++++++++++++++++++++++++------------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 552972b35547..c63846729d0b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4270,14 +4270,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)
+			    struct nfsd4_read *read, u32 *eof)
 {
 	struct xdr_stream *xdr = &resp->xdr;
 	struct file *file = read->rd_nf->nf_file;
+	unsigned long maxcount = read->rd_length;
+	loff_t hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE);
 	__be32 nfserr;
 	__be32 *p;
 
+	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)
@@ -4289,6 +4293,7 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp,
 		nfserr = nfsd4_encode_splice_read(resp, read, file, &maxcount, eof);
 	else
 		nfserr = nfsd4_encode_readv(resp, read, file, &maxcount, eof);
+	clear_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags);
 
 	if (nfserr)
 		return nfserr;
@@ -4303,18 +4308,24 @@ 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)
+nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp,
+			    struct nfsd4_read *read, u32 *eof, loff_t data_pos)
 {
 	struct file *file = read->rd_nf->nf_file;
+	unsigned long maxcount = read->rd_length;
 	__be32 *p;
 
+	if (data_pos == 0)
+		data_pos = vfs_llseek(file, read->rd_offset, SEEK_DATA);
+	if (data_pos == -ENXIO)
+		data_pos = i_size_read(file_inode(file));
+
 	/* Content type, offset, byte count */
 	p = xdr_reserve_space(&resp->xdr, 4 + 8 + 8);
 	if (!p)
 		return nfserr_resource;
 
-	maxcount = min_t(unsigned long, maxcount, read->rd_length);
+	maxcount = min_t(unsigned long, maxcount, data_pos - read->rd_offset);
 
 	*p++ = cpu_to_be32(NFS4_CONTENT_HOLE);
 	 p   = xdr_encode_hyper(p, read->rd_offset);
@@ -4338,6 +4349,7 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
 	int starting_len = xdr->buf->len;
 	unsigned int segments = 0;
 	loff_t data_pos;
+	bool is_data;
 	__be32 *p;
 
 	if (nfserr)
@@ -4361,21 +4373,26 @@ 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);
+	read->rd_length = maxcount;
 
 	data_pos = vfs_llseek(file, read->rd_offset, SEEK_DATA);
 	if (data_pos == -ENXIO)
 		data_pos = i_size_read(file_inode(file));
 	else if (data_pos < 0)
 		data_pos = read->rd_offset;
+	is_data = (data_pos == read->rd_offset);
+	eof = read->rd_offset > i_size_read(file_inode(file));
 
-	if (data_pos > read->rd_offset) {
-		nfserr = nfsd4_encode_read_plus_hole(resp, read,
-						     data_pos - read->rd_offset, &eof);
-		segments++;
-	}
+	while (read->rd_length > 0 && !eof) {
+		if (is_data)
+			nfserr = nfsd4_encode_read_plus_data(resp, read, &eof);
+		else
+			nfserr = nfsd4_encode_read_plus_hole(resp, read, &eof, data_pos);
 
-	if (!nfserr && !eof && read->rd_length > 0) {
-		nfserr = nfsd4_encode_read_plus_data(resp, read, maxcount, &eof);
+		if (nfserr)
+			break;
+		is_data = !is_data;
+		data_pos = 0;
 		segments++;
 	}
 
-- 
2.24.1


      parent reply index

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-10 22:35 [PATCH 0/4] NFSD: Add support for the v4.2 READ_PLUS operation schumaker.anna
2020-01-10 22:35 ` [PATCH 1/4] NFSD: Return eof and maxcount to nfsd4_encode_read() schumaker.anna
2020-01-10 22:35 ` [PATCH 2/4] NFSD: Add READ_PLUS data support schumaker.anna
2020-01-10 22:35 ` [PATCH 3/4] NFSD: Add READ_PLUS hole segment encoding schumaker.anna
2020-01-10 22:35 ` schumaker.anna [this message]

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200110223538.528560-5-Anna.Schumaker@Netapp.com \
    --to=schumaker.anna@gmail.com \
    --cc=Anna.Schumaker@Netapp.com \
    --cc=bfields@redhat.com \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-NFS Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-nfs/0 linux-nfs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-nfs linux-nfs/ https://lore.kernel.org/linux-nfs \
		linux-nfs@vger.kernel.org
	public-inbox-index linux-nfs

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-nfs


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git