SUNRPC: Clean up xs_send_pages()
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
bee57c99c3
commit
24c5684b65
1 changed files with 65 additions and 75 deletions
|
@ -168,37 +168,52 @@ static void xs_free_peer_addresses(struct rpc_xprt *xprt)
|
||||||
|
|
||||||
#define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL)
|
#define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL)
|
||||||
|
|
||||||
static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
|
static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, struct kvec *vec, unsigned int base, int more)
|
||||||
{
|
{
|
||||||
struct kvec iov = {
|
|
||||||
.iov_base = xdr->head[0].iov_base + base,
|
|
||||||
.iov_len = len - base,
|
|
||||||
};
|
|
||||||
struct msghdr msg = {
|
struct msghdr msg = {
|
||||||
.msg_name = addr,
|
.msg_name = addr,
|
||||||
.msg_namelen = addrlen,
|
.msg_namelen = addrlen,
|
||||||
.msg_flags = XS_SENDMSG_FLAGS,
|
.msg_flags = XS_SENDMSG_FLAGS | (more ? MSG_MORE : 0),
|
||||||
|
};
|
||||||
|
struct kvec iov = {
|
||||||
|
.iov_base = vec->iov_base + base,
|
||||||
|
.iov_len = vec->iov_len - base,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (xdr->len > len)
|
if (iov.iov_len != 0)
|
||||||
msg.msg_flags |= MSG_MORE;
|
|
||||||
|
|
||||||
if (likely(iov.iov_len))
|
|
||||||
return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
|
return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
|
||||||
return kernel_sendmsg(sock, &msg, NULL, 0, 0);
|
return kernel_sendmsg(sock, &msg, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
|
static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more)
|
||||||
{
|
{
|
||||||
struct kvec iov = {
|
struct page **ppage;
|
||||||
.iov_base = xdr->tail[0].iov_base + base,
|
unsigned int remainder;
|
||||||
.iov_len = len - base,
|
int err, sent = 0;
|
||||||
};
|
|
||||||
struct msghdr msg = {
|
|
||||||
.msg_flags = XS_SENDMSG_FLAGS,
|
|
||||||
};
|
|
||||||
|
|
||||||
return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
|
remainder = xdr->page_len - base;
|
||||||
|
base += xdr->page_base;
|
||||||
|
ppage = xdr->pages + (base >> PAGE_SHIFT);
|
||||||
|
base &= ~PAGE_MASK;
|
||||||
|
for(;;) {
|
||||||
|
unsigned int len = min_t(unsigned int, PAGE_SIZE - base, remainder);
|
||||||
|
int flags = XS_SENDMSG_FLAGS;
|
||||||
|
|
||||||
|
remainder -= len;
|
||||||
|
if (remainder != 0 || more)
|
||||||
|
flags |= MSG_MORE;
|
||||||
|
err = sock->ops->sendpage(sock, *ppage, base, len, flags);
|
||||||
|
if (remainder == 0 || err != len)
|
||||||
|
break;
|
||||||
|
sent += err;
|
||||||
|
ppage++;
|
||||||
|
base = 0;
|
||||||
|
}
|
||||||
|
if (sent == 0)
|
||||||
|
return err;
|
||||||
|
if (err > 0)
|
||||||
|
sent += err;
|
||||||
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -210,76 +225,51 @@ static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int b
|
||||||
* @base: starting position in the buffer
|
* @base: starting position in the buffer
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
|
static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
|
||||||
{
|
{
|
||||||
struct page **ppage = xdr->pages;
|
unsigned int remainder = xdr->len - base;
|
||||||
unsigned int len, pglen = xdr->page_len;
|
int err, sent = 0;
|
||||||
int err, ret = 0;
|
|
||||||
|
|
||||||
if (unlikely(!sock))
|
if (unlikely(!sock))
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
|
|
||||||
clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
|
clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
|
||||||
|
if (base != 0) {
|
||||||
|
addr = NULL;
|
||||||
|
addrlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
len = xdr->head[0].iov_len;
|
if (base < xdr->head[0].iov_len || addr != NULL) {
|
||||||
if (base < len || (addr != NULL && base == 0)) {
|
unsigned int len = xdr->head[0].iov_len - base;
|
||||||
err = xs_send_head(sock, addr, addrlen, xdr, base, len);
|
remainder -= len;
|
||||||
if (ret == 0)
|
err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0);
|
||||||
ret = err;
|
if (remainder == 0 || err != len)
|
||||||
else if (err > 0)
|
|
||||||
ret += err;
|
|
||||||
if (err != (len - base))
|
|
||||||
goto out;
|
goto out;
|
||||||
|
sent += err;
|
||||||
base = 0;
|
base = 0;
|
||||||
} else
|
} else
|
||||||
base -= len;
|
base -= xdr->head[0].iov_len;
|
||||||
|
|
||||||
if (unlikely(pglen == 0))
|
if (base < xdr->page_len) {
|
||||||
goto copy_tail;
|
unsigned int len = xdr->page_len - base;
|
||||||
if (unlikely(base >= pglen)) {
|
remainder -= len;
|
||||||
base -= pglen;
|
err = xs_send_pagedata(sock, xdr, base, remainder != 0);
|
||||||
goto copy_tail;
|
if (remainder == 0 || err != len)
|
||||||
}
|
|
||||||
if (base || xdr->page_base) {
|
|
||||||
pglen -= base;
|
|
||||||
base += xdr->page_base;
|
|
||||||
ppage += base >> PAGE_CACHE_SHIFT;
|
|
||||||
base &= ~PAGE_CACHE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
int flags = XS_SENDMSG_FLAGS;
|
|
||||||
|
|
||||||
len = PAGE_CACHE_SIZE;
|
|
||||||
if (base)
|
|
||||||
len -= base;
|
|
||||||
if (pglen < len)
|
|
||||||
len = pglen;
|
|
||||||
|
|
||||||
if (pglen != len || xdr->tail[0].iov_len != 0)
|
|
||||||
flags |= MSG_MORE;
|
|
||||||
|
|
||||||
err = kernel_sendpage(sock, *ppage, base, len, flags);
|
|
||||||
if (ret == 0)
|
|
||||||
ret = err;
|
|
||||||
else if (err > 0)
|
|
||||||
ret += err;
|
|
||||||
if (err != len)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
sent += err;
|
||||||
base = 0;
|
base = 0;
|
||||||
ppage++;
|
} else
|
||||||
} while ((pglen -= len) != 0);
|
base -= xdr->page_len;
|
||||||
copy_tail:
|
|
||||||
len = xdr->tail[0].iov_len;
|
if (base >= xdr->tail[0].iov_len)
|
||||||
if (base < len) {
|
return sent;
|
||||||
err = xs_send_tail(sock, xdr, base, len);
|
err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0);
|
||||||
if (ret == 0)
|
|
||||||
ret = err;
|
|
||||||
else if (err > 0)
|
|
||||||
ret += err;
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
if (sent == 0)
|
||||||
|
return err;
|
||||||
|
if (err > 0)
|
||||||
|
sent += err;
|
||||||
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue