Hi Bruce- Thanks for your careful review of this series! > On Mar 2, 2021, at 5:11 PM, J. Bruce Fields <bfields@xxxxxxxxxxxx> wrote: > > On Mon, Mar 01, 2021 at 10:17:13AM -0500, Chuck Lever wrote: >> The description of commit 2825a7f90753 ("nfsd4: allow encoding >> across page boundaries") states: >> >>> Also we can't handle a new operation starting close to the end of >>> a page. >> >> But does not detail why this is the case. > > That wasn't every helpful of me, sorry. > >> Subtracting the scratch buffer's "shift" value from the remaining >> stream space seems to make reserving space close to the end of the >> buf->pages array reliable. > > So, why is that? > > Thinking this through: > > When somebody asks for a buffer that would straddle a page boundary, > with frag1bytes at the end of this page and frag2bytes at the start of > the next page, we instead give them a buffer starting at start of the > next page. That gives them a nice contiguous buffer to write into. > When they're done using it, we fix things up by copying what they wrote > back to where it should be. > > That means we're temporarily wasting frag1bytes of space. So, I don't > know, maybe that's the logic behind subtracing frag1bytes from > space_left. > > It means you may end up with xdr->end frag1bytes short of the next page. > I'm not sure that's right. Why would that not be OK? the next call to xdr_get_next_encode_buffer() should do the right thing and bounce the new encoded data from the next page into this one again. So far I have not encountered any problems. Would such a problem show up with some frequency under normal use, or would it be especially subtle? > --b. > > >> >> This change is needed to make entry encoding with struct xdr_stream, >> introduced in a subsequent patch, work correctly when it approaches >> the end of the dirlist buffer. >> >> Fixes: 2825a7f90753 ("nfsd4: allow encoding across page boundaries") >> Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> >> --- >> net/sunrpc/xdr.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c >> index 3964ff74ee51..043b67229792 100644 >> --- a/net/sunrpc/xdr.c >> +++ b/net/sunrpc/xdr.c >> @@ -978,7 +978,7 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, >> * shifted this one back: >> */ >> xdr->p = (void *)p + frag2bytes; >> - space_left = xdr->buf->buflen - xdr->buf->len; >> + space_left = xdr->buf->buflen - xdr->buf->len - frag1bytes; >> xdr->end = (void *)p + min_t(int, space_left, PAGE_SIZE); >> xdr->buf->page_len += frag2bytes; >> xdr->buf->len += nbytes; >> -- Chuck Lever