Blame view
net/sunrpc/svcsock.c
43.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 |
/* * linux/net/sunrpc/svcsock.c * * These are the RPC server socket internals. * * The server scheduling algorithm does not always distribute the load * evenly when servicing a single client. May need to modify the |
f6150c3ca svc: Make the enq... |
8 |
* svc_xprt_enqueue procedure... |
1da177e4c Linux-2.6.12-rc2 |
9 10 11 12 13 14 15 16 17 18 19 20 |
* * TCP support is largely untested and may be a little slow. The problem * is that we currently do two separate recvfrom's, one for the 4-byte * record length, and the second for the actual record. This could possibly * be improved by always reading a minimum size of around 100 bytes and * tucking any superfluous bytes away in a temporary store. Still, that * leaves write requests out in the rain. An alternative may be to peek at * the first skb in the queue, and if it matches the next TCP sequence * number, to extract the record marker. Yuck. * * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ |
172589ccd [NET]: DIV_ROUND_... |
21 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
22 |
#include <linux/sched.h> |
3a9a231d9 net: Fix files ex... |
23 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 28 29 |
#include <linux/errno.h> #include <linux/fcntl.h> #include <linux/net.h> #include <linux/in.h> #include <linux/inet.h> #include <linux/udp.h> |
91483c4b7 [SUNRPC]: svcsock... |
30 |
#include <linux/tcp.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 |
#include <linux/unistd.h> #include <linux/slab.h> #include <linux/netdevice.h> #include <linux/skbuff.h> |
b41b66d63 [PATCH] knfsd: al... |
35 |
#include <linux/file.h> |
7dfb71030 [PATCH] Add inclu... |
36 |
#include <linux/freezer.h> |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 |
#include <net/sock.h> #include <net/checksum.h> #include <net/ip.h> |
b92503b25 [PATCH] knfsd: SU... |
40 |
#include <net/ipv6.h> |
b7872fe86 SUNRPC: RPC serve... |
41 |
#include <net/tcp.h> |
c752f0739 [TCP]: Move the t... |
42 |
#include <net/tcp_states.h> |
1da177e4c Linux-2.6.12-rc2 |
43 44 45 46 |
#include <asm/uaccess.h> #include <asm/ioctls.h> #include <linux/sunrpc/types.h> |
ad06e4bd6 [PATCH] knfsd: SU... |
47 |
#include <linux/sunrpc/clnt.h> |
1da177e4c Linux-2.6.12-rc2 |
48 |
#include <linux/sunrpc/xdr.h> |
c0401ea00 SUNRPC: Update RP... |
49 |
#include <linux/sunrpc/msg_prot.h> |
1da177e4c Linux-2.6.12-rc2 |
50 51 |
#include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/stats.h> |
4cfc7e601 nfsd41: sunrpc: A... |
52 |
#include <linux/sunrpc/xprt.h> |
1da177e4c Linux-2.6.12-rc2 |
53 |
|
177e4f998 svcsock.c: includ... |
54 |
#include "sunrpc.h" |
360d87386 svc: Make svc_soc... |
55 |
#define RPCDBG_FACILITY RPCDBG_SVCXPRT |
1da177e4c Linux-2.6.12-rc2 |
56 57 58 |
static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
6b174337e [PATCH] knfsd: SU... |
59 |
int *errp, int flags); |
1da177e4c Linux-2.6.12-rc2 |
60 61 62 |
static void svc_udp_data_ready(struct sock *, int); static int svc_udp_recvfrom(struct svc_rqst *); static int svc_udp_sendto(struct svc_rqst *); |
755cceaba svc: Add per-tran... |
63 |
static void svc_sock_detach(struct svc_xprt *); |
69b6ba371 SUNRPC: Ensure th... |
64 |
static void svc_tcp_sock_detach(struct svc_xprt *); |
755cceaba svc: Add per-tran... |
65 |
static void svc_sock_free(struct svc_xprt *); |
1da177e4c Linux-2.6.12-rc2 |
66 |
|
b700cbb11 svc: Add a generi... |
67 |
static struct svc_xprt *svc_create_socket(struct svc_serv *, int, |
62832c039 sunrpc: Pull net ... |
68 69 |
struct net *, struct sockaddr *, int, int); |
9e00abc3c SUNRPC: sunrpc sh... |
70 |
#if defined(CONFIG_SUNRPC_BACKCHANNEL) |
1f11a034c SUNRPC new transp... |
71 72 73 74 |
static struct svc_xprt *svc_bc_create_socket(struct svc_serv *, int, struct net *, struct sockaddr *, int, int); static void svc_bc_sock_free(struct svc_xprt *xprt); |
9e00abc3c SUNRPC: sunrpc sh... |
75 |
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1f11a034c SUNRPC new transp... |
76 |
|
ed07536ed [PATCH] lockdep: ... |
77 78 79 |
#ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key svc_key[2]; static struct lock_class_key svc_slock_key[2]; |
0f0257eaa svc: Move the xpr... |
80 |
static void svc_reclassify_socket(struct socket *sock) |
ed07536ed [PATCH] lockdep: ... |
81 82 |
{ struct sock *sk = sock->sk; |
02b3d3463 [NET] Cleanup: Us... |
83 |
BUG_ON(sock_owned_by_user(sk)); |
ed07536ed [PATCH] lockdep: ... |
84 85 86 |
switch (sk->sk_family) { case AF_INET: sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", |
def13d740 svc: Move the aut... |
87 88 89 |
&svc_slock_key[0], "sk_xprt.xpt_lock-AF_INET-NFSD", &svc_key[0]); |
ed07536ed [PATCH] lockdep: ... |
90 91 92 93 |
break; case AF_INET6: sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFSD", |
def13d740 svc: Move the aut... |
94 95 96 |
&svc_slock_key[1], "sk_xprt.xpt_lock-AF_INET6-NFSD", &svc_key[1]); |
ed07536ed [PATCH] lockdep: ... |
97 98 99 100 101 102 103 |
break; default: BUG(); } } #else |
0f0257eaa svc: Move the xpr... |
104 |
static void svc_reclassify_socket(struct socket *sock) |
ed07536ed [PATCH] lockdep: ... |
105 106 107 |
{ } #endif |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 |
/* * Release an skbuff after use */ |
5148bf4eb svc: Add transpor... |
111 |
static void svc_release_skb(struct svc_rqst *rqstp) |
1da177e4c Linux-2.6.12-rc2 |
112 |
{ |
5148bf4eb svc: Add transpor... |
113 |
struct sk_buff *skb = rqstp->rq_xprt_ctxt; |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
if (skb) { |
57b1d3bab svc: Removing rem... |
116 117 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
5148bf4eb svc: Add transpor... |
118 |
rqstp->rq_xprt_ctxt = NULL; |
1da177e4c Linux-2.6.12-rc2 |
119 120 121 |
dprintk("svc: service %p, releasing skb %p ", rqstp, skb); |
9d410c796 net: fix sk_forwa... |
122 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
1da177e4c Linux-2.6.12-rc2 |
123 |
} |
1da177e4c Linux-2.6.12-rc2 |
124 |
} |
b92503b25 [PATCH] knfsd: SU... |
125 126 |
union svc_pktinfo_u { struct in_pktinfo pkti; |
b92503b25 [PATCH] knfsd: SU... |
127 |
struct in6_pktinfo pkti6; |
b92503b25 [PATCH] knfsd: SU... |
128 |
}; |
bc375ea7e [SUNRPC]: Make su... |
129 130 |
#define SVC_PKTINFO_SPACE \ CMSG_SPACE(sizeof(union svc_pktinfo_u)) |
b92503b25 [PATCH] knfsd: SU... |
131 132 133 |
static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) { |
57b1d3bab svc: Removing rem... |
134 135 136 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); switch (svsk->sk_sk->sk_family) { |
b92503b25 [PATCH] knfsd: SU... |
137 138 139 140 141 142 |
case AF_INET: { struct in_pktinfo *pki = CMSG_DATA(cmh); cmh->cmsg_level = SOL_IP; cmh->cmsg_type = IP_PKTINFO; pki->ipi_ifindex = 0; |
849a1cf13 SUNRPC: Replace s... |
143 144 |
pki->ipi_spec_dst.s_addr = svc_daddr_in(rqstp)->sin_addr.s_addr; |
b92503b25 [PATCH] knfsd: SU... |
145 146 147 |
cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); } break; |
5a05ed73e [PATCH] knfsd: re... |
148 |
|
b92503b25 [PATCH] knfsd: SU... |
149 150 |
case AF_INET6: { struct in6_pktinfo *pki = CMSG_DATA(cmh); |
849a1cf13 SUNRPC: Replace s... |
151 |
struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); |
b92503b25 [PATCH] knfsd: SU... |
152 153 154 |
cmh->cmsg_level = SOL_IPV6; cmh->cmsg_type = IPV6_PKTINFO; |
849a1cf13 SUNRPC: Replace s... |
155 |
pki->ipi6_ifindex = daddr->sin6_scope_id; |
4e3fd7a06 net: remove ipv6_... |
156 |
pki->ipi6_addr = daddr->sin6_addr; |
b92503b25 [PATCH] knfsd: SU... |
157 158 159 |
cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); } break; |
b92503b25 [PATCH] knfsd: SU... |
160 |
} |
b92503b25 [PATCH] knfsd: SU... |
161 |
} |
1da177e4c Linux-2.6.12-rc2 |
162 |
/* |
4cfc7e601 nfsd41: sunrpc: A... |
163 |
* send routine intended to be shared by the fore- and back-channel |
1da177e4c Linux-2.6.12-rc2 |
164 |
*/ |
4cfc7e601 nfsd41: sunrpc: A... |
165 166 167 |
int svc_send_common(struct socket *sock, struct xdr_buf *xdr, struct page *headpage, unsigned long headoffset, struct page *tailpage, unsigned long tailoffset) |
1da177e4c Linux-2.6.12-rc2 |
168 |
{ |
1da177e4c Linux-2.6.12-rc2 |
169 170 171 172 173 174 |
int result; int size; struct page **ppage = xdr->pages; size_t base = xdr->page_base; unsigned int pglen = xdr->page_len; unsigned int flags = MSG_MORE; |
4cfc7e601 nfsd41: sunrpc: A... |
175 176 |
int slen; int len = 0; |
1da177e4c Linux-2.6.12-rc2 |
177 178 |
slen = xdr->len; |
1da177e4c Linux-2.6.12-rc2 |
179 180 181 |
/* send head */ if (slen == xdr->head[0].iov_len) flags = 0; |
4cfc7e601 nfsd41: sunrpc: A... |
182 |
len = kernel_sendpage(sock, headpage, headoffset, |
445243594 [PATCH] knfsd: Re... |
183 |
xdr->head[0].iov_len, flags); |
1da177e4c Linux-2.6.12-rc2 |
184 185 186 187 188 189 190 191 192 193 194 |
if (len != xdr->head[0].iov_len) goto out; slen -= xdr->head[0].iov_len; if (slen == 0) goto out; /* send page data */ size = PAGE_SIZE - base < pglen ? PAGE_SIZE - base : pglen; while (pglen > 0) { if (slen == size) flags = 0; |
e6242e928 [SUNRPC]: Update ... |
195 |
result = kernel_sendpage(sock, *ppage, base, size, flags); |
1da177e4c Linux-2.6.12-rc2 |
196 197 198 199 200 201 202 203 204 205 |
if (result > 0) len += result; if (result != size) goto out; slen -= size; pglen -= size; size = PAGE_SIZE < pglen ? PAGE_SIZE : pglen; base = 0; ppage++; } |
4cfc7e601 nfsd41: sunrpc: A... |
206 |
|
1da177e4c Linux-2.6.12-rc2 |
207 208 |
/* send tail */ if (xdr->tail[0].iov_len) { |
4cfc7e601 nfsd41: sunrpc: A... |
209 210 |
result = kernel_sendpage(sock, tailpage, tailoffset, xdr->tail[0].iov_len, 0); |
1da177e4c Linux-2.6.12-rc2 |
211 212 213 |
if (result > 0) len += result; } |
4cfc7e601 nfsd41: sunrpc: A... |
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
out: return len; } /* * Generic sendto routine */ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) { struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); struct socket *sock = svsk->sk_sock; union { struct cmsghdr hdr; long all[SVC_PKTINFO_SPACE / sizeof(long)]; } buffer; struct cmsghdr *cmh = &buffer.hdr; int len = 0; unsigned long tailoff; unsigned long headoff; RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); if (rqstp->rq_prot == IPPROTO_UDP) { struct msghdr msg = { .msg_name = &rqstp->rq_addr, .msg_namelen = rqstp->rq_addrlen, .msg_control = cmh, .msg_controllen = sizeof(buffer), .msg_flags = MSG_MORE, }; svc_set_cmsg_data(rqstp, cmh); if (sock_sendmsg(sock, &msg, 0) < 0) goto out; } tailoff = ((unsigned long)xdr->tail[0].iov_base) & (PAGE_SIZE-1); headoff = 0; len = svc_send_common(sock, xdr, rqstp->rq_respages[0], headoff, rqstp->rq_respages[0], tailoff); |
1da177e4c Linux-2.6.12-rc2 |
257 |
out: |
ad06e4bd6 [PATCH] knfsd: SU... |
258 259 |
dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s) ", |
57b1d3bab svc: Removing rem... |
260 |
svsk, xdr->head[0].iov_base, xdr->head[0].iov_len, |
ad06e4bd6 [PATCH] knfsd: SU... |
261 |
xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf))); |
1da177e4c Linux-2.6.12-rc2 |
262 263 264 265 266 |
return len; } /* |
80212d59e [PATCH] knfsd: de... |
267 268 |
* Report socket names for nfsdfs */ |
e7942b9f2 SUNRPC: Switch on... |
269 |
static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) |
80212d59e [PATCH] knfsd: de... |
270 |
{ |
017cb47f4 SUNRPC: Clean up ... |
271 272 273 |
const struct sock *sk = svsk->sk_sk; const char *proto_name = sk->sk_protocol == IPPROTO_UDP ? "udp" : "tcp"; |
80212d59e [PATCH] knfsd: de... |
274 |
int len; |
017cb47f4 SUNRPC: Clean up ... |
275 |
switch (sk->sk_family) { |
e7942b9f2 SUNRPC: Switch on... |
276 277 278 |
case PF_INET: len = snprintf(buf, remaining, "ipv4 %s %pI4 %d ", |
017cb47f4 SUNRPC: Clean up ... |
279 |
proto_name, |
c720c7e83 inet: rename some... |
280 281 |
&inet_sk(sk)->inet_rcv_saddr, inet_sk(sk)->inet_num); |
80212d59e [PATCH] knfsd: de... |
282 |
break; |
58de2f865 SUNRPC: Support P... |
283 284 285 |
case PF_INET6: len = snprintf(buf, remaining, "ipv6 %s %pI6 %d ", |
017cb47f4 SUNRPC: Clean up ... |
286 287 |
proto_name, &inet6_sk(sk)->rcv_saddr, |
c720c7e83 inet: rename some... |
288 |
inet_sk(sk)->inet_num); |
80212d59e [PATCH] knfsd: de... |
289 290 |
break; default: |
e7942b9f2 SUNRPC: Switch on... |
291 292 |
len = snprintf(buf, remaining, "*unknown-%d* ", |
017cb47f4 SUNRPC: Clean up ... |
293 |
sk->sk_family); |
80212d59e [PATCH] knfsd: de... |
294 |
} |
e7942b9f2 SUNRPC: Switch on... |
295 296 297 298 |
if (len >= remaining) { *buf = '\0'; return -ENAMETOOLONG; |
80212d59e [PATCH] knfsd: de... |
299 300 301 |
} return len; } |
8435d34db SUNRPC: pass buff... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
/** * svc_sock_names - construct a list of listener names in a string * @serv: pointer to RPC service * @buf: pointer to a buffer to fill in with socket names * @buflen: size of the buffer to be filled * @toclose: pointer to '\0'-terminated C string containing the name * of a listener to be closed * * Fills in @buf with a ' '-separated list of names of listener * sockets. If @toclose is not NULL, the socket named by @toclose * is closed, and is not included in the output list. * * Returns positive length of the socket name string, or a negative * errno value on error. */ int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, const char *toclose) |
80212d59e [PATCH] knfsd: de... |
320 |
{ |
b41b66d63 [PATCH] knfsd: al... |
321 |
struct svc_sock *svsk, *closesk = NULL; |
80212d59e [PATCH] knfsd: de... |
322 323 324 325 |
int len = 0; if (!serv) return 0; |
e7942b9f2 SUNRPC: Switch on... |
326 |
|
aaf68cfbf [PATCH] knfsd: fi... |
327 |
spin_lock_bh(&serv->sv_lock); |
7a1820838 svc: Make close t... |
328 |
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { |
e7942b9f2 SUNRPC: Switch on... |
329 330 331 332 333 |
int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); if (onelen < 0) { len = onelen; break; } |
3942302ea sunrpc: svc_sock_... |
334 |
if (toclose && strcmp(toclose, buf + len) == 0) { |
b41b66d63 [PATCH] knfsd: al... |
335 |
closesk = svsk; |
3942302ea sunrpc: svc_sock_... |
336 337 |
svc_xprt_get(&closesk->sk_xprt); } else |
b41b66d63 [PATCH] knfsd: al... |
338 |
len += onelen; |
80212d59e [PATCH] knfsd: de... |
339 |
} |
aaf68cfbf [PATCH] knfsd: fi... |
340 |
spin_unlock_bh(&serv->sv_lock); |
e7942b9f2 SUNRPC: Switch on... |
341 |
|
3942302ea sunrpc: svc_sock_... |
342 |
if (closesk) { |
5680c4463 [PATCH] knfsd: Fi... |
343 344 345 |
/* Should unregister with portmap, but you cannot * unregister just one protocol... */ |
7a1820838 svc: Make close t... |
346 |
svc_close_xprt(&closesk->sk_xprt); |
3942302ea sunrpc: svc_sock_... |
347 348 |
svc_xprt_put(&closesk->sk_xprt); } else if (toclose) |
37a034729 [PATCH] knfsd: ca... |
349 |
return -ENOENT; |
80212d59e [PATCH] knfsd: de... |
350 351 |
return len; } |
24c3767e4 SUNRPC: The sunrp... |
352 |
EXPORT_SYMBOL_GPL(svc_sock_names); |
80212d59e [PATCH] knfsd: de... |
353 354 |
/* |
1da177e4c Linux-2.6.12-rc2 |
355 356 |
* Check input queue length */ |
0f0257eaa svc: Move the xpr... |
357 |
static int svc_recv_available(struct svc_sock *svsk) |
1da177e4c Linux-2.6.12-rc2 |
358 |
{ |
1da177e4c Linux-2.6.12-rc2 |
359 360 |
struct socket *sock = svsk->sk_sock; int avail, err; |
e6242e928 [SUNRPC]: Update ... |
361 |
err = kernel_sock_ioctl(sock, TIOCINQ, (unsigned long) &avail); |
1da177e4c Linux-2.6.12-rc2 |
362 363 364 365 366 367 368 |
return (err >= 0)? avail : err; } /* * Generic recvfrom routine. */ |
0f0257eaa svc: Move the xpr... |
369 370 |
static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen) |
1da177e4c Linux-2.6.12-rc2 |
371 |
{ |
57b1d3bab svc: Removing rem... |
372 373 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
1ba951053 [PATCH] knfsd: SU... |
374 375 376 377 |
struct msghdr msg = { .msg_flags = MSG_DONTWAIT, }; int len; |
1da177e4c Linux-2.6.12-rc2 |
378 |
|
260c1d129 svc: Add transpor... |
379 |
rqstp->rq_xprt_hlen = 0; |
1ba951053 [PATCH] knfsd: SU... |
380 381 |
len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, msg.msg_flags); |
1da177e4c Linux-2.6.12-rc2 |
382 |
|
1da177e4c Linux-2.6.12-rc2 |
383 384 |
dprintk("svc: socket %p recvfrom(%p, %Zu) = %d ", |
1ba951053 [PATCH] knfsd: SU... |
385 |
svsk, iov[0].iov_base, iov[0].iov_len, len); |
1da177e4c Linux-2.6.12-rc2 |
386 387 |
return len; } |
31d68ef65 SUNRPC: Don't wai... |
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
static int svc_partial_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen, unsigned int base) { size_t save_iovlen; void __user *save_iovbase; unsigned int i; int ret; if (base == 0) return svc_recvfrom(rqstp, iov, nr, buflen); for (i = 0; i < nr; i++) { if (iov[i].iov_len > base) break; base -= iov[i].iov_len; } save_iovlen = iov[i].iov_len; save_iovbase = iov[i].iov_base; iov[i].iov_len -= base; iov[i].iov_base += base; ret = svc_recvfrom(rqstp, &iov[i], nr - i, buflen); iov[i].iov_len = save_iovlen; iov[i].iov_base = save_iovbase; return ret; } |
1da177e4c Linux-2.6.12-rc2 |
414 415 416 |
/* * Set socket snd and rcv buffer lengths */ |
0f0257eaa svc: Move the xpr... |
417 418 |
static void svc_sock_setbufsize(struct socket *sock, unsigned int snd, unsigned int rcv) |
1da177e4c Linux-2.6.12-rc2 |
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
{ #if 0 mm_segment_t oldfs; oldfs = get_fs(); set_fs(KERNEL_DS); sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&snd, sizeof(snd)); sock_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, sizeof(rcv)); #else /* sock_setsockopt limits use to sysctl_?mem_max, * which isn't acceptable. Until that is made conditional * on not having CAP_SYS_RESOURCE or similar, we go direct... * DaveM said I could! */ lock_sock(sock->sk); sock->sk->sk_sndbuf = snd * 2; sock->sk->sk_rcvbuf = rcv * 2; |
47fcb03fe SUNRPC: Fix the T... |
436 |
sock->sk->sk_write_space(sock->sk); |
1da177e4c Linux-2.6.12-rc2 |
437 438 439 440 441 442 |
release_sock(sock->sk); #endif } /* * INET callback when data has been received on the socket. */ |
0f0257eaa svc: Move the xpr... |
443 |
static void svc_udp_data_ready(struct sock *sk, int count) |
1da177e4c Linux-2.6.12-rc2 |
444 |
{ |
939bb7ef9 [PATCH] Code clea... |
445 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105 net: add __rcu an... |
446 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c Linux-2.6.12-rc2 |
447 |
|
939bb7ef9 [PATCH] Code clea... |
448 449 450 |
if (svsk) { dprintk("svc: socket %p(inet %p), count=%d, busy=%d ", |
02fc6c361 svc: Move sk_flag... |
451 452 453 |
svsk, sk, count, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
f6150c3ca svc: Make the enq... |
454 |
svc_xprt_enqueue(&svsk->sk_xprt); |
939bb7ef9 [PATCH] Code clea... |
455 |
} |
eaefd1105 net: add __rcu an... |
456 457 |
if (wq && waitqueue_active(wq)) wake_up_interruptible(wq); |
1da177e4c Linux-2.6.12-rc2 |
458 459 460 461 462 |
} /* * INET callback when space is newly available on the socket. */ |
0f0257eaa svc: Move the xpr... |
463 |
static void svc_write_space(struct sock *sk) |
1da177e4c Linux-2.6.12-rc2 |
464 465 |
{ struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); |
eaefd1105 net: add __rcu an... |
466 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c Linux-2.6.12-rc2 |
467 468 469 470 |
if (svsk) { dprintk("svc: socket %p(inet %p), write_space busy=%d ", |
02fc6c361 svc: Move sk_flag... |
471 |
svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
f6150c3ca svc: Make the enq... |
472 |
svc_xprt_enqueue(&svsk->sk_xprt); |
1da177e4c Linux-2.6.12-rc2 |
473 |
} |
eaefd1105 net: add __rcu an... |
474 |
if (wq && waitqueue_active(wq)) { |
939bb7ef9 [PATCH] Code clea... |
475 476 |
dprintk("RPC svc_write_space: someone sleeping on %p ", |
1da177e4c Linux-2.6.12-rc2 |
477 |
svsk); |
eaefd1105 net: add __rcu an... |
478 |
wake_up_interruptible(wq); |
1da177e4c Linux-2.6.12-rc2 |
479 480 |
} } |
47fcb03fe SUNRPC: Fix the T... |
481 482 483 484 485 486 487 488 |
static void svc_tcp_write_space(struct sock *sk) { struct socket *sock = sk->sk_socket; if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) clear_bit(SOCK_NOSPACE, &sock->flags); svc_write_space(sk); } |
9dbc240f1 svc: Move the soc... |
489 |
/* |
7702ce40b SUNRPC: handle IP... |
490 491 492 493 494 495 |
* See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo */ static int svc_udp_get_dest_address4(struct svc_rqst *rqstp, struct cmsghdr *cmh) { struct in_pktinfo *pki = CMSG_DATA(cmh); |
849a1cf13 SUNRPC: Replace s... |
496 |
struct sockaddr_in *daddr = svc_daddr_in(rqstp); |
7702ce40b SUNRPC: handle IP... |
497 498 |
if (cmh->cmsg_type != IP_PKTINFO) return 0; |
849a1cf13 SUNRPC: Replace s... |
499 500 501 |
daddr->sin_family = AF_INET; daddr->sin_addr.s_addr = pki->ipi_spec_dst.s_addr; |
7702ce40b SUNRPC: handle IP... |
502 503 504 505 506 507 508 509 510 511 |
return 1; } /* * See net/ipv6/datagram.c : datagram_recv_ctl */ static int svc_udp_get_dest_address6(struct svc_rqst *rqstp, struct cmsghdr *cmh) { struct in6_pktinfo *pki = CMSG_DATA(cmh); |
849a1cf13 SUNRPC: Replace s... |
512 |
struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); |
7702ce40b SUNRPC: handle IP... |
513 514 |
if (cmh->cmsg_type != IPV6_PKTINFO) return 0; |
849a1cf13 SUNRPC: Replace s... |
515 516 |
daddr->sin6_family = AF_INET6; |
4e3fd7a06 net: remove ipv6_... |
517 |
daddr->sin6_addr = pki->ipi6_addr; |
849a1cf13 SUNRPC: Replace s... |
518 |
daddr->sin6_scope_id = pki->ipi6_ifindex; |
7702ce40b SUNRPC: handle IP... |
519 520 521 522 |
return 1; } /* |
9dbc240f1 svc: Move the soc... |
523 524 525 526 527 528 |
* Copy the UDP datagram's destination address to the rqstp structure. * The 'destination' address in this case is the address to which the * peer sent the datagram, i.e. our local address. For multihomed * hosts, this can change from msg to msg. Note that only the IP * address changes, the port number should remain the same. */ |
7702ce40b SUNRPC: handle IP... |
529 530 |
static int svc_udp_get_dest_address(struct svc_rqst *rqstp, struct cmsghdr *cmh) |
95756482c [PATCH] knfsd: SU... |
531 |
{ |
7702ce40b SUNRPC: handle IP... |
532 533 534 535 536 |
switch (cmh->cmsg_level) { case SOL_IP: return svc_udp_get_dest_address4(rqstp, cmh); case SOL_IPV6: return svc_udp_get_dest_address6(rqstp, cmh); |
95756482c [PATCH] knfsd: SU... |
537 |
} |
7702ce40b SUNRPC: handle IP... |
538 539 |
return 0; |
95756482c [PATCH] knfsd: SU... |
540 |
} |
1da177e4c Linux-2.6.12-rc2 |
541 542 543 |
/* * Receive a datagram from a UDP socket. */ |
0f0257eaa svc: Move the xpr... |
544 |
static int svc_udp_recvfrom(struct svc_rqst *rqstp) |
1da177e4c Linux-2.6.12-rc2 |
545 |
{ |
57b1d3bab svc: Removing rem... |
546 547 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
bb5cf160b svc: Move sk_serv... |
548 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
1da177e4c Linux-2.6.12-rc2 |
549 |
struct sk_buff *skb; |
bc375ea7e [SUNRPC]: Make su... |
550 551 552 553 554 |
union { struct cmsghdr hdr; long all[SVC_PKTINFO_SPACE / sizeof(long)]; } buffer; struct cmsghdr *cmh = &buffer.hdr; |
7a37f5787 [PATCH] knfsd: us... |
555 556 557 558 559 560 |
struct msghdr msg = { .msg_name = svc_addr(rqstp), .msg_control = cmh, .msg_controllen = sizeof(buffer), .msg_flags = MSG_DONTWAIT, }; |
abc5c44d6 SUNRPC: Fix error... |
561 562 |
size_t len; int err; |
1da177e4c Linux-2.6.12-rc2 |
563 |
|
02fc6c361 svc: Move sk_flag... |
564 |
if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) |
1da177e4c Linux-2.6.12-rc2 |
565 566 567 |
/* udp sockets need large rcvbuf as all pending * requests are still in that buffer. sndbuf must * also be large enough that there is enough space |
3262c816a [PATCH] knfsd: sp... |
568 569 570 571 |
* for one reply per thread. We count all threads * rather than threads in a particular pool, which * provides an upper bound on the number of threads * which will access the socket. |
1da177e4c Linux-2.6.12-rc2 |
572 573 |
*/ svc_sock_setbufsize(svsk->sk_sock, |
c6b0a9f87 [PATCH] knfsd: ti... |
574 575 |
(serv->sv_nrthreads+3) * serv->sv_max_mesg, (serv->sv_nrthreads+3) * serv->sv_max_mesg); |
1da177e4c Linux-2.6.12-rc2 |
576 |
|
02fc6c361 svc: Move sk_flag... |
577 |
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
05ed690ef knfsd: simplify a... |
578 579 580 581 582 583 584 585 586 587 588 |
skb = NULL; err = kernel_recvmsg(svsk->sk_sock, &msg, NULL, 0, 0, MSG_PEEK | MSG_DONTWAIT); if (err >= 0) skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err); if (skb == NULL) { if (err != -EAGAIN) { /* possibly an icmp error */ dprintk("svc: recvfrom returned error %d ", -err); |
02fc6c361 svc: Move sk_flag... |
589 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
590 |
} |
05ed690ef knfsd: simplify a... |
591 |
return -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
592 |
} |
9dbc240f1 svc: Move the soc... |
593 |
len = svc_addr_len(svc_addr(rqstp)); |
abc5c44d6 SUNRPC: Fix error... |
594 595 |
if (len == 0) return -EAFNOSUPPORT; |
9dbc240f1 svc: Move the soc... |
596 |
rqstp->rq_addrlen = len; |
b7aa0bf70 [NET]: convert ne... |
597 598 |
if (skb->tstamp.tv64 == 0) { skb->tstamp = ktime_get_real(); |
cca5172a7 [NET] SUNRPC: Fix... |
599 |
/* Don't enable netstamp, sunrpc doesn't |
1da177e4c Linux-2.6.12-rc2 |
600 601 |
need that much accuracy */ } |
b7aa0bf70 [NET]: convert ne... |
602 |
svsk->sk_sk->sk_stamp = skb->tstamp; |
02fc6c361 svc: Move sk_flag... |
603 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); /* there may be more data... */ |
1da177e4c Linux-2.6.12-rc2 |
604 |
|
1da177e4c Linux-2.6.12-rc2 |
605 606 |
len = skb->len - sizeof(struct udphdr); rqstp->rq_arg.len = len; |
95756482c [PATCH] knfsd: SU... |
607 |
rqstp->rq_prot = IPPROTO_UDP; |
27459f094 [PATCH] knfsd: SU... |
608 |
|
7702ce40b SUNRPC: handle IP... |
609 |
if (!svc_udp_get_dest_address(rqstp, cmh)) { |
7a37f5787 [PATCH] knfsd: us... |
610 |
if (net_ratelimit()) |
7702ce40b SUNRPC: handle IP... |
611 612 613 614 615 |
printk(KERN_WARNING "svc: received unknown control message %d/%d; " "dropping RPC reply datagram ", cmh->cmsg_level, cmh->cmsg_type); |
9d410c796 net: fix sk_forwa... |
616 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
7a37f5787 [PATCH] knfsd: us... |
617 618 |
return 0; } |
849a1cf13 SUNRPC: Replace s... |
619 |
rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); |
1da177e4c Linux-2.6.12-rc2 |
620 621 622 623 624 625 626 |
if (skb_is_nonlinear(skb)) { /* we have to copy */ local_bh_disable(); if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { local_bh_enable(); /* checksum error */ |
9d410c796 net: fix sk_forwa... |
627 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
1da177e4c Linux-2.6.12-rc2 |
628 629 630 |
return 0; } local_bh_enable(); |
9d410c796 net: fix sk_forwa... |
631 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
1da177e4c Linux-2.6.12-rc2 |
632 633 |
} else { /* we can use it in-place */ |
0f0257eaa svc: Move the xpr... |
634 635 |
rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); |
1da177e4c Linux-2.6.12-rc2 |
636 |
rqstp->rq_arg.head[0].iov_len = len; |
fb286bb29 [NET]: Detect har... |
637 |
if (skb_checksum_complete(skb)) { |
9d410c796 net: fix sk_forwa... |
638 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
fb286bb29 [NET]: Detect har... |
639 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
640 |
} |
5148bf4eb svc: Add transpor... |
641 |
rqstp->rq_xprt_ctxt = skb; |
1da177e4c Linux-2.6.12-rc2 |
642 643 644 645 646 647 |
} rqstp->rq_arg.page_base = 0; if (len <= rqstp->rq_arg.head[0].iov_len) { rqstp->rq_arg.head[0].iov_len = len; rqstp->rq_arg.page_len = 0; |
445243594 [PATCH] knfsd: Re... |
648 |
rqstp->rq_respages = rqstp->rq_pages+1; |
1da177e4c Linux-2.6.12-rc2 |
649 650 |
} else { rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; |
445243594 [PATCH] knfsd: Re... |
651 |
rqstp->rq_respages = rqstp->rq_pages + 1 + |
172589ccd [NET]: DIV_ROUND_... |
652 |
DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 |
} if (serv->sv_stats) serv->sv_stats->netudpcnt++; return len; } static int svc_udp_sendto(struct svc_rqst *rqstp) { int error; error = svc_sendto(rqstp, &rqstp->rq_res); if (error == -ECONNREFUSED) /* ICMP error on earlier request. */ error = svc_sendto(rqstp, &rqstp->rq_res); return error; } |
e831fe65b svc: Add xpo_prep... |
673 674 675 |
static void svc_udp_prep_reply_hdr(struct svc_rqst *rqstp) { } |
323bee32e svc: Add a transp... |
676 677 678 |
static int svc_udp_has_wspace(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
bb5cf160b svc: Move sk_serv... |
679 |
struct svc_serv *serv = xprt->xpt_server; |
323bee32e svc: Add a transp... |
680 681 682 683 684 685 686 |
unsigned long required; /* * Set the SOCK_NOSPACE flag before checking the available * sock space. */ set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); |
7a90e8cc2 svc: Move sk_rese... |
687 |
required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg; |
323bee32e svc: Add a transp... |
688 689 690 691 692 |
if (required*2 > sock_wspace(svsk->sk_sk)) return 0; clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); return 1; } |
38a417cc9 svc: Add xpo_acce... |
693 694 695 696 697 |
static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt) { BUG(); return NULL; } |
b700cbb11 svc: Add a generi... |
698 |
static struct svc_xprt *svc_udp_create(struct svc_serv *serv, |
62832c039 sunrpc: Pull net ... |
699 |
struct net *net, |
b700cbb11 svc: Add a generi... |
700 701 702 |
struct sockaddr *sa, int salen, int flags) { |
62832c039 sunrpc: Pull net ... |
703 |
return svc_create_socket(serv, IPPROTO_UDP, net, sa, salen, flags); |
b700cbb11 svc: Add a generi... |
704 |
} |
360d87386 svc: Make svc_soc... |
705 |
static struct svc_xprt_ops svc_udp_ops = { |
b700cbb11 svc: Add a generi... |
706 |
.xpo_create = svc_udp_create, |
5d137990f svc: Move sk_send... |
707 708 |
.xpo_recvfrom = svc_udp_recvfrom, .xpo_sendto = svc_udp_sendto, |
5148bf4eb svc: Add transpor... |
709 |
.xpo_release_rqst = svc_release_skb, |
755cceaba svc: Add per-tran... |
710 711 |
.xpo_detach = svc_sock_detach, .xpo_free = svc_sock_free, |
e831fe65b svc: Add xpo_prep... |
712 |
.xpo_prep_reply_hdr = svc_udp_prep_reply_hdr, |
323bee32e svc: Add a transp... |
713 |
.xpo_has_wspace = svc_udp_has_wspace, |
38a417cc9 svc: Add xpo_acce... |
714 |
.xpo_accept = svc_udp_accept, |
360d87386 svc: Make svc_soc... |
715 716 717 718 |
}; static struct svc_xprt_class svc_udp_class = { .xcl_name = "udp", |
b700cbb11 svc: Add a generi... |
719 |
.xcl_owner = THIS_MODULE, |
360d87386 svc: Make svc_soc... |
720 |
.xcl_ops = &svc_udp_ops, |
490231558 svc: Add a max pa... |
721 |
.xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, |
360d87386 svc: Make svc_soc... |
722 |
}; |
bb5cf160b svc: Move sk_serv... |
723 |
static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) |
1da177e4c Linux-2.6.12-rc2 |
724 |
{ |
7702ce40b SUNRPC: handle IP... |
725 |
int err, level, optname, one = 1; |
7a37f5787 [PATCH] knfsd: us... |
726 |
|
bd4620ddf SUNRPC: create sv... |
727 728 |
svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class, &svsk->sk_xprt, serv); |
def13d740 svc: Move the aut... |
729 |
clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
730 731 |
svsk->sk_sk->sk_data_ready = svc_udp_data_ready; svsk->sk_sk->sk_write_space = svc_write_space; |
1da177e4c Linux-2.6.12-rc2 |
732 733 |
/* initialise setting must have enough space to |
cca5172a7 [NET] SUNRPC: Fix... |
734 |
* receive and respond to one request. |
1da177e4c Linux-2.6.12-rc2 |
735 736 737 |
* svc_udp_recvfrom will re-adjust if necessary */ svc_sock_setbufsize(svsk->sk_sock, |
bb5cf160b svc: Move sk_serv... |
738 739 |
3 * svsk->sk_xprt.xpt_server->sv_max_mesg, 3 * svsk->sk_xprt.xpt_server->sv_max_mesg); |
1da177e4c Linux-2.6.12-rc2 |
740 |
|
0f0257eaa svc: Move the xpr... |
741 742 |
/* data might have come in before data_ready set up */ set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
02fc6c361 svc: Move sk_flag... |
743 |
set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
7a37f5787 [PATCH] knfsd: us... |
744 |
|
7a37f5787 [PATCH] knfsd: us... |
745 |
/* make sure we get destination address info */ |
7702ce40b SUNRPC: handle IP... |
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 |
switch (svsk->sk_sk->sk_family) { case AF_INET: level = SOL_IP; optname = IP_PKTINFO; break; case AF_INET6: level = SOL_IPV6; optname = IPV6_RECVPKTINFO; break; default: BUG(); } err = kernel_setsockopt(svsk->sk_sock, level, optname, (char *)&one, sizeof(one)); dprintk("svc: kernel_setsockopt returned %d ", err); |
1da177e4c Linux-2.6.12-rc2 |
762 763 764 765 766 767 |
} /* * A data_ready event on a listening socket means there's a connection * pending. Do not use state_change as a substitute for it. */ |
0f0257eaa svc: Move the xpr... |
768 |
static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused) |
1da177e4c Linux-2.6.12-rc2 |
769 |
{ |
939bb7ef9 [PATCH] Code clea... |
770 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105 net: add __rcu an... |
771 |
wait_queue_head_t *wq; |
1da177e4c Linux-2.6.12-rc2 |
772 773 774 |
dprintk("svc: socket %p TCP (listen) state change %d ", |
939bb7ef9 [PATCH] Code clea... |
775 |
sk, sk->sk_state); |
1da177e4c Linux-2.6.12-rc2 |
776 |
|
939bb7ef9 [PATCH] Code clea... |
777 778 779 780 781 782 783 784 785 786 787 788 |
/* * This callback may called twice when a new connection * is established as a child socket inherits everything * from a parent LISTEN socket. * 1) data_ready method of the parent socket will be called * when one of child sockets become ESTABLISHED. * 2) data_ready method of the child socket may be called * when it receives data before the socket is accepted. * In case of 2, we should ignore it silently. */ if (sk->sk_state == TCP_LISTEN) { if (svsk) { |
02fc6c361 svc: Move sk_flag... |
789 |
set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
f6150c3ca svc: Make the enq... |
790 |
svc_xprt_enqueue(&svsk->sk_xprt); |
939bb7ef9 [PATCH] Code clea... |
791 792 793 |
} else printk("svc: socket %p: no user data ", sk); |
1da177e4c Linux-2.6.12-rc2 |
794 |
} |
939bb7ef9 [PATCH] Code clea... |
795 |
|
eaefd1105 net: add __rcu an... |
796 797 798 |
wq = sk_sleep(sk); if (wq && waitqueue_active(wq)) wake_up_interruptible_all(wq); |
1da177e4c Linux-2.6.12-rc2 |
799 800 801 802 803 |
} /* * A state change on a connected socket means it's dying or dead. */ |
0f0257eaa svc: Move the xpr... |
804 |
static void svc_tcp_state_change(struct sock *sk) |
1da177e4c Linux-2.6.12-rc2 |
805 |
{ |
939bb7ef9 [PATCH] Code clea... |
806 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105 net: add __rcu an... |
807 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c Linux-2.6.12-rc2 |
808 809 810 |
dprintk("svc: socket %p TCP (connected) state change %d (svsk %p) ", |
939bb7ef9 [PATCH] Code clea... |
811 |
sk, sk->sk_state, sk->sk_user_data); |
1da177e4c Linux-2.6.12-rc2 |
812 |
|
939bb7ef9 [PATCH] Code clea... |
813 |
if (!svsk) |
1da177e4c Linux-2.6.12-rc2 |
814 815 |
printk("svc: socket %p: no user data ", sk); |
939bb7ef9 [PATCH] Code clea... |
816 |
else { |
02fc6c361 svc: Move sk_flag... |
817 |
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
f6150c3ca svc: Make the enq... |
818 |
svc_xprt_enqueue(&svsk->sk_xprt); |
1da177e4c Linux-2.6.12-rc2 |
819 |
} |
eaefd1105 net: add __rcu an... |
820 821 |
if (wq && waitqueue_active(wq)) wake_up_interruptible_all(wq); |
1da177e4c Linux-2.6.12-rc2 |
822 |
} |
0f0257eaa svc: Move the xpr... |
823 |
static void svc_tcp_data_ready(struct sock *sk, int count) |
1da177e4c Linux-2.6.12-rc2 |
824 |
{ |
939bb7ef9 [PATCH] Code clea... |
825 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105 net: add __rcu an... |
826 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c Linux-2.6.12-rc2 |
827 828 829 |
dprintk("svc: socket %p TCP data ready (svsk %p) ", |
939bb7ef9 [PATCH] Code clea... |
830 831 |
sk, sk->sk_user_data); if (svsk) { |
02fc6c361 svc: Move sk_flag... |
832 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
f6150c3ca svc: Make the enq... |
833 |
svc_xprt_enqueue(&svsk->sk_xprt); |
939bb7ef9 [PATCH] Code clea... |
834 |
} |
eaefd1105 net: add __rcu an... |
835 836 |
if (wq && waitqueue_active(wq)) wake_up_interruptible(wq); |
1da177e4c Linux-2.6.12-rc2 |
837 838 839 840 841 |
} /* * Accept a TCP connection */ |
38a417cc9 svc: Add xpo_acce... |
842 |
static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) |
1da177e4c Linux-2.6.12-rc2 |
843 |
{ |
38a417cc9 svc: Add xpo_acce... |
844 |
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
cdd88b9f3 [PATCH] knfsd: SU... |
845 846 |
struct sockaddr_storage addr; struct sockaddr *sin = (struct sockaddr *) &addr; |
bb5cf160b svc: Move sk_serv... |
847 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
1da177e4c Linux-2.6.12-rc2 |
848 849 |
struct socket *sock = svsk->sk_sock; struct socket *newsock; |
1da177e4c Linux-2.6.12-rc2 |
850 851 |
struct svc_sock *newsvsk; int err, slen; |
5216a8e70 Wrap buffers used... |
852 |
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
1da177e4c Linux-2.6.12-rc2 |
853 854 855 856 |
dprintk("svc: tcp_accept %p sock %p ", svsk, sock); if (!sock) |
38a417cc9 svc: Add xpo_acce... |
857 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
858 |
|
02fc6c361 svc: Move sk_flag... |
859 |
clear_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
e6242e928 [SUNRPC]: Update ... |
860 861 |
err = kernel_accept(sock, &newsock, O_NONBLOCK); if (err < 0) { |
1da177e4c Linux-2.6.12-rc2 |
862 863 864 865 |
if (err == -ENOMEM) printk(KERN_WARNING "%s: no more sockets! ", serv->sv_name); |
e6242e928 [SUNRPC]: Update ... |
866 |
else if (err != -EAGAIN && net_ratelimit()) |
1da177e4c Linux-2.6.12-rc2 |
867 868 869 |
printk(KERN_WARNING "%s: accept failed (err %d)! ", serv->sv_name, -err); |
38a417cc9 svc: Add xpo_acce... |
870 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
871 |
} |
02fc6c361 svc: Move sk_flag... |
872 |
set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
873 |
|
cdd88b9f3 [PATCH] knfsd: SU... |
874 |
err = kernel_getpeername(newsock, sin, &slen); |
1da177e4c Linux-2.6.12-rc2 |
875 876 877 878 879 880 881 882 883 |
if (err < 0) { if (net_ratelimit()) printk(KERN_WARNING "%s: peername failed (err %d)! ", serv->sv_name, -err); goto failed; /* aborted connection or whatever */ } /* Ideally, we would want to reject connections from unauthorized |
ad06e4bd6 [PATCH] knfsd: SU... |
884 885 |
* hosts here, but when we get encryption, the IP of the host won't * tell us anything. For now just warn about unpriv connections. |
1da177e4c Linux-2.6.12-rc2 |
886 |
*/ |
cdd88b9f3 [PATCH] knfsd: SU... |
887 |
if (!svc_port_is_privileged(sin)) { |
1da177e4c Linux-2.6.12-rc2 |
888 |
dprintk(KERN_WARNING |
ad06e4bd6 [PATCH] knfsd: SU... |
889 890 |
"%s: connect from unprivileged port: %s ", |
cca5172a7 [NET] SUNRPC: Fix... |
891 |
serv->sv_name, |
cdd88b9f3 [PATCH] knfsd: SU... |
892 |
__svc_print_addr(sin, buf, sizeof(buf))); |
1da177e4c Linux-2.6.12-rc2 |
893 |
} |
ad06e4bd6 [PATCH] knfsd: SU... |
894 895 |
dprintk("%s: connect from %s ", serv->sv_name, |
cdd88b9f3 [PATCH] knfsd: SU... |
896 |
__svc_print_addr(sin, buf, sizeof(buf))); |
1da177e4c Linux-2.6.12-rc2 |
897 898 899 900 901 |
/* make sure that a write doesn't block forever when * low on memory */ newsock->sk->sk_sndtimeo = HZ*30; |
6b174337e [PATCH] knfsd: SU... |
902 903 |
if (!(newsvsk = svc_setup_socket(serv, newsock, &err, (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) |
1da177e4c Linux-2.6.12-rc2 |
904 |
goto failed; |
9dbc240f1 svc: Move the soc... |
905 |
svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); |
a97476926 SUNRPC server: re... |
906 907 908 909 910 911 |
err = kernel_getsockname(newsock, sin, &slen); if (unlikely(err < 0)) { dprintk("svc_tcp_accept: kernel_getsockname error %d ", -err); slen = offsetof(struct sockaddr, sa_data); } |
9dbc240f1 svc: Move the soc... |
912 |
svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen); |
067d78173 [PATCH] knfsd: SU... |
913 |
|
f9f3cc4fa svc: Move connect... |
914 915 916 917 918 919 920 921 922 |
if (serv->sv_stats) serv->sv_stats->nettcpconn++; return &newsvsk->sk_xprt; failed: sock_release(newsock); return NULL; } |
31d68ef65 SUNRPC: Don't wai... |
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) { unsigned int i, len, npages; if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) return 0; len = svsk->sk_tcplen - sizeof(rpc_fraghdr); npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { if (rqstp->rq_pages[i] != NULL) put_page(rqstp->rq_pages[i]); BUG_ON(svsk->sk_pages[i] == NULL); rqstp->rq_pages[i] = svsk->sk_pages[i]; svsk->sk_pages[i] = NULL; } rqstp->rq_arg.head[0].iov_base = page_address(rqstp->rq_pages[0]); return len; } static void svc_tcp_save_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) { unsigned int i, len, npages; if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) return; len = svsk->sk_tcplen - sizeof(rpc_fraghdr); npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { svsk->sk_pages[i] = rqstp->rq_pages[i]; rqstp->rq_pages[i] = NULL; } } static void svc_tcp_clear_pages(struct svc_sock *svsk) { unsigned int i, len, npages; if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) goto out; len = svsk->sk_tcplen - sizeof(rpc_fraghdr); npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { BUG_ON(svsk->sk_pages[i] == NULL); put_page(svsk->sk_pages[i]); svsk->sk_pages[i] = NULL; } out: svsk->sk_tcplen = 0; } |
f9f3cc4fa svc: Move connect... |
972 |
/* |
8f55f3c0a nfsd41: sunrpc: s... |
973 974 975 976 |
* Receive data. * If we haven't gotten the record length yet, get the next four bytes. * Otherwise try to gobble up as much as possible up to the complete * record length. |
1da177e4c Linux-2.6.12-rc2 |
977 |
*/ |
8f55f3c0a nfsd41: sunrpc: s... |
978 |
static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) |
1da177e4c Linux-2.6.12-rc2 |
979 |
{ |
bb5cf160b svc: Move sk_serv... |
980 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
5ee78d483 SUNRPC: svc_tcp_r... |
981 |
unsigned int want; |
8f55f3c0a nfsd41: sunrpc: s... |
982 |
int len; |
1da177e4c Linux-2.6.12-rc2 |
983 |
|
02fc6c361 svc: Move sk_flag... |
984 |
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
985 |
|
c0401ea00 SUNRPC: Update RP... |
986 |
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) { |
1da177e4c Linux-2.6.12-rc2 |
987 |
struct kvec iov; |
5ee78d483 SUNRPC: svc_tcp_r... |
988 |
want = sizeof(rpc_fraghdr) - svsk->sk_tcplen; |
1da177e4c Linux-2.6.12-rc2 |
989 990 991 992 993 994 995 |
iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; iov.iov_len = want; if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0) goto error; svsk->sk_tcplen += len; if (len < want) { |
c0401ea00 SUNRPC: Update RP... |
996 997 998 |
dprintk("svc: short recvfrom while reading record " "length (%d of %d) ", len, want); |
31d68ef65 SUNRPC: Don't wai... |
999 |
return -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
1000 1001 1002 |
} svsk->sk_reclen = ntohl(svsk->sk_reclen); |
c0401ea00 SUNRPC: Update RP... |
1003 |
if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) { |
1da177e4c Linux-2.6.12-rc2 |
1004 1005 1006 1007 1008 |
/* FIXME: technically, a record can be fragmented, * and non-terminal fragments will not have the top * bit set in the fragment length header. * But apparently no known nfs clients send fragmented * records. */ |
34e9a63b4 [PATCH] knfsd: ra... |
1009 |
if (net_ratelimit()) |
c0401ea00 SUNRPC: Update RP... |
1010 1011 1012 |
printk(KERN_NOTICE "RPC: multiple fragments " "per record not supported "); |
1da177e4c Linux-2.6.12-rc2 |
1013 1014 |
goto err_delete; } |
8f55f3c0a nfsd41: sunrpc: s... |
1015 |
|
c0401ea00 SUNRPC: Update RP... |
1016 |
svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK; |
1da177e4c Linux-2.6.12-rc2 |
1017 1018 |
dprintk("svc: TCP record, %d bytes ", svsk->sk_reclen); |
c6b0a9f87 [PATCH] knfsd: ti... |
1019 |
if (svsk->sk_reclen > serv->sv_max_mesg) { |
34e9a63b4 [PATCH] knfsd: ra... |
1020 |
if (net_ratelimit()) |
c0401ea00 SUNRPC: Update RP... |
1021 1022 1023 1024 |
printk(KERN_NOTICE "RPC: " "fragment too large: 0x%08lx ", (unsigned long)svsk->sk_reclen); |
1da177e4c Linux-2.6.12-rc2 |
1025 1026 1027 |
goto err_delete; } } |
cc6c2127f svcrpc: close con... |
1028 1029 |
if (svsk->sk_reclen < 8) goto err_delete; /* client is nuts. */ |
1da177e4c Linux-2.6.12-rc2 |
1030 |
len = svsk->sk_reclen; |
1da177e4c Linux-2.6.12-rc2 |
1031 |
|
8f55f3c0a nfsd41: sunrpc: s... |
1032 |
return len; |
31d68ef65 SUNRPC: Don't wai... |
1033 1034 1035 |
error: dprintk("RPC: TCP recv_record got %d ", len); |
8f55f3c0a nfsd41: sunrpc: s... |
1036 |
return len; |
31d68ef65 SUNRPC: Don't wai... |
1037 |
err_delete: |
8f55f3c0a nfsd41: sunrpc: s... |
1038 |
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
8f55f3c0a nfsd41: sunrpc: s... |
1039 1040 |
return -EAGAIN; } |
586c52cc6 svcrpc: copy cb r... |
1041 |
static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp) |
4cfc7e601 nfsd41: sunrpc: A... |
1042 |
{ |
586c52cc6 svcrpc: copy cb r... |
1043 |
struct rpc_xprt *bc_xprt = svsk->sk_xprt.xpt_bc_xprt; |
4cfc7e601 nfsd41: sunrpc: A... |
1044 |
struct rpc_rqst *req = NULL; |
586c52cc6 svcrpc: copy cb r... |
1045 1046 |
struct kvec *src, *dst; __be32 *p = (__be32 *)rqstp->rq_arg.head[0].iov_base; |
48e6555c7 svcrpc: note netw... |
1047 1048 |
__be32 xid; __be32 calldir; |
4cfc7e601 nfsd41: sunrpc: A... |
1049 |
|
4cfc7e601 nfsd41: sunrpc: A... |
1050 1051 |
xid = *p++; calldir = *p; |
586c52cc6 svcrpc: copy cb r... |
1052 1053 |
if (bc_xprt) req = xprt_lookup_rqst(bc_xprt, xid); |
4cfc7e601 nfsd41: sunrpc: A... |
1054 |
|
586c52cc6 svcrpc: copy cb r... |
1055 1056 1057 1058 1059 1060 1061 1062 |
if (!req) { printk(KERN_NOTICE "%s: Got unrecognized reply: " "calldir 0x%x xpt_bc_xprt %p xid %08x ", __func__, ntohl(calldir), bc_xprt, xid); return -EAGAIN; |
4cfc7e601 nfsd41: sunrpc: A... |
1063 |
} |
586c52cc6 svcrpc: copy cb r... |
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 |
memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf)); /* * XXX!: cheating for now! Only copying HEAD. * But we know this is good enough for now (in fact, for any * callback reply in the forseeable future). */ dst = &req->rq_private_buf.head[0]; src = &rqstp->rq_arg.head[0]; if (dst->iov_len < src->iov_len) return -EAGAIN; /* whatever; just giving up. */ memcpy(dst->iov_base, src->iov_base, src->iov_len); xprt_complete_rqst(req->rq_task, svsk->sk_reclen); rqstp->rq_arg.len = 0; return 0; } static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len) { int i = 0; int t = 0; while (t < len) { vec[i].iov_base = page_address(pages[i]); vec[i].iov_len = PAGE_SIZE; i++; t += PAGE_SIZE; } return i; |
4cfc7e601 nfsd41: sunrpc: A... |
1093 |
} |
31d68ef65 SUNRPC: Don't wai... |
1094 |
|
8f55f3c0a nfsd41: sunrpc: s... |
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 |
/* * Receive data from a TCP socket. */ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); struct svc_serv *serv = svsk->sk_xprt.xpt_server; int len; struct kvec *vec; |
31d68ef65 SUNRPC: Don't wai... |
1105 |
unsigned int want, base; |
586c52cc6 svcrpc: copy cb r... |
1106 1107 |
__be32 *p; __be32 calldir; |
5ee78d483 SUNRPC: svc_tcp_r... |
1108 |
int pnum; |
8f55f3c0a nfsd41: sunrpc: s... |
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 |
dprintk("svc: tcp_recv %p data %d conn %d close %d ", svsk, test_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags), test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags), test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)); len = svc_tcp_recv_record(svsk, rqstp); if (len < 0) goto error; |
31d68ef65 SUNRPC: Don't wai... |
1119 1120 |
base = svc_tcp_restore_pages(svsk, rqstp); want = svsk->sk_reclen - base; |
3cc03b164 [PATCH] knfsd: Av... |
1121 |
vec = rqstp->rq_vec; |
4cfc7e601 nfsd41: sunrpc: A... |
1122 |
|
586c52cc6 svcrpc: copy cb r... |
1123 1124 |
pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], svsk->sk_reclen); |
445243594 [PATCH] knfsd: Re... |
1125 |
rqstp->rq_respages = &rqstp->rq_pages[pnum]; |
1da177e4c Linux-2.6.12-rc2 |
1126 1127 |
/* Now receive data */ |
31d68ef65 SUNRPC: Don't wai... |
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 |
len = svc_partial_recvfrom(rqstp, vec, pnum, want, base); if (len >= 0) svsk->sk_tcplen += len; if (len != want) { if (len < 0 && len != -EAGAIN) goto err_other; svc_tcp_save_pages(svsk, rqstp); dprintk("svc: incomplete TCP record (%d of %d) ", svsk->sk_tcplen, svsk->sk_reclen); goto err_noclose; } |
1da177e4c Linux-2.6.12-rc2 |
1140 |
|
5ee78d483 SUNRPC: svc_tcp_r... |
1141 |
rqstp->rq_arg.len = svsk->sk_reclen; |
1da177e4c Linux-2.6.12-rc2 |
1142 |
rqstp->rq_arg.page_base = 0; |
5ee78d483 SUNRPC: svc_tcp_r... |
1143 1144 |
if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len; |
1da177e4c Linux-2.6.12-rc2 |
1145 |
rqstp->rq_arg.page_len = 0; |
5ee78d483 SUNRPC: svc_tcp_r... |
1146 1147 |
} else rqstp->rq_arg.page_len = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len; |
1da177e4c Linux-2.6.12-rc2 |
1148 |
|
5148bf4eb svc: Add transpor... |
1149 |
rqstp->rq_xprt_ctxt = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1150 |
rqstp->rq_prot = IPPROTO_TCP; |
586c52cc6 svcrpc: copy cb r... |
1151 1152 |
p = (__be32 *)rqstp->rq_arg.head[0].iov_base; calldir = p[1]; |
8985ef0b8 svcrpc: complete ... |
1153 |
if (calldir) |
586c52cc6 svcrpc: copy cb r... |
1154 |
len = receive_cb_reply(svsk, rqstp); |
586c52cc6 svcrpc: copy cb r... |
1155 |
|
1da177e4c Linux-2.6.12-rc2 |
1156 1157 1158 |
/* Reset TCP read info */ svsk->sk_reclen = 0; svsk->sk_tcplen = 0; |
0601f7939 SUNRPC: requeue t... |
1159 1160 1161 |
/* If we have more data, signal svc_xprt_enqueue() to try again */ if (svc_recv_available(svsk) > sizeof(rpc_fraghdr)) set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
8985ef0b8 svcrpc: complete ... |
1162 1163 |
if (len < 0) goto error; |
1da177e4c Linux-2.6.12-rc2 |
1164 |
|
9dbc240f1 svc: Move the soc... |
1165 |
svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt); |
1da177e4c Linux-2.6.12-rc2 |
1166 1167 |
if (serv->sv_stats) serv->sv_stats->nettcpcnt++; |
31d68ef65 SUNRPC: Don't wai... |
1168 1169 |
dprintk("svc: TCP complete record (%d bytes) ", rqstp->rq_arg.len); |
5ee78d483 SUNRPC: svc_tcp_r... |
1170 |
return rqstp->rq_arg.len; |
1da177e4c Linux-2.6.12-rc2 |
1171 |
|
8f55f3c0a nfsd41: sunrpc: s... |
1172 |
error: |
31d68ef65 SUNRPC: Don't wai... |
1173 1174 1175 1176 |
if (len != -EAGAIN) goto err_other; dprintk("RPC: TCP recvfrom got EAGAIN "); |
8f55f3c0a nfsd41: sunrpc: s... |
1177 |
return -EAGAIN; |
31d68ef65 SUNRPC: Don't wai... |
1178 1179 1180 1181 1182 1183 1184 |
err_other: printk(KERN_NOTICE "%s: recvfrom returned errno %d ", svsk->sk_xprt.xpt_server->sv_name, -len); set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); err_noclose: return -EAGAIN; /* record not complete */ |
1da177e4c Linux-2.6.12-rc2 |
1185 1186 1187 1188 1189 |
} /* * Send out data on TCP socket. */ |
0f0257eaa svc: Move the xpr... |
1190 |
static int svc_tcp_sendto(struct svc_rqst *rqstp) |
1da177e4c Linux-2.6.12-rc2 |
1191 1192 1193 |
{ struct xdr_buf *xbufp = &rqstp->rq_res; int sent; |
d8ed029d6 [SUNRPC]: trivial... |
1194 |
__be32 reclen; |
1da177e4c Linux-2.6.12-rc2 |
1195 1196 1197 1198 1199 1200 1201 |
/* Set up the first element of the reply kvec. * Any other kvecs that may be in use have been taken * care of by the server implementation itself. */ reclen = htonl(0x80000000|((xbufp->len ) - 4)); memcpy(xbufp->head[0].iov_base, &reclen, 4); |
1da177e4c Linux-2.6.12-rc2 |
1202 1203 |
sent = svc_sendto(rqstp, &rqstp->rq_res); if (sent != xbufp->len) { |
0f0257eaa svc: Move the xpr... |
1204 1205 1206 1207 |
printk(KERN_NOTICE "rpc-srv/tcp: %s: %s %d when sending %d bytes " "- shutting down socket ", |
57b1d3bab svc: Removing rem... |
1208 |
rqstp->rq_xprt->xpt_server->sv_name, |
1da177e4c Linux-2.6.12-rc2 |
1209 1210 |
(sent<0)?"got error":"sent only", sent, xbufp->len); |
57b1d3bab svc: Removing rem... |
1211 |
set_bit(XPT_CLOSE, &rqstp->rq_xprt->xpt_flags); |
f6150c3ca svc: Make the enq... |
1212 |
svc_xprt_enqueue(rqstp->rq_xprt); |
1da177e4c Linux-2.6.12-rc2 |
1213 1214 1215 1216 |
sent = -EAGAIN; } return sent; } |
e831fe65b svc: Add xpo_prep... |
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 |
/* * Setup response header. TCP has a 4B record length field. */ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) { struct kvec *resv = &rqstp->rq_res.head[0]; /* tcp needs a space for the record length... */ svc_putnl(resv, 0); } |
323bee32e svc: Add a transp... |
1227 1228 |
static int svc_tcp_has_wspace(struct svc_xprt *xprt) { |
57b1d3bab svc: Removing rem... |
1229 |
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
47fcb03fe SUNRPC: Fix the T... |
1230 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
323bee32e svc: Add a transp... |
1231 |
int required; |
323bee32e svc: Add a transp... |
1232 |
|
47fcb03fe SUNRPC: Fix the T... |
1233 1234 1235 1236 1237 |
if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) return 1; required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; if (sk_stream_wspace(svsk->sk_sk) >= required) return 1; |
323bee32e svc: Add a transp... |
1238 |
set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); |
47fcb03fe SUNRPC: Fix the T... |
1239 |
return 0; |
323bee32e svc: Add a transp... |
1240 |
} |
b700cbb11 svc: Add a generi... |
1241 |
static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
62832c039 sunrpc: Pull net ... |
1242 |
struct net *net, |
b700cbb11 svc: Add a generi... |
1243 1244 1245 |
struct sockaddr *sa, int salen, int flags) { |
62832c039 sunrpc: Pull net ... |
1246 |
return svc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags); |
b700cbb11 svc: Add a generi... |
1247 |
} |
9e00abc3c SUNRPC: sunrpc sh... |
1248 |
#if defined(CONFIG_SUNRPC_BACKCHANNEL) |
1f11a034c SUNRPC new transp... |
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 |
static struct svc_xprt *svc_bc_create_socket(struct svc_serv *, int, struct net *, struct sockaddr *, int, int); static void svc_bc_sock_free(struct svc_xprt *xprt); static struct svc_xprt *svc_bc_tcp_create(struct svc_serv *serv, struct net *net, struct sockaddr *sa, int salen, int flags) { return svc_bc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags); } static void svc_bc_tcp_sock_detach(struct svc_xprt *xprt) { } static struct svc_xprt_ops svc_tcp_bc_ops = { .xpo_create = svc_bc_tcp_create, .xpo_detach = svc_bc_tcp_sock_detach, .xpo_free = svc_bc_sock_free, .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, }; static struct svc_xprt_class svc_tcp_bc_class = { .xcl_name = "tcp-bc", .xcl_owner = THIS_MODULE, .xcl_ops = &svc_tcp_bc_ops, .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, }; |
16b2d1e1d SUNRPC register a... |
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 |
static void svc_init_bc_xprt_sock(void) { svc_reg_xprt_class(&svc_tcp_bc_class); } static void svc_cleanup_bc_xprt_sock(void) { svc_unreg_xprt_class(&svc_tcp_bc_class); } |
9e00abc3c SUNRPC: sunrpc sh... |
1289 |
#else /* CONFIG_SUNRPC_BACKCHANNEL */ |
16b2d1e1d SUNRPC register a... |
1290 1291 1292 1293 1294 1295 1296 |
static void svc_init_bc_xprt_sock(void) { } static void svc_cleanup_bc_xprt_sock(void) { } |
9e00abc3c SUNRPC: sunrpc sh... |
1297 |
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1f11a034c SUNRPC new transp... |
1298 |
|
360d87386 svc: Make svc_soc... |
1299 |
static struct svc_xprt_ops svc_tcp_ops = { |
b700cbb11 svc: Add a generi... |
1300 |
.xpo_create = svc_tcp_create, |
5d137990f svc: Move sk_send... |
1301 1302 |
.xpo_recvfrom = svc_tcp_recvfrom, .xpo_sendto = svc_tcp_sendto, |
5148bf4eb svc: Add transpor... |
1303 |
.xpo_release_rqst = svc_release_skb, |
69b6ba371 SUNRPC: Ensure th... |
1304 |
.xpo_detach = svc_tcp_sock_detach, |
755cceaba svc: Add per-tran... |
1305 |
.xpo_free = svc_sock_free, |
e831fe65b svc: Add xpo_prep... |
1306 |
.xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, |
323bee32e svc: Add a transp... |
1307 |
.xpo_has_wspace = svc_tcp_has_wspace, |
38a417cc9 svc: Add xpo_acce... |
1308 |
.xpo_accept = svc_tcp_accept, |
360d87386 svc: Make svc_soc... |
1309 1310 1311 1312 |
}; static struct svc_xprt_class svc_tcp_class = { .xcl_name = "tcp", |
b700cbb11 svc: Add a generi... |
1313 |
.xcl_owner = THIS_MODULE, |
360d87386 svc: Make svc_soc... |
1314 |
.xcl_ops = &svc_tcp_ops, |
490231558 svc: Add a max pa... |
1315 |
.xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
360d87386 svc: Make svc_soc... |
1316 1317 1318 1319 1320 1321 |
}; void svc_init_xprt_sock(void) { svc_reg_xprt_class(&svc_tcp_class); svc_reg_xprt_class(&svc_udp_class); |
16b2d1e1d SUNRPC register a... |
1322 |
svc_init_bc_xprt_sock(); |
360d87386 svc: Make svc_soc... |
1323 1324 1325 1326 1327 1328 |
} void svc_cleanup_xprt_sock(void) { svc_unreg_xprt_class(&svc_tcp_class); svc_unreg_xprt_class(&svc_udp_class); |
16b2d1e1d SUNRPC register a... |
1329 |
svc_cleanup_bc_xprt_sock(); |
360d87386 svc: Make svc_soc... |
1330 |
} |
bb5cf160b svc: Move sk_serv... |
1331 |
static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) |
1da177e4c Linux-2.6.12-rc2 |
1332 1333 |
{ struct sock *sk = svsk->sk_sk; |
1da177e4c Linux-2.6.12-rc2 |
1334 |
|
bd4620ddf SUNRPC: create sv... |
1335 1336 |
svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_tcp_class, &svsk->sk_xprt, serv); |
def13d740 svc: Move the aut... |
1337 |
set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
1338 1339 1340 |
if (sk->sk_state == TCP_LISTEN) { dprintk("setting up TCP socket for listening "); |
02fc6c361 svc: Move sk_flag... |
1341 |
set_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
1342 |
sk->sk_data_ready = svc_tcp_listen_data_ready; |
02fc6c361 svc: Move sk_flag... |
1343 |
set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
1344 1345 1346 1347 1348 |
} else { dprintk("setting up TCP socket for reading "); sk->sk_state_change = svc_tcp_state_change; sk->sk_data_ready = svc_tcp_data_ready; |
47fcb03fe SUNRPC: Fix the T... |
1349 |
sk->sk_write_space = svc_tcp_write_space; |
1da177e4c Linux-2.6.12-rc2 |
1350 1351 1352 |
svsk->sk_reclen = 0; svsk->sk_tcplen = 0; |
31d68ef65 SUNRPC: Don't wai... |
1353 |
memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages)); |
1da177e4c Linux-2.6.12-rc2 |
1354 |
|
b7872fe86 SUNRPC: RPC serve... |
1355 |
tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; |
1da177e4c Linux-2.6.12-rc2 |
1356 |
|
02fc6c361 svc: Move sk_flag... |
1357 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
cca5172a7 [NET] SUNRPC: Fix... |
1358 |
if (sk->sk_state != TCP_ESTABLISHED) |
02fc6c361 svc: Move sk_flag... |
1359 |
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
1360 1361 |
} } |
0f0257eaa svc: Move the xpr... |
1362 |
void svc_sock_update_bufs(struct svc_serv *serv) |
1da177e4c Linux-2.6.12-rc2 |
1363 1364 1365 1366 1367 |
{ /* * The number of server threads has changed. Update * rcvbuf and sndbuf accordingly on all sockets */ |
8f3a6de31 sunrpc: Turn list... |
1368 |
struct svc_sock *svsk; |
1da177e4c Linux-2.6.12-rc2 |
1369 1370 |
spin_lock_bh(&serv->sv_lock); |
8f3a6de31 sunrpc: Turn list... |
1371 |
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) |
02fc6c361 svc: Move sk_flag... |
1372 |
set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
8f3a6de31 sunrpc: Turn list... |
1373 |
list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list) |
02fc6c361 svc: Move sk_flag... |
1374 |
set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1da177e4c Linux-2.6.12-rc2 |
1375 1376 |
spin_unlock_bh(&serv->sv_lock); } |
24c3767e4 SUNRPC: The sunrp... |
1377 |
EXPORT_SYMBOL_GPL(svc_sock_update_bufs); |
1da177e4c Linux-2.6.12-rc2 |
1378 1379 |
/* |
1da177e4c Linux-2.6.12-rc2 |
1380 1381 1382 |
* Initialize socket for RPC use and create svc_sock struct * XXX: May want to setsockopt SO_SNDBUF and SO_RCVBUF. */ |
6b174337e [PATCH] knfsd: SU... |
1383 1384 1385 |
static struct svc_sock *svc_setup_socket(struct svc_serv *serv, struct socket *sock, int *errp, int flags) |
1da177e4c Linux-2.6.12-rc2 |
1386 1387 1388 |
{ struct svc_sock *svsk; struct sock *inet; |
6b174337e [PATCH] knfsd: SU... |
1389 |
int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
1da177e4c Linux-2.6.12-rc2 |
1390 1391 1392 |
dprintk("svc: svc_setup_socket %p ", sock); |
0da974f4f [NET]: Conversion... |
1393 |
if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { |
1da177e4c Linux-2.6.12-rc2 |
1394 1395 1396 |
*errp = -ENOMEM; return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
1397 1398 1399 1400 1401 |
inet = sock->sk; /* Register socket with portmapper */ if (*errp >= 0 && pmap_register) |
baf01caf0 SUNRPC: svc_setup... |
1402 |
*errp = svc_register(serv, inet->sk_family, inet->sk_protocol, |
c720c7e83 inet: rename some... |
1403 |
ntohs(inet_sk(inet)->inet_sport)); |
1da177e4c Linux-2.6.12-rc2 |
1404 1405 1406 1407 1408 |
if (*errp < 0) { kfree(svsk); return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
1409 1410 1411 1412 1413 1414 |
inet->sk_user_data = svsk; svsk->sk_sock = sock; svsk->sk_sk = inet; svsk->sk_ostate = inet->sk_state_change; svsk->sk_odata = inet->sk_data_ready; svsk->sk_owspace = inet->sk_write_space; |
1da177e4c Linux-2.6.12-rc2 |
1415 1416 1417 |
/* Initialize the socket */ if (sock->type == SOCK_DGRAM) |
bb5cf160b svc: Move sk_serv... |
1418 |
svc_udp_init(svsk, serv); |
966043986 svcrpc: take adva... |
1419 1420 1421 1422 1423 1424 |
else { /* initialise setting must have enough space to * receive and respond to one request. */ svc_sock_setbufsize(svsk->sk_sock, 4 * serv->sv_max_mesg, 4 * serv->sv_max_mesg); |
bb5cf160b svc: Move sk_serv... |
1425 |
svc_tcp_init(svsk, serv); |
966043986 svcrpc: take adva... |
1426 |
} |
1da177e4c Linux-2.6.12-rc2 |
1427 |
|
1da177e4c Linux-2.6.12-rc2 |
1428 1429 1430 |
dprintk("svc: svc_setup_socket created %p (inet %p) ", svsk, svsk->sk_sk); |
1da177e4c Linux-2.6.12-rc2 |
1431 1432 |
return svsk; } |
bfba9ab4c SUNRPC: pass buff... |
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 |
/** * svc_addsock - add a listener socket to an RPC service * @serv: pointer to RPC service to which to add a new listener * @fd: file descriptor of the new listener * @name_return: pointer to buffer to fill in with name of listener * @len: size of the buffer * * Fills in socket name and returns positive length of name if successful. * Name is terminated with ' '. On error, returns a negative errno * value. */ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, const size_t len) |
b41b66d63 [PATCH] knfsd: al... |
1447 1448 1449 1450 1451 1452 1453 |
{ int err = 0; struct socket *so = sockfd_lookup(fd, &err); struct svc_sock *svsk = NULL; if (!so) return err; |
205ba4230 NFSD: Support AF_... |
1454 |
if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) |
b41b66d63 [PATCH] knfsd: al... |
1455 1456 1457 1458 1459 1460 1461 |
err = -EAFNOSUPPORT; else if (so->sk->sk_protocol != IPPROTO_TCP && so->sk->sk_protocol != IPPROTO_UDP) err = -EPROTONOSUPPORT; else if (so->state > SS_UNCONNECTED) err = -EISCONN; else { |
2da2c21d7 Add a reference t... |
1462 1463 1464 1465 1466 |
if (!try_module_get(THIS_MODULE)) err = -ENOENT; else svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS); |
e79eff1f9 [PATCH] knfsd: SU... |
1467 |
if (svsk) { |
9dbc240f1 svc: Move the soc... |
1468 1469 1470 1471 1472 |
struct sockaddr_storage addr; struct sockaddr *sin = (struct sockaddr *)&addr; int salen; if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) svc_xprt_set_local(&svsk->sk_xprt, sin, salen); |
4e5caaa5f svc: Move create ... |
1473 1474 1475 1476 |
clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); spin_lock_bh(&serv->sv_lock); list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks); spin_unlock_bh(&serv->sv_lock); |
a6046f71f svc: Change svc_s... |
1477 |
svc_xprt_received(&svsk->sk_xprt); |
b41b66d63 [PATCH] knfsd: al... |
1478 |
err = 0; |
2da2c21d7 Add a reference t... |
1479 1480 |
} else module_put(THIS_MODULE); |
b41b66d63 [PATCH] knfsd: al... |
1481 1482 1483 1484 1485 |
} if (err) { sockfd_put(so); return err; } |
e7942b9f2 SUNRPC: Switch on... |
1486 |
return svc_one_sock_name(svsk, name_return, len); |
b41b66d63 [PATCH] knfsd: al... |
1487 1488 |
} EXPORT_SYMBOL_GPL(svc_addsock); |
1da177e4c Linux-2.6.12-rc2 |
1489 1490 1491 |
/* * Create socket for RPC service. */ |
b700cbb11 svc: Add a generi... |
1492 1493 |
static struct svc_xprt *svc_create_socket(struct svc_serv *serv, int protocol, |
62832c039 sunrpc: Pull net ... |
1494 |
struct net *net, |
b700cbb11 svc: Add a generi... |
1495 1496 |
struct sockaddr *sin, int len, int flags) |
1da177e4c Linux-2.6.12-rc2 |
1497 1498 1499 1500 1501 |
{ struct svc_sock *svsk; struct socket *sock; int error; int type; |
9dbc240f1 svc: Move the soc... |
1502 1503 1504 |
struct sockaddr_storage addr; struct sockaddr *newsin = (struct sockaddr *)&addr; int newlen; |
c69da774b SUNRPC: Ensure IP... |
1505 1506 |
int family; int val; |
5216a8e70 Wrap buffers used... |
1507 |
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
1da177e4c Linux-2.6.12-rc2 |
1508 |
|
ad06e4bd6 [PATCH] knfsd: SU... |
1509 1510 1511 |
dprintk("svc: svc_create_socket(%s, %d, %s) ", serv->sv_program->pg_name, protocol, |
77f1f67a1 [PATCH] knfsd: SU... |
1512 |
__svc_print_addr(sin, buf, sizeof(buf))); |
1da177e4c Linux-2.6.12-rc2 |
1513 1514 1515 1516 1517 |
if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) { printk(KERN_WARNING "svc: only UDP and TCP " "sockets supported "); |
b700cbb11 svc: Add a generi... |
1518 |
return ERR_PTR(-EINVAL); |
1da177e4c Linux-2.6.12-rc2 |
1519 |
} |
c69da774b SUNRPC: Ensure IP... |
1520 |
|
1da177e4c Linux-2.6.12-rc2 |
1521 |
type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; |
c69da774b SUNRPC: Ensure IP... |
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 |
switch (sin->sa_family) { case AF_INET6: family = PF_INET6; break; case AF_INET: family = PF_INET; break; default: return ERR_PTR(-EINVAL); } |
1da177e4c Linux-2.6.12-rc2 |
1532 |
|
14ec63c33 sunrpc: Create so... |
1533 |
error = __sock_create(net, family, type, protocol, &sock, 1); |
77f1f67a1 [PATCH] knfsd: SU... |
1534 |
if (error < 0) |
b700cbb11 svc: Add a generi... |
1535 |
return ERR_PTR(error); |
1da177e4c Linux-2.6.12-rc2 |
1536 |
|
ed07536ed [PATCH] lockdep: ... |
1537 |
svc_reclassify_socket(sock); |
c69da774b SUNRPC: Ensure IP... |
1538 1539 1540 1541 1542 1543 1544 1545 1546 |
/* * If this is an PF_INET6 listener, we want to avoid * getting requests from IPv4 remotes. Those should * be shunted to a PF_INET listener via rpcbind. */ val = 1; if (family == PF_INET6) kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val)); |
181147462 [SUNRPC]: Remove ... |
1547 |
if (type == SOCK_STREAM) |
77f1f67a1 [PATCH] knfsd: SU... |
1548 1549 |
sock->sk->sk_reuse = 1; /* allow address reuse */ error = kernel_bind(sock, sin, len); |
181147462 [SUNRPC]: Remove ... |
1550 1551 |
if (error < 0) goto bummer; |
1da177e4c Linux-2.6.12-rc2 |
1552 |
|
9dbc240f1 svc: Move the soc... |
1553 1554 1555 1556 |
newlen = len; error = kernel_getsockname(sock, newsin, &newlen); if (error < 0) goto bummer; |
1da177e4c Linux-2.6.12-rc2 |
1557 |
if (protocol == IPPROTO_TCP) { |
e6242e928 [SUNRPC]: Update ... |
1558 |
if ((error = kernel_listen(sock, 64)) < 0) |
1da177e4c Linux-2.6.12-rc2 |
1559 1560 |
goto bummer; } |
e79eff1f9 [PATCH] knfsd: SU... |
1561 |
if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { |
9dbc240f1 svc: Move the soc... |
1562 |
svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); |
b700cbb11 svc: Add a generi... |
1563 |
return (struct svc_xprt *)svsk; |
e79eff1f9 [PATCH] knfsd: SU... |
1564 |
} |
1da177e4c Linux-2.6.12-rc2 |
1565 1566 1567 1568 1569 |
bummer: dprintk("svc: svc_create_socket error = %d ", -error); sock_release(sock); |
b700cbb11 svc: Add a generi... |
1570 |
return ERR_PTR(error); |
1da177e4c Linux-2.6.12-rc2 |
1571 1572 1573 |
} /* |
755cceaba svc: Add per-tran... |
1574 1575 1576 1577 1578 1579 1580 |
* Detach the svc_sock from the socket so that no * more callbacks occur. */ static void svc_sock_detach(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); struct sock *sk = svsk->sk_sk; |
eaefd1105 net: add __rcu an... |
1581 |
wait_queue_head_t *wq; |
755cceaba svc: Add per-tran... |
1582 1583 1584 1585 1586 1587 1588 1589 |
dprintk("svc: svc_sock_detach(%p) ", svsk); /* put back the old socket callbacks */ sk->sk_state_change = svsk->sk_ostate; sk->sk_data_ready = svsk->sk_odata; sk->sk_write_space = svsk->sk_owspace; |
69b6ba371 SUNRPC: Ensure th... |
1590 |
|
eaefd1105 net: add __rcu an... |
1591 1592 1593 |
wq = sk_sleep(sk); if (wq && waitqueue_active(wq)) wake_up_interruptible(wq); |
69b6ba371 SUNRPC: Ensure th... |
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 |
} /* * Disconnect the socket, and reset the callbacks */ static void svc_tcp_sock_detach(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); dprintk("svc: svc_tcp_sock_detach(%p) ", svsk); svc_sock_detach(xprt); |
31d68ef65 SUNRPC: Don't wai... |
1607 1608 |
if (!test_bit(XPT_LISTENER, &xprt->xpt_flags)) { svc_tcp_clear_pages(svsk); |
69b6ba371 SUNRPC: Ensure th... |
1609 |
kernel_sock_shutdown(svsk->sk_sock, SHUT_RDWR); |
31d68ef65 SUNRPC: Don't wai... |
1610 |
} |
755cceaba svc: Add per-tran... |
1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 |
} /* * Free the svc_sock's socket resources and the svc_sock itself. */ static void svc_sock_free(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); dprintk("svc: svc_sock_free(%p) ", svsk); |
755cceaba svc: Add per-tran... |
1621 1622 1623 1624 1625 1626 |
if (svsk->sk_sock->file) sockfd_put(svsk->sk_sock); else sock_release(svsk->sk_sock); kfree(svsk); } |
7652e5a09 nfs41: sunrpc: pr... |
1627 |
|
9e00abc3c SUNRPC: sunrpc sh... |
1628 |
#if defined(CONFIG_SUNRPC_BACKCHANNEL) |
7652e5a09 nfs41: sunrpc: pr... |
1629 |
/* |
1f11a034c SUNRPC new transp... |
1630 |
* Create a back channel svc_xprt which shares the fore channel socket. |
7652e5a09 nfs41: sunrpc: pr... |
1631 |
*/ |
1f11a034c SUNRPC new transp... |
1632 1633 1634 1635 1636 |
static struct svc_xprt *svc_bc_create_socket(struct svc_serv *serv, int protocol, struct net *net, struct sockaddr *sin, int len, int flags) |
7652e5a09 nfs41: sunrpc: pr... |
1637 1638 |
{ struct svc_sock *svsk; |
1f11a034c SUNRPC new transp... |
1639 1640 1641 1642 1643 1644 1645 1646 |
struct svc_xprt *xprt; if (protocol != IPPROTO_TCP) { printk(KERN_WARNING "svc: only TCP sockets" " supported on shared back channel "); return ERR_PTR(-EINVAL); } |
7652e5a09 nfs41: sunrpc: pr... |
1647 |
|
7652e5a09 nfs41: sunrpc: pr... |
1648 1649 |
svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); if (!svsk) |
1f11a034c SUNRPC new transp... |
1650 |
return ERR_PTR(-ENOMEM); |
7652e5a09 nfs41: sunrpc: pr... |
1651 1652 |
xprt = &svsk->sk_xprt; |
bd4620ddf SUNRPC: create sv... |
1653 |
svc_xprt_init(net, &svc_tcp_bc_class, xprt, serv); |
1f11a034c SUNRPC new transp... |
1654 |
|
4a19de0f4 NFS rename client... |
1655 |
serv->sv_bc_xprt = xprt; |
1f11a034c SUNRPC new transp... |
1656 |
|
7652e5a09 nfs41: sunrpc: pr... |
1657 1658 |
return xprt; } |
7652e5a09 nfs41: sunrpc: pr... |
1659 1660 |
/* |
1f11a034c SUNRPC new transp... |
1661 |
* Free a back channel svc_sock. |
7652e5a09 nfs41: sunrpc: pr... |
1662 |
*/ |
1f11a034c SUNRPC new transp... |
1663 |
static void svc_bc_sock_free(struct svc_xprt *xprt) |
7652e5a09 nfs41: sunrpc: pr... |
1664 |
{ |
778be232a NFS do not find c... |
1665 |
if (xprt) |
7652e5a09 nfs41: sunrpc: pr... |
1666 1667 |
kfree(container_of(xprt, struct svc_sock, sk_xprt)); } |
9e00abc3c SUNRPC: sunrpc sh... |
1668 |
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ |