On Fri, 2019-02-15 at 14:33 -0600, Jason L Tibbitts III wrote: > > > > > > "BC" == Benjamin Coddington <bcodding@xxxxxxxxxx> writes: > > BC> Hmm.. commit c443305529d1d3d3bee0d68fdd14ae89835e091f changed > BC> xs_read_stream_reply() to return recv.copied instead of "ret" to > BC> xprt_complete_rqst().. That's a good thing. xprt_complete_rqst() really dislikes negative error values. > BC> You could try reverting that commit and see if the problem goes > BC> away.. > > So patching a revert of that into 4.20.7 was beyond me, but I > received > some help from Jeremy Cline on IRC (in #fedora-kernel) and ended up > with > a patch I'll include at the end. So far it does seem to be better, > but > because of secure boot annoyances I haven't been able to roll it out > more generally. However, it has been stable for a week on a few > hosts > which have been problematic with stock 4.20.6. > > I will continue to test, but hopefully this helps folks to understand > what's happening. > Hmm... Does the following patch help at all? --- diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7754aa3e434f..a1a8903ae5d0 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -404,8 +404,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, size_t want, seek_init = seek, offset = 0; ssize_t ret; - if (seek < buf->head[0].iov_len) { - want = min_t(size_t, count, buf->head[0].iov_len); + want = min_t(size_t, count, buf->head[0].iov_len); + if (seek < want) { ret = xs_read_kvec(sock, msg, flags, &buf->head[0], want, seek); if (ret <= 0) goto sock_err; @@ -416,8 +416,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, goto out; seek = 0; } else { - seek -= buf->head[0].iov_len; - offset += buf->head[0].iov_len; + seek -= want; + offset += want; } want = xs_alloc_sparse_pages(buf, @@ -442,8 +442,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, offset += want; } - if (seek < buf->tail[0].iov_len) { - want = min_t(size_t, count - offset, buf- >tail[0].iov_len); + want = min_t(size_t, count - offset, buf->tail[0].iov_len); + if (seek < want) { ret = xs_read_kvec(sock, msg, flags, &buf->tail[0], want, seek); if (ret <= 0) goto sock_err; @@ -453,7 +453,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, if (ret != want) goto out; } else - offset += buf->tail[0].iov_len; + offset = seek_init; ret = -EMSGSIZE; out: *read = offset - seek_init; @@ -497,11 +497,9 @@ xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg, &read); transport->recv.offset += read; transport->recv.copied += read; - if (transport->recv.offset == transport->recv.len) { - if (xs_read_stream_request_done(transport)) - msg->msg_flags |= MSG_EOR; - return read; - } + if (transport->recv.offset == transport->recv.len && + xs_read_stream_request_done(transport)) + msg->msg_flags |= MSG_EOR; switch (ret) { default: @@ -671,6 +669,8 @@ static void xs_stream_data_receive(struct sock_xprt *transport) read += ret; cond_resched(); } + if (ret == -ESHUTDOWN) + kernel_sock_shutdown(transport->sock, SHUT_RDWR); out: mutex_unlock(&transport->recv_mutex); trace_xs_stream_read_data(&transport->xprt, ret, read); -- Trond Myklebust Linux NFS client maintainer, Hammerspace trond.myklebust@xxxxxxxxxxxxxxx