Commit e92053a5 authored by Trond Myklebust's avatar Trond Myklebust

SUNRPC: Handle zero length fragments correctly

A zero length fragment is really a bug, but let's ensure we don't
go nuts when one turns up.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent ae053551
...@@ -405,8 +405,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, ...@@ -405,8 +405,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
size_t want, seek_init = seek, offset = 0; size_t want, seek_init = seek, offset = 0;
ssize_t ret; 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); ret = xs_read_kvec(sock, msg, flags, &buf->head[0], want, seek);
if (ret <= 0) if (ret <= 0)
goto sock_err; goto sock_err;
...@@ -417,8 +417,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, ...@@ -417,8 +417,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
goto out; goto out;
seek = 0; seek = 0;
} else { } else {
seek -= buf->head[0].iov_len; seek -= want;
offset += buf->head[0].iov_len; offset += want;
} }
want = xs_alloc_sparse_pages(buf, want = xs_alloc_sparse_pages(buf,
...@@ -443,8 +443,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, ...@@ -443,8 +443,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
offset += want; 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); ret = xs_read_kvec(sock, msg, flags, &buf->tail[0], want, seek);
if (ret <= 0) if (ret <= 0)
goto sock_err; goto sock_err;
...@@ -454,7 +454,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, ...@@ -454,7 +454,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
if (ret != want) if (ret != want)
goto out; goto out;
} else } else
offset += buf->tail[0].iov_len; offset = seek_init;
ret = -EMSGSIZE; ret = -EMSGSIZE;
out: out:
*read = offset - seek_init; *read = offset - seek_init;
...@@ -482,6 +482,14 @@ xs_read_stream_request_done(struct sock_xprt *transport) ...@@ -482,6 +482,14 @@ xs_read_stream_request_done(struct sock_xprt *transport)
return transport->recv.fraghdr & cpu_to_be32(RPC_LAST_STREAM_FRAGMENT); return transport->recv.fraghdr & cpu_to_be32(RPC_LAST_STREAM_FRAGMENT);
} }
static void
xs_read_stream_check_eor(struct sock_xprt *transport,
struct msghdr *msg)
{
if (xs_read_stream_request_done(transport))
msg->msg_flags |= MSG_EOR;
}
static ssize_t static ssize_t
xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg, xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg,
int flags, struct rpc_rqst *req) int flags, struct rpc_rqst *req)
...@@ -493,17 +501,24 @@ xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg, ...@@ -493,17 +501,24 @@ xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg,
xs_read_header(transport, buf); xs_read_header(transport, buf);
want = transport->recv.len - transport->recv.offset; want = transport->recv.len - transport->recv.offset;
if (want != 0) {
ret = xs_read_xdr_buf(transport->sock, msg, flags, buf, ret = xs_read_xdr_buf(transport->sock, msg, flags, buf,
transport->recv.copied + want, transport->recv.copied, transport->recv.copied + want,
transport->recv.copied,
&read); &read);
transport->recv.offset += read; transport->recv.offset += read;
transport->recv.copied += read; transport->recv.copied += read;
} else
read = 0;
if (transport->recv.offset == transport->recv.len) { if (transport->recv.offset == transport->recv.len) {
if (xs_read_stream_request_done(transport)) xs_read_stream_check_eor(transport, msg);
msg->msg_flags |= MSG_EOR;
return read; return read;
} }
if (want == 0)
return 0;
switch (ret) { switch (ret) {
default: default:
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment