All of lore.kernel.org
 help / color / mirror / Atom feed
From: "J. Bruce Fields" <bfields@fieldses.org>
To: Anna Schumaker <schumaker.anna@gmail.com>
Cc: "J. Bruce Fields" <bfields@redhat.com>,
	Chuck Lever <chuck.lever@oracle.com>,
	Linux NFS Mailing List <linux-nfs@vger.kernel.org>
Subject: Re: [PATCH v5 4/5] NFSD: Return both a hole and a data segment
Date: Wed, 9 Sep 2020 16:44:29 -0400	[thread overview]
Message-ID: <20200909204429.GD3894@fieldses.org> (raw)
In-Reply-To: <20200909202400.GB3894@fieldses.org>

On Wed, Sep 09, 2020 at 04:24:00PM -0400, bfields wrote:
> On Wed, Sep 09, 2020 at 12:51:38PM -0400, Anna Schumaker wrote:
> > On Tue, Sep 8, 2020 at 3:49 PM J. Bruce Fields <bfields@redhat.com> wrote:
> > > I think there's still a race here:
> > >
> > >         vfs_llseek(.,0,SEEK_HOLE) returns 1024
> > >         read 1024 bytes of data
> > >                                         another process fills the hole
> > >         vfs_llseek(.,1024,SEEK_DATA) returns 1024
> > >         code above returns nfserr_resource
> > >
> > > We end up returning an error to the client when we should have just
> > > returned more data.
> > 
> > As long as we've encoded at least one segment successfully, we'll
> > actually return a short read in this case (as of the most recent
> > patches). I tried implementing a check for what each segment actually
> > was before encoding, but it lead to a lot of extra lseeks (so
> > potential for races / performance problems on btrfs). Returning a
> > short read seemed like a better approach to me.
> 
> Argh, right, I forgot the "if (nfserr && segments == 0)" at the end of
> nfsd4_encode_read_plus().

(Oops, it's actually the "if (nfserr)" below that handles that case.)

> It's still possible to get a spurious error return if this happens at
> the very start of the READ_PLUS, though.  Hm.  Might be better to just
> encode another data segment?

So, I mean, if nfsd4_encode_read_plus_hole() doesn't find a hole after
all, just keep going, and create a data segment.

--b.

> 
> --b.
> 
> > 
> > Anna
> > 
> > >
> > > --b.
> > >
> > > > +     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;
> > > > --
> > > > 2.28.0
> > > >
> > >

  reply	other threads:[~2020-09-09 20:44 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-08 16:25 [PATCH v5 0/5] NFSD: Add support for the v4.2 READ_PLUS operation schumaker.anna
2020-09-08 16:25 ` [PATCH v5 1/5] SUNRPC/NFSD: Implement xdr_reserve_space_vec() schumaker.anna
2020-09-08 16:25 ` [PATCH v5 2/5] NFSD: Add READ_PLUS data support schumaker.anna
2020-09-08 19:42   ` J. Bruce Fields
2020-09-09 16:53     ` Anna Schumaker
2020-09-09 20:25       ` J. Bruce Fields
2020-09-09 20:50         ` J. Bruce Fields
2020-09-08 16:25 ` [PATCH v5 3/5] NFSD: Add READ_PLUS hole segment encoding schumaker.anna
2020-09-08 16:25 ` [PATCH v5 4/5] NFSD: Return both a hole and a data segment schumaker.anna
2020-09-08 19:49   ` J. Bruce Fields
2020-09-09 16:51     ` Anna Schumaker
2020-09-09 20:24       ` J. Bruce Fields
2020-09-09 20:44         ` J. Bruce Fields [this message]
2020-09-08 16:25 ` [PATCH v5 5/5] NFSD: Encode a full READ_PLUS reply schumaker.anna

Reply instructions:

You may reply publicly 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=20200909204429.GD3894@fieldses.org \
    --to=bfields@fieldses.org \
    --cc=bfields@redhat.com \
    --cc=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=schumaker.anna@gmail.com \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.