aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <cel@citi.umich.edu>2005-08-11 16:25:29 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-09-23 12:38:16 -0400
commitb4b5cc85ed4ecbe4adbfbc4df028850de67a9f09 (patch)
tree41b4a8d22847f816e555ad5e4566b9c33dea5c0f
parent9903cd1c27a1f30e8efea75e125be3b2002f7cb9 (diff)
[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>
-rw-r--r--net/sunrpc/xprtsock.c73
1 files changed, 43 insertions, 30 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 80222de3afa4..a5a04203a6b0 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -68,6 +68,41 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
68} 68}
69#endif 69#endif
70 70
71#define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL)
72
73static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
74{
75 struct kvec iov = {
76 .iov_base = xdr->head[0].iov_base + base,
77 .iov_len = len - base,
78 };
79 struct msghdr msg = {
80 .msg_name = addr,
81 .msg_namelen = addrlen,
82 .msg_flags = XS_SENDMSG_FLAGS,
83 };
84
85 if (xdr->len > len)
86 msg.msg_flags |= MSG_MORE;
87
88 if (likely(iov.iov_len))
89 return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
90 return kernel_sendmsg(sock, &msg, NULL, 0, 0);
91}
92
93static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
94{
95 struct kvec iov = {
96 .iov_base = xdr->tail[0].iov_base + base,
97 .iov_len = len - base,
98 };
99 struct msghdr msg = {
100 .msg_flags = XS_SENDMSG_FLAGS,
101 };
102
103 return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
104}
105
71/** 106/**
72 * xs_sendpages - write pages directly to a socket 107 * xs_sendpages - write pages directly to a socket
73 * @sock: socket to send on 108 * @sock: socket to send on
@@ -77,7 +112,7 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
77 * @base: starting position in the buffer 112 * @base: starting position in the buffer
78 * 113 *
79 */ 114 */
80static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags) 115static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
81{ 116{
82 struct page **ppage = xdr->pages; 117 struct page **ppage = xdr->pages;
83 unsigned int len, pglen = xdr->page_len; 118 unsigned int len, pglen = xdr->page_len;
@@ -86,35 +121,20 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
86 121
87 len = xdr->head[0].iov_len; 122 len = xdr->head[0].iov_len;
88 if (base < len || (addr != NULL && base == 0)) { 123 if (base < len || (addr != NULL && base == 0)) {
89 struct kvec iov = { 124 err = xs_send_head(sock, addr, addrlen, xdr, base, len);
90 .iov_base = xdr->head[0].iov_base + base,
91 .iov_len = len - base,
92 };
93 struct msghdr msg = {
94 .msg_name = addr,
95 .msg_namelen = addrlen,
96 .msg_flags = msgflags,
97 };
98 if (xdr->len > len)
99 msg.msg_flags |= MSG_MORE;
100
101 if (iov.iov_len != 0)
102 err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
103 else
104 err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
105 if (ret == 0) 125 if (ret == 0)
106 ret = err; 126 ret = err;
107 else if (err > 0) 127 else if (err > 0)
108 ret += err; 128 ret += err;
109 if (err != iov.iov_len) 129 if (err != (len - base))
110 goto out; 130 goto out;
111 base = 0; 131 base = 0;
112 } else 132 } else
113 base -= len; 133 base -= len;
114 134
115 if (pglen == 0) 135 if (unlikely(pglen == 0))
116 goto copy_tail; 136 goto copy_tail;
117 if (base >= pglen) { 137 if (unlikely(base >= pglen)) {
118 base -= pglen; 138 base -= pglen;
119 goto copy_tail; 139 goto copy_tail;
120 } 140 }
@@ -127,7 +147,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
127 147
128 sendpage = sock->ops->sendpage ? : sock_no_sendpage; 148 sendpage = sock->ops->sendpage ? : sock_no_sendpage;
129 do { 149 do {
130 int flags = msgflags; 150 int flags = XS_SENDMSG_FLAGS;
131 151
132 len = PAGE_CACHE_SIZE; 152 len = PAGE_CACHE_SIZE;
133 if (base) 153 if (base)
@@ -154,14 +174,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
154copy_tail: 174copy_tail:
155 len = xdr->tail[0].iov_len; 175 len = xdr->tail[0].iov_len;
156 if (base < len) { 176 if (base < len) {
157 struct kvec iov = { 177 err = xs_send_tail(sock, xdr, base, len);
158 .iov_base = xdr->tail[0].iov_base + base,
159 .iov_len = len - base,
160 };
161 struct msghdr msg = {
162 .msg_flags = msgflags,
163 };
164 err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
165 if (ret == 0) 178 if (ret == 0)
166 ret = err; 179 ret = err;
167 else if (err > 0) 180 else if (err > 0)
@@ -202,7 +215,7 @@ static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
202 skip = req->rq_bytes_sent; 215 skip = req->rq_bytes_sent;
203 216
204 clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); 217 clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
205 result = xs_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT); 218 result = xs_sendpages(sock, addr, addrlen, xdr, skip);
206 219
207 dprintk("RPC: xs_sendmsg(%d) = %d\n", xdr->len - skip, result); 220 dprintk("RPC: xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
208 221