Blame view

net/sunrpc/xprtsock.c 76.9 KB
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1
2
3
4
5
  /*
   * linux/net/sunrpc/xprtsock.c
   *
   * Client-side transport implementation for sockets.
   *
113aa838e   Alan Cox   net: Rationalise ...
6
7
   * TCP callback races fixes (C) 1998 Red Hat
   * TCP send fixes (C) 1998 Red Hat
a246b0105   Chuck Lever   [PATCH] RPC: intr...
8
9
10
11
12
13
   * TCP NFS related read + write fixes
   *  (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
   *
   * Rewrite of larges part of the code in order to stabilize TCP stuff.
   * Fix behaviour when socket buffer is full.
   *  (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no>
55aa4f58a   Chuck Lever   [PATCH] RPC: clie...
14
15
   *
   * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com>
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
16
17
18
   *
   * IPv6 support contributed by Gilles Quillard, Bull Open Source, 2005.
   *   <gilles.quillard@bull.net>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
19
20
21
   */
  
  #include <linux/types.h>
176e21ee2   Chuck Lever   SUNRPC: Support f...
22
  #include <linux/string.h>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
23
  #include <linux/slab.h>
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
24
  #include <linux/module.h>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
25
  #include <linux/capability.h>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
26
27
28
29
30
31
  #include <linux/pagemap.h>
  #include <linux/errno.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/net.h>
  #include <linux/mm.h>
176e21ee2   Chuck Lever   SUNRPC: Support f...
32
  #include <linux/un.h>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
33
34
35
  #include <linux/udp.h>
  #include <linux/tcp.h>
  #include <linux/sunrpc/clnt.h>
021071483   Chuck Lever   SUNRPC: switchabl...
36
  #include <linux/sunrpc/sched.h>
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
37
  #include <linux/sunrpc/svcsock.h>
49c36fcc4   \"Talpey, Thomas\   SUNRPC: rearrange...
38
  #include <linux/sunrpc/xprtsock.h>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
39
  #include <linux/file.h>
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
40
  #ifdef CONFIG_SUNRPC_BACKCHANNEL
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
41
42
  #include <linux/sunrpc/bc_xprt.h>
  #endif
a246b0105   Chuck Lever   [PATCH] RPC: intr...
43
44
45
46
47
  
  #include <net/sock.h>
  #include <net/checksum.h>
  #include <net/udp.h>
  #include <net/tcp.h>
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
48
  #include "sunrpc.h"
176e21ee2   Chuck Lever   SUNRPC: Support f...
49
50
  
  static void xs_close(struct rpc_xprt *xprt);
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
51
  /*
c556b7549   Chuck Lever   SUNRPC: allow sun...
52
53
54
   * xprtsock tunables
   */
  unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
55
56
  unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE;
  unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE;
c556b7549   Chuck Lever   SUNRPC: allow sun...
57
58
59
  
  unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
  unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
60
  #define XS_TCP_LINGER_TO	(15U * HZ)
25fe6142a   Trond Myklebust   SUNRPC: Add a sys...
61
  static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO;
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
62

c556b7549   Chuck Lever   SUNRPC: allow sun...
63
  /*
fbf76683f   Chuck Lever   SUNRPC: relocate ...
64
65
66
67
68
69
70
71
72
73
74
75
   * We can register our own files under /proc/sys/sunrpc by
   * calling register_sysctl_table() again.  The files in that
   * directory become the union of all files registered there.
   *
   * We simply need to make sure that we don't collide with
   * someone else's file names!
   */
  
  #ifdef RPC_DEBUG
  
  static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
  static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
76
  static unsigned int max_tcp_slot_table_limit = RPC_MAX_SLOT_TABLE_LIMIT;
fbf76683f   Chuck Lever   SUNRPC: relocate ...
77
78
79
80
81
82
83
84
85
86
87
  static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
  static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
  
  static struct ctl_table_header *sunrpc_table_header;
  
  /*
   * FIXME: changing the UDP slot table size should also resize the UDP
   *        socket buffers for existing UDP transports
   */
  static ctl_table xs_tunables_table[] = {
  	{
fbf76683f   Chuck Lever   SUNRPC: relocate ...
88
89
90
91
  		.procname	= "udp_slot_table_entries",
  		.data		= &xprt_udp_slot_table_entries,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
92
  		.proc_handler	= proc_dointvec_minmax,
fbf76683f   Chuck Lever   SUNRPC: relocate ...
93
94
95
96
  		.extra1		= &min_slot_table_size,
  		.extra2		= &max_slot_table_size
  	},
  	{
fbf76683f   Chuck Lever   SUNRPC: relocate ...
97
98
99
100
  		.procname	= "tcp_slot_table_entries",
  		.data		= &xprt_tcp_slot_table_entries,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
101
  		.proc_handler	= proc_dointvec_minmax,
fbf76683f   Chuck Lever   SUNRPC: relocate ...
102
103
104
105
  		.extra1		= &min_slot_table_size,
  		.extra2		= &max_slot_table_size
  	},
  	{
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
106
107
108
109
110
111
112
113
114
  		.procname	= "tcp_max_slot_table_entries",
  		.data		= &xprt_max_tcp_slot_table_entries,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
  		.proc_handler	= proc_dointvec_minmax,
  		.extra1		= &min_slot_table_size,
  		.extra2		= &max_tcp_slot_table_limit
  	},
  	{
fbf76683f   Chuck Lever   SUNRPC: relocate ...
115
116
117
118
  		.procname	= "min_resvport",
  		.data		= &xprt_min_resvport,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
119
  		.proc_handler	= proc_dointvec_minmax,
fbf76683f   Chuck Lever   SUNRPC: relocate ...
120
121
122
123
  		.extra1		= &xprt_min_resvport_limit,
  		.extra2		= &xprt_max_resvport_limit
  	},
  	{
fbf76683f   Chuck Lever   SUNRPC: relocate ...
124
125
126
127
  		.procname	= "max_resvport",
  		.data		= &xprt_max_resvport,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
128
  		.proc_handler	= proc_dointvec_minmax,
fbf76683f   Chuck Lever   SUNRPC: relocate ...
129
130
131
132
  		.extra1		= &xprt_min_resvport_limit,
  		.extra2		= &xprt_max_resvport_limit
  	},
  	{
25fe6142a   Trond Myklebust   SUNRPC: Add a sys...
133
134
135
136
  		.procname	= "tcp_fin_timeout",
  		.data		= &xs_tcp_fin_timeout,
  		.maxlen		= sizeof(xs_tcp_fin_timeout),
  		.mode		= 0644,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
137
  		.proc_handler	= proc_dointvec_jiffies,
fbf76683f   Chuck Lever   SUNRPC: relocate ...
138
  	},
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
139
  	{ },
fbf76683f   Chuck Lever   SUNRPC: relocate ...
140
141
142
143
  };
  
  static ctl_table sunrpc_table[] = {
  	{
fbf76683f   Chuck Lever   SUNRPC: relocate ...
144
145
146
147
  		.procname	= "sunrpc",
  		.mode		= 0555,
  		.child		= xs_tunables_table
  	},
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
148
  	{ },
fbf76683f   Chuck Lever   SUNRPC: relocate ...
149
150
151
152
153
  };
  
  #endif
  
  /*
03bf4b707   Chuck Lever   [PATCH] RPC: para...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
   * Wait duration for a reply from the RPC portmapper.
   */
  #define XS_BIND_TO		(60U * HZ)
  
  /*
   * Delay if a UDP socket connect error occurs.  This is most likely some
   * kind of resource problem on the local host.
   */
  #define XS_UDP_REEST_TO		(2U * HZ)
  
  /*
   * The reestablish timeout allows clients to delay for a bit before attempting
   * to reconnect to a server that just dropped our connection.
   *
   * We implement an exponential backoff when trying to reestablish a TCP
   * transport connection with the server.  Some servers like to drop a TCP
   * connection when they are overworked, so we start with a short timeout and
   * increase over time if the server is down or not responding.
   */
  #define XS_TCP_INIT_REEST_TO	(3U * HZ)
  #define XS_TCP_MAX_REEST_TO	(5U * 60 * HZ)
  
  /*
   * TCP idle timeout; client drops the transport socket if it is idle
   * for this long.  Note that we also timeout UDP sockets to prevent
   * holding port numbers when there is no RPC traffic.
   */
  #define XS_IDLE_DISC_TO		(5U * 60 * HZ)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
182
183
  #ifdef RPC_DEBUG
  # undef  RPC_DEBUG_DATA
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
184
  # define RPCDBG_FACILITY	RPCDBG_TRANS
a246b0105   Chuck Lever   [PATCH] RPC: intr...
185
  #endif
a246b0105   Chuck Lever   [PATCH] RPC: intr...
186
  #ifdef RPC_DEBUG_DATA
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
187
  static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
188
  {
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
189
190
  	u8 *buf = (u8 *) packet;
  	int j;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
191

46121cf7d   Chuck Lever   SUNRPC: fix print...
192
193
  	dprintk("RPC:       %s
  ", msg);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  	for (j = 0; j < count && j < 128; j += 4) {
  		if (!(j & 31)) {
  			if (j)
  				dprintk("
  ");
  			dprintk("0x%04x ", j);
  		}
  		dprintk("%02x%02x%02x%02x ",
  			buf[j], buf[j+1], buf[j+2], buf[j+3]);
  	}
  	dprintk("
  ");
  }
  #else
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
208
  static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
209
210
211
212
  {
  	/* NOP */
  }
  #endif
ffc2e518c   Chuck Lever   SUNRPC: Allocate ...
213
214
  struct sock_xprt {
  	struct rpc_xprt		xprt;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
215
216
217
218
219
220
  
  	/*
  	 * Network layer
  	 */
  	struct socket *		sock;
  	struct sock *		inet;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
221
222
223
224
225
  
  	/*
  	 * State of TCP reply receive
  	 */
  	__be32			tcp_fraghdr,
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
226
227
  				tcp_xid,
  				tcp_calldir;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
228
229
230
231
232
233
  
  	u32			tcp_offset,
  				tcp_reclen;
  
  	unsigned long		tcp_copied,
  				tcp_flags;
c84754618   Chuck Lever   SUNRPC: Move rpc_...
234
235
236
237
  
  	/*
  	 * Connection of transports
  	 */
34161db6b   Trond Myklebust   Merge branch 'mas...
238
  	struct delayed_work	connect_worker;
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
239
240
  	struct sockaddr_storage	srcaddr;
  	unsigned short		srcport;
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
241
242
243
244
245
246
  
  	/*
  	 * UDP socket buffer size parameters
  	 */
  	size_t			rcvsize,
  				sndsize;
314dfd798   Chuck Lever   SUNRPC: move save...
247
248
249
250
251
252
253
  
  	/*
  	 * Saved socket callback addresses
  	 */
  	void			(*old_data_ready)(struct sock *, int);
  	void			(*old_state_change)(struct sock *);
  	void			(*old_write_space)(struct sock *);
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
254
  	void			(*old_error_report)(struct sock *);
ffc2e518c   Chuck Lever   SUNRPC: Allocate ...
255
  };
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
256
257
258
259
260
261
262
  /*
   * TCP receive state flags
   */
  #define TCP_RCV_LAST_FRAG	(1UL << 0)
  #define TCP_RCV_COPY_FRAGHDR	(1UL << 1)
  #define TCP_RCV_COPY_XID	(1UL << 2)
  #define TCP_RCV_COPY_DATA	(1UL << 3)
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
263
264
  #define TCP_RCV_READ_CALLDIR	(1UL << 4)
  #define TCP_RCV_COPY_CALLDIR	(1UL << 5)
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
265
266
267
268
  
  /*
   * TCP RPC flags
   */
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
269
  #define TCP_RPC_REPLY		(1UL << 6)
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
270

95392c593   Chuck Lever   SUNRPC: Add a hel...
271
272
273
274
  static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
  {
  	return (struct sockaddr *) &xprt->addr;
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
275
276
277
278
  static inline struct sockaddr_un *xs_addr_un(struct rpc_xprt *xprt)
  {
  	return (struct sockaddr_un *) &xprt->addr;
  }
95392c593   Chuck Lever   SUNRPC: Add a hel...
279
  static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt)
edb267a68   Chuck Lever   SUNRPC: add xprt ...
280
  {
95392c593   Chuck Lever   SUNRPC: Add a hel...
281
282
283
284
285
286
287
  	return (struct sockaddr_in *) &xprt->addr;
  }
  
  static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt)
  {
  	return (struct sockaddr_in6 *) &xprt->addr;
  }
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
288
  static void xs_format_common_peer_addresses(struct rpc_xprt *xprt)
edb267a68   Chuck Lever   SUNRPC: add xprt ...
289
  {
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
290
  	struct sockaddr *sap = xs_addr(xprt);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
291
292
  	struct sockaddr_in6 *sin6;
  	struct sockaddr_in *sin;
176e21ee2   Chuck Lever   SUNRPC: Support f...
293
  	struct sockaddr_un *sun;
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
294
  	char buf[128];
edb267a68   Chuck Lever   SUNRPC: add xprt ...
295

9dc3b095b   Chuck Lever   SUNRPC: Update xp...
296
  	switch (sap->sa_family) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
297
298
299
300
301
302
  	case AF_LOCAL:
  		sun = xs_addr_un(xprt);
  		strlcpy(buf, sun->sun_path, sizeof(buf));
  		xprt->address_strings[RPC_DISPLAY_ADDR] =
  						kstrdup(buf, GFP_KERNEL);
  		break;
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
303
  	case AF_INET:
176e21ee2   Chuck Lever   SUNRPC: Support f...
304
305
306
  		(void)rpc_ntop(sap, buf, sizeof(buf));
  		xprt->address_strings[RPC_DISPLAY_ADDR] =
  						kstrdup(buf, GFP_KERNEL);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
307
  		sin = xs_addr_in(xprt);
fc0b57916   Joe Perches   net/sunrpc: Remov...
308
  		snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr));
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
309
310
  		break;
  	case AF_INET6:
176e21ee2   Chuck Lever   SUNRPC: Support f...
311
312
313
  		(void)rpc_ntop(sap, buf, sizeof(buf));
  		xprt->address_strings[RPC_DISPLAY_ADDR] =
  						kstrdup(buf, GFP_KERNEL);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
314
  		sin6 = xs_addr_in6(xprt);
fc0b57916   Joe Perches   net/sunrpc: Remov...
315
  		snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
316
317
318
  		break;
  	default:
  		BUG();
756805e7a   Chuck Lever   SUNRPC: Add suppo...
319
  	}
176e21ee2   Chuck Lever   SUNRPC: Support f...
320

9dc3b095b   Chuck Lever   SUNRPC: Update xp...
321
  	xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
322
  }
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
323
  static void xs_format_common_peer_ports(struct rpc_xprt *xprt)
4b6473fba   Chuck Lever   SUNRPC: add a fun...
324
  {
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
325
326
  	struct sockaddr *sap = xs_addr(xprt);
  	char buf[128];
4b6473fba   Chuck Lever   SUNRPC: add a fun...
327

81160e66c   Joe Perches   net/sunrpc: Conve...
328
  	snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap));
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
329
  	xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL);
4b6473fba   Chuck Lever   SUNRPC: add a fun...
330

81160e66c   Joe Perches   net/sunrpc: Conve...
331
  	snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap));
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
332
333
  	xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);
  }
4b6473fba   Chuck Lever   SUNRPC: add a fun...
334

9dc3b095b   Chuck Lever   SUNRPC: Update xp...
335
336
337
  static void xs_format_peer_addresses(struct rpc_xprt *xprt,
  				     const char *protocol,
  				     const char *netid)
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
338
  {
b454ae906   Chuck Lever   SUNRPC: fewer con...
339
  	xprt->address_strings[RPC_DISPLAY_PROTO] = protocol;
b454ae906   Chuck Lever   SUNRPC: fewer con...
340
  	xprt->address_strings[RPC_DISPLAY_NETID] = netid;
c877b849d   Chuck Lever   SUNRPC: Use rpc_n...
341
  	xs_format_common_peer_addresses(xprt);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
342
  	xs_format_common_peer_ports(xprt);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
343
  }
4b6473fba   Chuck Lever   SUNRPC: add a fun...
344

9dc3b095b   Chuck Lever   SUNRPC: Update xp...
345
  static void xs_update_peer_port(struct rpc_xprt *xprt)
4b6473fba   Chuck Lever   SUNRPC: add a fun...
346
  {
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
347
348
  	kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]);
  	kfree(xprt->address_strings[RPC_DISPLAY_PORT]);
4417c8c41   \"Talpey, Thomas\   SUNRPC: export pe...
349

9dc3b095b   Chuck Lever   SUNRPC: Update xp...
350
  	xs_format_common_peer_ports(xprt);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
351
352
353
354
  }
  
  static void xs_free_peer_addresses(struct rpc_xprt *xprt)
  {
33e01dc7f   Chuck Lever   SUNRPC: Clean up ...
355
356
357
358
359
360
361
362
363
364
  	unsigned int i;
  
  	for (i = 0; i < RPC_DISPLAY_MAX; i++)
  		switch (i) {
  		case RPC_DISPLAY_PROTO:
  		case RPC_DISPLAY_NETID:
  			continue;
  		default:
  			kfree(xprt->address_strings[i]);
  		}
edb267a68   Chuck Lever   SUNRPC: add xprt ...
365
  }
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
366
  #define XS_SENDMSG_FLAGS	(MSG_DONTWAIT | MSG_NOSIGNAL)
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
367
  static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, struct kvec *vec, unsigned int base, int more)
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
368
  {
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
369
370
371
  	struct msghdr msg = {
  		.msg_name	= addr,
  		.msg_namelen	= addrlen,
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
372
373
374
375
376
  		.msg_flags	= XS_SENDMSG_FLAGS | (more ? MSG_MORE : 0),
  	};
  	struct kvec iov = {
  		.iov_base	= vec->iov_base + base,
  		.iov_len	= vec->iov_len - base,
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
377
  	};
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
378
  	if (iov.iov_len != 0)
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
379
380
381
  		return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
  	return kernel_sendmsg(sock, &msg, NULL, 0, 0);
  }
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
382
  static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more)
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
383
  {
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
384
385
386
387
388
389
390
391
392
393
394
  	struct page **ppage;
  	unsigned int remainder;
  	int err, sent = 0;
  
  	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;
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
395

24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  		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;
b4b5cc85e   Chuck Lever   [PATCH] RPC: Redu...
411
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
412
413
414
415
416
417
418
419
  /**
   * xs_sendpages - write pages directly to a socket
   * @sock: socket to send on
   * @addr: UDP only -- address of destination
   * @addrlen: UDP only -- length of destination address
   * @xdr: buffer containing this request
   * @base: starting position in the buffer
   *
a246b0105   Chuck Lever   [PATCH] RPC: intr...
420
   */
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
421
  static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
422
  {
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
423
424
  	unsigned int remainder = xdr->len - base;
  	int err, sent = 0;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
425

262965f53   Chuck Lever   [PATCH] RPC: sepa...
426
  	if (unlikely(!sock))
fba91afbe   Trond Myklebust   SUNRPC: Fix an Oo...
427
  		return -ENOTSOCK;
262965f53   Chuck Lever   [PATCH] RPC: sepa...
428
429
  
  	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
430
431
432
433
  	if (base != 0) {
  		addr = NULL;
  		addrlen = 0;
  	}
262965f53   Chuck Lever   [PATCH] RPC: sepa...
434

24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
435
436
437
438
439
  	if (base < xdr->head[0].iov_len || addr != NULL) {
  		unsigned int len = xdr->head[0].iov_len - base;
  		remainder -= len;
  		err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0);
  		if (remainder == 0 || err != len)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
440
  			goto out;
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
441
  		sent += err;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
442
443
  		base = 0;
  	} else
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
444
  		base -= xdr->head[0].iov_len;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
445

24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
446
447
448
449
450
  	if (base < xdr->page_len) {
  		unsigned int len = xdr->page_len - base;
  		remainder -= len;
  		err = xs_send_pagedata(sock, xdr, base, remainder != 0);
  		if (remainder == 0 || err != len)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
451
  			goto out;
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
452
  		sent += err;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
453
  		base = 0;
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
454
455
456
457
458
459
  	} else
  		base -= xdr->page_len;
  
  	if (base >= xdr->tail[0].iov_len)
  		return sent;
  	err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
460
  out:
24c5684b6   Trond Myklebust   SUNRPC: Clean up ...
461
462
463
464
465
  	if (sent == 0)
  		return err;
  	if (err > 0)
  		sent += err;
  	return sent;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
466
  }
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
467
468
469
470
471
472
473
  static void xs_nospace_callback(struct rpc_task *task)
  {
  	struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
  
  	transport->inet->sk_write_pending--;
  	clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
474
  /**
262965f53   Chuck Lever   [PATCH] RPC: sepa...
475
476
   * xs_nospace - place task on wait queue if transmit was incomplete
   * @task: task to put to sleep
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
477
   *
a246b0105   Chuck Lever   [PATCH] RPC: intr...
478
   */
5e3771ce2   Trond Myklebust   SUNRPC: Ensure th...
479
  static int xs_nospace(struct rpc_task *task)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
480
  {
262965f53   Chuck Lever   [PATCH] RPC: sepa...
481
482
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = req->rq_xprt;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
483
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
24ca9a847   Trond Myklebust   SUNRPC: Ensure we...
484
  	int ret = -EAGAIN;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
485

46121cf7d   Chuck Lever   SUNRPC: fix print...
486
487
  	dprintk("RPC: %5u xmit incomplete (%u left of %u)
  ",
262965f53   Chuck Lever   [PATCH] RPC: sepa...
488
489
  			task->tk_pid, req->rq_slen - req->rq_bytes_sent,
  			req->rq_slen);
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
  	/* Protect against races with write_space */
  	spin_lock_bh(&xprt->transport_lock);
  
  	/* Don't race with disconnect */
  	if (xprt_connected(xprt)) {
  		if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
  			/*
  			 * Notify TCP that we're limited by the application
  			 * window size
  			 */
  			set_bit(SOCK_NOSPACE, &transport->sock->flags);
  			transport->inet->sk_write_pending++;
  			/* ...and wait for more buffer space */
  			xprt_wait_for_buffer_space(task, xs_nospace_callback);
  		}
  	} else {
  		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
5e3771ce2   Trond Myklebust   SUNRPC: Ensure th...
507
  		ret = -ENOTCONN;
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
508
  	}
262965f53   Chuck Lever   [PATCH] RPC: sepa...
509

b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
510
  	spin_unlock_bh(&xprt->transport_lock);
5e3771ce2   Trond Myklebust   SUNRPC: Ensure th...
511
  	return ret;
262965f53   Chuck Lever   [PATCH] RPC: sepa...
512
  }
61677eeec   Chuck Lever   SUNRPC: Rename xs...
513
514
515
516
517
518
519
520
521
  /*
   * Construct a stream transport record marker in @buf.
   */
  static inline void xs_encode_stream_record_marker(struct xdr_buf *buf)
  {
  	u32 reclen = buf->len - sizeof(rpc_fraghdr);
  	rpc_fraghdr *base = buf->head[0].iov_base;
  	*base = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | reclen);
  }
262965f53   Chuck Lever   [PATCH] RPC: sepa...
522
  /**
176e21ee2   Chuck Lever   SUNRPC: Support f...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
   * xs_local_send_request - write an RPC request to an AF_LOCAL socket
   * @task: RPC task that manages the state of an RPC request
   *
   * Return values:
   *        0:	The request has been sent
   *   EAGAIN:	The socket was blocked, please call again later to
   *		complete the request
   * ENOTCONN:	Caller needs to invoke connect logic then call again
   *    other:	Some other error occured, the request was not sent
   */
  static int xs_local_send_request(struct rpc_task *task)
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = req->rq_xprt;
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
  	struct xdr_buf *xdr = &req->rq_snd_buf;
  	int status;
  
  	xs_encode_stream_record_marker(&req->rq_snd_buf);
  
  	xs_pktdump("packet data:",
  			req->rq_svec->iov_base, req->rq_svec->iov_len);
  
  	status = xs_sendpages(transport->sock, NULL, 0,
  						xdr, req->rq_bytes_sent);
  	dprintk("RPC:       %s(%u) = %d
  ",
  			__func__, xdr->len - req->rq_bytes_sent, status);
  	if (likely(status >= 0)) {
  		req->rq_bytes_sent += status;
  		req->rq_xmit_bytes_sent += status;
  		if (likely(req->rq_bytes_sent >= req->rq_slen)) {
  			req->rq_bytes_sent = 0;
  			return 0;
  		}
  		status = -EAGAIN;
  	}
  
  	switch (status) {
  	case -EAGAIN:
  		status = xs_nospace(task);
  		break;
  	default:
  		dprintk("RPC:       sendmsg returned unrecognized error %d
  ",
  			-status);
  	case -EPIPE:
  		xs_close(xprt);
  		status = -ENOTCONN;
  	}
  
  	return status;
  }
  
  /**
262965f53   Chuck Lever   [PATCH] RPC: sepa...
579
580
581
582
583
584
585
586
   * xs_udp_send_request - write an RPC request to a UDP socket
   * @task: address of RPC task that manages the state of an RPC request
   *
   * Return values:
   *        0:	The request has been sent
   *   EAGAIN:	The socket was blocked, please call again later to
   *		complete the request
   * ENOTCONN:	Caller needs to invoke connect logic then call again
25985edce   Lucas De Marchi   Fix common misspe...
587
   *    other:	Some other error occurred, the request was not sent
262965f53   Chuck Lever   [PATCH] RPC: sepa...
588
589
590
591
592
   */
  static int xs_udp_send_request(struct rpc_task *task)
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = req->rq_xprt;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
593
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
262965f53   Chuck Lever   [PATCH] RPC: sepa...
594
595
  	struct xdr_buf *xdr = &req->rq_snd_buf;
  	int status;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
596

9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
597
  	xs_pktdump("packet data:",
a246b0105   Chuck Lever   [PATCH] RPC: intr...
598
599
  				req->rq_svec->iov_base,
  				req->rq_svec->iov_len);
01d37c428   Trond Myklebust   SUNRPC: xprt_conn...
600
601
  	if (!xprt_bound(xprt))
  		return -ENOTCONN;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
602
  	status = xs_sendpages(transport->sock,
95392c593   Chuck Lever   SUNRPC: Add a hel...
603
  			      xs_addr(xprt),
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
604
605
  			      xprt->addrlen, xdr,
  			      req->rq_bytes_sent);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
606

46121cf7d   Chuck Lever   SUNRPC: fix print...
607
608
  	dprintk("RPC:       xs_udp_send_request(%u) = %d
  ",
262965f53   Chuck Lever   [PATCH] RPC: sepa...
609
  			xdr->len - req->rq_bytes_sent, status);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
610

2199700f1   Trond Myklebust   SUNRPC: Fix buggy...
611
  	if (status >= 0) {
d60dbb20a   Trond Myklebust   SUNRPC: Move the ...
612
  		req->rq_xmit_bytes_sent += status;
2199700f1   Trond Myklebust   SUNRPC: Fix buggy...
613
614
615
  		if (status >= req->rq_slen)
  			return 0;
  		/* Still some bytes left; set up for a retry later. */
262965f53   Chuck Lever   [PATCH] RPC: sepa...
616
  		status = -EAGAIN;
2199700f1   Trond Myklebust   SUNRPC: Fix buggy...
617
  	}
a246b0105   Chuck Lever   [PATCH] RPC: intr...
618

262965f53   Chuck Lever   [PATCH] RPC: sepa...
619
  	switch (status) {
fba91afbe   Trond Myklebust   SUNRPC: Fix an Oo...
620
621
622
623
  	case -ENOTSOCK:
  		status = -ENOTCONN;
  		/* Should we call xs_close() here? */
  		break;
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
624
  	case -EAGAIN:
5e3771ce2   Trond Myklebust   SUNRPC: Ensure th...
625
  		status = xs_nospace(task);
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
626
  		break;
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
627
628
629
630
  	default:
  		dprintk("RPC:       sendmsg returned unrecognized error %d
  ",
  			-status);
262965f53   Chuck Lever   [PATCH] RPC: sepa...
631
632
  	case -ENETUNREACH:
  	case -EPIPE:
a246b0105   Chuck Lever   [PATCH] RPC: intr...
633
634
  	case -ECONNREFUSED:
  		/* When the server has died, an ICMP port unreachable message
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
635
  		 * prompts ECONNREFUSED. */
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
636
  		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
637
  	}
5fe46e9d7   Bian Naimeng   rpc client can no...
638

262965f53   Chuck Lever   [PATCH] RPC: sepa...
639
  	return status;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
640
  }
e06799f95   Trond Myklebust   SUNRPC: Use shutd...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  /**
   * xs_tcp_shutdown - gracefully shut down a TCP socket
   * @xprt: transport
   *
   * Initiates a graceful shutdown of the TCP socket by calling the
   * equivalent of shutdown(SHUT_WR);
   */
  static void xs_tcp_shutdown(struct rpc_xprt *xprt)
  {
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
  	struct socket *sock = transport->sock;
  
  	if (sock != NULL)
  		kernel_sock_shutdown(sock, SHUT_WR);
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
656
  /**
262965f53   Chuck Lever   [PATCH] RPC: sepa...
657
   * xs_tcp_send_request - write an RPC request to a TCP socket
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
658
659
660
   * @task: address of RPC task that manages the state of an RPC request
   *
   * Return values:
262965f53   Chuck Lever   [PATCH] RPC: sepa...
661
662
663
664
   *        0:	The request has been sent
   *   EAGAIN:	The socket was blocked, please call again later to
   *		complete the request
   * ENOTCONN:	Caller needs to invoke connect logic then call again
25985edce   Lucas De Marchi   Fix common misspe...
665
   *    other:	Some other error occurred, the request was not sent
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
666
667
   *
   * XXX: In the case of soft timeouts, should we eventually give up
262965f53   Chuck Lever   [PATCH] RPC: sepa...
668
   *	if sendmsg is not able to make progress?
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
669
   */
262965f53   Chuck Lever   [PATCH] RPC: sepa...
670
  static int xs_tcp_send_request(struct rpc_task *task)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
671
672
673
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = req->rq_xprt;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
674
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
262965f53   Chuck Lever   [PATCH] RPC: sepa...
675
  	struct xdr_buf *xdr = &req->rq_snd_buf;
b595bb150   Chuck Lever   SUNRPC: Fix a sig...
676
  	int status;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
677

61677eeec   Chuck Lever   SUNRPC: Rename xs...
678
  	xs_encode_stream_record_marker(&req->rq_snd_buf);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
679

262965f53   Chuck Lever   [PATCH] RPC: sepa...
680
681
682
  	xs_pktdump("packet data:",
  				req->rq_svec->iov_base,
  				req->rq_svec->iov_len);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
683
684
685
  
  	/* Continue transmitting the packet/record. We must be careful
  	 * to cope with writespace callbacks arriving _after_ we have
262965f53   Chuck Lever   [PATCH] RPC: sepa...
686
  	 * called sendmsg(). */
a246b0105   Chuck Lever   [PATCH] RPC: intr...
687
  	while (1) {
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
688
689
  		status = xs_sendpages(transport->sock,
  					NULL, 0, xdr, req->rq_bytes_sent);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
690

46121cf7d   Chuck Lever   SUNRPC: fix print...
691
692
  		dprintk("RPC:       xs_tcp_send_request(%u) = %d
  ",
262965f53   Chuck Lever   [PATCH] RPC: sepa...
693
  				xdr->len - req->rq_bytes_sent, status);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
694

262965f53   Chuck Lever   [PATCH] RPC: sepa...
695
  		if (unlikely(status < 0))
a246b0105   Chuck Lever   [PATCH] RPC: intr...
696
  			break;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
697

262965f53   Chuck Lever   [PATCH] RPC: sepa...
698
699
700
  		/* If we've sent the entire packet, immediately
  		 * reset the count of bytes sent. */
  		req->rq_bytes_sent += status;
d60dbb20a   Trond Myklebust   SUNRPC: Move the ...
701
  		req->rq_xmit_bytes_sent += status;
262965f53   Chuck Lever   [PATCH] RPC: sepa...
702
703
704
705
  		if (likely(req->rq_bytes_sent >= req->rq_slen)) {
  			req->rq_bytes_sent = 0;
  			return 0;
  		}
a246b0105   Chuck Lever   [PATCH] RPC: intr...
706

06b4b681a   Trond Myklebust   SUNRPC: remove XS...
707
708
  		if (status != 0)
  			continue;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
709
  		status = -EAGAIN;
06b4b681a   Trond Myklebust   SUNRPC: remove XS...
710
  		break;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
711
  	}
262965f53   Chuck Lever   [PATCH] RPC: sepa...
712
  	switch (status) {
fba91afbe   Trond Myklebust   SUNRPC: Fix an Oo...
713
714
715
716
  	case -ENOTSOCK:
  		status = -ENOTCONN;
  		/* Should we call xs_close() here? */
  		break;
262965f53   Chuck Lever   [PATCH] RPC: sepa...
717
  	case -EAGAIN:
5e3771ce2   Trond Myklebust   SUNRPC: Ensure th...
718
  		status = xs_nospace(task);
262965f53   Chuck Lever   [PATCH] RPC: sepa...
719
  		break;
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
720
721
722
723
  	default:
  		dprintk("RPC:       sendmsg returned unrecognized error %d
  ",
  			-status);
262965f53   Chuck Lever   [PATCH] RPC: sepa...
724
  	case -ECONNRESET:
55420c24a   Trond Myklebust   SUNRPC: Ensure we...
725
  	case -EPIPE:
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
726
727
  		xs_tcp_shutdown(xprt);
  	case -ECONNREFUSED:
262965f53   Chuck Lever   [PATCH] RPC: sepa...
728
  	case -ENOTCONN:
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
729
  		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
730
  	}
5fe46e9d7   Bian Naimeng   rpc client can no...
731

a246b0105   Chuck Lever   [PATCH] RPC: intr...
732
733
  	return status;
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
734
  /**
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
   * xs_tcp_release_xprt - clean up after a tcp transmission
   * @xprt: transport
   * @task: rpc task
   *
   * This cleans up if an error causes us to abort the transmission of a request.
   * In this case, the socket may need to be reset in order to avoid confusing
   * the server.
   */
  static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
  {
  	struct rpc_rqst *req;
  
  	if (task != xprt->snd_task)
  		return;
  	if (task == NULL)
  		goto out_release;
  	req = task->tk_rqstp;
43cedbf0e   Trond Myklebust   SUNRPC: Ensure th...
752
753
  	if (req == NULL)
  		goto out_release;
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
754
755
756
757
758
759
760
761
  	if (req->rq_bytes_sent == 0)
  		goto out_release;
  	if (req->rq_bytes_sent == req->rq_snd_buf.len)
  		goto out_release;
  	set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state);
  out_release:
  	xprt_release_xprt(xprt, task);
  }
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
  static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
  {
  	transport->old_data_ready = sk->sk_data_ready;
  	transport->old_state_change = sk->sk_state_change;
  	transport->old_write_space = sk->sk_write_space;
  	transport->old_error_report = sk->sk_error_report;
  }
  
  static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
  {
  	sk->sk_data_ready = transport->old_data_ready;
  	sk->sk_state_change = transport->old_state_change;
  	sk->sk_write_space = transport->old_write_space;
  	sk->sk_error_report = transport->old_error_report;
  }
fe315e76f   Chuck Lever   SUNRPC: Avoid spu...
777
  static void xs_reset_transport(struct sock_xprt *transport)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
778
  {
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
779
780
  	struct socket *sock = transport->sock;
  	struct sock *sk = transport->inet;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
781

fe315e76f   Chuck Lever   SUNRPC: Avoid spu...
782
783
  	if (sk == NULL)
  		return;
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
784

246408dcd   Trond Myklebust   SUNRPC: Never reu...
785
  	transport->srcport = 0;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
786
  	write_lock_bh(&sk->sk_callback_lock);
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
787
788
  	transport->inet = NULL;
  	transport->sock = NULL;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
789

9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
790
  	sk->sk_user_data = NULL;
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
791
792
  
  	xs_restore_old_callbacks(transport, sk);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
793
  	write_unlock_bh(&sk->sk_callback_lock);
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
794
  	sk->sk_no_check = 0;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
795
796
  
  	sock_release(sock);
fe315e76f   Chuck Lever   SUNRPC: Avoid spu...
797
798
799
800
801
802
803
804
  }
  
  /**
   * xs_close - close a socket
   * @xprt: transport
   *
   * This is used when all requests are complete; ie, no DRC state remains
   * on the server we want to save.
f75e6745a   Trond Myklebust   SUNRPC: Fix the p...
805
806
807
   *
   * The caller _must_ be holding XPRT_LOCKED in order to avoid issues with
   * xs_reset_transport() zeroing the socket from underneath a writer.
fe315e76f   Chuck Lever   SUNRPC: Avoid spu...
808
809
810
811
812
813
814
815
816
   */
  static void xs_close(struct rpc_xprt *xprt)
  {
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
  
  	dprintk("RPC:       xs_close xprt %p
  ", xprt);
  
  	xs_reset_transport(transport);
61d0a8e6a   Neil Brown   NFS/RPC: fix prob...
817
  	xprt->reestablish_timeout = 0;
fe315e76f   Chuck Lever   SUNRPC: Avoid spu...
818

632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
819
  	smp_mb__before_clear_bit();
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
820
  	clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
821
  	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
822
  	clear_bit(XPRT_CLOSING, &xprt->state);
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
823
  	smp_mb__after_clear_bit();
62da3b248   Trond Myklebust   SUNRPC: Rename xp...
824
  	xprt_disconnect_done(xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
825
  }
f75e6745a   Trond Myklebust   SUNRPC: Fix the p...
826
827
828
829
830
831
832
  static void xs_tcp_close(struct rpc_xprt *xprt)
  {
  	if (test_and_clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state))
  		xs_close(xprt);
  	else
  		xs_tcp_shutdown(xprt);
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
833
834
835
836
837
838
  /**
   * xs_destroy - prepare to shutdown a transport
   * @xprt: doomed transport
   *
   */
  static void xs_destroy(struct rpc_xprt *xprt)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
839
  {
c84754618   Chuck Lever   SUNRPC: Move rpc_...
840
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
46121cf7d   Chuck Lever   SUNRPC: fix print...
841
842
  	dprintk("RPC:       xs_destroy xprt %p
  ", xprt);
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
843

afe2c511f   Tejun Heo   workqueue: conver...
844
  	cancel_delayed_work_sync(&transport->connect_worker);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
845

9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
846
  	xs_close(xprt);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
847
  	xs_free_peer_addresses(xprt);
e204e621b   Pavel Emelyanov   sunrpc: Factor ou...
848
  	xprt_free(xprt);
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
849
  	module_put(THIS_MODULE);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
850
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
851
852
853
854
  static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
  {
  	return (struct rpc_xprt *) sk->sk_user_data;
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
  static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
  {
  	struct xdr_skb_reader desc = {
  		.skb		= skb,
  		.offset		= sizeof(rpc_fraghdr),
  		.count		= skb->len - sizeof(rpc_fraghdr),
  	};
  
  	if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0)
  		return -1;
  	if (desc.count)
  		return -1;
  	return 0;
  }
  
  /**
   * xs_local_data_ready - "data ready" callback for AF_LOCAL sockets
   * @sk: socket with data to read
   * @len: how much data to read
   *
   * Currently this assumes we can read the whole reply in a single gulp.
   */
  static void xs_local_data_ready(struct sock *sk, int len)
  {
  	struct rpc_task *task;
  	struct rpc_xprt *xprt;
  	struct rpc_rqst *rovr;
  	struct sk_buff *skb;
  	int err, repsize, copied;
  	u32 _xid;
  	__be32 *xp;
  
  	read_lock_bh(&sk->sk_callback_lock);
  	dprintk("RPC:       %s...
  ", __func__);
  	xprt = xprt_from_sock(sk);
  	if (xprt == NULL)
  		goto out;
  
  	skb = skb_recv_datagram(sk, 0, 1, &err);
  	if (skb == NULL)
  		goto out;
  
  	if (xprt->shutdown)
  		goto dropit;
  
  	repsize = skb->len - sizeof(rpc_fraghdr);
  	if (repsize < 4) {
  		dprintk("RPC:       impossible RPC reply size %d
  ", repsize);
  		goto dropit;
  	}
  
  	/* Copy the XID from the skb... */
  	xp = skb_header_pointer(skb, sizeof(rpc_fraghdr), sizeof(_xid), &_xid);
  	if (xp == NULL)
  		goto dropit;
  
  	/* Look up and lock the request corresponding to the given XID */
  	spin_lock(&xprt->transport_lock);
  	rovr = xprt_lookup_rqst(xprt, *xp);
  	if (!rovr)
  		goto out_unlock;
  	task = rovr->rq_task;
  
  	copied = rovr->rq_private_buf.buflen;
  	if (copied > repsize)
  		copied = repsize;
  
  	if (xs_local_copy_to_xdr(&rovr->rq_private_buf, skb)) {
  		dprintk("RPC:       sk_buff copy failed
  ");
  		goto out_unlock;
  	}
  
  	xprt_complete_rqst(task, copied);
  
   out_unlock:
  	spin_unlock(&xprt->transport_lock);
   dropit:
  	skb_free_datagram(sk, skb);
   out:
  	read_unlock_bh(&sk->sk_callback_lock);
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
939
940
941
942
943
  /**
   * xs_udp_data_ready - "data ready" callback for UDP sockets
   * @sk: socket with data to read
   * @len: how much data to read
   *
a246b0105   Chuck Lever   [PATCH] RPC: intr...
944
   */
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
945
  static void xs_udp_data_ready(struct sock *sk, int len)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
946
  {
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
947
948
  	struct rpc_task *task;
  	struct rpc_xprt *xprt;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
949
  	struct rpc_rqst *rovr;
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
950
  	struct sk_buff *skb;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
951
  	int err, repsize, copied;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
952
953
  	u32 _xid;
  	__be32 *xp;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
954

f064af1e5   Eric Dumazet   net: fix a lockde...
955
  	read_lock_bh(&sk->sk_callback_lock);
46121cf7d   Chuck Lever   SUNRPC: fix print...
956
957
  	dprintk("RPC:       xs_udp_data_ready...
  ");
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
958
  	if (!(xprt = xprt_from_sock(sk)))
a246b0105   Chuck Lever   [PATCH] RPC: intr...
959
  		goto out;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
960
961
962
963
964
965
966
967
968
  
  	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
  		goto out;
  
  	if (xprt->shutdown)
  		goto dropit;
  
  	repsize = skb->len - sizeof(struct udphdr);
  	if (repsize < 4) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
969
970
  		dprintk("RPC:       impossible RPC reply size %d!
  ", repsize);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
971
972
973
974
975
976
977
978
979
980
  		goto dropit;
  	}
  
  	/* Copy the XID from the skb... */
  	xp = skb_header_pointer(skb, sizeof(struct udphdr),
  				sizeof(_xid), &_xid);
  	if (xp == NULL)
  		goto dropit;
  
  	/* Look up and lock the request corresponding to the given XID */
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
981
  	spin_lock(&xprt->transport_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
982
983
984
985
  	rovr = xprt_lookup_rqst(xprt, *xp);
  	if (!rovr)
  		goto out_unlock;
  	task = rovr->rq_task;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
986
987
988
989
  	if ((copied = rovr->rq_private_buf.buflen) > repsize)
  		copied = repsize;
  
  	/* Suck it into the iovec, verify checksum if not done by hw. */
1781f7f58   Herbert Xu   [UDP]: Restore mi...
990
991
  	if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb)) {
  		UDPX_INC_STATS_BH(sk, UDP_MIB_INERRORS);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
992
  		goto out_unlock;
1781f7f58   Herbert Xu   [UDP]: Restore mi...
993
994
995
  	}
  
  	UDPX_INC_STATS_BH(sk, UDP_MIB_INDATAGRAMS);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
996
997
  
  	/* Something worked... */
adf30907d   Eric Dumazet   net: skb->dst acc...
998
  	dst_confirm(skb_dst(skb));
a246b0105   Chuck Lever   [PATCH] RPC: intr...
999

1570c1e41   Chuck Lever   [PATCH] RPC: add ...
1000
  	xprt_adjust_cwnd(task, copied);
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
1001
  	xprt_complete_rqst(task, copied);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1002
1003
  
   out_unlock:
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
1004
  	spin_unlock(&xprt->transport_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1005
1006
1007
   dropit:
  	skb_free_datagram(sk, skb);
   out:
f064af1e5   Eric Dumazet   net: fix a lockde...
1008
  	read_unlock_bh(&sk->sk_callback_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1009
  }
dd4564715   Chuck Lever   SUNRPC: Rename sk...
1010
  static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1011
  {
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1012
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1013
1014
  	size_t len, used;
  	char *p;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1015
1016
  	p = ((char *) &transport->tcp_fraghdr) + transport->tcp_offset;
  	len = sizeof(transport->tcp_fraghdr) - transport->tcp_offset;
9d2923169   Chuck Lever   SUNRPC: skb_read_...
1017
  	used = xdr_skb_read_bits(desc, p, len);
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1018
  	transport->tcp_offset += used;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1019
1020
  	if (used != len)
  		return;
808012fbb   Chuck Lever   [PATCH] RPC: skip...
1021

51971139b   Chuck Lever   SUNRPC: Move TCP ...
1022
1023
  	transport->tcp_reclen = ntohl(transport->tcp_fraghdr);
  	if (transport->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1024
  		transport->tcp_flags |= TCP_RCV_LAST_FRAG;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1025
  	else
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1026
  		transport->tcp_flags &= ~TCP_RCV_LAST_FRAG;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1027
  	transport->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
808012fbb   Chuck Lever   [PATCH] RPC: skip...
1028

e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1029
  	transport->tcp_flags &= ~TCP_RCV_COPY_FRAGHDR;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1030
  	transport->tcp_offset = 0;
808012fbb   Chuck Lever   [PATCH] RPC: skip...
1031

a246b0105   Chuck Lever   [PATCH] RPC: intr...
1032
  	/* Sanity check of the record length */
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1033
  	if (unlikely(transport->tcp_reclen < 8)) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1034
1035
  		dprintk("RPC:       invalid TCP record fragment length
  ");
3ebb067d9   Trond Myklebust   SUNRPC: Make call...
1036
  		xprt_force_disconnect(xprt);
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1037
  		return;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1038
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
1039
1040
  	dprintk("RPC:       reading TCP record fragment of length %d
  ",
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1041
  			transport->tcp_reclen);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1042
  }
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1043
  static void xs_tcp_check_fraghdr(struct sock_xprt *transport)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1044
  {
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1045
  	if (transport->tcp_offset == transport->tcp_reclen) {
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1046
  		transport->tcp_flags |= TCP_RCV_COPY_FRAGHDR;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1047
  		transport->tcp_offset = 0;
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1048
1049
1050
  		if (transport->tcp_flags & TCP_RCV_LAST_FRAG) {
  			transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
  			transport->tcp_flags |= TCP_RCV_COPY_XID;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1051
  			transport->tcp_copied = 0;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1052
1053
1054
  		}
  	}
  }
dd4564715   Chuck Lever   SUNRPC: Rename sk...
1055
  static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_reader *desc)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1056
1057
1058
  {
  	size_t len, used;
  	char *p;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1059
  	len = sizeof(transport->tcp_xid) - transport->tcp_offset;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1060
1061
  	dprintk("RPC:       reading XID (%Zu bytes)
  ", len);
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1062
  	p = ((char *) &transport->tcp_xid) + transport->tcp_offset;
9d2923169   Chuck Lever   SUNRPC: skb_read_...
1063
  	used = xdr_skb_read_bits(desc, p, len);
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1064
  	transport->tcp_offset += used;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1065
1066
  	if (used != len)
  		return;
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1067
  	transport->tcp_flags &= ~TCP_RCV_COPY_XID;
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1068
  	transport->tcp_flags |= TCP_RCV_READ_CALLDIR;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1069
  	transport->tcp_copied = 4;
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1070
1071
1072
1073
  	dprintk("RPC:       reading %s XID %08x
  ",
  			(transport->tcp_flags & TCP_RPC_REPLY) ? "reply for"
  							      : "request with",
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1074
1075
  			ntohl(transport->tcp_xid));
  	xs_tcp_check_fraghdr(transport);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1076
  }
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1077
1078
  static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
  				       struct xdr_skb_reader *desc)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1079
  {
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1080
1081
  	size_t len, used;
  	u32 offset;
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1082
  	char *p;
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1083
1084
1085
1086
1087
1088
1089
1090
  
  	/*
  	 * We want transport->tcp_offset to be 8 at the end of this routine
  	 * (4 bytes for the xid and 4 bytes for the call/reply flag).
  	 * When this function is called for the first time,
  	 * transport->tcp_offset is 4 (after having already read the xid).
  	 */
  	offset = transport->tcp_offset - sizeof(transport->tcp_xid);
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1091
  	len = sizeof(transport->tcp_calldir) - offset;
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1092
1093
  	dprintk("RPC:       reading CALL/REPLY flag (%Zu bytes)
  ", len);
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1094
1095
  	p = ((char *) &transport->tcp_calldir) + offset;
  	used = xdr_skb_read_bits(desc, p, len);
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1096
1097
1098
  	transport->tcp_offset += used;
  	if (used != len)
  		return;
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1099
  	transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1100
1101
1102
1103
  	/*
  	 * We don't yet have the XDR buffer, so we will write the calldir
  	 * out after we get the buffer from the 'struct rpc_rqst'
  	 */
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1104
1105
1106
1107
  	switch (ntohl(transport->tcp_calldir)) {
  	case RPC_REPLY:
  		transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
  		transport->tcp_flags |= TCP_RCV_COPY_DATA;
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1108
  		transport->tcp_flags |= TCP_RPC_REPLY;
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1109
1110
1111
1112
  		break;
  	case RPC_CALL:
  		transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
  		transport->tcp_flags |= TCP_RCV_COPY_DATA;
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1113
  		transport->tcp_flags &= ~TCP_RPC_REPLY;
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1114
1115
1116
1117
1118
1119
  		break;
  	default:
  		dprintk("RPC:       invalid request message type
  ");
  		xprt_force_disconnect(&transport->xprt);
  	}
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1120
1121
  	xs_tcp_check_fraghdr(transport);
  }
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1122
1123
1124
  static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
  				     struct xdr_skb_reader *desc,
  				     struct rpc_rqst *req)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1125
  {
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1126
1127
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1128
1129
1130
  	struct xdr_buf *rcvbuf;
  	size_t len;
  	ssize_t r;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1131
  	rcvbuf = &req->rq_private_buf;
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1132
1133
1134
1135
1136
  
  	if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
  		/*
  		 * Save the RPC direction in the XDR buffer
  		 */
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1137
  		memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
b76ce5619   Trond Myklebust   SUNRPC: Fix a re-...
1138
1139
1140
  			&transport->tcp_calldir,
  			sizeof(transport->tcp_calldir));
  		transport->tcp_copied += sizeof(transport->tcp_calldir);
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1141
  		transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1142
  	}
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1143
  	len = desc->count;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1144
  	if (len > transport->tcp_reclen - transport->tcp_offset) {
dd4564715   Chuck Lever   SUNRPC: Rename sk...
1145
  		struct xdr_skb_reader my_desc;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1146

51971139b   Chuck Lever   SUNRPC: Move TCP ...
1147
  		len = transport->tcp_reclen - transport->tcp_offset;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1148
1149
  		memcpy(&my_desc, desc, sizeof(my_desc));
  		my_desc.count = len;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1150
  		r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
9d2923169   Chuck Lever   SUNRPC: skb_read_...
1151
  					  &my_desc, xdr_skb_read_bits);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1152
1153
1154
  		desc->count -= r;
  		desc->offset += r;
  	} else
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1155
  		r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
9d2923169   Chuck Lever   SUNRPC: skb_read_...
1156
  					  desc, xdr_skb_read_bits);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1157
1158
  
  	if (r > 0) {
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1159
1160
  		transport->tcp_copied += r;
  		transport->tcp_offset += r;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1161
1162
1163
1164
1165
  	}
  	if (r != len) {
  		/* Error when copying to the receive buffer,
  		 * usually because we weren't able to allocate
  		 * additional buffer pages. All we can do now
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1166
  		 * is turn off TCP_RCV_COPY_DATA, so the request
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1167
1168
1169
1170
1171
  		 * will not receive any additional updates,
  		 * and time out.
  		 * Any remaining data from this record will
  		 * be discarded.
  		 */
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1172
  		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1173
1174
  		dprintk("RPC:       XID %08x truncated request
  ",
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1175
  				ntohl(transport->tcp_xid));
46121cf7d   Chuck Lever   SUNRPC: fix print...
1176
1177
1178
1179
1180
  		dprintk("RPC:       xprt = %p, tcp_copied = %lu, "
  				"tcp_offset = %u, tcp_reclen = %u
  ",
  				xprt, transport->tcp_copied,
  				transport->tcp_offset, transport->tcp_reclen);
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1181
  		return;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1182
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
1183
1184
  	dprintk("RPC:       XID %08x read %Zd bytes
  ",
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1185
  			ntohl(transport->tcp_xid), r);
46121cf7d   Chuck Lever   SUNRPC: fix print...
1186
1187
1188
1189
  	dprintk("RPC:       xprt = %p, tcp_copied = %lu, tcp_offset = %u, "
  			"tcp_reclen = %u
  ", xprt, transport->tcp_copied,
  			transport->tcp_offset, transport->tcp_reclen);
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1190
1191
  
  	if (transport->tcp_copied == req->rq_private_buf.buflen)
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1192
  		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1193
  	else if (transport->tcp_offset == transport->tcp_reclen) {
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1194
1195
  		if (transport->tcp_flags & TCP_RCV_LAST_FRAG)
  			transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1196
  	}
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  }
  
  /*
   * Finds the request corresponding to the RPC xid and invokes the common
   * tcp read code to read the data.
   */
  static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
  				    struct xdr_skb_reader *desc)
  {
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
  	struct rpc_rqst *req;
  
  	dprintk("RPC:       read reply XID %08x
  ", ntohl(transport->tcp_xid));
  
  	/* Find and lock the request corresponding to this xid */
  	spin_lock(&xprt->transport_lock);
  	req = xprt_lookup_rqst(xprt, transport->tcp_xid);
  	if (!req) {
  		dprintk("RPC:       XID %08x request not found!
  ",
  				ntohl(transport->tcp_xid));
  		spin_unlock(&xprt->transport_lock);
  		return -1;
  	}
  
  	xs_tcp_read_common(xprt, desc, req);
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1225
  	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1226
  		xprt_complete_rqst(req->rq_task, transport->tcp_copied);
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1227

4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
1228
  	spin_unlock(&xprt->transport_lock);
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1229
1230
  	return 0;
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
1231
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
  /*
   * Obtains an rpc_rqst previously allocated and invokes the common
   * tcp read code to read the data.  The result is placed in the callback
   * queue.
   * If we're unable to obtain the rpc_rqst we schedule the closing of the
   * connection and return -1.
   */
  static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
  				       struct xdr_skb_reader *desc)
  {
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
  	struct rpc_rqst *req;
  
  	req = xprt_alloc_bc_request(xprt);
  	if (req == NULL) {
  		printk(KERN_WARNING "Callback slot table overflowed
  ");
  		xprt_force_disconnect(xprt);
  		return -1;
  	}
  
  	req->rq_xid = transport->tcp_xid;
  	dprintk("RPC:       read callback  XID %08x
  ", ntohl(req->rq_xid));
  	xs_tcp_read_common(xprt, desc, req);
  
  	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
  		struct svc_serv *bc_serv = xprt->bc_serv;
  
  		/*
  		 * Add callback request to callback list.  The callback
  		 * service sleeps on the sv_cb_waitq waiting for new
  		 * requests.  Wake it up after adding enqueing the
  		 * request.
  		 */
  		dprintk("RPC:       add callback request to list
  ");
  		spin_lock(&bc_serv->sv_cb_lock);
  		list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
  		spin_unlock(&bc_serv->sv_cb_lock);
  		wake_up(&bc_serv->sv_cb_waitq);
  	}
  
  	req->rq_private_buf.len = transport->tcp_copied;
  
  	return 0;
  }
  
  static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
  					struct xdr_skb_reader *desc)
  {
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
  
  	return (transport->tcp_flags & TCP_RPC_REPLY) ?
  		xs_tcp_read_reply(xprt, desc) :
  		xs_tcp_read_callback(xprt, desc);
  }
  #else
  static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
  					struct xdr_skb_reader *desc)
  {
  	return xs_tcp_read_reply(xprt, desc);
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
1297
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
  
  /*
   * Read data off the transport.  This can be either an RPC_CALL or an
   * RPC_REPLY.  Relay the processing to helper functions.
   */
  static void xs_tcp_read_data(struct rpc_xprt *xprt,
  				    struct xdr_skb_reader *desc)
  {
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
  
  	if (_xs_tcp_read_data(xprt, desc) == 0)
  		xs_tcp_check_fraghdr(transport);
  	else {
  		/*
  		 * The transport_lock protects the request handling.
  		 * There's no need to hold it to update the tcp_flags.
  		 */
  		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
  	}
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1318
  }
dd4564715   Chuck Lever   SUNRPC: Rename sk...
1319
  static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1320
1321
  {
  	size_t len;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1322
  	len = transport->tcp_reclen - transport->tcp_offset;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1323
1324
1325
1326
  	if (len > desc->count)
  		len = desc->count;
  	desc->count -= len;
  	desc->offset += len;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1327
  	transport->tcp_offset += len;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1328
1329
  	dprintk("RPC:       discarded %Zu bytes
  ", len);
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1330
  	xs_tcp_check_fraghdr(transport);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1331
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1332
  static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1333
1334
  {
  	struct rpc_xprt *xprt = rd_desc->arg.data;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1335
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
dd4564715   Chuck Lever   SUNRPC: Rename sk...
1336
  	struct xdr_skb_reader desc = {
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1337
1338
1339
  		.skb	= skb,
  		.offset	= offset,
  		.count	= len,
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1340
  	};
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1341

46121cf7d   Chuck Lever   SUNRPC: fix print...
1342
1343
  	dprintk("RPC:       xs_tcp_data_recv started
  ");
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1344
1345
1346
  	do {
  		/* Read in a new fragment marker if necessary */
  		/* Can we ever really expect to get completely empty fragments? */
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1347
  		if (transport->tcp_flags & TCP_RCV_COPY_FRAGHDR) {
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1348
  			xs_tcp_read_fraghdr(xprt, &desc);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1349
1350
1351
  			continue;
  		}
  		/* Read in the xid if necessary */
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1352
  		if (transport->tcp_flags & TCP_RCV_COPY_XID) {
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1353
  			xs_tcp_read_xid(transport, &desc);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1354
1355
  			continue;
  		}
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1356
  		/* Read in the call/reply flag */
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1357
  		if (transport->tcp_flags & TCP_RCV_READ_CALLDIR) {
18dca02ae   Ricardo Labiaga   nfs41: Add abilit...
1358
1359
1360
  			xs_tcp_read_calldir(transport, &desc);
  			continue;
  		}
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1361
  		/* Read in the request data */
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1362
  		if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
44b98efdd   Ricardo Labiaga   nfs41: New xs_tcp...
1363
  			xs_tcp_read_data(xprt, &desc);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1364
1365
1366
  			continue;
  		}
  		/* Skip over any trailing bytes on short reads */
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1367
  		xs_tcp_read_discard(transport, &desc);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1368
  	} while (desc.count);
46121cf7d   Chuck Lever   SUNRPC: fix print...
1369
1370
  	dprintk("RPC:       xs_tcp_data_recv done
  ");
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1371
1372
  	return len - desc.count;
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1373
1374
1375
1376
1377
1378
1379
  /**
   * xs_tcp_data_ready - "data ready" callback for TCP sockets
   * @sk: socket with data to read
   * @bytes: how much data to read
   *
   */
  static void xs_tcp_data_ready(struct sock *sk, int bytes)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1380
1381
1382
  {
  	struct rpc_xprt *xprt;
  	read_descriptor_t rd_desc;
ff2d7db84   Trond Myklebust   SUNRPC: Ensure th...
1383
  	int read;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1384

46121cf7d   Chuck Lever   SUNRPC: fix print...
1385
1386
  	dprintk("RPC:       xs_tcp_data_ready...
  ");
f064af1e5   Eric Dumazet   net: fix a lockde...
1387
  	read_lock_bh(&sk->sk_callback_lock);
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1388
  	if (!(xprt = xprt_from_sock(sk)))
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1389
  		goto out;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1390
1391
  	if (xprt->shutdown)
  		goto out;
61d0a8e6a   Neil Brown   NFS/RPC: fix prob...
1392
1393
1394
1395
1396
  	/* Any data means we had a useful conversation, so
  	 * the we don't need to delay the next reconnect
  	 */
  	if (xprt->reestablish_timeout)
  		xprt->reestablish_timeout = 0;
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1397
  	/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1398
  	rd_desc.arg.data = xprt;
ff2d7db84   Trond Myklebust   SUNRPC: Ensure th...
1399
1400
1401
1402
  	do {
  		rd_desc.count = 65536;
  		read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
  	} while (read > 0);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1403
  out:
f064af1e5   Eric Dumazet   net: fix a lockde...
1404
  	read_unlock_bh(&sk->sk_callback_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1405
  }
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  /*
   * Do the equivalent of linger/linger2 handling for dealing with
   * broken servers that don't close the socket in a timely
   * fashion
   */
  static void xs_tcp_schedule_linger_timeout(struct rpc_xprt *xprt,
  		unsigned long timeout)
  {
  	struct sock_xprt *transport;
  
  	if (xprt_test_and_set_connecting(xprt))
  		return;
  	set_bit(XPRT_CONNECTION_ABORT, &xprt->state);
  	transport = container_of(xprt, struct sock_xprt, xprt);
  	queue_delayed_work(rpciod_workqueue, &transport->connect_worker,
  			   timeout);
  }
  
  static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
  {
  	struct sock_xprt *transport;
  
  	transport = container_of(xprt, struct sock_xprt, xprt);
  
  	if (!test_bit(XPRT_CONNECTION_ABORT, &xprt->state) ||
  	    !cancel_delayed_work(&transport->connect_worker))
  		return;
  	clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
  	xprt_clear_connecting(xprt);
  }
  
  static void xs_sock_mark_closed(struct rpc_xprt *xprt)
  {
  	smp_mb__before_clear_bit();
  	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
  	clear_bit(XPRT_CLOSING, &xprt->state);
  	smp_mb__after_clear_bit();
  	/* Mark transport as closed and wake up all pending tasks */
  	xprt_disconnect_done(xprt);
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1446
1447
1448
1449
1450
1451
  /**
   * xs_tcp_state_change - callback to handle TCP socket state changes
   * @sk: socket whose state has changed
   *
   */
  static void xs_tcp_state_change(struct sock *sk)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1452
  {
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1453
  	struct rpc_xprt *xprt;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1454

f064af1e5   Eric Dumazet   net: fix a lockde...
1455
  	read_lock_bh(&sk->sk_callback_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1456
1457
  	if (!(xprt = xprt_from_sock(sk)))
  		goto out;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1458
1459
  	dprintk("RPC:       xs_tcp_state_change client %p...
  ", xprt);
669502ff3   Andy Chittenden   SUNRPC: fix NFS c...
1460
1461
  	dprintk("RPC:       state %x conn %d dead %d zapped %d sk_shutdown %d
  ",
46121cf7d   Chuck Lever   SUNRPC: fix print...
1462
1463
  			sk->sk_state, xprt_connected(xprt),
  			sock_flag(sk, SOCK_DEAD),
669502ff3   Andy Chittenden   SUNRPC: fix NFS c...
1464
1465
  			sock_flag(sk, SOCK_ZAPPED),
  			sk->sk_shutdown);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1466
1467
1468
  
  	switch (sk->sk_state) {
  	case TCP_ESTABLISHED:
f064af1e5   Eric Dumazet   net: fix a lockde...
1469
  		spin_lock(&xprt->transport_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1470
  		if (!xprt_test_and_set_connected(xprt)) {
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1471
1472
  			struct sock_xprt *transport = container_of(xprt,
  					struct sock_xprt, xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1473
  			/* Reset TCP record info */
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1474
1475
1476
  			transport->tcp_offset = 0;
  			transport->tcp_reclen = 0;
  			transport->tcp_copied = 0;
e136d0926   Chuck Lever   SUNRPC: Move TCP ...
1477
1478
  			transport->tcp_flags =
  				TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID;
51971139b   Chuck Lever   SUNRPC: Move TCP ...
1479

2a4919919   Trond Myklebust   SUNRPC: Return EA...
1480
  			xprt_wake_pending_tasks(xprt, -EAGAIN);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1481
  		}
f064af1e5   Eric Dumazet   net: fix a lockde...
1482
  		spin_unlock(&xprt->transport_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1483
  		break;
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
1484
1485
  	case TCP_FIN_WAIT1:
  		/* The client initiated a shutdown of the socket */
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
1486
  		xprt->connect_cookie++;
663b8858d   Trond Myklebust   SUNRPC: Reconnect...
1487
  		xprt->reestablish_timeout = 0;
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
1488
1489
1490
  		set_bit(XPRT_CLOSING, &xprt->state);
  		smp_mb__before_clear_bit();
  		clear_bit(XPRT_CONNECTED, &xprt->state);
ef8036707   Trond Myklebust   SUNRPC: TCP clear...
1491
  		clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
1492
  		smp_mb__after_clear_bit();
25fe6142a   Trond Myklebust   SUNRPC: Add a sys...
1493
  		xs_tcp_schedule_linger_timeout(xprt, xs_tcp_fin_timeout);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1494
  		break;
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
1495
  	case TCP_CLOSE_WAIT:
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
1496
  		/* The server initiated a shutdown of the socket */
66af1e558   Trond Myklebust   SUNRPC: Fix a rac...
1497
  		xprt_force_disconnect(xprt);
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
1498
  		xprt->connect_cookie++;
663b8858d   Trond Myklebust   SUNRPC: Reconnect...
1499
1500
1501
1502
1503
1504
1505
  	case TCP_CLOSING:
  		/*
  		 * If the server closed down the connection, make sure that
  		 * we back off before reconnecting
  		 */
  		if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
  			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
1506
1507
  		break;
  	case TCP_LAST_ACK:
670f94573   Trond Myklebust   SUNRPC: Ensure we...
1508
  		set_bit(XPRT_CLOSING, &xprt->state);
25fe6142a   Trond Myklebust   SUNRPC: Add a sys...
1509
  		xs_tcp_schedule_linger_timeout(xprt, xs_tcp_fin_timeout);
3b948ae5b   Trond Myklebust   SUNRPC: Allow the...
1510
1511
1512
1513
1514
  		smp_mb__before_clear_bit();
  		clear_bit(XPRT_CONNECTED, &xprt->state);
  		smp_mb__after_clear_bit();
  		break;
  	case TCP_CLOSE:
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
1515
1516
  		xs_tcp_cancel_linger_timeout(xprt);
  		xs_sock_mark_closed(xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1517
1518
  	}
   out:
f064af1e5   Eric Dumazet   net: fix a lockde...
1519
  	read_unlock_bh(&sk->sk_callback_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1520
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1521
  /**
482f32e65   Trond Myklebust   SUNRPC: Handle so...
1522
   * xs_error_report - callback mainly for catching socket errors
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1523
1524
   * @sk: socket
   */
482f32e65   Trond Myklebust   SUNRPC: Handle so...
1525
  static void xs_error_report(struct sock *sk)
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1526
1527
  {
  	struct rpc_xprt *xprt;
f064af1e5   Eric Dumazet   net: fix a lockde...
1528
  	read_lock_bh(&sk->sk_callback_lock);
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1529
1530
1531
1532
1533
1534
1535
  	if (!(xprt = xprt_from_sock(sk)))
  		goto out;
  	dprintk("RPC:       %s client %p...
  "
  			"RPC:       error %d
  ",
  			__func__, xprt, sk->sk_err);
482f32e65   Trond Myklebust   SUNRPC: Handle so...
1536
  	xprt_wake_pending_tasks(xprt, -EAGAIN);
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1537
  out:
f064af1e5   Eric Dumazet   net: fix a lockde...
1538
  	read_unlock_bh(&sk->sk_callback_lock);
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1539
  }
1f0fa1543   Ilpo Järvinen   net/sunrpc/xprtso...
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
  static void xs_write_space(struct sock *sk)
  {
  	struct socket *sock;
  	struct rpc_xprt *xprt;
  
  	if (unlikely(!(sock = sk->sk_socket)))
  		return;
  	clear_bit(SOCK_NOSPACE, &sock->flags);
  
  	if (unlikely(!(xprt = xprt_from_sock(sk))))
  		return;
  	if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
  		return;
  
  	xprt_write_space(xprt);
  }
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1556
  /**
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1557
1558
   * xs_udp_write_space - callback invoked when socket buffer space
   *                             becomes available
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1559
1560
   * @sk: socket whose state has changed
   *
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1561
1562
   * Called when more output buffer space is available for this socket.
   * We try not to wake our writers until they can make "significant"
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1563
   * progress, otherwise we'll waste resources thrashing kernel_sendmsg
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1564
1565
   * with a bunch of small requests.
   */
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1566
  static void xs_udp_write_space(struct sock *sk)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1567
  {
f064af1e5   Eric Dumazet   net: fix a lockde...
1568
  	read_lock_bh(&sk->sk_callback_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1569

c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1570
  	/* from net/core/sock.c:sock_def_write_space */
1f0fa1543   Ilpo Järvinen   net/sunrpc/xprtso...
1571
1572
  	if (sock_writeable(sk))
  		xs_write_space(sk);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1573

f064af1e5   Eric Dumazet   net: fix a lockde...
1574
  	read_unlock_bh(&sk->sk_callback_lock);
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1575
  }
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1576

c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
  /**
   * xs_tcp_write_space - callback invoked when socket buffer space
   *                             becomes available
   * @sk: socket whose state has changed
   *
   * Called when more output buffer space is available for this socket.
   * We try not to wake our writers until they can make "significant"
   * progress, otherwise we'll waste resources thrashing kernel_sendmsg
   * with a bunch of small requests.
   */
  static void xs_tcp_write_space(struct sock *sk)
  {
f064af1e5   Eric Dumazet   net: fix a lockde...
1589
  	read_lock_bh(&sk->sk_callback_lock);
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
1590
1591
  
  	/* from net/core/stream.c:sk_stream_write_space */
1f0fa1543   Ilpo Järvinen   net/sunrpc/xprtso...
1592
1593
  	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
  		xs_write_space(sk);
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
1594

f064af1e5   Eric Dumazet   net: fix a lockde...
1595
  	read_unlock_bh(&sk->sk_callback_lock);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1596
  }
470056c28   Chuck Lever   [PATCH] RPC: rati...
1597
  static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1598
  {
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
1599
1600
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
  	struct sock *sk = transport->inet;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1601

7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1602
  	if (transport->rcvsize) {
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1603
  		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1604
  		sk->sk_rcvbuf = transport->rcvsize * xprt->max_reqs * 2;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1605
  	}
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1606
  	if (transport->sndsize) {
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1607
  		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1608
  		sk->sk_sndbuf = transport->sndsize * xprt->max_reqs * 2;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1609
1610
1611
  		sk->sk_write_space(sk);
  	}
  }
43118c29d   Chuck Lever   [PATCH] RPC: get ...
1612
  /**
470056c28   Chuck Lever   [PATCH] RPC: rati...
1613
   * xs_udp_set_buffer_size - set send and receive limits
43118c29d   Chuck Lever   [PATCH] RPC: get ...
1614
   * @xprt: generic transport
470056c28   Chuck Lever   [PATCH] RPC: rati...
1615
1616
   * @sndsize: requested size of send buffer, in bytes
   * @rcvsize: requested size of receive buffer, in bytes
43118c29d   Chuck Lever   [PATCH] RPC: get ...
1617
   *
470056c28   Chuck Lever   [PATCH] RPC: rati...
1618
   * Set socket send and receive buffer size limits.
43118c29d   Chuck Lever   [PATCH] RPC: get ...
1619
   */
470056c28   Chuck Lever   [PATCH] RPC: rati...
1620
  static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
43118c29d   Chuck Lever   [PATCH] RPC: get ...
1621
  {
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1622
1623
1624
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
  
  	transport->sndsize = 0;
470056c28   Chuck Lever   [PATCH] RPC: rati...
1625
  	if (sndsize)
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1626
1627
  		transport->sndsize = sndsize + 1024;
  	transport->rcvsize = 0;
470056c28   Chuck Lever   [PATCH] RPC: rati...
1628
  	if (rcvsize)
7c6e066ec   Chuck Lever   SUNRPC: Move the ...
1629
  		transport->rcvsize = rcvsize + 1024;
470056c28   Chuck Lever   [PATCH] RPC: rati...
1630
1631
  
  	xs_udp_do_set_buffer_size(xprt);
43118c29d   Chuck Lever   [PATCH] RPC: get ...
1632
  }
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
  /**
   * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
   * @task: task that timed out
   *
   * Adjust the congestion window after a retransmit timeout has occurred.
   */
  static void xs_udp_timer(struct rpc_task *task)
  {
  	xprt_adjust_cwnd(task, -ETIMEDOUT);
  }
b85d88068   Chuck Lever   SUNRPC: select pr...
1643
1644
1645
1646
1647
1648
  static unsigned short xs_get_random_port(void)
  {
  	unsigned short range = xprt_max_resvport - xprt_min_resvport;
  	unsigned short rand = (unsigned short) net_random() % range;
  	return rand + xprt_min_resvport;
  }
922004120   Chuck Lever   SUNRPC: transport...
1649
1650
1651
1652
1653
1654
1655
1656
  /**
   * xs_set_port - reset the port number in the remote endpoint address
   * @xprt: generic transport
   * @port: new port number
   *
   */
  static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1657
1658
  	dprintk("RPC:       setting port for xprt %p to %u
  ", xprt, port);
c4efcb1d3   Chuck Lever   SUNRPC: Use "sock...
1659

9dc3b095b   Chuck Lever   SUNRPC: Update xp...
1660
1661
  	rpc_set_port(xs_addr(xprt), port);
  	xs_update_peer_port(xprt);
922004120   Chuck Lever   SUNRPC: transport...
1662
  }
5d4ec9329   Pavel Emelyanov   sunrpc: Remove un...
1663
  static unsigned short xs_get_srcport(struct sock_xprt *transport)
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1664
  {
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
1665
  	unsigned short port = transport->srcport;
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1666
1667
1668
1669
1670
  
  	if (port == 0 && transport->xprt.resvport)
  		port = xs_get_random_port();
  	return port;
  }
baaf4e487   Pavel Emelyanov   sunrpc: Remove un...
1671
  static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port)
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1672
  {
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
1673
1674
  	if (transport->srcport != 0)
  		transport->srcport = 0;
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1675
1676
1677
1678
1679
1680
  	if (!transport->xprt.resvport)
  		return 0;
  	if (port <= xprt_min_resvport || port > xprt_max_resvport)
  		return xprt_max_resvport;
  	return --port;
  }
beb59b682   Pavel Emelyanov   sunrpc: Merge the...
1681
  static int xs_bind(struct sock_xprt *transport, struct socket *sock)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1682
  {
beb59b682   Pavel Emelyanov   sunrpc: Merge the...
1683
  	struct sockaddr_storage myaddr;
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1684
  	int err, nloop = 0;
5d4ec9329   Pavel Emelyanov   sunrpc: Remove un...
1685
  	unsigned short port = xs_get_srcport(transport);
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1686
  	unsigned short last;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1687

beb59b682   Pavel Emelyanov   sunrpc: Merge the...
1688
  	memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1689
  	do {
beb59b682   Pavel Emelyanov   sunrpc: Merge the...
1690
1691
1692
  		rpc_set_port((struct sockaddr *)&myaddr, port);
  		err = kernel_bind(sock, (struct sockaddr *)&myaddr,
  				transport->xprt.addrlen);
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1693
  		if (port == 0)
d3bc9a1de   Frank van Maarseveen   SUNRPC client: ad...
1694
  			break;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1695
  		if (err == 0) {
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
1696
  			transport->srcport = port;
d3bc9a1de   Frank van Maarseveen   SUNRPC client: ad...
1697
  			break;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1698
  		}
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1699
  		last = port;
baaf4e487   Pavel Emelyanov   sunrpc: Remove un...
1700
  		port = xs_next_srcport(transport, port);
67a391d72   Trond Myklebust   SUNRPC: Fix TCP r...
1701
1702
1703
  		if (port > last)
  			nloop++;
  	} while (err == -EADDRINUSE && nloop != 2);
90058d37c   Chuck Lever   SUNRPC: create an...
1704

4232e8634   Chuck Lever   SUNRPC: Use conve...
1705
  	if (myaddr.ss_family == AF_INET)
beb59b682   Pavel Emelyanov   sunrpc: Merge the...
1706
1707
1708
1709
1710
1711
1712
1713
1714
  		dprintk("RPC:       %s %pI4:%u: %s (%d)
  ", __func__,
  				&((struct sockaddr_in *)&myaddr)->sin_addr,
  				port, err ? "failed" : "ok", err);
  	else
  		dprintk("RPC:       %s %pI6:%u: %s (%d)
  ", __func__,
  				&((struct sockaddr_in6 *)&myaddr)->sin6_addr,
  				port, err ? "failed" : "ok", err);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1715
1716
  	return err;
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
  /*
   * We don't support autobind on AF_LOCAL sockets
   */
  static void xs_local_rpcbind(struct rpc_task *task)
  {
  	xprt_set_bound(task->tk_xprt);
  }
  
  static void xs_local_set_port(struct rpc_xprt *xprt, unsigned short port)
  {
  }
beb59b682   Pavel Emelyanov   sunrpc: Merge the...
1728

ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1729
1730
1731
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  static struct lock_class_key xs_key[2];
  static struct lock_class_key xs_slock_key[2];
176e21ee2   Chuck Lever   SUNRPC: Support f...
1732
1733
1734
1735
1736
1737
1738
1739
  static inline void xs_reclassify_socketu(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  
  	BUG_ON(sock_owned_by_user(sk));
  	sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC",
  		&xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]);
  }
8945ee5e2   Chuck Lever   SUNRPC: Split xs_...
1740
  static inline void xs_reclassify_socket4(struct socket *sock)
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1741
1742
  {
  	struct sock *sk = sock->sk;
8945ee5e2   Chuck Lever   SUNRPC: Split xs_...
1743

02b3d3463   John Heffner   [NET] Cleanup: Us...
1744
  	BUG_ON(sock_owned_by_user(sk));
8945ee5e2   Chuck Lever   SUNRPC: Split xs_...
1745
1746
1747
  	sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC",
  		&xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]);
  }
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1748

8945ee5e2   Chuck Lever   SUNRPC: Split xs_...
1749
1750
1751
  static inline void xs_reclassify_socket6(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1752

f4921aff5   Linus Torvalds   Merge git://git.l...
1753
  	BUG_ON(sock_owned_by_user(sk));
8945ee5e2   Chuck Lever   SUNRPC: Split xs_...
1754
1755
  	sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC",
  		&xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]);
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1756
  }
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1757
1758
1759
  
  static inline void xs_reclassify_socket(int family, struct socket *sock)
  {
4232e8634   Chuck Lever   SUNRPC: Use conve...
1760
  	switch (family) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
1761
1762
1763
  	case AF_LOCAL:
  		xs_reclassify_socketu(sock);
  		break;
4232e8634   Chuck Lever   SUNRPC: Use conve...
1764
  	case AF_INET:
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1765
  		xs_reclassify_socket4(sock);
4232e8634   Chuck Lever   SUNRPC: Use conve...
1766
1767
  		break;
  	case AF_INET6:
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1768
  		xs_reclassify_socket6(sock);
4232e8634   Chuck Lever   SUNRPC: Use conve...
1769
1770
  		break;
  	}
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1771
  }
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1772
  #else
176e21ee2   Chuck Lever   SUNRPC: Support f...
1773
1774
1775
  static inline void xs_reclassify_socketu(struct socket *sock)
  {
  }
8945ee5e2   Chuck Lever   SUNRPC: Split xs_...
1776
1777
1778
1779
1780
  static inline void xs_reclassify_socket4(struct socket *sock)
  {
  }
  
  static inline void xs_reclassify_socket6(struct socket *sock)
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1781
1782
  {
  }
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1783
1784
1785
1786
  
  static inline void xs_reclassify_socket(int family, struct socket *sock)
  {
  }
ed07536ed   Peter Zijlstra   [PATCH] lockdep: ...
1787
  #endif
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1788
1789
  static struct socket *xs_create_sock(struct rpc_xprt *xprt,
  		struct sock_xprt *transport, int family, int type, int protocol)
22f793268   Pavel Emelyanov   sunrpc: Factor ou...
1790
1791
1792
  {
  	struct socket *sock;
  	int err;
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1793
  	err = __sock_create(xprt->xprt_net, family, type, protocol, &sock, 1);
22f793268   Pavel Emelyanov   sunrpc: Factor ou...
1794
1795
1796
1797
1798
1799
  	if (err < 0) {
  		dprintk("RPC:       can't create %d transport socket (%d).
  ",
  				protocol, -err);
  		goto out;
  	}
6bc9638ab   Pavel Emelyanov   sunrpc: Merge xs_...
1800
  	xs_reclassify_socket(family, sock);
22f793268   Pavel Emelyanov   sunrpc: Factor ou...
1801

4cea288aa   Ben Hutchings   sunrpc: Propagate...
1802
1803
  	err = xs_bind(transport, sock);
  	if (err) {
22f793268   Pavel Emelyanov   sunrpc: Factor ou...
1804
1805
1806
1807
1808
1809
1810
1811
  		sock_release(sock);
  		goto out;
  	}
  
  	return sock;
  out:
  	return ERR_PTR(err);
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
  static int xs_local_finish_connecting(struct rpc_xprt *xprt,
  				      struct socket *sock)
  {
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt,
  									xprt);
  
  	if (!transport->inet) {
  		struct sock *sk = sock->sk;
  
  		write_lock_bh(&sk->sk_callback_lock);
  
  		xs_save_old_callbacks(transport, sk);
  
  		sk->sk_user_data = xprt;
  		sk->sk_data_ready = xs_local_data_ready;
  		sk->sk_write_space = xs_udp_write_space;
  		sk->sk_error_report = xs_error_report;
  		sk->sk_allocation = GFP_ATOMIC;
  
  		xprt_clear_connected(xprt);
  
  		/* Reset to new socket */
  		transport->sock = sock;
  		transport->inet = sk;
  
  		write_unlock_bh(&sk->sk_callback_lock);
  	}
  
  	/* Tell the socket layer to start connecting... */
  	xprt->stat.connect_count++;
  	xprt->stat.connect_start = jiffies;
  	return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, 0);
  }
  
  /**
   * xs_local_setup_socket - create AF_LOCAL socket, connect to a local endpoint
   * @xprt: RPC transport to connect
   * @transport: socket transport to connect
   * @create_sock: function to create a socket of the correct type
   *
   * Invoked by a work queue tasklet.
   */
  static void xs_local_setup_socket(struct work_struct *work)
  {
  	struct sock_xprt *transport =
  		container_of(work, struct sock_xprt, connect_worker.work);
  	struct rpc_xprt *xprt = &transport->xprt;
  	struct socket *sock;
  	int status = -EIO;
  
  	if (xprt->shutdown)
  		goto out;
  
  	clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
  	status = __sock_create(xprt->xprt_net, AF_LOCAL,
  					SOCK_STREAM, 0, &sock, 1);
  	if (status < 0) {
  		dprintk("RPC:       can't create AF_LOCAL "
  			"transport socket (%d).
  ", -status);
  		goto out;
  	}
  	xs_reclassify_socketu(sock);
  
  	dprintk("RPC:       worker connecting xprt %p via AF_LOCAL to %s
  ",
  			xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);
  
  	status = xs_local_finish_connecting(xprt, sock);
  	switch (status) {
  	case 0:
  		dprintk("RPC:       xprt %p connected to %s
  ",
  				xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);
  		xprt_set_connected(xprt);
  		break;
  	case -ENOENT:
  		dprintk("RPC:       xprt %p: socket %s does not exist
  ",
  				xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);
  		break;
  	default:
  		printk(KERN_ERR "%s: unhandled error (%d) connecting to %s
  ",
  				__func__, -status,
  				xprt->address_strings[RPC_DISPLAY_ADDR]);
  	}
  
  out:
  	xprt_clear_connecting(xprt);
  	xprt_wake_pending_tasks(xprt, status);
  }
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
1904
1905
1906
1907
1908
1909
1910
1911
  static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
  {
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
  
  	if (!transport->inet) {
  		struct sock *sk = sock->sk;
  
  		write_lock_bh(&sk->sk_callback_lock);
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
1912
  		xs_save_old_callbacks(transport, sk);
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
1913
  		sk->sk_user_data = xprt;
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
1914
1915
  		sk->sk_data_ready = xs_udp_data_ready;
  		sk->sk_write_space = xs_udp_write_space;
482f32e65   Trond Myklebust   SUNRPC: Handle so...
1916
  		sk->sk_error_report = xs_error_report;
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
  		sk->sk_no_check = UDP_CSUM_NORCV;
  		sk->sk_allocation = GFP_ATOMIC;
  
  		xprt_set_connected(xprt);
  
  		/* Reset to new socket */
  		transport->sock = sock;
  		transport->inet = sk;
  
  		write_unlock_bh(&sk->sk_callback_lock);
  	}
  	xs_udp_do_set_buffer_size(xprt);
  }
8c14ff2aa   Pavel Emelyanov   sunrpc: Remove UD...
1930
  static void xs_udp_setup_socket(struct work_struct *work)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1931
  {
34161db6b   Trond Myklebust   Merge branch 'mas...
1932
1933
  	struct sock_xprt *transport =
  		container_of(work, struct sock_xprt, connect_worker.work);
c84754618   Chuck Lever   SUNRPC: Move rpc_...
1934
  	struct rpc_xprt *xprt = &transport->xprt;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
1935
  	struct socket *sock = transport->sock;
b65c03106   Pavel Emelyanov   sunrpc: Factor ou...
1936
  	int status = -EIO;
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1937

01d37c428   Trond Myklebust   SUNRPC: xprt_conn...
1938
  	if (xprt->shutdown)
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
1939
  		goto out;
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1940

b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
1941
  	/* Start by resetting any existing state */
fe315e76f   Chuck Lever   SUNRPC: Avoid spu...
1942
  	xs_reset_transport(transport);
8c14ff2aa   Pavel Emelyanov   sunrpc: Remove UD...
1943
1944
  	sock = xs_create_sock(xprt, transport,
  			xs_addr(xprt)->sa_family, SOCK_DGRAM, IPPROTO_UDP);
b65c03106   Pavel Emelyanov   sunrpc: Factor ou...
1945
  	if (IS_ERR(sock))
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
1946
  		goto out;
68e220bd5   Chuck Lever   SUNRPC: create co...
1947

c740eff84   Chuck Lever   SUNRPC: Kill RPC_...
1948
1949
1950
1951
1952
1953
  	dprintk("RPC:       worker connecting xprt %p via %s to "
  				"%s (port %s)
  ", xprt,
  			xprt->address_strings[RPC_DISPLAY_PROTO],
  			xprt->address_strings[RPC_DISPLAY_ADDR],
  			xprt->address_strings[RPC_DISPLAY_PORT]);
68e220bd5   Chuck Lever   SUNRPC: create co...
1954
1955
  
  	xs_udp_finish_connecting(xprt, sock);
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
1956
1957
  	status = 0;
  out:
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
1958
  	xprt_clear_connecting(xprt);
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
1959
  	xprt_wake_pending_tasks(xprt, status);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1960
  }
3167e12c0   Chuck Lever   [PATCH] RPC: make...
1961
1962
1963
1964
  /*
   * We need to preserve the port number so the reply cache on the server can
   * find our cached RPC replies when we get around to reconnecting.
   */
58dddac9c   Pavel Emelyanov   sunrpc: Remove du...
1965
  static void xs_abort_connection(struct sock_xprt *transport)
3167e12c0   Chuck Lever   [PATCH] RPC: make...
1966
1967
  {
  	int result;
3167e12c0   Chuck Lever   [PATCH] RPC: make...
1968
  	struct sockaddr any;
58dddac9c   Pavel Emelyanov   sunrpc: Remove du...
1969
1970
  	dprintk("RPC:       disconnecting xprt %p to reuse port
  ", transport);
3167e12c0   Chuck Lever   [PATCH] RPC: make...
1971
1972
1973
1974
1975
1976
1977
  
  	/*
  	 * Disconnect the transport socket by doing a connect operation
  	 * with AF_UNSPEC.  This should return immediately...
  	 */
  	memset(&any, 0, sizeof(any));
  	any.sa_family = AF_UNSPEC;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
1978
  	result = kernel_connect(transport->sock, &any, sizeof(any), 0);
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
1979
  	if (!result)
58dddac9c   Pavel Emelyanov   sunrpc: Remove du...
1980
  		xs_sock_mark_closed(&transport->xprt);
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
1981
  	else
46121cf7d   Chuck Lever   SUNRPC: fix print...
1982
1983
  		dprintk("RPC:       AF_UNSPEC connect return code %d
  ",
3167e12c0   Chuck Lever   [PATCH] RPC: make...
1984
1985
  				result);
  }
58dddac9c   Pavel Emelyanov   sunrpc: Remove du...
1986
  static void xs_tcp_reuse_connection(struct sock_xprt *transport)
40d2549db   Trond Myklebust   SUNRPC: Don't dis...
1987
1988
  {
  	unsigned int state = transport->inet->sk_state;
669502ff3   Andy Chittenden   SUNRPC: fix NFS c...
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
  	if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) {
  		/* we don't need to abort the connection if the socket
  		 * hasn't undergone a shutdown
  		 */
  		if (transport->inet->sk_shutdown == 0)
  			return;
  		dprintk("RPC:       %s: TCP_CLOSEd and sk_shutdown set to %d
  ",
  				__func__, transport->inet->sk_shutdown);
  	}
  	if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) {
  		/* we don't need to abort the connection if the socket
  		 * hasn't undergone a shutdown
  		 */
  		if (transport->inet->sk_shutdown == 0)
  			return;
  		dprintk("RPC:       %s: ESTABLISHED/SYN_SENT "
  				"sk_shutdown set to %d
  ",
  				__func__, transport->inet->sk_shutdown);
  	}
58dddac9c   Pavel Emelyanov   sunrpc: Remove du...
2010
  	xs_abort_connection(transport);
40d2549db   Trond Myklebust   SUNRPC: Don't dis...
2011
  }
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
2012
  static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2013
  {
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
2014
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
fe19a96b1   Trond Myklebust   SUNRPC: Deal with...
2015
  	int ret = -ENOTCONN;
edb267a68   Chuck Lever   SUNRPC: add xprt ...
2016

ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
2017
  	if (!transport->inet) {
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2018
2019
2020
  		struct sock *sk = sock->sk;
  
  		write_lock_bh(&sk->sk_callback_lock);
2a9e1cfa2   Trond Myklebust   SUNRPC: Respond p...
2021
  		xs_save_old_callbacks(transport, sk);
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2022
  		sk->sk_user_data = xprt;
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2023
2024
2025
  		sk->sk_data_ready = xs_tcp_data_ready;
  		sk->sk_state_change = xs_tcp_state_change;
  		sk->sk_write_space = xs_tcp_write_space;
482f32e65   Trond Myklebust   SUNRPC: Handle so...
2026
  		sk->sk_error_report = xs_error_report;
b079fa7ba   Trond Myklebust   RPC: Do not block...
2027
  		sk->sk_allocation = GFP_ATOMIC;
3167e12c0   Chuck Lever   [PATCH] RPC: make...
2028
2029
2030
2031
2032
2033
  
  		/* socket options */
  		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
  		sock_reset_flag(sk, SOCK_LINGER);
  		tcp_sk(sk)->linger2 = 0;
  		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2034
2035
2036
2037
  
  		xprt_clear_connected(xprt);
  
  		/* Reset to new socket */
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
2038
2039
  		transport->sock = sock;
  		transport->inet = sk;
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2040
2041
2042
  
  		write_unlock_bh(&sk->sk_callback_lock);
  	}
01d37c428   Trond Myklebust   SUNRPC: xprt_conn...
2043
  	if (!xprt_bound(xprt))
fe19a96b1   Trond Myklebust   SUNRPC: Deal with...
2044
  		goto out;
01d37c428   Trond Myklebust   SUNRPC: xprt_conn...
2045

b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2046
  	/* Tell the socket layer to start connecting... */
262ca07de   Chuck Lever   SUNRPC: add a han...
2047
2048
  	xprt->stat.connect_count++;
  	xprt->stat.connect_start = jiffies;
fe19a96b1   Trond Myklebust   SUNRPC: Deal with...
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
  	ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
  	switch (ret) {
  	case 0:
  	case -EINPROGRESS:
  		/* SYN_SENT! */
  		xprt->connect_cookie++;
  		if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
  			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
  	}
  out:
  	return ret;
16be2d20d   Chuck Lever   SUNRPC: Refactor ...
2060
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2061
  /**
b61d59fff   Trond Myklebust   SUNRPC: xs_tcp_co...
2062
2063
2064
2065
   * xs_tcp_setup_socket - create a TCP socket and connect to a remote endpoint
   * @xprt: RPC transport to connect
   * @transport: socket transport to connect
   * @create_sock: function to create a socket of the correct type
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2066
2067
   *
   * Invoked by a work queue tasklet.
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2068
   */
cdd518d52   Pavel Emelyanov   sunrpc: Remove TC...
2069
  static void xs_tcp_setup_socket(struct work_struct *work)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2070
  {
cdd518d52   Pavel Emelyanov   sunrpc: Remove TC...
2071
2072
  	struct sock_xprt *transport =
  		container_of(work, struct sock_xprt, connect_worker.work);
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
2073
  	struct socket *sock = transport->sock;
a9f5f0f7b   Pavel Emelyanov   sunrpc: Get xprt ...
2074
  	struct rpc_xprt *xprt = &transport->xprt;
b61d59fff   Trond Myklebust   SUNRPC: xs_tcp_co...
2075
  	int status = -EIO;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2076

01d37c428   Trond Myklebust   SUNRPC: xprt_conn...
2077
  	if (xprt->shutdown)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2078
  		goto out;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
2079
  	if (!sock) {
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2080
  		clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
cdd518d52   Pavel Emelyanov   sunrpc: Remove TC...
2081
2082
  		sock = xs_create_sock(xprt, transport,
  				xs_addr(xprt)->sa_family, SOCK_STREAM, IPPROTO_TCP);
b61d59fff   Trond Myklebust   SUNRPC: xs_tcp_co...
2083
2084
  		if (IS_ERR(sock)) {
  			status = PTR_ERR(sock);
3167e12c0   Chuck Lever   [PATCH] RPC: make...
2085
2086
  			goto out;
  		}
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2087
2088
  	} else {
  		int abort_and_exit;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2089

7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2090
2091
  		abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT,
  				&xprt->state);
3167e12c0   Chuck Lever   [PATCH] RPC: make...
2092
  		/* "close" the socket, preserving the local port */
58dddac9c   Pavel Emelyanov   sunrpc: Remove du...
2093
  		xs_tcp_reuse_connection(transport);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2094

7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2095
2096
2097
  		if (abort_and_exit)
  			goto out_eagain;
  	}
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2098

c740eff84   Chuck Lever   SUNRPC: Kill RPC_...
2099
2100
2101
2102
2103
2104
  	dprintk("RPC:       worker connecting xprt %p via %s to "
  				"%s (port %s)
  ", xprt,
  			xprt->address_strings[RPC_DISPLAY_PROTO],
  			xprt->address_strings[RPC_DISPLAY_ADDR],
  			xprt->address_strings[RPC_DISPLAY_PORT]);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
2105

16be2d20d   Chuck Lever   SUNRPC: Refactor ...
2106
  	status = xs_tcp_finish_connecting(xprt, sock);
46121cf7d   Chuck Lever   SUNRPC: fix print...
2107
2108
2109
2110
  	dprintk("RPC:       %p connect status %d connected %d sock state %d
  ",
  			xprt, -status, xprt_connected(xprt),
  			sock->sk->sk_state);
2a4919919   Trond Myklebust   SUNRPC: Return EA...
2111
  	switch (status) {
f75e6745a   Trond Myklebust   SUNRPC: Fix the p...
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
  	default:
  		printk("%s: connect returned unhandled error %d
  ",
  			__func__, status);
  	case -EADDRNOTAVAIL:
  		/* We're probably in TIME_WAIT. Get rid of existing socket,
  		 * and retry
  		 */
  		set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
  		xprt_force_disconnect(xprt);
88b5ed73b   Trond Myklebust   SUNRPC: Fix a mis...
2122
  		break;
8a2cec295   Trond Myklebust   SUNRPC: Delay, th...
2123
2124
2125
2126
  	case -ECONNREFUSED:
  	case -ECONNRESET:
  	case -ENETUNREACH:
  		/* retry with existing socket, after a delay */
2a4919919   Trond Myklebust   SUNRPC: Return EA...
2127
2128
2129
  	case 0:
  	case -EINPROGRESS:
  	case -EALREADY:
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2130
2131
  		xprt_clear_connecting(xprt);
  		return;
9fcfe0c83   Trond Myklebust   SUNRPC: Handle EI...
2132
2133
2134
2135
2136
  	case -EINVAL:
  		/* Happens, for instance, if the user specified a link
  		 * local IPv6 address without a scope-id.
  		 */
  		goto out;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2137
  	}
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2138
  out_eagain:
2a4919919   Trond Myklebust   SUNRPC: Return EA...
2139
  	status = -EAGAIN;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2140
  out:
68e220bd5   Chuck Lever   SUNRPC: create co...
2141
  	xprt_clear_connecting(xprt);
7d1e8255c   Trond Myklebust   SUNRPC: Add the e...
2142
  	xprt_wake_pending_tasks(xprt, status);
68e220bd5   Chuck Lever   SUNRPC: create co...
2143
  }
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2144

9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2145
2146
2147
2148
2149
  /**
   * xs_connect - connect a socket to a remote endpoint
   * @task: address of RPC task that manages state of connect request
   *
   * TCP: If the remote end dropped the connection, delay reconnecting.
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2150
2151
2152
2153
2154
2155
2156
   *
   * UDP socket connects are synchronous, but we use a work queue anyway
   * to guarantee that even unprivileged user processes can set up a
   * socket on a privileged port.
   *
   * If a UDP socket connect fails, the delay behavior here prevents
   * retry floods (hard mounts).
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2157
2158
   */
  static void xs_connect(struct rpc_task *task)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2159
2160
  {
  	struct rpc_xprt *xprt = task->tk_xprt;
ee0ac0c22   Chuck Lever   SUNRPC: Remove so...
2161
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2162

09a21c410   Chuck Lever   SUNRPC: Allow RPC...
2163
  	if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
2164
2165
2166
  		dprintk("RPC:       xs_connect delayed xprt %p for %lu "
  				"seconds
  ",
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2167
  				xprt, xprt->reestablish_timeout / HZ);
c1384c9c4   Trond Myklebust   SUNRPC: fix hang ...
2168
2169
2170
  		queue_delayed_work(rpciod_workqueue,
  				   &transport->connect_worker,
  				   xprt->reestablish_timeout);
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2171
  		xprt->reestablish_timeout <<= 1;
61d0a8e6a   Neil Brown   NFS/RPC: fix prob...
2172
2173
  		if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
  			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2174
2175
  		if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
  			xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
b0d93ad51   Chuck Lever   [PATCH] RPC: sepa...
2176
  	} else {
46121cf7d   Chuck Lever   SUNRPC: fix print...
2177
2178
  		dprintk("RPC:       xs_connect scheduled xprt %p
  ", xprt);
c1384c9c4   Trond Myklebust   SUNRPC: fix hang ...
2179
2180
  		queue_delayed_work(rpciod_workqueue,
  				   &transport->connect_worker, 0);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2181
2182
  	}
  }
262ca07de   Chuck Lever   SUNRPC: add a han...
2183
  /**
176e21ee2   Chuck Lever   SUNRPC: Support f...
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
   * xs_local_print_stats - display AF_LOCAL socket-specifc stats
   * @xprt: rpc_xprt struct containing statistics
   * @seq: output file
   *
   */
  static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
  {
  	long idle_time = 0;
  
  	if (xprt_connected(xprt))
  		idle_time = (long)(jiffies - xprt->last_used) / HZ;
  
  	seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu "
  			"%llu %llu
  ",
  			xprt->stat.bind_count,
  			xprt->stat.connect_count,
  			xprt->stat.connect_time,
  			idle_time,
  			xprt->stat.sends,
  			xprt->stat.recvs,
  			xprt->stat.bad_xids,
  			xprt->stat.req_u,
  			xprt->stat.bklog_u);
  }
  
  /**
262ca07de   Chuck Lever   SUNRPC: add a han...
2211
2212
2213
2214
2215
2216
2217
   * xs_udp_print_stats - display UDP socket-specifc stats
   * @xprt: rpc_xprt struct containing statistics
   * @seq: output file
   *
   */
  static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
  {
c84754618   Chuck Lever   SUNRPC: Move rpc_...
2218
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
262ca07de   Chuck Lever   SUNRPC: add a han...
2219
2220
  	seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu
  ",
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
2221
  			transport->srcport,
262ca07de   Chuck Lever   SUNRPC: add a han...
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
  			xprt->stat.bind_count,
  			xprt->stat.sends,
  			xprt->stat.recvs,
  			xprt->stat.bad_xids,
  			xprt->stat.req_u,
  			xprt->stat.bklog_u);
  }
  
  /**
   * xs_tcp_print_stats - display TCP socket-specifc stats
   * @xprt: rpc_xprt struct containing statistics
   * @seq: output file
   *
   */
  static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
  {
c84754618   Chuck Lever   SUNRPC: Move rpc_...
2238
  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
262ca07de   Chuck Lever   SUNRPC: add a han...
2239
2240
2241
2242
2243
2244
2245
  	long idle_time = 0;
  
  	if (xprt_connected(xprt))
  		idle_time = (long)(jiffies - xprt->last_used) / HZ;
  
  	seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu
  ",
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
2246
  			transport->srcport,
262ca07de   Chuck Lever   SUNRPC: add a han...
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
  			xprt->stat.bind_count,
  			xprt->stat.connect_count,
  			xprt->stat.connect_time,
  			idle_time,
  			xprt->stat.sends,
  			xprt->stat.recvs,
  			xprt->stat.bad_xids,
  			xprt->stat.req_u,
  			xprt->stat.bklog_u);
  }
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2257
2258
2259
2260
2261
  /*
   * Allocate a bunch of pages for a scratch buffer for the rpc code. The reason
   * we allocate pages instead doing a kmalloc like rpc_malloc is because we want
   * to use the server side send routines.
   */
5a51f13ad   H Hartley Sweeten   xprtsock.c: make ...
2262
  static void *bc_malloc(struct rpc_task *task, size_t size)
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
  {
  	struct page *page;
  	struct rpc_buffer *buf;
  
  	BUG_ON(size > PAGE_SIZE - sizeof(struct rpc_buffer));
  	page = alloc_page(GFP_KERNEL);
  
  	if (!page)
  		return NULL;
  
  	buf = page_address(page);
  	buf->len = PAGE_SIZE;
  
  	return buf->data;
  }
  
  /*
   * Free the space allocated in the bc_alloc routine
   */
5a51f13ad   H Hartley Sweeten   xprtsock.c: make ...
2282
  static void bc_free(void *buffer)
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
  {
  	struct rpc_buffer *buf;
  
  	if (!buffer)
  		return;
  
  	buf = container_of(buffer, struct rpc_buffer, data);
  	free_page((unsigned long)buf);
  }
  
  /*
   * Use the svc_sock to send the callback. Must be called with svsk->sk_mutex
   * held. Borrows heavily from svc_tcp_sendto and xs_tcp_send_request.
   */
  static int bc_sendto(struct rpc_rqst *req)
  {
  	int len;
  	struct xdr_buf *xbufp = &req->rq_snd_buf;
  	struct rpc_xprt *xprt = req->rq_xprt;
  	struct sock_xprt *transport =
  				container_of(xprt, struct sock_xprt, xprt);
  	struct socket *sock = transport->sock;
  	unsigned long headoff;
  	unsigned long tailoff;
61677eeec   Chuck Lever   SUNRPC: Rename xs...
2307
  	xs_encode_stream_record_marker(xbufp);
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
  
  	tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK;
  	headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK;
  	len = svc_send_common(sock, xbufp,
  			      virt_to_page(xbufp->head[0].iov_base), headoff,
  			      xbufp->tail[0].iov_base, tailoff);
  
  	if (len != xbufp->len) {
  		printk(KERN_NOTICE "Error sending entire callback!
  ");
  		len = -EAGAIN;
  	}
  
  	return len;
  }
  
  /*
   * The send routine. Borrows from svc_send
   */
  static int bc_send_request(struct rpc_task *task)
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct svc_xprt	*xprt;
  	struct svc_sock         *svsk;
  	u32                     len;
  
  	dprintk("sending request with xid: %08x
  ", ntohl(req->rq_xid));
  	/*
  	 * Get the server socket associated with this callback xprt
  	 */
  	xprt = req->rq_xprt->bc_xprt;
  	svsk = container_of(xprt, struct svc_sock, sk_xprt);
  
  	/*
  	 * Grab the mutex to serialize data as the connection is shared
  	 * with the fore channel
  	 */
  	if (!mutex_trylock(&xprt->xpt_mutex)) {
  		rpc_sleep_on(&xprt->xpt_bc_pending, task, NULL);
  		if (!mutex_trylock(&xprt->xpt_mutex))
  			return -EAGAIN;
  		rpc_wake_up_queued_task(&xprt->xpt_bc_pending, task);
  	}
  	if (test_bit(XPT_DEAD, &xprt->xpt_flags))
  		len = -ENOTCONN;
  	else
  		len = bc_sendto(req);
  	mutex_unlock(&xprt->xpt_mutex);
  
  	if (len > 0)
  		len = 0;
  
  	return len;
  }
  
  /*
   * The close routine. Since this is client initiated, we do nothing
   */
  
  static void bc_close(struct rpc_xprt *xprt)
  {
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2370
2371
2372
2373
2374
2375
2376
2377
2378
  }
  
  /*
   * The xprt destroy routine. Again, because this connection is client
   * initiated, we do nothing
   */
  
  static void bc_destroy(struct rpc_xprt *xprt)
  {
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2379
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
  static struct rpc_xprt_ops xs_local_ops = {
  	.reserve_xprt		= xprt_reserve_xprt,
  	.release_xprt		= xs_tcp_release_xprt,
  	.rpcbind		= xs_local_rpcbind,
  	.set_port		= xs_local_set_port,
  	.connect		= xs_connect,
  	.buf_alloc		= rpc_malloc,
  	.buf_free		= rpc_free,
  	.send_request		= xs_local_send_request,
  	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
  	.close			= xs_close,
  	.destroy		= xs_destroy,
  	.print_stats		= xs_local_print_stats,
  };
262965f53   Chuck Lever   [PATCH] RPC: sepa...
2394
  static struct rpc_xprt_ops xs_udp_ops = {
43118c29d   Chuck Lever   [PATCH] RPC: get ...
2395
  	.set_buffer_size	= xs_udp_set_buffer_size,
12a804698   Chuck Lever   [PATCH] RPC: expo...
2396
  	.reserve_xprt		= xprt_reserve_xprt_cong,
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
2397
  	.release_xprt		= xprt_release_xprt_cong,
45160d627   Chuck Lever   SUNRPC: Rename rp...
2398
  	.rpcbind		= rpcb_getport_async,
922004120   Chuck Lever   SUNRPC: transport...
2399
  	.set_port		= xs_set_port,
262965f53   Chuck Lever   [PATCH] RPC: sepa...
2400
  	.connect		= xs_connect,
021071483   Chuck Lever   SUNRPC: switchabl...
2401
2402
  	.buf_alloc		= rpc_malloc,
  	.buf_free		= rpc_free,
262965f53   Chuck Lever   [PATCH] RPC: sepa...
2403
  	.send_request		= xs_udp_send_request,
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
2404
  	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
2405
  	.timer			= xs_udp_timer,
a58dd398f   Chuck Lever   [PATCH] RPC: add ...
2406
  	.release_request	= xprt_release_rqst_cong,
262965f53   Chuck Lever   [PATCH] RPC: sepa...
2407
2408
  	.close			= xs_close,
  	.destroy		= xs_destroy,
262ca07de   Chuck Lever   SUNRPC: add a han...
2409
  	.print_stats		= xs_udp_print_stats,
262965f53   Chuck Lever   [PATCH] RPC: sepa...
2410
2411
2412
  };
  
  static struct rpc_xprt_ops xs_tcp_ops = {
12a804698   Chuck Lever   [PATCH] RPC: expo...
2413
  	.reserve_xprt		= xprt_reserve_xprt,
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
2414
  	.release_xprt		= xs_tcp_release_xprt,
45160d627   Chuck Lever   SUNRPC: Rename rp...
2415
  	.rpcbind		= rpcb_getport_async,
922004120   Chuck Lever   SUNRPC: transport...
2416
  	.set_port		= xs_set_port,
0b9e79431   Trond Myklebust   SUNRPC: Move the ...
2417
  	.connect		= xs_connect,
021071483   Chuck Lever   SUNRPC: switchabl...
2418
2419
  	.buf_alloc		= rpc_malloc,
  	.buf_free		= rpc_free,
262965f53   Chuck Lever   [PATCH] RPC: sepa...
2420
  	.send_request		= xs_tcp_send_request,
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
2421
  	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
f75e6745a   Trond Myklebust   SUNRPC: Fix the p...
2422
  	.close			= xs_tcp_close,
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2423
  	.destroy		= xs_destroy,
262ca07de   Chuck Lever   SUNRPC: add a han...
2424
  	.print_stats		= xs_tcp_print_stats,
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2425
  };
4cfc7e601   Rahul Iyer   nfsd41: sunrpc: A...
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
  /*
   * The rpc_xprt_ops for the server backchannel
   */
  
  static struct rpc_xprt_ops bc_tcp_ops = {
  	.reserve_xprt		= xprt_reserve_xprt,
  	.release_xprt		= xprt_release_xprt,
  	.buf_alloc		= bc_malloc,
  	.buf_free		= bc_free,
  	.send_request		= bc_send_request,
  	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
  	.close			= bc_close,
  	.destroy		= bc_destroy,
  	.print_stats		= xs_tcp_print_stats,
  };
924768508   Chuck Lever   SUNRPC: Properly ...
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
  static int xs_init_anyaddr(const int family, struct sockaddr *sap)
  {
  	static const struct sockaddr_in sin = {
  		.sin_family		= AF_INET,
  		.sin_addr.s_addr	= htonl(INADDR_ANY),
  	};
  	static const struct sockaddr_in6 sin6 = {
  		.sin6_family		= AF_INET6,
  		.sin6_addr		= IN6ADDR_ANY_INIT,
  	};
  
  	switch (family) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
2453
2454
  	case AF_LOCAL:
  		break;
924768508   Chuck Lever   SUNRPC: Properly ...
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
  	case AF_INET:
  		memcpy(sap, &sin, sizeof(sin));
  		break;
  	case AF_INET6:
  		memcpy(sap, &sin6, sizeof(sin6));
  		break;
  	default:
  		dprintk("RPC:       %s: Bad address family
  ", __func__);
  		return -EAFNOSUPPORT;
  	}
  	return 0;
  }
3c341b0b9   \"Talpey, Thomas\   SUNRPC: rename th...
2468
  static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2469
2470
  				      unsigned int slot_table_size,
  				      unsigned int max_slot_table_size)
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2471
2472
  {
  	struct rpc_xprt *xprt;
ffc2e518c   Chuck Lever   SUNRPC: Allocate ...
2473
  	struct sock_xprt *new;
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2474

96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
2475
  	if (args->addrlen > sizeof(xprt->addr)) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
2476
2477
  		dprintk("RPC:       xs_setup_xprt: address too large
  ");
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2478
2479
  		return ERR_PTR(-EBADF);
  	}
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2480
2481
  	xprt = xprt_alloc(args->net, sizeof(*new), slot_table_size,
  			max_slot_table_size);
bd1722d43   Pavel Emelyanov   sunrpc: Factor ou...
2482
  	if (xprt == NULL) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
2483
2484
2485
  		dprintk("RPC:       xs_setup_xprt: couldn't allocate "
  				"rpc_xprt
  ");
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2486
2487
  		return ERR_PTR(-ENOMEM);
  	}
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2488

bd1722d43   Pavel Emelyanov   sunrpc: Factor ou...
2489
  	new = container_of(xprt, struct sock_xprt, xprt);
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
2490
2491
  	memcpy(&xprt->addr, args->dstaddr, args->addrlen);
  	xprt->addrlen = args->addrlen;
d3bc9a1de   Frank van Maarseveen   SUNRPC client: ad...
2492
  	if (args->srcaddr)
fbfffbd5e   Chuck Lever   SUNRPC: Rename so...
2493
  		memcpy(&new->srcaddr, args->srcaddr, args->addrlen);
924768508   Chuck Lever   SUNRPC: Properly ...
2494
2495
2496
2497
  	else {
  		int err;
  		err = xs_init_anyaddr(args->dstaddr->sa_family,
  					(struct sockaddr *)&new->srcaddr);
2aa13531b   Stanislav Kinsbursky   SUNRPC: destroy f...
2498
2499
  		if (err != 0) {
  			xprt_free(xprt);
924768508   Chuck Lever   SUNRPC: Properly ...
2500
  			return ERR_PTR(err);
2aa13531b   Stanislav Kinsbursky   SUNRPC: destroy f...
2501
  		}
924768508   Chuck Lever   SUNRPC: Properly ...
2502
  	}
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2503
2504
2505
  
  	return xprt;
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
  static const struct rpc_timeout xs_local_default_timeout = {
  	.to_initval = 10 * HZ,
  	.to_maxval = 10 * HZ,
  	.to_retries = 2,
  };
  
  /**
   * xs_setup_local - Set up transport to use an AF_LOCAL socket
   * @args: rpc transport creation arguments
   *
   * AF_LOCAL is a "tpi_cots_ord" transport, just like TCP
   */
  static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
  {
  	struct sockaddr_un *sun = (struct sockaddr_un *)args->dstaddr;
  	struct sock_xprt *transport;
  	struct rpc_xprt *xprt;
  	struct rpc_xprt *ret;
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2524
2525
  	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
  			xprt_max_tcp_slot_table_entries);
176e21ee2   Chuck Lever   SUNRPC: Support f...
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
  	if (IS_ERR(xprt))
  		return xprt;
  	transport = container_of(xprt, struct sock_xprt, xprt);
  
  	xprt->prot = 0;
  	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
  	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
  
  	xprt->bind_timeout = XS_BIND_TO;
  	xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
  	xprt->idle_timeout = XS_IDLE_DISC_TO;
  
  	xprt->ops = &xs_local_ops;
  	xprt->timeout = &xs_local_default_timeout;
  
  	switch (sun->sun_family) {
  	case AF_LOCAL:
  		if (sun->sun_path[0] != '/') {
  			dprintk("RPC:       bad AF_LOCAL address: %s
  ",
  					sun->sun_path);
  			ret = ERR_PTR(-EINVAL);
  			goto out_err;
  		}
  		xprt_set_bound(xprt);
  		INIT_DELAYED_WORK(&transport->connect_worker,
  					xs_local_setup_socket);
  		xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
  		break;
  	default:
  		ret = ERR_PTR(-EAFNOSUPPORT);
  		goto out_err;
  	}
  
  	dprintk("RPC:       set up xprt to %s via AF_LOCAL
  ",
  			xprt->address_strings[RPC_DISPLAY_ADDR]);
  
  	if (try_module_get(THIS_MODULE))
  		return xprt;
  	ret = ERR_PTR(-EINVAL);
  out_err:
  	xprt_free(xprt);
  	return ret;
  }
2881ae74e   Trond Myklebust   SUNRPC: Clean up ...
2571
2572
2573
2574
2575
2576
  static const struct rpc_timeout xs_udp_default_timeout = {
  	.to_initval = 5 * HZ,
  	.to_maxval = 30 * HZ,
  	.to_increment = 5 * HZ,
  	.to_retries = 5,
  };
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2577
2578
  /**
   * xs_setup_udp - Set up transport to use a UDP socket
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
2579
   * @args: rpc transport creation arguments
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2580
2581
   *
   */
483066d62   Adrian Bunk   SUNRPC: make sunr...
2582
  static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2583
  {
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2584
  	struct sockaddr *addr = args->dstaddr;
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2585
  	struct rpc_xprt *xprt;
c84754618   Chuck Lever   SUNRPC: Move rpc_...
2586
  	struct sock_xprt *transport;
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2587
  	struct rpc_xprt *ret;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2588

d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2589
2590
  	xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries,
  			xprt_udp_slot_table_entries);
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2591
2592
  	if (IS_ERR(xprt))
  		return xprt;
c84754618   Chuck Lever   SUNRPC: Move rpc_...
2593
  	transport = container_of(xprt, struct sock_xprt, xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2594

ec739ef03   Chuck Lever   SUNRPC: Create a ...
2595
  	xprt->prot = IPPROTO_UDP;
808012fbb   Chuck Lever   [PATCH] RPC: skip...
2596
  	xprt->tsh_size = 0;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2597
2598
  	/* XXX: header size can vary due to auth type, IPv6, etc. */
  	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2599
  	xprt->bind_timeout = XS_BIND_TO;
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2600
2601
  	xprt->reestablish_timeout = XS_UDP_REEST_TO;
  	xprt->idle_timeout = XS_IDLE_DISC_TO;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2602

262965f53   Chuck Lever   [PATCH] RPC: sepa...
2603
  	xprt->ops = &xs_udp_ops;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2604

ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
2605
  	xprt->timeout = &xs_udp_default_timeout;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2606

8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2607
2608
2609
2610
2611
2612
  	switch (addr->sa_family) {
  	case AF_INET:
  		if (((struct sockaddr_in *)addr)->sin_port != htons(0))
  			xprt_set_bound(xprt);
  
  		INIT_DELAYED_WORK(&transport->connect_worker,
8c14ff2aa   Pavel Emelyanov   sunrpc: Remove UD...
2613
  					xs_udp_setup_socket);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
2614
  		xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP);
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2615
2616
2617
2618
2619
2620
  		break;
  	case AF_INET6:
  		if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0))
  			xprt_set_bound(xprt);
  
  		INIT_DELAYED_WORK(&transport->connect_worker,
8c14ff2aa   Pavel Emelyanov   sunrpc: Remove UD...
2621
  					xs_udp_setup_socket);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
2622
  		xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6);
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2623
2624
  		break;
  	default:
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2625
2626
  		ret = ERR_PTR(-EAFNOSUPPORT);
  		goto out_err;
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2627
  	}
c740eff84   Chuck Lever   SUNRPC: Kill RPC_...
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
  	if (xprt_bound(xprt))
  		dprintk("RPC:       set up xprt to %s (port %s) via %s
  ",
  				xprt->address_strings[RPC_DISPLAY_ADDR],
  				xprt->address_strings[RPC_DISPLAY_PORT],
  				xprt->address_strings[RPC_DISPLAY_PROTO]);
  	else
  		dprintk("RPC:       set up xprt to %s (autobind) via %s
  ",
  				xprt->address_strings[RPC_DISPLAY_ADDR],
  				xprt->address_strings[RPC_DISPLAY_PROTO]);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
2639

bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2640
2641
  	if (try_module_get(THIS_MODULE))
  		return xprt;
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2642
2643
  	ret = ERR_PTR(-EINVAL);
  out_err:
e204e621b   Pavel Emelyanov   sunrpc: Factor ou...
2644
  	xprt_free(xprt);
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2645
  	return ret;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2646
  }
2881ae74e   Trond Myklebust   SUNRPC: Clean up ...
2647
2648
2649
2650
2651
  static const struct rpc_timeout xs_tcp_default_timeout = {
  	.to_initval = 60 * HZ,
  	.to_maxval = 60 * HZ,
  	.to_retries = 2,
  };
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2652
2653
  /**
   * xs_setup_tcp - Set up transport to use a TCP socket
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
2654
   * @args: rpc transport creation arguments
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
2655
2656
   *
   */
483066d62   Adrian Bunk   SUNRPC: make sunr...
2657
  static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2658
  {
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2659
  	struct sockaddr *addr = args->dstaddr;
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2660
  	struct rpc_xprt *xprt;
c84754618   Chuck Lever   SUNRPC: Move rpc_...
2661
  	struct sock_xprt *transport;
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2662
  	struct rpc_xprt *ret;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2663

d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2664
2665
  	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
  			xprt_max_tcp_slot_table_entries);
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
2666
2667
  	if (IS_ERR(xprt))
  		return xprt;
c84754618   Chuck Lever   SUNRPC: Move rpc_...
2668
  	transport = container_of(xprt, struct sock_xprt, xprt);
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2669

ec739ef03   Chuck Lever   SUNRPC: Create a ...
2670
  	xprt->prot = IPPROTO_TCP;
808012fbb   Chuck Lever   [PATCH] RPC: skip...
2671
  	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
808012fbb   Chuck Lever   [PATCH] RPC: skip...
2672
  	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2673

03bf4b707   Chuck Lever   [PATCH] RPC: para...
2674
  	xprt->bind_timeout = XS_BIND_TO;
03bf4b707   Chuck Lever   [PATCH] RPC: para...
2675
2676
  	xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
  	xprt->idle_timeout = XS_IDLE_DISC_TO;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2677

262965f53   Chuck Lever   [PATCH] RPC: sepa...
2678
  	xprt->ops = &xs_tcp_ops;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
2679
  	xprt->timeout = &xs_tcp_default_timeout;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2680

8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2681
2682
2683
2684
  	switch (addr->sa_family) {
  	case AF_INET:
  		if (((struct sockaddr_in *)addr)->sin_port != htons(0))
  			xprt_set_bound(xprt);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
2685
  		INIT_DELAYED_WORK(&transport->connect_worker,
cdd518d52   Pavel Emelyanov   sunrpc: Remove TC...
2686
  					xs_tcp_setup_socket);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
2687
  		xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP);
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2688
2689
2690
2691
  		break;
  	case AF_INET6:
  		if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0))
  			xprt_set_bound(xprt);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
2692
  		INIT_DELAYED_WORK(&transport->connect_worker,
cdd518d52   Pavel Emelyanov   sunrpc: Remove TC...
2693
  					xs_tcp_setup_socket);
9dc3b095b   Chuck Lever   SUNRPC: Update xp...
2694
  		xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6);
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2695
2696
  		break;
  	default:
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2697
2698
  		ret = ERR_PTR(-EAFNOSUPPORT);
  		goto out_err;
8f9d5b1a2   Chuck Lever   SUNRPC: Add IPv6 ...
2699
  	}
c740eff84   Chuck Lever   SUNRPC: Kill RPC_...
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
  	if (xprt_bound(xprt))
  		dprintk("RPC:       set up xprt to %s (port %s) via %s
  ",
  				xprt->address_strings[RPC_DISPLAY_ADDR],
  				xprt->address_strings[RPC_DISPLAY_PORT],
  				xprt->address_strings[RPC_DISPLAY_PROTO]);
  	else
  		dprintk("RPC:       set up xprt to %s (autobind) via %s
  ",
  				xprt->address_strings[RPC_DISPLAY_ADDR],
  				xprt->address_strings[RPC_DISPLAY_PROTO]);
edb267a68   Chuck Lever   SUNRPC: add xprt ...
2711

bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2712
2713
  	if (try_module_get(THIS_MODULE))
  		return xprt;
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2714
2715
  	ret = ERR_PTR(-EINVAL);
  out_err:
e204e621b   Pavel Emelyanov   sunrpc: Factor ou...
2716
  	xprt_free(xprt);
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2717
  	return ret;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
2718
  }
282b32e17   Chuck Lever   SUNRPC: create st...
2719

f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
  /**
   * xs_setup_bc_tcp - Set up transport to use a TCP backchannel socket
   * @args: rpc transport creation arguments
   *
   */
  static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
  {
  	struct sockaddr *addr = args->dstaddr;
  	struct rpc_xprt *xprt;
  	struct sock_xprt *transport;
  	struct svc_sock *bc_sock;
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2731
  	struct rpc_xprt *ret;
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2732

f0418aa4b   J. Bruce Fields   rpc: allow xprt_c...
2733
2734
2735
2736
2737
2738
2739
2740
2741
  	if (args->bc_xprt->xpt_bc_xprt) {
  		/*
  		 * This server connection already has a backchannel
  		 * export; we can't create a new one, as we wouldn't be
  		 * able to match replies based on xid any more.  So,
  		 * reuse the already-existing one:
  		 */
  		 return args->bc_xprt->xpt_bc_xprt;
  	}
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2742
2743
  	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
  			xprt_tcp_slot_table_entries);
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
  	if (IS_ERR(xprt))
  		return xprt;
  	transport = container_of(xprt, struct sock_xprt, xprt);
  
  	xprt->prot = IPPROTO_TCP;
  	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
  	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
  	xprt->timeout = &xs_tcp_default_timeout;
  
  	/* backchannel */
  	xprt_set_bound(xprt);
  	xprt->bind_timeout = 0;
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2756
2757
  	xprt->reestablish_timeout = 0;
  	xprt->idle_timeout = 0;
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
  	xprt->ops = &bc_tcp_ops;
  
  	switch (addr->sa_family) {
  	case AF_INET:
  		xs_format_peer_addresses(xprt, "tcp",
  					 RPCBIND_NETID_TCP);
  		break;
  	case AF_INET6:
  		xs_format_peer_addresses(xprt, "tcp",
  				   RPCBIND_NETID_TCP6);
  		break;
  	default:
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2770
2771
  		ret = ERR_PTR(-EAFNOSUPPORT);
  		goto out_err;
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2772
  	}
50fa0d40a   Pavel Emelyanov   sunrpc: Remove de...
2773
2774
2775
2776
2777
  	dprintk("RPC:       set up xprt to %s (port %s) via %s
  ",
  			xprt->address_strings[RPC_DISPLAY_ADDR],
  			xprt->address_strings[RPC_DISPLAY_PORT],
  			xprt->address_strings[RPC_DISPLAY_PROTO]);
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2778
2779
  
  	/*
99de8ea96   J. Bruce Fields   rpc: keep backcha...
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
  	 * Once we've associated a backchannel xprt with a connection,
  	 * we want to keep it around as long as long as the connection
  	 * lasts, in case we need to start using it for a backchannel
  	 * again; this reference won't be dropped until bc_xprt is
  	 * destroyed.
  	 */
  	xprt_get(xprt);
  	args->bc_xprt->xpt_bc_xprt = xprt;
  	xprt->bc_xprt = args->bc_xprt;
  	bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt);
  	transport->sock = bc_sock->sk_sock;
  	transport->inet = bc_sock->sk_sk;
  
  	/*
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2794
2795
2796
2797
2798
2799
2800
2801
  	 * Since we don't want connections for the backchannel, we set
  	 * the xprt status to connected
  	 */
  	xprt_set_connected(xprt);
  
  
  	if (try_module_get(THIS_MODULE))
  		return xprt;
99de8ea96   J. Bruce Fields   rpc: keep backcha...
2802
  	xprt_put(xprt);
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2803
2804
  	ret = ERR_PTR(-EINVAL);
  out_err:
e204e621b   Pavel Emelyanov   sunrpc: Factor ou...
2805
  	xprt_free(xprt);
0a68b0bed   J. Bruce Fields   sunrpc: fix leak ...
2806
  	return ret;
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2807
  }
176e21ee2   Chuck Lever   SUNRPC: Support f...
2808
2809
2810
2811
2812
2813
2814
  static struct xprt_class	xs_local_transport = {
  	.list		= LIST_HEAD_INIT(xs_local_transport.list),
  	.name		= "named UNIX socket",
  	.owner		= THIS_MODULE,
  	.ident		= XPRT_TRANSPORT_LOCAL,
  	.setup		= xs_setup_local,
  };
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2815
2816
2817
2818
  static struct xprt_class	xs_udp_transport = {
  	.list		= LIST_HEAD_INIT(xs_udp_transport.list),
  	.name		= "udp",
  	.owner		= THIS_MODULE,
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2819
  	.ident		= XPRT_TRANSPORT_UDP,
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2820
2821
2822
2823
2824
2825
2826
  	.setup		= xs_setup_udp,
  };
  
  static struct xprt_class	xs_tcp_transport = {
  	.list		= LIST_HEAD_INIT(xs_tcp_transport.list),
  	.name		= "tcp",
  	.owner		= THIS_MODULE,
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2827
  	.ident		= XPRT_TRANSPORT_TCP,
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2828
2829
  	.setup		= xs_setup_tcp,
  };
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2830
2831
2832
2833
2834
2835
2836
  static struct xprt_class	xs_bc_tcp_transport = {
  	.list		= LIST_HEAD_INIT(xs_bc_tcp_transport.list),
  	.name		= "tcp NFSv4.1 backchannel",
  	.owner		= THIS_MODULE,
  	.ident		= XPRT_TRANSPORT_BC_TCP,
  	.setup		= xs_setup_bc_tcp,
  };
282b32e17   Chuck Lever   SUNRPC: create st...
2837
  /**
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2838
   * init_socket_xprt - set up xprtsock's sysctls, register with RPC client
282b32e17   Chuck Lever   SUNRPC: create st...
2839
2840
2841
2842
   *
   */
  int init_socket_xprt(void)
  {
fbf76683f   Chuck Lever   SUNRPC: relocate ...
2843
  #ifdef RPC_DEBUG
2b1bec5f5   Eric W. Biederman   [PATCH] sysctl: s...
2844
  	if (!sunrpc_table_header)
0b4d41471   Eric W. Biederman   [PATCH] sysctl: r...
2845
  		sunrpc_table_header = register_sysctl_table(sunrpc_table);
fbf76683f   Chuck Lever   SUNRPC: relocate ...
2846
  #endif
176e21ee2   Chuck Lever   SUNRPC: Support f...
2847
  	xprt_register_transport(&xs_local_transport);
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2848
2849
  	xprt_register_transport(&xs_udp_transport);
  	xprt_register_transport(&xs_tcp_transport);
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2850
  	xprt_register_transport(&xs_bc_tcp_transport);
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2851

282b32e17   Chuck Lever   SUNRPC: create st...
2852
2853
2854
2855
  	return 0;
  }
  
  /**
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2856
   * cleanup_socket_xprt - remove xprtsock's sysctls, unregister
282b32e17   Chuck Lever   SUNRPC: create st...
2857
2858
2859
2860
   *
   */
  void cleanup_socket_xprt(void)
  {
fbf76683f   Chuck Lever   SUNRPC: relocate ...
2861
2862
2863
2864
2865
2866
  #ifdef RPC_DEBUG
  	if (sunrpc_table_header) {
  		unregister_sysctl_table(sunrpc_table_header);
  		sunrpc_table_header = NULL;
  	}
  #endif
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2867

176e21ee2   Chuck Lever   SUNRPC: Support f...
2868
  	xprt_unregister_transport(&xs_local_transport);
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
2869
2870
  	xprt_unregister_transport(&xs_udp_transport);
  	xprt_unregister_transport(&xs_tcp_transport);
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
2871
  	xprt_unregister_transport(&xs_bc_tcp_transport);
282b32e17   Chuck Lever   SUNRPC: create st...
2872
  }
cbf110712   Trond Myklebust   SUNRPC: convert s...
2873

9bbb9e5a3   Rusty Russell   param: use ops in...
2874
2875
  static int param_set_uint_minmax(const char *val,
  		const struct kernel_param *kp,
cbf110712   Trond Myklebust   SUNRPC: convert s...
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
  		unsigned int min, unsigned int max)
  {
  	unsigned long num;
  	int ret;
  
  	if (!val)
  		return -EINVAL;
  	ret = strict_strtoul(val, 0, &num);
  	if (ret == -EINVAL || num < min || num > max)
  		return -EINVAL;
  	*((unsigned int *)kp->arg) = num;
  	return 0;
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
2889
  static int param_set_portnr(const char *val, const struct kernel_param *kp)
cbf110712   Trond Myklebust   SUNRPC: convert s...
2890
2891
2892
2893
2894
  {
  	return param_set_uint_minmax(val, kp,
  			RPC_MIN_RESVPORT,
  			RPC_MAX_RESVPORT);
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
2895
2896
2897
2898
  static struct kernel_param_ops param_ops_portnr = {
  	.set = param_set_portnr,
  	.get = param_get_uint,
  };
cbf110712   Trond Myklebust   SUNRPC: convert s...
2899
2900
2901
2902
2903
  #define param_check_portnr(name, p) \
  	__param_check(name, p, unsigned int);
  
  module_param_named(min_resvport, xprt_min_resvport, portnr, 0644);
  module_param_named(max_resvport, xprt_max_resvport, portnr, 0644);
9bbb9e5a3   Rusty Russell   param: use ops in...
2904
2905
  static int param_set_slot_table_size(const char *val,
  				     const struct kernel_param *kp)
cbf110712   Trond Myklebust   SUNRPC: convert s...
2906
2907
2908
2909
2910
  {
  	return param_set_uint_minmax(val, kp,
  			RPC_MIN_SLOT_TABLE,
  			RPC_MAX_SLOT_TABLE);
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
2911
2912
2913
2914
  static struct kernel_param_ops param_ops_slot_table_size = {
  	.set = param_set_slot_table_size,
  	.get = param_get_uint,
  };
cbf110712   Trond Myklebust   SUNRPC: convert s...
2915
2916
  #define param_check_slot_table_size(name, p) \
  	__param_check(name, p, unsigned int);
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
  static int param_set_max_slot_table_size(const char *val,
  				     const struct kernel_param *kp)
  {
  	return param_set_uint_minmax(val, kp,
  			RPC_MIN_SLOT_TABLE,
  			RPC_MAX_SLOT_TABLE_LIMIT);
  }
  
  static struct kernel_param_ops param_ops_max_slot_table_size = {
  	.set = param_set_max_slot_table_size,
  	.get = param_get_uint,
  };
  
  #define param_check_max_slot_table_size(name, p) \
  	__param_check(name, p, unsigned int);
cbf110712   Trond Myklebust   SUNRPC: convert s...
2932
2933
  module_param_named(tcp_slot_table_entries, xprt_tcp_slot_table_entries,
  		   slot_table_size, 0644);
d9ba131d8   Trond Myklebust   SUNRPC: Support d...
2934
2935
  module_param_named(tcp_max_slot_table_entries, xprt_max_tcp_slot_table_entries,
  		   max_slot_table_size, 0644);
cbf110712   Trond Myklebust   SUNRPC: convert s...
2936
2937
  module_param_named(udp_slot_table_entries, xprt_udp_slot_table_entries,
  		   slot_table_size, 0644);