diff options
author | Chuck Lever <cel@citi.umich.edu> | 2005-08-11 16:25:29 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-09-23 12:38:16 -0400 |
commit | b4b5cc85ed4ecbe4adbfbc4df028850de67a9f09 (patch) | |
tree | 41b4a8d22847f816e555ad5e4566b9c33dea5c0f | |
parent | 9903cd1c27a1f30e8efea75e125be3b2002f7cb9 (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.c | 73 |
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 | |||
73 | static 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 | |||
93 | static 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 | */ |
80 | static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags) | 115 | static 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, | |||
154 | copy_tail: | 174 | copy_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 | ||