From patchwork Mon Mar 16 21:18:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 6025731 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E56F89F399 for ; Mon, 16 Mar 2015 21:18:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 11143203EB for ; Mon, 16 Mar 2015 21:18:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 83D3D20451 for ; Mon, 16 Mar 2015 21:18:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932768AbbCPVSP (ORCPT ); Mon, 16 Mar 2015 17:18:15 -0400 Received: from mx143.netapp.com ([216.240.21.24]:44147 "EHLO mx143.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932714AbbCPVSN (ORCPT ); Mon, 16 Mar 2015 17:18:13 -0400 X-IronPort-AV: E=Sophos;i="5.11,411,1422950400"; d="scan'208";a="29835289" Received: from vmwexchts03-prd.hq.netapp.com ([10.122.105.31]) by mx143-out.netapp.com with ESMTP; 16 Mar 2015 14:18:13 -0700 Received: from smtp1.corp.netapp.com (10.57.156.124) by VMWEXCHTS03-PRD.hq.netapp.com (10.122.105.31) with Microsoft SMTP Server id 15.0.995.29; Mon, 16 Mar 2015 14:18:13 -0700 Received: from davros.com ([10.63.237.161]) by smtp1.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id t2GLI99d014736; Mon, 16 Mar 2015 14:18:12 -0700 (PDT) From: Anna Schumaker To: CC: Subject: [PATCH v3 3/3] NFSD: Add support for encoding multiple segments Date: Mon, 16 Mar 2015 17:18:08 -0400 Message-ID: <1426540688-32095-4-git-send-email-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.3.3 In-Reply-To: <1426540688-32095-1-git-send-email-Anna.Schumaker@Netapp.com> References: <1426540688-32095-1-git-send-email-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 X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch implements sending an array of segments back to the client. Clients should be prepared to handle multiple segment reads to make this useful. We try to splice the first data segment into the XDR result, and remaining segments are encoded directly. Signed-off-by: Anna Schumaker --- fs/nfsd/nfs4proc.c | 4 ++-- fs/nfsd/nfs4xdr.c | 35 ++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index e9f4d8f..6801973 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1862,8 +1862,8 @@ static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op { u32 maxcount = svc_max_payload(rqstp); u32 rlen = min(op->u.read.rd_length, maxcount); - /* enough extra xdr space for encoding either a hole or data segment. */ - u32 xdr = 5; + /* Extra xdr padding for encoding multiple segments. */ + u32 xdr = 20; return (op_encode_hdr_size + 2 + xdr + XDR_QUADLEN(rlen)) * sizeof(__be32); } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 799d52c..5eaecd2 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4117,7 +4117,7 @@ nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr, static __be32 nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct nfsd4_read *read, - struct file *file) + struct file *file, loff_t hole_pos) { __be32 *p, err; unsigned long maxcount; @@ -4128,20 +4128,26 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct nfsd4_read *r return nfserr_resource; xdr_commit_encode(xdr); + if (hole_pos <= read->rd_offset) + hole_pos = i_size_read(file_inode(file)); + 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); + maxcount = min_t(unsigned long, maxcount, hole_pos - read->rd_offset); if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) err = nfsd4_encode_splice_read(resp, read, file, &maxcount); else err = nfsd4_encode_readv(resp, read, file, &maxcount); + clear_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags); *p++ = cpu_to_be32(NFS4_CONTENT_DATA); p = xdr_encode_hyper(p, read->rd_offset); *p++ = cpu_to_be32(maxcount); read->rd_offset += maxcount; + read->rd_length -= maxcount; return err; } @@ -4156,7 +4162,7 @@ nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, struct nfsd4_read *r if (data_pos == -ENXIO) data_pos = i_size_read(file_inode(file)); if (data_pos <= read->rd_offset) - return nfsd4_encode_read_plus_data(resp, read, file); + return nfsd4_encode_read_plus_data(resp, read, file, 0); maxcount = data_pos - read->rd_offset; p = xdr_reserve_space(&resp->xdr, 4 + 8 + 8); @@ -4165,6 +4171,10 @@ nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, struct nfsd4_read *r p = xdr_encode_hyper(p, maxcount); read->rd_offset += maxcount; + if (maxcount > read->rd_length) + read->rd_length = 0; + else + read->rd_length -= maxcount; return nfs_ok; } @@ -4197,17 +4207,20 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, goto err_truncate; } - hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE); - if (hole_pos == -ENXIO) - goto out_encode; + do { + hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE); + if (hole_pos == -ENXIO) + break; - if (hole_pos == read->rd_offset) - err = nfsd4_encode_read_plus_hole(resp, read, file); - else - err = nfsd4_encode_read_plus_data(resp, read, file); - segments++; + if (hole_pos == read->rd_offset) + err = nfsd4_encode_read_plus_hole(resp, read, file); + else + err = nfsd4_encode_read_plus_data(resp, read, file, hole_pos); + if (err) + break; + segments++; + } while (read->rd_length > 0); -out_encode: eof = (read->rd_offset >= i_size_read(file_inode(file))); *p++ = cpu_to_be32(eof); *p++ = cpu_to_be32(segments);