[PATCH] RPC: Reduce stack utilization in xs_sendpages

Reduce stack utilization of the RPC socket transport's send path.

 A couple of unlikely()s are added to ensure the compiler places the
 tail processing at the end of the csect.

 Test-plan:
 Millions of fsx operations.  Performance characterization such as "sio" or
 "iozone".

 Version: Thu, 11 Aug 2005 16:04:30 -0400

 Signed-off-by: Chuck Lever <cel@netapp.com>
 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Chuck Lever 2005-08-11 16:25:29 -04:00 committed by Trond Myklebust
parent 9903cd1c27
commit b4b5cc85ed

View File

@ -68,6 +68,41 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
} }
#endif #endif
#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)
{
struct kvec iov = {
.iov_base = xdr->head[0].iov_base + base,
.iov_len = len - base,
};
struct msghdr msg = {
.msg_name = addr,
.msg_namelen = addrlen,
.msg_flags = XS_SENDMSG_FLAGS,
};
if (xdr->len > len)
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, NULL, 0, 0);
}
static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
{
struct kvec iov = {
.iov_base = xdr->tail[0].iov_base + base,
.iov_len = len - base,
};
struct msghdr msg = {
.msg_flags = XS_SENDMSG_FLAGS,
};
return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
}
/** /**
* xs_sendpages - write pages directly to a socket * xs_sendpages - write pages directly to a socket
* @sock: socket to send on * @sock: socket to send on
@ -77,7 +112,7 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
* @base: starting position in the buffer * @base: starting position in the buffer
* *
*/ */
static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags) static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
{ {
struct page **ppage = xdr->pages; struct page **ppage = xdr->pages;
unsigned int len, pglen = xdr->page_len; unsigned int len, pglen = xdr->page_len;
@ -86,35 +121,20 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
len = xdr->head[0].iov_len; len = xdr->head[0].iov_len;
if (base < len || (addr != NULL && base == 0)) { if (base < len || (addr != NULL && base == 0)) {
struct kvec iov = { err = xs_send_head(sock, addr, addrlen, xdr, base, len);
.iov_base = xdr->head[0].iov_base + base,
.iov_len = len - base,
};
struct msghdr msg = {
.msg_name = addr,
.msg_namelen = addrlen,
.msg_flags = msgflags,
};
if (xdr->len > len)
msg.msg_flags |= MSG_MORE;
if (iov.iov_len != 0)
err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
else
err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
if (ret == 0) if (ret == 0)
ret = err; ret = err;
else if (err > 0) else if (err > 0)
ret += err; ret += err;
if (err != iov.iov_len) if (err != (len - base))
goto out; goto out;
base = 0; base = 0;
} else } else
base -= len; base -= len;
if (pglen == 0) if (unlikely(pglen == 0))
goto copy_tail; goto copy_tail;
if (base >= pglen) { if (unlikely(base >= pglen)) {
base -= pglen; base -= pglen;
goto copy_tail; goto copy_tail;
} }
@ -127,7 +147,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
sendpage = sock->ops->sendpage ? : sock_no_sendpage; sendpage = sock->ops->sendpage ? : sock_no_sendpage;
do { do {
int flags = msgflags; int flags = XS_SENDMSG_FLAGS;
len = PAGE_CACHE_SIZE; len = PAGE_CACHE_SIZE;
if (base) if (base)
@ -154,14 +174,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
copy_tail: copy_tail:
len = xdr->tail[0].iov_len; len = xdr->tail[0].iov_len;
if (base < len) { if (base < len) {
struct kvec iov = { err = xs_send_tail(sock, xdr, base, len);
.iov_base = xdr->tail[0].iov_base + base,
.iov_len = len - base,
};
struct msghdr msg = {
.msg_flags = msgflags,
};
err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
if (ret == 0) if (ret == 0)
ret = err; ret = err;
else if (err > 0) else if (err > 0)
@ -202,7 +215,7 @@ static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
skip = req->rq_bytes_sent; skip = req->rq_bytes_sent;
clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
result = xs_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT); result = xs_sendpages(sock, addr, addrlen, xdr, skip);
dprintk("RPC: xs_sendmsg(%d) = %d\n", xdr->len - skip, result); dprintk("RPC: xs_sendmsg(%d) = %d\n", xdr->len - skip, result);