blob: 7f0b9f7f167bcad1c846710effdc9b025988cdba [file] [log] [blame]
Chuck Levera246b012005-08-11 16:25:23 -04001/*
2 * linux/net/sunrpc/xprtsock.c
3 *
4 * Client-side transport implementation for sockets.
5 *
6 * TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
7 * TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
8 * TCP NFS related read + write fixes
9 * (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
10 *
11 * Rewrite of larges part of the code in order to stabilize TCP stuff.
12 * Fix behaviour when socket buffer is full.
13 * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no>
Chuck Lever55aa4f52005-08-11 16:25:47 -040014 *
15 * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com>
Chuck Levera246b012005-08-11 16:25:23 -040016 */
17
18#include <linux/types.h>
19#include <linux/slab.h>
20#include <linux/capability.h>
21#include <linux/sched.h>
22#include <linux/pagemap.h>
23#include <linux/errno.h>
24#include <linux/socket.h>
25#include <linux/in.h>
26#include <linux/net.h>
27#include <linux/mm.h>
28#include <linux/udp.h>
29#include <linux/tcp.h>
30#include <linux/sunrpc/clnt.h>
31#include <linux/file.h>
32
33#include <net/sock.h>
34#include <net/checksum.h>
35#include <net/udp.h>
36#include <net/tcp.h>
37
Chuck Lever9903cd12005-08-11 16:25:26 -040038/*
39 * Maximum port number to use when requesting a reserved port.
40 */
41#define XS_MAX_RESVPORT (800U)
42
Chuck Levera246b012005-08-11 16:25:23 -040043#ifdef RPC_DEBUG
44# undef RPC_DEBUG_DATA
Chuck Lever9903cd12005-08-11 16:25:26 -040045# define RPCDBG_FACILITY RPCDBG_TRANS
Chuck Levera246b012005-08-11 16:25:23 -040046#endif
47
Chuck Levera246b012005-08-11 16:25:23 -040048#ifdef RPC_DEBUG_DATA
Chuck Lever9903cd12005-08-11 16:25:26 -040049static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
Chuck Levera246b012005-08-11 16:25:23 -040050{
Chuck Lever9903cd12005-08-11 16:25:26 -040051 u8 *buf = (u8 *) packet;
52 int j;
Chuck Levera246b012005-08-11 16:25:23 -040053
54 dprintk("RPC: %s\n", msg);
55 for (j = 0; j < count && j < 128; j += 4) {
56 if (!(j & 31)) {
57 if (j)
58 dprintk("\n");
59 dprintk("0x%04x ", j);
60 }
61 dprintk("%02x%02x%02x%02x ",
62 buf[j], buf[j+1], buf[j+2], buf[j+3]);
63 }
64 dprintk("\n");
65}
66#else
Chuck Lever9903cd12005-08-11 16:25:26 -040067static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
Chuck Levera246b012005-08-11 16:25:23 -040068{
69 /* NOP */
70}
71#endif
72
Chuck Leverb4b5cc82005-08-11 16:25:29 -040073#define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL)
74
75static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
76{
77 struct kvec iov = {
78 .iov_base = xdr->head[0].iov_base + base,
79 .iov_len = len - base,
80 };
81 struct msghdr msg = {
82 .msg_name = addr,
83 .msg_namelen = addrlen,
84 .msg_flags = XS_SENDMSG_FLAGS,
85 };
86
87 if (xdr->len > len)
88 msg.msg_flags |= MSG_MORE;
89
90 if (likely(iov.iov_len))
91 return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
92 return kernel_sendmsg(sock, &msg, NULL, 0, 0);
93}
94
95static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
96{
97 struct kvec iov = {
98 .iov_base = xdr->tail[0].iov_base + base,
99 .iov_len = len - base,
100 };
101 struct msghdr msg = {
102 .msg_flags = XS_SENDMSG_FLAGS,
103 };
104
105 return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
106}
107
Chuck Lever9903cd12005-08-11 16:25:26 -0400108/**
109 * xs_sendpages - write pages directly to a socket
110 * @sock: socket to send on
111 * @addr: UDP only -- address of destination
112 * @addrlen: UDP only -- length of destination address
113 * @xdr: buffer containing this request
114 * @base: starting position in the buffer
115 *
Chuck Levera246b012005-08-11 16:25:23 -0400116 */
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400117static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
Chuck Levera246b012005-08-11 16:25:23 -0400118{
119 struct page **ppage = xdr->pages;
120 unsigned int len, pglen = xdr->page_len;
121 int err, ret = 0;
122 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
123
124 len = xdr->head[0].iov_len;
125 if (base < len || (addr != NULL && base == 0)) {
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400126 err = xs_send_head(sock, addr, addrlen, xdr, base, len);
Chuck Levera246b012005-08-11 16:25:23 -0400127 if (ret == 0)
128 ret = err;
129 else if (err > 0)
130 ret += err;
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400131 if (err != (len - base))
Chuck Levera246b012005-08-11 16:25:23 -0400132 goto out;
133 base = 0;
134 } else
135 base -= len;
136
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400137 if (unlikely(pglen == 0))
Chuck Levera246b012005-08-11 16:25:23 -0400138 goto copy_tail;
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400139 if (unlikely(base >= pglen)) {
Chuck Levera246b012005-08-11 16:25:23 -0400140 base -= pglen;
141 goto copy_tail;
142 }
143 if (base || xdr->page_base) {
144 pglen -= base;
Chuck Lever9903cd12005-08-11 16:25:26 -0400145 base += xdr->page_base;
Chuck Levera246b012005-08-11 16:25:23 -0400146 ppage += base >> PAGE_CACHE_SHIFT;
147 base &= ~PAGE_CACHE_MASK;
148 }
149
150 sendpage = sock->ops->sendpage ? : sock_no_sendpage;
151 do {
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400152 int flags = XS_SENDMSG_FLAGS;
Chuck Levera246b012005-08-11 16:25:23 -0400153
154 len = PAGE_CACHE_SIZE;
155 if (base)
156 len -= base;
157 if (pglen < len)
158 len = pglen;
159
160 if (pglen != len || xdr->tail[0].iov_len != 0)
161 flags |= MSG_MORE;
162
163 /* Hmm... We might be dealing with highmem pages */
164 if (PageHighMem(*ppage))
165 sendpage = sock_no_sendpage;
166 err = sendpage(sock, *ppage, base, len, flags);
167 if (ret == 0)
168 ret = err;
169 else if (err > 0)
170 ret += err;
171 if (err != len)
172 goto out;
173 base = 0;
174 ppage++;
175 } while ((pglen -= len) != 0);
176copy_tail:
177 len = xdr->tail[0].iov_len;
178 if (base < len) {
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400179 err = xs_send_tail(sock, xdr, base, len);
Chuck Levera246b012005-08-11 16:25:23 -0400180 if (ret == 0)
181 ret = err;
182 else if (err > 0)
183 ret += err;
184 }
185out:
186 return ret;
187}
188
Chuck Lever9903cd12005-08-11 16:25:26 -0400189/**
190 * xs_sendmsg - write an RPC request to a socket
191 * @xprt: generic transport
192 * @req: the RPC request to write
193 *
Chuck Levera246b012005-08-11 16:25:23 -0400194 */
Chuck Lever9903cd12005-08-11 16:25:26 -0400195static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
Chuck Levera246b012005-08-11 16:25:23 -0400196{
Chuck Lever9903cd12005-08-11 16:25:26 -0400197 struct socket *sock = xprt->sock;
198 struct xdr_buf *xdr = &req->rq_snd_buf;
Chuck Levera246b012005-08-11 16:25:23 -0400199 struct sockaddr *addr = NULL;
200 int addrlen = 0;
Chuck Lever9903cd12005-08-11 16:25:26 -0400201 unsigned int skip;
202 int result;
Chuck Levera246b012005-08-11 16:25:23 -0400203
204 if (!sock)
205 return -ENOTCONN;
206
Chuck Lever9903cd12005-08-11 16:25:26 -0400207 xs_pktdump("packet data:",
Chuck Levera246b012005-08-11 16:25:23 -0400208 req->rq_svec->iov_base,
209 req->rq_svec->iov_len);
210
211 /* For UDP, we need to provide an address */
212 if (!xprt->stream) {
213 addr = (struct sockaddr *) &xprt->addr;
214 addrlen = sizeof(xprt->addr);
215 }
Chuck Lever9903cd12005-08-11 16:25:26 -0400216 /* Don't repeat bytes */
Chuck Levera246b012005-08-11 16:25:23 -0400217 skip = req->rq_bytes_sent;
218
219 clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
Chuck Leverb4b5cc82005-08-11 16:25:29 -0400220 result = xs_sendpages(sock, addr, addrlen, xdr, skip);
Chuck Levera246b012005-08-11 16:25:23 -0400221
Chuck Lever9903cd12005-08-11 16:25:26 -0400222 dprintk("RPC: xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
Chuck Levera246b012005-08-11 16:25:23 -0400223
224 if (result >= 0)
225 return result;
226
227 switch (result) {
228 case -ECONNREFUSED:
229 /* When the server has died, an ICMP port unreachable message
Chuck Lever9903cd12005-08-11 16:25:26 -0400230 * prompts ECONNREFUSED. */
Chuck Levera246b012005-08-11 16:25:23 -0400231 case -EAGAIN:
232 break;
233 case -ECONNRESET:
234 case -ENOTCONN:
235 case -EPIPE:
236 /* connection broken */
237 if (xprt->stream)
238 result = -ENOTCONN;
239 break;
240 default:
Chuck Lever9903cd12005-08-11 16:25:26 -0400241 break;
Chuck Levera246b012005-08-11 16:25:23 -0400242 }
243 return result;
244}
245
Chuck Lever9903cd12005-08-11 16:25:26 -0400246/**
247 * xs_send_request - write an RPC request to a socket
248 * @task: address of RPC task that manages the state of an RPC request
249 *
250 * Return values:
251 * 0: The request has been sent
252 * EAGAIN: The socket was blocked, please call again later to
253 * complete the request
254 * other: Some other error occured, the request was not sent
255 *
256 * XXX: In the case of soft timeouts, should we eventually give up
257 * if the socket is not able to make progress?
258 */
259static int xs_send_request(struct rpc_task *task)
Chuck Levera246b012005-08-11 16:25:23 -0400260{
261 struct rpc_rqst *req = task->tk_rqstp;
262 struct rpc_xprt *xprt = req->rq_xprt;
263 int status, retry = 0;
264
265 /* set up everything as needed. */
266 /* Write the record marker */
267 if (xprt->stream) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400268 u32 *marker = req->rq_svec[0].iov_base;
Chuck Levera246b012005-08-11 16:25:23 -0400269
270 *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
271 }
272
273 /* Continue transmitting the packet/record. We must be careful
274 * to cope with writespace callbacks arriving _after_ we have
Chuck Lever9903cd12005-08-11 16:25:26 -0400275 * called sendmsg().
Chuck Levera246b012005-08-11 16:25:23 -0400276 */
277 while (1) {
278 req->rq_xtime = jiffies;
Chuck Lever9903cd12005-08-11 16:25:26 -0400279 status = xs_sendmsg(xprt, req);
Chuck Levera246b012005-08-11 16:25:23 -0400280
281 if (status < 0)
282 break;
283
284 if (xprt->stream) {
285 req->rq_bytes_sent += status;
286
287 /* If we've sent the entire packet, immediately
288 * reset the count of bytes sent. */
289 if (req->rq_bytes_sent >= req->rq_slen) {
290 req->rq_bytes_sent = 0;
291 return 0;
292 }
293 } else {
294 if (status >= req->rq_slen)
295 return 0;
296 status = -EAGAIN;
297 break;
298 }
299
300 dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
301 task->tk_pid, req->rq_slen - req->rq_bytes_sent,
302 req->rq_slen);
303
304 status = -EAGAIN;
305 if (retry++ > 50)
306 break;
307 }
308
309 if (status == -EAGAIN) {
310 if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400311 /* Protect against races with xs_write_space */
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400312 spin_lock_bh(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400313 /* Don't race with disconnect */
314 if (!xprt_connected(xprt))
315 task->tk_status = -ENOTCONN;
316 else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
317 task->tk_timeout = req->rq_timeout;
318 rpc_sleep_on(&xprt->pending, task, NULL, NULL);
319 }
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400320 spin_unlock_bh(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400321 return status;
322 }
323 /* Keep holding the socket if it is blocked */
324 rpc_delay(task, HZ>>4);
325 }
326 return status;
327}
328
Chuck Lever9903cd12005-08-11 16:25:26 -0400329/**
330 * xs_close - close a socket
331 * @xprt: transport
332 *
Chuck Levera246b012005-08-11 16:25:23 -0400333 */
Chuck Lever9903cd12005-08-11 16:25:26 -0400334static void xs_close(struct rpc_xprt *xprt)
Chuck Levera246b012005-08-11 16:25:23 -0400335{
Chuck Lever9903cd12005-08-11 16:25:26 -0400336 struct socket *sock = xprt->sock;
337 struct sock *sk = xprt->inet;
Chuck Levera246b012005-08-11 16:25:23 -0400338
339 if (!sk)
340 return;
341
Chuck Lever9903cd12005-08-11 16:25:26 -0400342 dprintk("RPC: xs_close xprt %p\n", xprt);
343
Chuck Levera246b012005-08-11 16:25:23 -0400344 write_lock_bh(&sk->sk_callback_lock);
345 xprt->inet = NULL;
346 xprt->sock = NULL;
347
Chuck Lever9903cd12005-08-11 16:25:26 -0400348 sk->sk_user_data = NULL;
349 sk->sk_data_ready = xprt->old_data_ready;
Chuck Levera246b012005-08-11 16:25:23 -0400350 sk->sk_state_change = xprt->old_state_change;
Chuck Lever9903cd12005-08-11 16:25:26 -0400351 sk->sk_write_space = xprt->old_write_space;
Chuck Levera246b012005-08-11 16:25:23 -0400352 write_unlock_bh(&sk->sk_callback_lock);
353
Chuck Lever9903cd12005-08-11 16:25:26 -0400354 sk->sk_no_check = 0;
Chuck Levera246b012005-08-11 16:25:23 -0400355
356 sock_release(sock);
357}
358
Chuck Lever9903cd12005-08-11 16:25:26 -0400359/**
360 * xs_destroy - prepare to shutdown a transport
361 * @xprt: doomed transport
362 *
363 */
364static void xs_destroy(struct rpc_xprt *xprt)
Chuck Levera246b012005-08-11 16:25:23 -0400365{
Chuck Lever9903cd12005-08-11 16:25:26 -0400366 dprintk("RPC: xs_destroy xprt %p\n", xprt);
367
Chuck Lever55aa4f52005-08-11 16:25:47 -0400368 cancel_delayed_work(&xprt->connect_worker);
Chuck Levera246b012005-08-11 16:25:23 -0400369 flush_scheduled_work();
370
371 xprt_disconnect(xprt);
Chuck Lever9903cd12005-08-11 16:25:26 -0400372 xs_close(xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400373 kfree(xprt->slot);
374}
375
Chuck Lever9903cd12005-08-11 16:25:26 -0400376static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
Chuck Levera246b012005-08-11 16:25:23 -0400377{
Chuck Lever9903cd12005-08-11 16:25:26 -0400378 return (struct rpc_xprt *) sk->sk_user_data;
379}
380
381/**
382 * xs_udp_data_ready - "data ready" callback for UDP sockets
383 * @sk: socket with data to read
384 * @len: how much data to read
385 *
386 */
387static void xs_udp_data_ready(struct sock *sk, int len)
388{
389 struct rpc_task *task;
390 struct rpc_xprt *xprt;
Chuck Levera246b012005-08-11 16:25:23 -0400391 struct rpc_rqst *rovr;
Chuck Lever9903cd12005-08-11 16:25:26 -0400392 struct sk_buff *skb;
Chuck Levera246b012005-08-11 16:25:23 -0400393 int err, repsize, copied;
394 u32 _xid, *xp;
395
396 read_lock(&sk->sk_callback_lock);
Chuck Lever9903cd12005-08-11 16:25:26 -0400397 dprintk("RPC: xs_udp_data_ready...\n");
398 if (!(xprt = xprt_from_sock(sk)))
Chuck Levera246b012005-08-11 16:25:23 -0400399 goto out;
Chuck Levera246b012005-08-11 16:25:23 -0400400
401 if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
402 goto out;
403
404 if (xprt->shutdown)
405 goto dropit;
406
407 repsize = skb->len - sizeof(struct udphdr);
408 if (repsize < 4) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400409 dprintk("RPC: impossible RPC reply size %d!\n", repsize);
Chuck Levera246b012005-08-11 16:25:23 -0400410 goto dropit;
411 }
412
413 /* Copy the XID from the skb... */
414 xp = skb_header_pointer(skb, sizeof(struct udphdr),
415 sizeof(_xid), &_xid);
416 if (xp == NULL)
417 goto dropit;
418
419 /* Look up and lock the request corresponding to the given XID */
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400420 spin_lock(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400421 rovr = xprt_lookup_rqst(xprt, *xp);
422 if (!rovr)
423 goto out_unlock;
424 task = rovr->rq_task;
425
426 dprintk("RPC: %4d received reply\n", task->tk_pid);
427
428 if ((copied = rovr->rq_private_buf.buflen) > repsize)
429 copied = repsize;
430
431 /* Suck it into the iovec, verify checksum if not done by hw. */
432 if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
433 goto out_unlock;
434
435 /* Something worked... */
436 dst_confirm(skb->dst);
437
438 xprt_complete_rqst(xprt, rovr, copied);
439
440 out_unlock:
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400441 spin_unlock(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400442 dropit:
443 skb_free_datagram(sk, skb);
444 out:
445 read_unlock(&sk->sk_callback_lock);
446}
447
Chuck Lever9903cd12005-08-11 16:25:26 -0400448static inline size_t xs_tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
Chuck Levera246b012005-08-11 16:25:23 -0400449{
450 if (len > desc->count)
451 len = desc->count;
452 if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
453 dprintk("RPC: failed to copy %zu bytes from skb. %zu bytes remain\n",
454 len, desc->count);
455 return 0;
456 }
457 desc->offset += len;
458 desc->count -= len;
459 dprintk("RPC: copied %zu bytes from skb. %zu bytes remain\n",
460 len, desc->count);
461 return len;
462}
463
Chuck Lever9903cd12005-08-11 16:25:26 -0400464static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
Chuck Levera246b012005-08-11 16:25:23 -0400465{
466 size_t len, used;
467 char *p;
468
469 p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
470 len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
Chuck Lever9903cd12005-08-11 16:25:26 -0400471 used = xs_tcp_copy_data(desc, p, len);
Chuck Levera246b012005-08-11 16:25:23 -0400472 xprt->tcp_offset += used;
473 if (used != len)
474 return;
475 xprt->tcp_reclen = ntohl(xprt->tcp_recm);
476 if (xprt->tcp_reclen & 0x80000000)
477 xprt->tcp_flags |= XPRT_LAST_FRAG;
478 else
479 xprt->tcp_flags &= ~XPRT_LAST_FRAG;
480 xprt->tcp_reclen &= 0x7fffffff;
481 xprt->tcp_flags &= ~XPRT_COPY_RECM;
482 xprt->tcp_offset = 0;
483 /* Sanity check of the record length */
484 if (xprt->tcp_reclen < 4) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400485 dprintk("RPC: invalid TCP record fragment length\n");
Chuck Levera246b012005-08-11 16:25:23 -0400486 xprt_disconnect(xprt);
Chuck Lever9903cd12005-08-11 16:25:26 -0400487 return;
Chuck Levera246b012005-08-11 16:25:23 -0400488 }
489 dprintk("RPC: reading TCP record fragment of length %d\n",
490 xprt->tcp_reclen);
491}
492
Chuck Lever9903cd12005-08-11 16:25:26 -0400493static void xs_tcp_check_recm(struct rpc_xprt *xprt)
Chuck Levera246b012005-08-11 16:25:23 -0400494{
495 dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
496 xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
497 if (xprt->tcp_offset == xprt->tcp_reclen) {
498 xprt->tcp_flags |= XPRT_COPY_RECM;
499 xprt->tcp_offset = 0;
500 if (xprt->tcp_flags & XPRT_LAST_FRAG) {
501 xprt->tcp_flags &= ~XPRT_COPY_DATA;
502 xprt->tcp_flags |= XPRT_COPY_XID;
503 xprt->tcp_copied = 0;
504 }
505 }
506}
507
Chuck Lever9903cd12005-08-11 16:25:26 -0400508static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
Chuck Levera246b012005-08-11 16:25:23 -0400509{
510 size_t len, used;
511 char *p;
512
513 len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
514 dprintk("RPC: reading XID (%Zu bytes)\n", len);
515 p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
Chuck Lever9903cd12005-08-11 16:25:26 -0400516 used = xs_tcp_copy_data(desc, p, len);
Chuck Levera246b012005-08-11 16:25:23 -0400517 xprt->tcp_offset += used;
518 if (used != len)
519 return;
520 xprt->tcp_flags &= ~XPRT_COPY_XID;
521 xprt->tcp_flags |= XPRT_COPY_DATA;
522 xprt->tcp_copied = 4;
523 dprintk("RPC: reading reply for XID %08x\n",
524 ntohl(xprt->tcp_xid));
Chuck Lever9903cd12005-08-11 16:25:26 -0400525 xs_tcp_check_recm(xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400526}
527
Chuck Lever9903cd12005-08-11 16:25:26 -0400528static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
Chuck Levera246b012005-08-11 16:25:23 -0400529{
530 struct rpc_rqst *req;
531 struct xdr_buf *rcvbuf;
532 size_t len;
533 ssize_t r;
534
535 /* Find and lock the request corresponding to this xid */
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400536 spin_lock(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400537 req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
538 if (!req) {
539 xprt->tcp_flags &= ~XPRT_COPY_DATA;
540 dprintk("RPC: XID %08x request not found!\n",
541 ntohl(xprt->tcp_xid));
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400542 spin_unlock(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400543 return;
544 }
545
546 rcvbuf = &req->rq_private_buf;
547 len = desc->count;
548 if (len > xprt->tcp_reclen - xprt->tcp_offset) {
549 skb_reader_t my_desc;
550
551 len = xprt->tcp_reclen - xprt->tcp_offset;
552 memcpy(&my_desc, desc, sizeof(my_desc));
553 my_desc.count = len;
554 r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
Chuck Lever9903cd12005-08-11 16:25:26 -0400555 &my_desc, xs_tcp_copy_data);
Chuck Levera246b012005-08-11 16:25:23 -0400556 desc->count -= r;
557 desc->offset += r;
558 } else
559 r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
Chuck Lever9903cd12005-08-11 16:25:26 -0400560 desc, xs_tcp_copy_data);
Chuck Levera246b012005-08-11 16:25:23 -0400561
562 if (r > 0) {
563 xprt->tcp_copied += r;
564 xprt->tcp_offset += r;
565 }
566 if (r != len) {
567 /* Error when copying to the receive buffer,
568 * usually because we weren't able to allocate
569 * additional buffer pages. All we can do now
570 * is turn off XPRT_COPY_DATA, so the request
571 * will not receive any additional updates,
572 * and time out.
573 * Any remaining data from this record will
574 * be discarded.
575 */
576 xprt->tcp_flags &= ~XPRT_COPY_DATA;
577 dprintk("RPC: XID %08x truncated request\n",
578 ntohl(xprt->tcp_xid));
579 dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
580 xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
581 goto out;
582 }
583
584 dprintk("RPC: XID %08x read %Zd bytes\n",
585 ntohl(xprt->tcp_xid), r);
586 dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
587 xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
588
589 if (xprt->tcp_copied == req->rq_private_buf.buflen)
590 xprt->tcp_flags &= ~XPRT_COPY_DATA;
591 else if (xprt->tcp_offset == xprt->tcp_reclen) {
592 if (xprt->tcp_flags & XPRT_LAST_FRAG)
593 xprt->tcp_flags &= ~XPRT_COPY_DATA;
594 }
595
596out:
597 if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
598 dprintk("RPC: %4d received reply complete\n",
599 req->rq_task->tk_pid);
600 xprt_complete_rqst(xprt, req, xprt->tcp_copied);
601 }
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400602 spin_unlock(&xprt->transport_lock);
Chuck Lever9903cd12005-08-11 16:25:26 -0400603 xs_tcp_check_recm(xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400604}
605
Chuck Lever9903cd12005-08-11 16:25:26 -0400606static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
Chuck Levera246b012005-08-11 16:25:23 -0400607{
608 size_t len;
609
610 len = xprt->tcp_reclen - xprt->tcp_offset;
611 if (len > desc->count)
612 len = desc->count;
613 desc->count -= len;
614 desc->offset += len;
615 xprt->tcp_offset += len;
616 dprintk("RPC: discarded %Zu bytes\n", len);
Chuck Lever9903cd12005-08-11 16:25:26 -0400617 xs_tcp_check_recm(xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400618}
619
Chuck Lever9903cd12005-08-11 16:25:26 -0400620static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
Chuck Levera246b012005-08-11 16:25:23 -0400621{
622 struct rpc_xprt *xprt = rd_desc->arg.data;
623 skb_reader_t desc = {
624 .skb = skb,
625 .offset = offset,
626 .count = len,
627 .csum = 0
Chuck Lever9903cd12005-08-11 16:25:26 -0400628 };
Chuck Levera246b012005-08-11 16:25:23 -0400629
Chuck Lever9903cd12005-08-11 16:25:26 -0400630 dprintk("RPC: xs_tcp_data_recv started\n");
Chuck Levera246b012005-08-11 16:25:23 -0400631 do {
632 /* Read in a new fragment marker if necessary */
633 /* Can we ever really expect to get completely empty fragments? */
634 if (xprt->tcp_flags & XPRT_COPY_RECM) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400635 xs_tcp_read_fraghdr(xprt, &desc);
Chuck Levera246b012005-08-11 16:25:23 -0400636 continue;
637 }
638 /* Read in the xid if necessary */
639 if (xprt->tcp_flags & XPRT_COPY_XID) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400640 xs_tcp_read_xid(xprt, &desc);
Chuck Levera246b012005-08-11 16:25:23 -0400641 continue;
642 }
643 /* Read in the request data */
644 if (xprt->tcp_flags & XPRT_COPY_DATA) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400645 xs_tcp_read_request(xprt, &desc);
Chuck Levera246b012005-08-11 16:25:23 -0400646 continue;
647 }
648 /* Skip over any trailing bytes on short reads */
Chuck Lever9903cd12005-08-11 16:25:26 -0400649 xs_tcp_read_discard(xprt, &desc);
Chuck Levera246b012005-08-11 16:25:23 -0400650 } while (desc.count);
Chuck Lever9903cd12005-08-11 16:25:26 -0400651 dprintk("RPC: xs_tcp_data_recv done\n");
Chuck Levera246b012005-08-11 16:25:23 -0400652 return len - desc.count;
653}
654
Chuck Lever9903cd12005-08-11 16:25:26 -0400655/**
656 * xs_tcp_data_ready - "data ready" callback for TCP sockets
657 * @sk: socket with data to read
658 * @bytes: how much data to read
659 *
660 */
661static void xs_tcp_data_ready(struct sock *sk, int bytes)
Chuck Levera246b012005-08-11 16:25:23 -0400662{
663 struct rpc_xprt *xprt;
664 read_descriptor_t rd_desc;
665
666 read_lock(&sk->sk_callback_lock);
Chuck Lever9903cd12005-08-11 16:25:26 -0400667 dprintk("RPC: xs_tcp_data_ready...\n");
668 if (!(xprt = xprt_from_sock(sk)))
Chuck Levera246b012005-08-11 16:25:23 -0400669 goto out;
Chuck Levera246b012005-08-11 16:25:23 -0400670 if (xprt->shutdown)
671 goto out;
672
Chuck Lever9903cd12005-08-11 16:25:26 -0400673 /* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
Chuck Levera246b012005-08-11 16:25:23 -0400674 rd_desc.arg.data = xprt;
675 rd_desc.count = 65536;
Chuck Lever9903cd12005-08-11 16:25:26 -0400676 tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
Chuck Levera246b012005-08-11 16:25:23 -0400677out:
678 read_unlock(&sk->sk_callback_lock);
679}
680
Chuck Lever9903cd12005-08-11 16:25:26 -0400681/**
682 * xs_tcp_state_change - callback to handle TCP socket state changes
683 * @sk: socket whose state has changed
684 *
685 */
686static void xs_tcp_state_change(struct sock *sk)
Chuck Levera246b012005-08-11 16:25:23 -0400687{
Chuck Lever9903cd12005-08-11 16:25:26 -0400688 struct rpc_xprt *xprt;
Chuck Levera246b012005-08-11 16:25:23 -0400689
690 read_lock(&sk->sk_callback_lock);
691 if (!(xprt = xprt_from_sock(sk)))
692 goto out;
Chuck Lever9903cd12005-08-11 16:25:26 -0400693 dprintk("RPC: xs_tcp_state_change client %p...\n", xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400694 dprintk("RPC: state %x conn %d dead %d zapped %d\n",
695 sk->sk_state, xprt_connected(xprt),
696 sock_flag(sk, SOCK_DEAD),
697 sock_flag(sk, SOCK_ZAPPED));
698
699 switch (sk->sk_state) {
700 case TCP_ESTABLISHED:
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400701 spin_lock_bh(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400702 if (!xprt_test_and_set_connected(xprt)) {
703 /* Reset TCP record info */
704 xprt->tcp_offset = 0;
705 xprt->tcp_reclen = 0;
706 xprt->tcp_copied = 0;
707 xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
Chuck Lever44fbac22005-08-11 16:25:44 -0400708 xprt_wake_pending_tasks(xprt, 0);
Chuck Levera246b012005-08-11 16:25:23 -0400709 }
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400710 spin_unlock_bh(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400711 break;
712 case TCP_SYN_SENT:
713 case TCP_SYN_RECV:
714 break;
715 default:
716 xprt_disconnect(xprt);
717 break;
718 }
719 out:
720 read_unlock(&sk->sk_callback_lock);
721}
722
Chuck Lever9903cd12005-08-11 16:25:26 -0400723/**
724 * xs_write_space - callback invoked when socket buffer space becomes
725 * available
726 * @sk: socket whose state has changed
727 *
Chuck Levera246b012005-08-11 16:25:23 -0400728 * Called when more output buffer space is available for this socket.
729 * We try not to wake our writers until they can make "significant"
730 * progress, otherwise we'll waste resources thrashing sock_sendmsg
731 * with a bunch of small requests.
732 */
Chuck Lever9903cd12005-08-11 16:25:26 -0400733static void xs_write_space(struct sock *sk)
Chuck Levera246b012005-08-11 16:25:23 -0400734{
Chuck Lever9903cd12005-08-11 16:25:26 -0400735 struct rpc_xprt *xprt;
736 struct socket *sock;
Chuck Levera246b012005-08-11 16:25:23 -0400737
738 read_lock(&sk->sk_callback_lock);
739 if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
740 goto out;
741 if (xprt->shutdown)
742 goto out;
743
744 /* Wait until we have enough socket memory */
745 if (xprt->stream) {
746 /* from net/core/stream.c:sk_stream_write_space */
747 if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
748 goto out;
749 } else {
750 /* from net/core/sock.c:sock_def_write_space */
751 if (!sock_writeable(sk))
752 goto out;
753 }
754
755 if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
756 goto out;
757
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400758 spin_lock_bh(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400759 if (xprt->snd_task)
760 rpc_wake_up_task(xprt->snd_task);
Chuck Lever4a0f8c02005-08-11 16:25:32 -0400761 spin_unlock_bh(&xprt->transport_lock);
Chuck Levera246b012005-08-11 16:25:23 -0400762out:
763 read_unlock(&sk->sk_callback_lock);
764}
765
Chuck Lever9903cd12005-08-11 16:25:26 -0400766/**
767 * xs_set_buffer_size - set send and receive limits
768 * @xprt: generic transport
769 *
770 * Set socket send and receive limits based on the
771 * sndsize and rcvsize fields in the generic transport
772 * structure. This applies only to UDP sockets.
Chuck Levera246b012005-08-11 16:25:23 -0400773 */
Chuck Lever9903cd12005-08-11 16:25:26 -0400774static void xs_set_buffer_size(struct rpc_xprt *xprt)
Chuck Levera246b012005-08-11 16:25:23 -0400775{
776 struct sock *sk = xprt->inet;
777
778 if (xprt->stream)
779 return;
780 if (xprt->rcvsize) {
781 sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
782 sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs * 2;
783 }
784 if (xprt->sndsize) {
785 sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
786 sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
787 sk->sk_write_space(sk);
788 }
789}
790
Chuck Lever9903cd12005-08-11 16:25:26 -0400791static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
Chuck Levera246b012005-08-11 16:25:23 -0400792{
793 struct sockaddr_in myaddr = {
794 .sin_family = AF_INET,
795 };
Chuck Lever9903cd12005-08-11 16:25:26 -0400796 int err, port;
Chuck Levera246b012005-08-11 16:25:23 -0400797
798 /* Were we already bound to a given port? Try to reuse it */
799 port = xprt->port;
800 do {
801 myaddr.sin_port = htons(port);
802 err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
803 sizeof(myaddr));
804 if (err == 0) {
805 xprt->port = port;
Chuck Lever9903cd12005-08-11 16:25:26 -0400806 dprintk("RPC: xs_bindresvport bound to port %u\n",
807 port);
Chuck Levera246b012005-08-11 16:25:23 -0400808 return 0;
809 }
810 if (--port == 0)
Chuck Lever9903cd12005-08-11 16:25:26 -0400811 port = XS_MAX_RESVPORT;
Chuck Levera246b012005-08-11 16:25:23 -0400812 } while (err == -EADDRINUSE && port != xprt->port);
813
Chuck Lever9903cd12005-08-11 16:25:26 -0400814 dprintk("RPC: can't bind to reserved port (%d).\n", -err);
Chuck Levera246b012005-08-11 16:25:23 -0400815 return err;
816}
817
Chuck Lever9903cd12005-08-11 16:25:26 -0400818static struct socket *xs_create(struct rpc_xprt *xprt, int proto, int resvport)
Chuck Levera246b012005-08-11 16:25:23 -0400819{
Chuck Lever9903cd12005-08-11 16:25:26 -0400820 struct socket *sock;
821 int type, err;
822
823 dprintk("RPC: xs_create(%s %d)\n",
824 (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
825
826 type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
827
828 if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
829 dprintk("RPC: can't create socket (%d).\n", -err);
830 return NULL;
831 }
832
833 /* If the caller has the capability, bind to a reserved port */
834 if (resvport && xs_bindresvport(xprt, sock) < 0)
835 goto failed;
836
837 return sock;
838
839failed:
840 sock_release(sock);
841 return NULL;
842}
843
844static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
845{
846 struct sock *sk = sock->sk;
Chuck Levera246b012005-08-11 16:25:23 -0400847
848 if (xprt->inet)
849 return;
850
851 write_lock_bh(&sk->sk_callback_lock);
852 sk->sk_user_data = xprt;
853 xprt->old_data_ready = sk->sk_data_ready;
854 xprt->old_state_change = sk->sk_state_change;
855 xprt->old_write_space = sk->sk_write_space;
856 if (xprt->prot == IPPROTO_UDP) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400857 sk->sk_data_ready = xs_udp_data_ready;
Chuck Levera246b012005-08-11 16:25:23 -0400858 sk->sk_no_check = UDP_CSUM_NORCV;
859 xprt_set_connected(xprt);
860 } else {
861 tcp_sk(sk)->nonagle = 1; /* disable Nagle's algorithm */
Chuck Lever9903cd12005-08-11 16:25:26 -0400862 sk->sk_data_ready = xs_tcp_data_ready;
863 sk->sk_state_change = xs_tcp_state_change;
Chuck Levera246b012005-08-11 16:25:23 -0400864 xprt_clear_connected(xprt);
865 }
Chuck Lever9903cd12005-08-11 16:25:26 -0400866 sk->sk_write_space = xs_write_space;
Chuck Levera246b012005-08-11 16:25:23 -0400867
868 /* Reset to new socket */
869 xprt->sock = sock;
870 xprt->inet = sk;
871 write_unlock_bh(&sk->sk_callback_lock);
872
873 return;
874}
875
Chuck Lever9903cd12005-08-11 16:25:26 -0400876/**
877 * xs_connect_worker - try to connect a socket to a remote endpoint
878 * @args: RPC transport to connect
879 *
880 * Invoked by a work queue tasklet.
Chuck Levera246b012005-08-11 16:25:23 -0400881 */
Chuck Lever9903cd12005-08-11 16:25:26 -0400882static void xs_connect_worker(void *args)
Chuck Levera246b012005-08-11 16:25:23 -0400883{
884 struct rpc_xprt *xprt = (struct rpc_xprt *)args;
885 struct socket *sock = xprt->sock;
886 int status = -EIO;
887
888 if (xprt->shutdown || xprt->addr.sin_port == 0)
889 goto out;
890
Chuck Lever9903cd12005-08-11 16:25:26 -0400891 dprintk("RPC: xs_connect_worker xprt %p\n", xprt);
892
Chuck Levera246b012005-08-11 16:25:23 -0400893 /*
894 * Start by resetting any existing state
895 */
Chuck Lever9903cd12005-08-11 16:25:26 -0400896 xs_close(xprt);
897 sock = xs_create(xprt, xprt->prot, xprt->resvport);
Chuck Levera246b012005-08-11 16:25:23 -0400898 if (sock == NULL) {
899 /* couldn't create socket or bind to reserved port;
900 * this is likely a permanent error, so cause an abort */
901 goto out;
902 }
Chuck Lever9903cd12005-08-11 16:25:26 -0400903 xs_bind(xprt, sock);
904 xs_set_buffer_size(xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400905
906 status = 0;
907 if (!xprt->stream)
908 goto out;
909
910 /*
911 * Tell the socket layer to start connecting...
912 */
913 status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
914 sizeof(xprt->addr), O_NONBLOCK);
915 dprintk("RPC: %p connect status %d connected %d sock state %d\n",
916 xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
917 if (status < 0) {
918 switch (status) {
919 case -EINPROGRESS:
920 case -EALREADY:
921 goto out_clear;
922 }
923 }
924out:
Chuck Lever44fbac22005-08-11 16:25:44 -0400925 xprt_wake_pending_tasks(xprt, status);
Chuck Levera246b012005-08-11 16:25:23 -0400926out_clear:
Chuck Lever2226feb2005-08-11 16:25:38 -0400927 xprt_clear_connecting(xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400928}
929
Chuck Lever9903cd12005-08-11 16:25:26 -0400930/**
931 * xs_connect - connect a socket to a remote endpoint
932 * @task: address of RPC task that manages state of connect request
933 *
934 * TCP: If the remote end dropped the connection, delay reconnecting.
935 */
936static void xs_connect(struct rpc_task *task)
Chuck Levera246b012005-08-11 16:25:23 -0400937{
938 struct rpc_xprt *xprt = task->tk_xprt;
939
Chuck Lever2226feb2005-08-11 16:25:38 -0400940 if (!xprt_test_and_set_connecting(xprt)) {
Chuck Lever9903cd12005-08-11 16:25:26 -0400941 if (xprt->sock != NULL) {
942 dprintk("RPC: xs_connect delayed xprt %p\n", xprt);
Chuck Lever55aa4f52005-08-11 16:25:47 -0400943 schedule_delayed_work(&xprt->connect_worker,
Chuck Levera246b012005-08-11 16:25:23 -0400944 RPC_REESTABLISH_TIMEOUT);
Chuck Lever9903cd12005-08-11 16:25:26 -0400945 } else {
946 dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
Chuck Lever55aa4f52005-08-11 16:25:47 -0400947 schedule_work(&xprt->connect_worker);
Chuck Levera246b012005-08-11 16:25:23 -0400948 /* flush_scheduled_work can sleep... */
949 if (!RPC_IS_ASYNC(task))
950 flush_scheduled_work();
951 }
952 }
953}
954
Chuck Lever9903cd12005-08-11 16:25:26 -0400955static struct rpc_xprt_ops xs_ops = {
956 .set_buffer_size = xs_set_buffer_size,
957 .connect = xs_connect,
958 .send_request = xs_send_request,
959 .close = xs_close,
960 .destroy = xs_destroy,
Chuck Levera246b012005-08-11 16:25:23 -0400961};
962
963extern unsigned int xprt_udp_slot_table_entries;
964extern unsigned int xprt_tcp_slot_table_entries;
965
Chuck Lever9903cd12005-08-11 16:25:26 -0400966/**
967 * xs_setup_udp - Set up transport to use a UDP socket
968 * @xprt: transport to set up
969 * @to: timeout parameters
970 *
971 */
Chuck Levera246b012005-08-11 16:25:23 -0400972int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
973{
974 size_t slot_table_size;
975
976 dprintk("RPC: setting up udp-ipv4 transport...\n");
977
978 xprt->max_reqs = xprt_udp_slot_table_entries;
979 slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
980 xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
981 if (xprt->slot == NULL)
982 return -ENOMEM;
983 memset(xprt->slot, 0, slot_table_size);
984
985 xprt->prot = IPPROTO_UDP;
Chuck Lever9903cd12005-08-11 16:25:26 -0400986 xprt->port = XS_MAX_RESVPORT;
Chuck Levera246b012005-08-11 16:25:23 -0400987 xprt->stream = 0;
988 xprt->nocong = 0;
989 xprt->cwnd = RPC_INITCWND;
990 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
991 /* XXX: header size can vary due to auth type, IPv6, etc. */
992 xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
993
Chuck Lever55aa4f52005-08-11 16:25:47 -0400994 INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
Chuck Levera246b012005-08-11 16:25:23 -0400995
Chuck Lever9903cd12005-08-11 16:25:26 -0400996 xprt->ops = &xs_ops;
Chuck Levera246b012005-08-11 16:25:23 -0400997
998 if (to)
999 xprt->timeout = *to;
1000 else
Chuck Lever9903cd12005-08-11 16:25:26 -04001001 xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
Chuck Levera246b012005-08-11 16:25:23 -04001002
1003 return 0;
1004}
1005
Chuck Lever9903cd12005-08-11 16:25:26 -04001006/**
1007 * xs_setup_tcp - Set up transport to use a TCP socket
1008 * @xprt: transport to set up
1009 * @to: timeout parameters
1010 *
1011 */
Chuck Levera246b012005-08-11 16:25:23 -04001012int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
1013{
1014 size_t slot_table_size;
1015
1016 dprintk("RPC: setting up tcp-ipv4 transport...\n");
1017
1018 xprt->max_reqs = xprt_tcp_slot_table_entries;
1019 slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
1020 xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
1021 if (xprt->slot == NULL)
1022 return -ENOMEM;
1023 memset(xprt->slot, 0, slot_table_size);
1024
1025 xprt->prot = IPPROTO_TCP;
Chuck Lever9903cd12005-08-11 16:25:26 -04001026 xprt->port = XS_MAX_RESVPORT;
Chuck Levera246b012005-08-11 16:25:23 -04001027 xprt->stream = 1;
1028 xprt->nocong = 1;
1029 xprt->cwnd = RPC_MAXCWND(xprt);
1030 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
1031 xprt->max_payload = (1U << 31) - 1;
1032
Chuck Lever55aa4f52005-08-11 16:25:47 -04001033 INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
Chuck Levera246b012005-08-11 16:25:23 -04001034
Chuck Lever9903cd12005-08-11 16:25:26 -04001035 xprt->ops = &xs_ops;
Chuck Levera246b012005-08-11 16:25:23 -04001036
1037 if (to)
1038 xprt->timeout = *to;
1039 else
Chuck Lever9903cd12005-08-11 16:25:26 -04001040 xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
Chuck Levera246b012005-08-11 16:25:23 -04001041
1042 return 0;
1043}