Blame view
net/sunrpc/svcsock.c
42.5 KB
1da177e4c
|
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
|
8 |
* svc_xprt_enqueue procedure... |
1da177e4c
|
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
|
21 |
#include <linux/kernel.h> |
1da177e4c
|
22 |
#include <linux/sched.h> |
3a9a231d9
|
23 |
#include <linux/module.h> |
1da177e4c
|
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
|
30 |
#include <linux/tcp.h> |
1da177e4c
|
31 32 33 34 |
#include <linux/unistd.h> #include <linux/slab.h> #include <linux/netdevice.h> #include <linux/skbuff.h> |
b41b66d63
|
35 |
#include <linux/file.h> |
7dfb71030
|
36 |
#include <linux/freezer.h> |
1da177e4c
|
37 38 39 |
#include <net/sock.h> #include <net/checksum.h> #include <net/ip.h> |
b92503b25
|
40 |
#include <net/ipv6.h> |
b7872fe86
|
41 |
#include <net/tcp.h> |
c752f0739
|
42 |
#include <net/tcp_states.h> |
1da177e4c
|
43 44 |
#include <asm/uaccess.h> #include <asm/ioctls.h> |
22911fc58
|
45 |
#include <trace/events/skb.h> |
1da177e4c
|
46 47 |
#include <linux/sunrpc/types.h> |
ad06e4bd6
|
48 |
#include <linux/sunrpc/clnt.h> |
1da177e4c
|
49 |
#include <linux/sunrpc/xdr.h> |
c0401ea00
|
50 |
#include <linux/sunrpc/msg_prot.h> |
1da177e4c
|
51 52 |
#include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/stats.h> |
4cfc7e601
|
53 |
#include <linux/sunrpc/xprt.h> |
1da177e4c
|
54 |
|
177e4f998
|
55 |
#include "sunrpc.h" |
360d87386
|
56 |
#define RPCDBG_FACILITY RPCDBG_SVCXPRT |
1da177e4c
|
57 58 59 |
static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
72c353760
|
60 |
int flags); |
676d23690
|
61 |
static void svc_udp_data_ready(struct sock *); |
1da177e4c
|
62 63 |
static int svc_udp_recvfrom(struct svc_rqst *); static int svc_udp_sendto(struct svc_rqst *); |
755cceaba
|
64 |
static void svc_sock_detach(struct svc_xprt *); |
69b6ba371
|
65 |
static void svc_tcp_sock_detach(struct svc_xprt *); |
755cceaba
|
66 |
static void svc_sock_free(struct svc_xprt *); |
1da177e4c
|
67 |
|
b700cbb11
|
68 |
static struct svc_xprt *svc_create_socket(struct svc_serv *, int, |
62832c039
|
69 70 |
struct net *, struct sockaddr *, int, int); |
9e00abc3c
|
71 |
#if defined(CONFIG_SUNRPC_BACKCHANNEL) |
1f11a034c
|
72 73 74 75 |
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
|
76 |
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1f11a034c
|
77 |
|
ed07536ed
|
78 79 80 |
#ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key svc_key[2]; static struct lock_class_key svc_slock_key[2]; |
0f0257eaa
|
81 |
static void svc_reclassify_socket(struct socket *sock) |
ed07536ed
|
82 83 |
{ struct sock *sk = sock->sk; |
1b7a18190
|
84 85 86 87 |
WARN_ON_ONCE(sock_owned_by_user(sk)); if (sock_owned_by_user(sk)) return; |
ed07536ed
|
88 89 90 |
switch (sk->sk_family) { case AF_INET: sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", |
def13d740
|
91 92 93 |
&svc_slock_key[0], "sk_xprt.xpt_lock-AF_INET-NFSD", &svc_key[0]); |
ed07536ed
|
94 95 96 97 |
break; case AF_INET6: sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFSD", |
def13d740
|
98 99 100 |
&svc_slock_key[1], "sk_xprt.xpt_lock-AF_INET6-NFSD", &svc_key[1]); |
ed07536ed
|
101 102 103 104 105 106 107 |
break; default: BUG(); } } #else |
0f0257eaa
|
108 |
static void svc_reclassify_socket(struct socket *sock) |
ed07536ed
|
109 110 111 |
{ } #endif |
1da177e4c
|
112 113 114 |
/* * Release an skbuff after use */ |
5148bf4eb
|
115 |
static void svc_release_skb(struct svc_rqst *rqstp) |
1da177e4c
|
116 |
{ |
5148bf4eb
|
117 |
struct sk_buff *skb = rqstp->rq_xprt_ctxt; |
1da177e4c
|
118 119 |
if (skb) { |
57b1d3bab
|
120 121 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
5148bf4eb
|
122 |
rqstp->rq_xprt_ctxt = NULL; |
1da177e4c
|
123 124 125 |
dprintk("svc: service %p, releasing skb %p ", rqstp, skb); |
9d410c796
|
126 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
1da177e4c
|
127 |
} |
1da177e4c
|
128 |
} |
b92503b25
|
129 130 |
union svc_pktinfo_u { struct in_pktinfo pkti; |
b92503b25
|
131 |
struct in6_pktinfo pkti6; |
b92503b25
|
132 |
}; |
bc375ea7e
|
133 134 |
#define SVC_PKTINFO_SPACE \ CMSG_SPACE(sizeof(union svc_pktinfo_u)) |
b92503b25
|
135 136 137 |
static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) { |
57b1d3bab
|
138 139 140 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); switch (svsk->sk_sk->sk_family) { |
b92503b25
|
141 142 143 144 145 146 |
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
|
147 148 |
pki->ipi_spec_dst.s_addr = svc_daddr_in(rqstp)->sin_addr.s_addr; |
b92503b25
|
149 150 151 |
cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); } break; |
5a05ed73e
|
152 |
|
b92503b25
|
153 154 |
case AF_INET6: { struct in6_pktinfo *pki = CMSG_DATA(cmh); |
849a1cf13
|
155 |
struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); |
b92503b25
|
156 157 158 |
cmh->cmsg_level = SOL_IPV6; cmh->cmsg_type = IPV6_PKTINFO; |
849a1cf13
|
159 |
pki->ipi6_ifindex = daddr->sin6_scope_id; |
4e3fd7a06
|
160 |
pki->ipi6_addr = daddr->sin6_addr; |
b92503b25
|
161 162 163 |
cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); } break; |
b92503b25
|
164 |
} |
b92503b25
|
165 |
} |
1da177e4c
|
166 |
/* |
4cfc7e601
|
167 |
* send routine intended to be shared by the fore- and back-channel |
1da177e4c
|
168 |
*/ |
4cfc7e601
|
169 170 171 |
int svc_send_common(struct socket *sock, struct xdr_buf *xdr, struct page *headpage, unsigned long headoffset, struct page *tailpage, unsigned long tailoffset) |
1da177e4c
|
172 |
{ |
1da177e4c
|
173 174 175 176 177 178 |
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
|
179 180 |
int slen; int len = 0; |
1da177e4c
|
181 182 |
slen = xdr->len; |
1da177e4c
|
183 184 185 |
/* send head */ if (slen == xdr->head[0].iov_len) flags = 0; |
4cfc7e601
|
186 |
len = kernel_sendpage(sock, headpage, headoffset, |
445243594
|
187 |
xdr->head[0].iov_len, flags); |
1da177e4c
|
188 189 190 191 192 193 194 195 196 197 198 |
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
|
199 |
result = kernel_sendpage(sock, *ppage, base, size, flags); |
1da177e4c
|
200 201 202 203 204 205 206 207 208 209 |
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
|
210 |
|
1da177e4c
|
211 212 |
/* send tail */ if (xdr->tail[0].iov_len) { |
4cfc7e601
|
213 214 |
result = kernel_sendpage(sock, tailpage, tailoffset, xdr->tail[0].iov_len, 0); |
1da177e4c
|
215 216 217 |
if (result > 0) len += result; } |
4cfc7e601
|
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 257 258 259 260 |
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
|
261 |
out: |
ad06e4bd6
|
262 263 |
dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s) ", |
57b1d3bab
|
264 |
svsk, xdr->head[0].iov_base, xdr->head[0].iov_len, |
ad06e4bd6
|
265 |
xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf))); |
1da177e4c
|
266 267 268 269 270 |
return len; } /* |
80212d59e
|
271 272 |
* Report socket names for nfsdfs */ |
e7942b9f2
|
273 |
static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) |
80212d59e
|
274 |
{ |
017cb47f4
|
275 276 277 |
const struct sock *sk = svsk->sk_sk; const char *proto_name = sk->sk_protocol == IPPROTO_UDP ? "udp" : "tcp"; |
80212d59e
|
278 |
int len; |
017cb47f4
|
279 |
switch (sk->sk_family) { |
e7942b9f2
|
280 281 282 |
case PF_INET: len = snprintf(buf, remaining, "ipv4 %s %pI4 %d ", |
017cb47f4
|
283 |
proto_name, |
c720c7e83
|
284 285 |
&inet_sk(sk)->inet_rcv_saddr, inet_sk(sk)->inet_num); |
80212d59e
|
286 |
break; |
c2bb06db5
|
287 |
#if IS_ENABLED(CONFIG_IPV6) |
58de2f865
|
288 289 290 |
case PF_INET6: len = snprintf(buf, remaining, "ipv6 %s %pI6 %d ", |
017cb47f4
|
291 |
proto_name, |
efe4208f4
|
292 |
&sk->sk_v6_rcv_saddr, |
c720c7e83
|
293 |
inet_sk(sk)->inet_num); |
80212d59e
|
294 |
break; |
c2bb06db5
|
295 |
#endif |
80212d59e
|
296 |
default: |
e7942b9f2
|
297 298 |
len = snprintf(buf, remaining, "*unknown-%d* ", |
017cb47f4
|
299 |
sk->sk_family); |
80212d59e
|
300 |
} |
e7942b9f2
|
301 302 303 304 |
if (len >= remaining) { *buf = '\0'; return -ENAMETOOLONG; |
80212d59e
|
305 306 307 |
} return len; } |
80212d59e
|
308 |
/* |
1da177e4c
|
309 310 |
* Generic recvfrom routine. */ |
0f0257eaa
|
311 312 |
static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen) |
1da177e4c
|
313 |
{ |
57b1d3bab
|
314 315 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
1ba951053
|
316 317 318 319 |
struct msghdr msg = { .msg_flags = MSG_DONTWAIT, }; int len; |
1da177e4c
|
320 |
|
260c1d129
|
321 |
rqstp->rq_xprt_hlen = 0; |
f8d1ff47b
|
322 |
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
1ba951053
|
323 324 |
len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, msg.msg_flags); |
f8d1ff47b
|
325 326 327 328 329 |
/* If we read a full record, then assume there may be more * data to read (stream based sockets only!) */ if (len == buflen) set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
330 |
|
1da177e4c
|
331 332 |
dprintk("svc: socket %p recvfrom(%p, %Zu) = %d ", |
1ba951053
|
333 |
svsk, iov[0].iov_base, iov[0].iov_len, len); |
1da177e4c
|
334 335 |
return len; } |
31d68ef65
|
336 337 338 339 340 |
static int svc_partial_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen, unsigned int base) { size_t save_iovlen; |
09acfea5d
|
341 |
void *save_iovbase; |
31d68ef65
|
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
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
|
362 363 364 |
/* * Set socket snd and rcv buffer lengths */ |
0f0257eaa
|
365 366 |
static void svc_sock_setbufsize(struct socket *sock, unsigned int snd, unsigned int rcv) |
1da177e4c
|
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
{ #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
|
384 |
sock->sk->sk_write_space(sock->sk); |
1da177e4c
|
385 386 387 |
release_sock(sock->sk); #endif } |
16e4d93f6
|
388 389 390 391 392 |
static int svc_sock_secure_port(struct svc_rqst *rqstp) { return svc_port_is_privileged(svc_addr(rqstp)); } |
1da177e4c
|
393 394 395 |
/* * INET callback when data has been received on the socket. */ |
676d23690
|
396 |
static void svc_udp_data_ready(struct sock *sk) |
1da177e4c
|
397 |
{ |
939bb7ef9
|
398 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105
|
399 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c
|
400 |
|
939bb7ef9
|
401 |
if (svsk) { |
676d23690
|
402 403 404 |
dprintk("svc: socket %p(inet %p), busy=%d ", svsk, sk, |
02fc6c361
|
405 406 |
test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
f6150c3ca
|
407 |
svc_xprt_enqueue(&svsk->sk_xprt); |
939bb7ef9
|
408 |
} |
eaefd1105
|
409 410 |
if (wq && waitqueue_active(wq)) wake_up_interruptible(wq); |
1da177e4c
|
411 412 413 414 415 |
} /* * INET callback when space is newly available on the socket. */ |
0f0257eaa
|
416 |
static void svc_write_space(struct sock *sk) |
1da177e4c
|
417 418 |
{ struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); |
eaefd1105
|
419 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c
|
420 421 422 423 |
if (svsk) { dprintk("svc: socket %p(inet %p), write_space busy=%d ", |
02fc6c361
|
424 |
svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
f6150c3ca
|
425 |
svc_xprt_enqueue(&svsk->sk_xprt); |
1da177e4c
|
426 |
} |
eaefd1105
|
427 |
if (wq && waitqueue_active(wq)) { |
939bb7ef9
|
428 429 |
dprintk("RPC svc_write_space: someone sleeping on %p ", |
1da177e4c
|
430 |
svsk); |
eaefd1105
|
431 |
wake_up_interruptible(wq); |
1da177e4c
|
432 433 |
} } |
c7fb3f063
|
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 |
static int svc_tcp_has_wspace(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); struct svc_serv *serv = svsk->sk_xprt.xpt_server; int required; 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 || (sk_stream_min_wspace(svsk->sk_sk) == 0 && atomic_read(&xprt->xpt_reserved) == 0)) return 1; set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); return 0; } |
47fcb03fe
|
450 451 |
static void svc_tcp_write_space(struct sock *sk) { |
c7fb3f063
|
452 |
struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); |
47fcb03fe
|
453 |
struct socket *sock = sk->sk_socket; |
c7fb3f063
|
454 455 456 |
if (!sk_stream_is_writeable(sk) || !sock) return; if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt)) |
47fcb03fe
|
457 458 459 |
clear_bit(SOCK_NOSPACE, &sock->flags); svc_write_space(sk); } |
518776800
|
460 461 462 463 464 465 466 |
static void svc_tcp_adjust_wspace(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); if (svc_tcp_has_wspace(xprt)) clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); } |
9dbc240f1
|
467 |
/* |
7702ce40b
|
468 469 470 471 472 473 |
* 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
|
474 |
struct sockaddr_in *daddr = svc_daddr_in(rqstp); |
7702ce40b
|
475 476 |
if (cmh->cmsg_type != IP_PKTINFO) return 0; |
849a1cf13
|
477 478 479 |
daddr->sin_family = AF_INET; daddr->sin_addr.s_addr = pki->ipi_spec_dst.s_addr; |
7702ce40b
|
480 481 482 483 |
return 1; } /* |
73df66f8b
|
484 |
* See net/ipv6/datagram.c : ip6_datagram_recv_ctl |
7702ce40b
|
485 486 487 488 489 |
*/ static int svc_udp_get_dest_address6(struct svc_rqst *rqstp, struct cmsghdr *cmh) { struct in6_pktinfo *pki = CMSG_DATA(cmh); |
849a1cf13
|
490 |
struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); |
7702ce40b
|
491 492 |
if (cmh->cmsg_type != IPV6_PKTINFO) return 0; |
849a1cf13
|
493 494 |
daddr->sin6_family = AF_INET6; |
4e3fd7a06
|
495 |
daddr->sin6_addr = pki->ipi6_addr; |
849a1cf13
|
496 |
daddr->sin6_scope_id = pki->ipi6_ifindex; |
7702ce40b
|
497 498 499 500 |
return 1; } /* |
9dbc240f1
|
501 502 503 504 505 506 |
* 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
|
507 508 |
static int svc_udp_get_dest_address(struct svc_rqst *rqstp, struct cmsghdr *cmh) |
95756482c
|
509 |
{ |
7702ce40b
|
510 511 512 513 514 |
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
|
515 |
} |
7702ce40b
|
516 517 |
return 0; |
95756482c
|
518 |
} |
1da177e4c
|
519 520 521 |
/* * Receive a datagram from a UDP socket. */ |
0f0257eaa
|
522 |
static int svc_udp_recvfrom(struct svc_rqst *rqstp) |
1da177e4c
|
523 |
{ |
57b1d3bab
|
524 525 |
struct svc_sock *svsk = container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
bb5cf160b
|
526 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
1da177e4c
|
527 |
struct sk_buff *skb; |
bc375ea7e
|
528 529 530 531 532 |
union { struct cmsghdr hdr; long all[SVC_PKTINFO_SPACE / sizeof(long)]; } buffer; struct cmsghdr *cmh = &buffer.hdr; |
7a37f5787
|
533 534 535 536 537 538 |
struct msghdr msg = { .msg_name = svc_addr(rqstp), .msg_control = cmh, .msg_controllen = sizeof(buffer), .msg_flags = MSG_DONTWAIT, }; |
abc5c44d6
|
539 540 |
size_t len; int err; |
1da177e4c
|
541 |
|
02fc6c361
|
542 |
if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) |
1da177e4c
|
543 544 545 |
/* 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
|
546 547 548 549 |
* 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
|
550 551 |
*/ svc_sock_setbufsize(svsk->sk_sock, |
c6b0a9f87
|
552 553 |
(serv->sv_nrthreads+3) * serv->sv_max_mesg, (serv->sv_nrthreads+3) * serv->sv_max_mesg); |
1da177e4c
|
554 |
|
02fc6c361
|
555 |
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
05ed690ef
|
556 557 558 559 560 561 562 563 564 565 566 |
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
|
567 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
568 |
} |
9f9d2ebe6
|
569 |
return 0; |
1da177e4c
|
570 |
} |
9dbc240f1
|
571 |
len = svc_addr_len(svc_addr(rqstp)); |
9dbc240f1
|
572 |
rqstp->rq_addrlen = len; |
b7aa0bf70
|
573 574 |
if (skb->tstamp.tv64 == 0) { skb->tstamp = ktime_get_real(); |
cca5172a7
|
575 |
/* Don't enable netstamp, sunrpc doesn't |
1da177e4c
|
576 577 |
need that much accuracy */ } |
b7aa0bf70
|
578 |
svsk->sk_sk->sk_stamp = skb->tstamp; |
02fc6c361
|
579 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); /* there may be more data... */ |
1da177e4c
|
580 |
|
1da177e4c
|
581 582 |
len = skb->len - sizeof(struct udphdr); rqstp->rq_arg.len = len; |
95756482c
|
583 |
rqstp->rq_prot = IPPROTO_UDP; |
27459f094
|
584 |
|
7702ce40b
|
585 |
if (!svc_udp_get_dest_address(rqstp, cmh)) { |
e87cc4728
|
586 587 588 |
net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram ", cmh->cmsg_level, cmh->cmsg_type); |
f23abfdb9
|
589 |
goto out_free; |
7a37f5787
|
590 |
} |
849a1cf13
|
591 |
rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); |
1da177e4c
|
592 593 594 595 596 597 598 |
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 */ |
22911fc58
|
599 |
goto out_free; |
1da177e4c
|
600 601 |
} local_bh_enable(); |
9d410c796
|
602 |
skb_free_datagram_locked(svsk->sk_sk, skb); |
1da177e4c
|
603 604 |
} else { /* we can use it in-place */ |
0f0257eaa
|
605 606 |
rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); |
1da177e4c
|
607 |
rqstp->rq_arg.head[0].iov_len = len; |
22911fc58
|
608 609 |
if (skb_checksum_complete(skb)) goto out_free; |
5148bf4eb
|
610 |
rqstp->rq_xprt_ctxt = skb; |
1da177e4c
|
611 612 613 614 615 616 |
} 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
|
617 |
rqstp->rq_respages = rqstp->rq_pages+1; |
1da177e4c
|
618 619 |
} else { rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; |
445243594
|
620 |
rqstp->rq_respages = rqstp->rq_pages + 1 + |
172589ccd
|
621 |
DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE); |
1da177e4c
|
622 |
} |
afc59400d
|
623 |
rqstp->rq_next_page = rqstp->rq_respages+1; |
1da177e4c
|
624 625 626 627 628 |
if (serv->sv_stats) serv->sv_stats->netudpcnt++; return len; |
f23abfdb9
|
629 630 631 632 |
out_free: trace_kfree_skb(skb, svc_udp_recvfrom); skb_free_datagram_locked(svsk->sk_sk, skb); return 0; |
1da177e4c
|
633 634 635 636 637 638 639 640 641 642 643 644 645 646 |
} 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
|
647 648 649 |
static void svc_udp_prep_reply_hdr(struct svc_rqst *rqstp) { } |
323bee32e
|
650 651 652 |
static int svc_udp_has_wspace(struct svc_xprt *xprt) { struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
bb5cf160b
|
653 |
struct svc_serv *serv = xprt->xpt_server; |
323bee32e
|
654 655 656 657 658 659 660 |
unsigned long required; /* * Set the SOCK_NOSPACE flag before checking the available * sock space. */ set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); |
7a90e8cc2
|
661 |
required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg; |
323bee32e
|
662 663 664 665 666 |
if (required*2 > sock_wspace(svsk->sk_sk)) return 0; clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); return 1; } |
38a417cc9
|
667 668 669 670 671 |
static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt) { BUG(); return NULL; } |
b700cbb11
|
672 |
static struct svc_xprt *svc_udp_create(struct svc_serv *serv, |
62832c039
|
673 |
struct net *net, |
b700cbb11
|
674 675 676 |
struct sockaddr *sa, int salen, int flags) { |
62832c039
|
677 |
return svc_create_socket(serv, IPPROTO_UDP, net, sa, salen, flags); |
b700cbb11
|
678 |
} |
360d87386
|
679 |
static struct svc_xprt_ops svc_udp_ops = { |
b700cbb11
|
680 |
.xpo_create = svc_udp_create, |
5d137990f
|
681 682 |
.xpo_recvfrom = svc_udp_recvfrom, .xpo_sendto = svc_udp_sendto, |
5148bf4eb
|
683 |
.xpo_release_rqst = svc_release_skb, |
755cceaba
|
684 685 |
.xpo_detach = svc_sock_detach, .xpo_free = svc_sock_free, |
e831fe65b
|
686 |
.xpo_prep_reply_hdr = svc_udp_prep_reply_hdr, |
323bee32e
|
687 |
.xpo_has_wspace = svc_udp_has_wspace, |
38a417cc9
|
688 |
.xpo_accept = svc_udp_accept, |
16e4d93f6
|
689 |
.xpo_secure_port = svc_sock_secure_port, |
360d87386
|
690 691 692 693 |
}; static struct svc_xprt_class svc_udp_class = { .xcl_name = "udp", |
b700cbb11
|
694 |
.xcl_owner = THIS_MODULE, |
360d87386
|
695 |
.xcl_ops = &svc_udp_ops, |
490231558
|
696 |
.xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, |
3c45ddf82
|
697 |
.xcl_ident = XPRT_TRANSPORT_UDP, |
360d87386
|
698 |
}; |
bb5cf160b
|
699 |
static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) |
1da177e4c
|
700 |
{ |
7702ce40b
|
701 |
int err, level, optname, one = 1; |
7a37f5787
|
702 |
|
bd4620ddf
|
703 704 |
svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class, &svsk->sk_xprt, serv); |
def13d740
|
705 |
clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
706 707 |
svsk->sk_sk->sk_data_ready = svc_udp_data_ready; svsk->sk_sk->sk_write_space = svc_write_space; |
1da177e4c
|
708 709 |
/* initialise setting must have enough space to |
cca5172a7
|
710 |
* receive and respond to one request. |
1da177e4c
|
711 712 713 |
* svc_udp_recvfrom will re-adjust if necessary */ svc_sock_setbufsize(svsk->sk_sock, |
bb5cf160b
|
714 715 |
3 * svsk->sk_xprt.xpt_server->sv_max_mesg, 3 * svsk->sk_xprt.xpt_server->sv_max_mesg); |
1da177e4c
|
716 |
|
0f0257eaa
|
717 718 |
/* data might have come in before data_ready set up */ set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
02fc6c361
|
719 |
set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
7a37f5787
|
720 |
|
7a37f5787
|
721 |
/* make sure we get destination address info */ |
7702ce40b
|
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 |
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
|
738 739 740 741 742 743 |
} /* * A data_ready event on a listening socket means there's a connection * pending. Do not use state_change as a substitute for it. */ |
676d23690
|
744 |
static void svc_tcp_listen_data_ready(struct sock *sk) |
1da177e4c
|
745 |
{ |
939bb7ef9
|
746 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105
|
747 |
wait_queue_head_t *wq; |
1da177e4c
|
748 749 750 |
dprintk("svc: socket %p TCP (listen) state change %d ", |
939bb7ef9
|
751 |
sk, sk->sk_state); |
1da177e4c
|
752 |
|
939bb7ef9
|
753 754 755 756 757 758 759 760 761 762 763 764 |
/* * 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
|
765 |
set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
f6150c3ca
|
766 |
svc_xprt_enqueue(&svsk->sk_xprt); |
939bb7ef9
|
767 768 769 |
} else printk("svc: socket %p: no user data ", sk); |
1da177e4c
|
770 |
} |
939bb7ef9
|
771 |
|
eaefd1105
|
772 773 774 |
wq = sk_sleep(sk); if (wq && waitqueue_active(wq)) wake_up_interruptible_all(wq); |
1da177e4c
|
775 776 777 778 779 |
} /* * A state change on a connected socket means it's dying or dead. */ |
0f0257eaa
|
780 |
static void svc_tcp_state_change(struct sock *sk) |
1da177e4c
|
781 |
{ |
939bb7ef9
|
782 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105
|
783 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c
|
784 785 786 |
dprintk("svc: socket %p TCP (connected) state change %d (svsk %p) ", |
939bb7ef9
|
787 |
sk, sk->sk_state, sk->sk_user_data); |
1da177e4c
|
788 |
|
939bb7ef9
|
789 |
if (!svsk) |
1da177e4c
|
790 791 |
printk("svc: socket %p: no user data ", sk); |
939bb7ef9
|
792 |
else { |
02fc6c361
|
793 |
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
f6150c3ca
|
794 |
svc_xprt_enqueue(&svsk->sk_xprt); |
1da177e4c
|
795 |
} |
eaefd1105
|
796 797 |
if (wq && waitqueue_active(wq)) wake_up_interruptible_all(wq); |
1da177e4c
|
798 |
} |
676d23690
|
799 |
static void svc_tcp_data_ready(struct sock *sk) |
1da177e4c
|
800 |
{ |
939bb7ef9
|
801 |
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
eaefd1105
|
802 |
wait_queue_head_t *wq = sk_sleep(sk); |
1da177e4c
|
803 804 805 |
dprintk("svc: socket %p TCP data ready (svsk %p) ", |
939bb7ef9
|
806 807 |
sk, sk->sk_user_data); if (svsk) { |
02fc6c361
|
808 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
f6150c3ca
|
809 |
svc_xprt_enqueue(&svsk->sk_xprt); |
939bb7ef9
|
810 |
} |
eaefd1105
|
811 812 |
if (wq && waitqueue_active(wq)) wake_up_interruptible(wq); |
1da177e4c
|
813 814 815 816 817 |
} /* * Accept a TCP connection */ |
38a417cc9
|
818 |
static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) |
1da177e4c
|
819 |
{ |
38a417cc9
|
820 |
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
cdd88b9f3
|
821 822 |
struct sockaddr_storage addr; struct sockaddr *sin = (struct sockaddr *) &addr; |
bb5cf160b
|
823 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
1da177e4c
|
824 825 |
struct socket *sock = svsk->sk_sock; struct socket *newsock; |
1da177e4c
|
826 827 |
struct svc_sock *newsvsk; int err, slen; |
5216a8e70
|
828 |
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
1da177e4c
|
829 830 831 832 |
dprintk("svc: tcp_accept %p sock %p ", svsk, sock); if (!sock) |
38a417cc9
|
833 |
return NULL; |
1da177e4c
|
834 |
|
02fc6c361
|
835 |
clear_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
e6242e928
|
836 837 |
err = kernel_accept(sock, &newsock, O_NONBLOCK); if (err < 0) { |
1da177e4c
|
838 839 840 841 |
if (err == -ENOMEM) printk(KERN_WARNING "%s: no more sockets! ", serv->sv_name); |
e87cc4728
|
842 843 844 845 |
else if (err != -EAGAIN) net_warn_ratelimited("%s: accept failed (err %d)! ", serv->sv_name, -err); |
38a417cc9
|
846 |
return NULL; |
1da177e4c
|
847 |
} |
02fc6c361
|
848 |
set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
849 |
|
cdd88b9f3
|
850 |
err = kernel_getpeername(newsock, sin, &slen); |
1da177e4c
|
851 |
if (err < 0) { |
e87cc4728
|
852 853 854 |
net_warn_ratelimited("%s: peername failed (err %d)! ", serv->sv_name, -err); |
1da177e4c
|
855 856 857 858 |
goto failed; /* aborted connection or whatever */ } /* Ideally, we would want to reject connections from unauthorized |
ad06e4bd6
|
859 860 |
* 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
|
861 |
*/ |
cdd88b9f3
|
862 |
if (!svc_port_is_privileged(sin)) { |
a48fd0f9f
|
863 864 |
dprintk("%s: connect from unprivileged port: %s ", |
cca5172a7
|
865 |
serv->sv_name, |
cdd88b9f3
|
866 |
__svc_print_addr(sin, buf, sizeof(buf))); |
1da177e4c
|
867 |
} |
ad06e4bd6
|
868 869 |
dprintk("%s: connect from %s ", serv->sv_name, |
cdd88b9f3
|
870 |
__svc_print_addr(sin, buf, sizeof(buf))); |
1da177e4c
|
871 872 873 874 875 |
/* make sure that a write doesn't block forever when * low on memory */ newsock->sk->sk_sndtimeo = HZ*30; |
72c353760
|
876 877 878 |
newsvsk = svc_setup_socket(serv, newsock, (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)); if (IS_ERR(newsvsk)) |
1da177e4c
|
879 |
goto failed; |
9dbc240f1
|
880 |
svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); |
a97476926
|
881 882 883 884 885 886 |
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
|
887 |
svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen); |
067d78173
|
888 |
|
ef11ce248
|
889 890 891 892 |
if (sock_is_loopback(newsock->sk)) set_bit(XPT_LOCAL, &newsvsk->sk_xprt.xpt_flags); else clear_bit(XPT_LOCAL, &newsvsk->sk_xprt.xpt_flags); |
f9f3cc4fa
|
893 894 895 896 897 898 899 900 901 |
if (serv->sv_stats) serv->sv_stats->nettcpconn++; return &newsvsk->sk_xprt; failed: sock_release(newsock); return NULL; } |
31d68ef65
|
902 903 904 |
static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) { unsigned int i, len, npages; |
8af345f58
|
905 |
if (svsk->sk_datalen == 0) |
31d68ef65
|
906 |
return 0; |
8af345f58
|
907 |
len = svsk->sk_datalen; |
31d68ef65
|
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 |
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; |
8af345f58
|
923 |
if (svsk->sk_datalen == 0) |
31d68ef65
|
924 |
return; |
8af345f58
|
925 |
len = svsk->sk_datalen; |
31d68ef65
|
926 927 928 929 930 931 932 933 934 935 |
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; |
8af345f58
|
936 |
if (svsk->sk_datalen == 0) |
31d68ef65
|
937 |
goto out; |
8af345f58
|
938 |
len = svsk->sk_datalen; |
31d68ef65
|
939 940 |
npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { |
cf3aa02cb
|
941 942 943 944 |
if (svsk->sk_pages[i] == NULL) { WARN_ON_ONCE(1); continue; } |
31d68ef65
|
945 946 947 948 949 |
put_page(svsk->sk_pages[i]); svsk->sk_pages[i] = NULL; } out: svsk->sk_tcplen = 0; |
8af345f58
|
950 |
svsk->sk_datalen = 0; |
31d68ef65
|
951 |
} |
f9f3cc4fa
|
952 |
/* |
ad46ccf09
|
953 |
* Receive fragment record header. |
8f55f3c0a
|
954 |
* If we haven't gotten the record length yet, get the next four bytes. |
1da177e4c
|
955 |
*/ |
8f55f3c0a
|
956 |
static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) |
1da177e4c
|
957 |
{ |
bb5cf160b
|
958 |
struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
5ee78d483
|
959 |
unsigned int want; |
8f55f3c0a
|
960 |
int len; |
1da177e4c
|
961 |
|
c0401ea00
|
962 |
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) { |
1da177e4c
|
963 |
struct kvec iov; |
5ee78d483
|
964 |
want = sizeof(rpc_fraghdr) - svsk->sk_tcplen; |
1da177e4c
|
965 966 967 968 969 970 971 |
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
|
972 973 974 |
dprintk("svc: short recvfrom while reading record " "length (%d of %d) ", len, want); |
31d68ef65
|
975 |
return -EAGAIN; |
1da177e4c
|
976 |
} |
cc248d4b1
|
977 978 |
dprintk("svc: TCP record, %d bytes ", svc_sock_reclen(svsk)); |
836fbadb9
|
979 980 |
if (svc_sock_reclen(svsk) + svsk->sk_datalen > serv->sv_max_mesg) { |
3a28e3311
|
981 982 983 |
net_notice_ratelimited("RPC: fragment too large: %d ", svc_sock_reclen(svsk)); |
1da177e4c
|
984 985 986 |
goto err_delete; } } |
cc248d4b1
|
987 |
return svc_sock_reclen(svsk); |
31d68ef65
|
988 989 990 |
error: dprintk("RPC: TCP recv_record got %d ", len); |
8f55f3c0a
|
991 |
return len; |
31d68ef65
|
992 |
err_delete: |
8f55f3c0a
|
993 |
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
8f55f3c0a
|
994 995 |
return -EAGAIN; } |
586c52cc6
|
996 |
static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp) |
4cfc7e601
|
997 |
{ |
586c52cc6
|
998 |
struct rpc_xprt *bc_xprt = svsk->sk_xprt.xpt_bc_xprt; |
4cfc7e601
|
999 |
struct rpc_rqst *req = NULL; |
586c52cc6
|
1000 1001 |
struct kvec *src, *dst; __be32 *p = (__be32 *)rqstp->rq_arg.head[0].iov_base; |
48e6555c7
|
1002 1003 |
__be32 xid; __be32 calldir; |
4cfc7e601
|
1004 |
|
4cfc7e601
|
1005 1006 |
xid = *p++; calldir = *p; |
093a1468b
|
1007 |
if (!bc_xprt) |
586c52cc6
|
1008 |
return -EAGAIN; |
093a1468b
|
1009 1010 1011 1012 |
spin_lock_bh(&bc_xprt->transport_lock); req = xprt_lookup_rqst(bc_xprt, xid); if (!req) goto unlock_notfound; |
586c52cc6
|
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 |
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) |
093a1468b
|
1023 |
goto unlock_eagain; /* whatever; just giving up. */ |
586c52cc6
|
1024 |
memcpy(dst->iov_base, src->iov_base, src->iov_len); |
cc248d4b1
|
1025 |
xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len); |
586c52cc6
|
1026 |
rqstp->rq_arg.len = 0; |
093a1468b
|
1027 |
spin_unlock_bh(&bc_xprt->transport_lock); |
586c52cc6
|
1028 |
return 0; |
093a1468b
|
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 |
unlock_notfound: printk(KERN_NOTICE "%s: Got unrecognized reply: " "calldir 0x%x xpt_bc_xprt %p xid %08x ", __func__, ntohl(calldir), bc_xprt, ntohl(xid)); unlock_eagain: spin_unlock_bh(&bc_xprt->transport_lock); return -EAGAIN; |
586c52cc6
|
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 |
} 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
|
1053 |
} |
836fbadb9
|
1054 1055 1056 |
static void svc_tcp_fragment_received(struct svc_sock *svsk) { /* If we have more data, signal svc_xprt_enqueue() to try again */ |
836fbadb9
|
1057 1058 1059 1060 1061 1062 1063 |
dprintk("svc: TCP %s record (%d bytes) ", svc_sock_final_rec(svsk) ? "final" : "nonfinal", svc_sock_reclen(svsk)); svsk->sk_tcplen = 0; svsk->sk_reclen = 0; } |
31d68ef65
|
1064 |
|
8f55f3c0a
|
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 |
/* * 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
|
1075 |
unsigned int want, base; |
586c52cc6
|
1076 1077 |
__be32 *p; __be32 calldir; |
5ee78d483
|
1078 |
int pnum; |
8f55f3c0a
|
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 |
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
|
1089 |
base = svc_tcp_restore_pages(svsk, rqstp); |
836fbadb9
|
1090 |
want = svc_sock_reclen(svsk) - (svsk->sk_tcplen - sizeof(rpc_fraghdr)); |
31d68ef65
|
1091 |
|
3cc03b164
|
1092 |
vec = rqstp->rq_vec; |
4cfc7e601
|
1093 |
|
586c52cc6
|
1094 |
pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], |
836fbadb9
|
1095 |
svsk->sk_datalen + want); |
586c52cc6
|
1096 |
|
445243594
|
1097 |
rqstp->rq_respages = &rqstp->rq_pages[pnum]; |
afc59400d
|
1098 |
rqstp->rq_next_page = rqstp->rq_respages + 1; |
1da177e4c
|
1099 1100 |
/* Now receive data */ |
31d68ef65
|
1101 |
len = svc_partial_recvfrom(rqstp, vec, pnum, want, base); |
8af345f58
|
1102 |
if (len >= 0) { |
31d68ef65
|
1103 |
svsk->sk_tcplen += len; |
8af345f58
|
1104 1105 |
svsk->sk_datalen += len; } |
836fbadb9
|
1106 |
if (len != want || !svc_sock_final_rec(svsk)) { |
be1e44441
|
1107 |
svc_tcp_save_pages(svsk, rqstp); |
31d68ef65
|
1108 |
if (len < 0 && len != -EAGAIN) |
ad46ccf09
|
1109 |
goto err_delete; |
836fbadb9
|
1110 1111 1112 |
if (len == want) svc_tcp_fragment_received(svsk); else |
3a28e3311
|
1113 1114 1115 |
dprintk("svc: incomplete TCP record (%d of %d) ", (int)(svsk->sk_tcplen - sizeof(rpc_fraghdr)), |
836fbadb9
|
1116 |
svc_sock_reclen(svsk)); |
31d68ef65
|
1117 1118 |
goto err_noclose; } |
1da177e4c
|
1119 |
|
1f691b07c
|
1120 |
if (svsk->sk_datalen < 8) { |
cf3aa02cb
|
1121 |
svsk->sk_datalen = 0; |
ad46ccf09
|
1122 |
goto err_delete; /* client is nuts. */ |
cf3aa02cb
|
1123 |
} |
ad46ccf09
|
1124 |
|
836fbadb9
|
1125 |
rqstp->rq_arg.len = svsk->sk_datalen; |
1da177e4c
|
1126 |
rqstp->rq_arg.page_base = 0; |
5ee78d483
|
1127 1128 |
if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len; |
1da177e4c
|
1129 |
rqstp->rq_arg.page_len = 0; |
5ee78d483
|
1130 1131 |
} else rqstp->rq_arg.page_len = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len; |
1da177e4c
|
1132 |
|
5148bf4eb
|
1133 |
rqstp->rq_xprt_ctxt = NULL; |
1da177e4c
|
1134 |
rqstp->rq_prot = IPPROTO_TCP; |
7501cc2bc
|
1135 1136 1137 1138 |
if (test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags)) set_bit(RQ_LOCAL, &rqstp->rq_flags); else clear_bit(RQ_LOCAL, &rqstp->rq_flags); |
1da177e4c
|
1139 |
|
586c52cc6
|
1140 1141 |
p = (__be32 *)rqstp->rq_arg.head[0].iov_base; calldir = p[1]; |
8985ef0b8
|
1142 |
if (calldir) |
586c52cc6
|
1143 |
len = receive_cb_reply(svsk, rqstp); |
586c52cc6
|
1144 |
|
1da177e4c
|
1145 |
/* Reset TCP read info */ |
8af345f58
|
1146 |
svsk->sk_datalen = 0; |
836fbadb9
|
1147 |
svc_tcp_fragment_received(svsk); |
0601f7939
|
1148 |
|
8985ef0b8
|
1149 1150 |
if (len < 0) goto error; |
1da177e4c
|
1151 |
|
9dbc240f1
|
1152 |
svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt); |
1da177e4c
|
1153 1154 |
if (serv->sv_stats) serv->sv_stats->nettcpcnt++; |
5ee78d483
|
1155 |
return rqstp->rq_arg.len; |
1da177e4c
|
1156 |
|
8f55f3c0a
|
1157 |
error: |
31d68ef65
|
1158 |
if (len != -EAGAIN) |
ad46ccf09
|
1159 |
goto err_delete; |
31d68ef65
|
1160 1161 |
dprintk("RPC: TCP recvfrom got EAGAIN "); |
9f9d2ebe6
|
1162 |
return 0; |
ad46ccf09
|
1163 |
err_delete: |
31d68ef65
|
1164 1165 1166 1167 1168 |
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: |
9f9d2ebe6
|
1169 |
return 0; /* record not complete */ |
1da177e4c
|
1170 1171 1172 1173 1174 |
} /* * Send out data on TCP socket. */ |
0f0257eaa
|
1175 |
static int svc_tcp_sendto(struct svc_rqst *rqstp) |
1da177e4c
|
1176 1177 1178 |
{ struct xdr_buf *xbufp = &rqstp->rq_res; int sent; |
d8ed029d6
|
1179 |
__be32 reclen; |
1da177e4c
|
1180 1181 1182 1183 1184 1185 1186 |
/* 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
|
1187 1188 |
sent = svc_sendto(rqstp, &rqstp->rq_res); if (sent != xbufp->len) { |
0f0257eaa
|
1189 1190 1191 1192 |
printk(KERN_NOTICE "rpc-srv/tcp: %s: %s %d when sending %d bytes " "- shutting down socket ", |
57b1d3bab
|
1193 |
rqstp->rq_xprt->xpt_server->sv_name, |
1da177e4c
|
1194 1195 |
(sent<0)?"got error":"sent only", sent, xbufp->len); |
57b1d3bab
|
1196 |
set_bit(XPT_CLOSE, &rqstp->rq_xprt->xpt_flags); |
f6150c3ca
|
1197 |
svc_xprt_enqueue(rqstp->rq_xprt); |
1da177e4c
|
1198 1199 1200 1201 |
sent = -EAGAIN; } return sent; } |
e831fe65b
|
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 |
/* * 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); } |
b700cbb11
|
1212 |
static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
62832c039
|
1213 |
struct net *net, |
b700cbb11
|
1214 1215 1216 |
struct sockaddr *sa, int salen, int flags) { |
62832c039
|
1217 |
return svc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags); |
b700cbb11
|
1218 |
} |
9e00abc3c
|
1219 |
#if defined(CONFIG_SUNRPC_BACKCHANNEL) |
1f11a034c
|
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
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, |
16e4d93f6
|
1242 |
.xpo_secure_port = svc_sock_secure_port, |
1f11a034c
|
1243 1244 1245 1246 1247 1248 1249 1250 |
}; 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
|
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 |
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
|
1261 |
#else /* CONFIG_SUNRPC_BACKCHANNEL */ |
16b2d1e1d
|
1262 1263 1264 1265 1266 1267 1268 |
static void svc_init_bc_xprt_sock(void) { } static void svc_cleanup_bc_xprt_sock(void) { } |
9e00abc3c
|
1269 |
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1f11a034c
|
1270 |
|
360d87386
|
1271 |
static struct svc_xprt_ops svc_tcp_ops = { |
b700cbb11
|
1272 |
.xpo_create = svc_tcp_create, |
5d137990f
|
1273 1274 |
.xpo_recvfrom = svc_tcp_recvfrom, .xpo_sendto = svc_tcp_sendto, |
5148bf4eb
|
1275 |
.xpo_release_rqst = svc_release_skb, |
69b6ba371
|
1276 |
.xpo_detach = svc_tcp_sock_detach, |
755cceaba
|
1277 |
.xpo_free = svc_sock_free, |
e831fe65b
|
1278 |
.xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, |
323bee32e
|
1279 |
.xpo_has_wspace = svc_tcp_has_wspace, |
38a417cc9
|
1280 |
.xpo_accept = svc_tcp_accept, |
16e4d93f6
|
1281 |
.xpo_secure_port = svc_sock_secure_port, |
518776800
|
1282 |
.xpo_adjust_wspace = svc_tcp_adjust_wspace, |
360d87386
|
1283 1284 1285 1286 |
}; static struct svc_xprt_class svc_tcp_class = { .xcl_name = "tcp", |
b700cbb11
|
1287 |
.xcl_owner = THIS_MODULE, |
360d87386
|
1288 |
.xcl_ops = &svc_tcp_ops, |
490231558
|
1289 |
.xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
3c45ddf82
|
1290 |
.xcl_ident = XPRT_TRANSPORT_TCP, |
360d87386
|
1291 1292 1293 1294 1295 1296 |
}; void svc_init_xprt_sock(void) { svc_reg_xprt_class(&svc_tcp_class); svc_reg_xprt_class(&svc_udp_class); |
16b2d1e1d
|
1297 |
svc_init_bc_xprt_sock(); |
360d87386
|
1298 1299 1300 1301 1302 1303 |
} void svc_cleanup_xprt_sock(void) { svc_unreg_xprt_class(&svc_tcp_class); svc_unreg_xprt_class(&svc_udp_class); |
16b2d1e1d
|
1304 |
svc_cleanup_bc_xprt_sock(); |
360d87386
|
1305 |
} |
bb5cf160b
|
1306 |
static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) |
1da177e4c
|
1307 1308 |
{ struct sock *sk = svsk->sk_sk; |
1da177e4c
|
1309 |
|
bd4620ddf
|
1310 1311 |
svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_tcp_class, &svsk->sk_xprt, serv); |
def13d740
|
1312 |
set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
1313 1314 1315 |
if (sk->sk_state == TCP_LISTEN) { dprintk("setting up TCP socket for listening "); |
02fc6c361
|
1316 |
set_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
1317 |
sk->sk_data_ready = svc_tcp_listen_data_ready; |
02fc6c361
|
1318 |
set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
1319 1320 1321 1322 1323 |
} 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
|
1324 |
sk->sk_write_space = svc_tcp_write_space; |
1da177e4c
|
1325 1326 1327 |
svsk->sk_reclen = 0; svsk->sk_tcplen = 0; |
8af345f58
|
1328 |
svsk->sk_datalen = 0; |
31d68ef65
|
1329 |
memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages)); |
1da177e4c
|
1330 |
|
b7872fe86
|
1331 |
tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; |
1da177e4c
|
1332 |
|
02fc6c361
|
1333 |
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
cca5172a7
|
1334 |
if (sk->sk_state != TCP_ESTABLISHED) |
02fc6c361
|
1335 |
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
1336 1337 |
} } |
0f0257eaa
|
1338 |
void svc_sock_update_bufs(struct svc_serv *serv) |
1da177e4c
|
1339 1340 1341 1342 1343 |
{ /* * The number of server threads has changed. Update * rcvbuf and sndbuf accordingly on all sockets */ |
8f3a6de31
|
1344 |
struct svc_sock *svsk; |
1da177e4c
|
1345 1346 |
spin_lock_bh(&serv->sv_lock); |
8f3a6de31
|
1347 |
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) |
02fc6c361
|
1348 |
set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1da177e4c
|
1349 1350 |
spin_unlock_bh(&serv->sv_lock); } |
24c3767e4
|
1351 |
EXPORT_SYMBOL_GPL(svc_sock_update_bufs); |
1da177e4c
|
1352 1353 |
/* |
1da177e4c
|
1354 1355 1356 |
* Initialize socket for RPC use and create svc_sock struct * XXX: May want to setsockopt SO_SNDBUF and SO_RCVBUF. */ |
6b174337e
|
1357 1358 |
static struct svc_sock *svc_setup_socket(struct svc_serv *serv, struct socket *sock, |
72c353760
|
1359 |
int flags) |
1da177e4c
|
1360 1361 1362 |
{ struct svc_sock *svsk; struct sock *inet; |
6b174337e
|
1363 |
int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
72c353760
|
1364 |
int err = 0; |
1da177e4c
|
1365 1366 1367 |
dprintk("svc: svc_setup_socket %p ", sock); |
72c353760
|
1368 1369 1370 |
svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); if (!svsk) return ERR_PTR(-ENOMEM); |
1da177e4c
|
1371 1372 1373 1374 |
inet = sock->sk; /* Register socket with portmapper */ |
72c353760
|
1375 1376 |
if (pmap_register) err = svc_register(serv, sock_net(sock->sk), inet->sk_family, |
5247fab5c
|
1377 |
inet->sk_protocol, |
c720c7e83
|
1378 |
ntohs(inet_sk(inet)->inet_sport)); |
1da177e4c
|
1379 |
|
72c353760
|
1380 |
if (err < 0) { |
1da177e4c
|
1381 |
kfree(svsk); |
72c353760
|
1382 |
return ERR_PTR(err); |
1da177e4c
|
1383 |
} |
1da177e4c
|
1384 1385 1386 1387 1388 1389 |
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
|
1390 1391 1392 |
/* Initialize the socket */ if (sock->type == SOCK_DGRAM) |
bb5cf160b
|
1393 |
svc_udp_init(svsk, serv); |
966043986
|
1394 1395 1396 1397 1398 1399 |
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
|
1400 |
svc_tcp_init(svsk, serv); |
966043986
|
1401 |
} |
1da177e4c
|
1402 |
|
1da177e4c
|
1403 1404 1405 |
dprintk("svc: svc_setup_socket created %p (inet %p) ", svsk, svsk->sk_sk); |
1da177e4c
|
1406 1407 |
return svsk; } |
306463942
|
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 |
bool svc_alien_sock(struct net *net, int fd) { int err; struct socket *sock = sockfd_lookup(fd, &err); bool ret = false; if (!sock) goto out; if (sock_net(sock->sk) != net) ret = true; sockfd_put(sock); out: return ret; } EXPORT_SYMBOL_GPL(svc_alien_sock); |
bfba9ab4c
|
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 |
/** * 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
|
1437 1438 1439 1440 |
{ int err = 0; struct socket *so = sockfd_lookup(fd, &err); struct svc_sock *svsk = NULL; |
a8e10078a
|
1441 1442 1443 |
struct sockaddr_storage addr; struct sockaddr *sin = (struct sockaddr *)&addr; int salen; |
b41b66d63
|
1444 1445 1446 |
if (!so) return err; |
a8e10078a
|
1447 |
err = -EAFNOSUPPORT; |
205ba4230
|
1448 |
if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) |
a8e10078a
|
1449 1450 1451 |
goto out; err = -EPROTONOSUPPORT; if (so->sk->sk_protocol != IPPROTO_TCP && |
b41b66d63
|
1452 |
so->sk->sk_protocol != IPPROTO_UDP) |
a8e10078a
|
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 |
goto out; err = -EISCONN; if (so->state > SS_UNCONNECTED) goto out; err = -ENOENT; if (!try_module_get(THIS_MODULE)) goto out; svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS); if (IS_ERR(svsk)) { module_put(THIS_MODULE); err = PTR_ERR(svsk); goto out; |
b41b66d63
|
1465 |
} |
a8e10078a
|
1466 1467 |
if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) svc_xprt_set_local(&svsk->sk_xprt, sin, salen); |
39b553013
|
1468 |
svc_add_new_perm_xprt(serv, &svsk->sk_xprt); |
e7942b9f2
|
1469 |
return svc_one_sock_name(svsk, name_return, len); |
a8e10078a
|
1470 1471 1472 |
out: sockfd_put(so); return err; |
b41b66d63
|
1473 1474 |
} EXPORT_SYMBOL_GPL(svc_addsock); |
1da177e4c
|
1475 1476 1477 |
/* * Create socket for RPC service. */ |
b700cbb11
|
1478 1479 |
static struct svc_xprt *svc_create_socket(struct svc_serv *serv, int protocol, |
62832c039
|
1480 |
struct net *net, |
b700cbb11
|
1481 1482 |
struct sockaddr *sin, int len, int flags) |
1da177e4c
|
1483 1484 1485 1486 1487 |
{ struct svc_sock *svsk; struct socket *sock; int error; int type; |
9dbc240f1
|
1488 1489 1490 |
struct sockaddr_storage addr; struct sockaddr *newsin = (struct sockaddr *)&addr; int newlen; |
c69da774b
|
1491 1492 |
int family; int val; |
5216a8e70
|
1493 |
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
1da177e4c
|
1494 |
|
ad06e4bd6
|
1495 1496 1497 |
dprintk("svc: svc_create_socket(%s, %d, %s) ", serv->sv_program->pg_name, protocol, |
77f1f67a1
|
1498 |
__svc_print_addr(sin, buf, sizeof(buf))); |
1da177e4c
|
1499 1500 1501 1502 1503 |
if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) { printk(KERN_WARNING "svc: only UDP and TCP " "sockets supported "); |
b700cbb11
|
1504 |
return ERR_PTR(-EINVAL); |
1da177e4c
|
1505 |
} |
c69da774b
|
1506 |
|
1da177e4c
|
1507 |
type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; |
c69da774b
|
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 |
switch (sin->sa_family) { case AF_INET6: family = PF_INET6; break; case AF_INET: family = PF_INET; break; default: return ERR_PTR(-EINVAL); } |
1da177e4c
|
1518 |
|
14ec63c33
|
1519 |
error = __sock_create(net, family, type, protocol, &sock, 1); |
77f1f67a1
|
1520 |
if (error < 0) |
b700cbb11
|
1521 |
return ERR_PTR(error); |
1da177e4c
|
1522 |
|
ed07536ed
|
1523 |
svc_reclassify_socket(sock); |
c69da774b
|
1524 1525 1526 1527 1528 1529 1530 1531 1532 |
/* * 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
|
1533 |
if (type == SOCK_STREAM) |
4a17fd522
|
1534 |
sock->sk->sk_reuse = SK_CAN_REUSE; /* allow address reuse */ |
77f1f67a1
|
1535 |
error = kernel_bind(sock, sin, len); |
181147462
|
1536 1537 |
if (error < 0) goto bummer; |
1da177e4c
|
1538 |
|
9dbc240f1
|
1539 1540 1541 1542 |
newlen = len; error = kernel_getsockname(sock, newsin, &newlen); if (error < 0) goto bummer; |
1da177e4c
|
1543 |
if (protocol == IPPROTO_TCP) { |
e6242e928
|
1544 |
if ((error = kernel_listen(sock, 64)) < 0) |
1da177e4c
|
1545 1546 |
goto bummer; } |
72c353760
|
1547 |
svsk = svc_setup_socket(serv, sock, flags); |
a8e10078a
|
1548 1549 1550 |
if (IS_ERR(svsk)) { error = PTR_ERR(svsk); goto bummer; |
e79eff1f9
|
1551 |
} |
a8e10078a
|
1552 1553 |
svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); return (struct svc_xprt *)svsk; |
1da177e4c
|
1554 1555 1556 1557 |
bummer: dprintk("svc: svc_create_socket error = %d ", -error); sock_release(sock); |
b700cbb11
|
1558 |
return ERR_PTR(error); |
1da177e4c
|
1559 1560 1561 |
} /* |
755cceaba
|
1562 1563 1564 1565 1566 1567 1568 |
* 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
|
1569 |
wait_queue_head_t *wq; |
755cceaba
|
1570 1571 1572 1573 1574 1575 1576 1577 |
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
|
1578 |
|
eaefd1105
|
1579 1580 1581 |
wq = sk_sleep(sk); if (wq && waitqueue_active(wq)) wake_up_interruptible(wq); |
69b6ba371
|
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 |
} /* * 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
|
1595 1596 |
if (!test_bit(XPT_LISTENER, &xprt->xpt_flags)) { svc_tcp_clear_pages(svsk); |
69b6ba371
|
1597 |
kernel_sock_shutdown(svsk->sk_sock, SHUT_RDWR); |
31d68ef65
|
1598 |
} |
755cceaba
|
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 |
} /* * 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
|
1609 1610 1611 1612 1613 1614 |
if (svsk->sk_sock->file) sockfd_put(svsk->sk_sock); else sock_release(svsk->sk_sock); kfree(svsk); } |
7652e5a09
|
1615 |
|
9e00abc3c
|
1616 |
#if defined(CONFIG_SUNRPC_BACKCHANNEL) |
7652e5a09
|
1617 |
/* |
1f11a034c
|
1618 |
* Create a back channel svc_xprt which shares the fore channel socket. |
7652e5a09
|
1619 |
*/ |
1f11a034c
|
1620 1621 1622 1623 1624 |
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
|
1625 1626 |
{ struct svc_sock *svsk; |
1f11a034c
|
1627 1628 1629 1630 1631 1632 1633 1634 |
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
|
1635 |
|
7652e5a09
|
1636 1637 |
svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); if (!svsk) |
1f11a034c
|
1638 |
return ERR_PTR(-ENOMEM); |
7652e5a09
|
1639 1640 |
xprt = &svsk->sk_xprt; |
bd4620ddf
|
1641 |
svc_xprt_init(net, &svc_tcp_bc_class, xprt, serv); |
1f11a034c
|
1642 |
|
4a19de0f4
|
1643 |
serv->sv_bc_xprt = xprt; |
1f11a034c
|
1644 |
|
7652e5a09
|
1645 1646 |
return xprt; } |
7652e5a09
|
1647 1648 |
/* |
1f11a034c
|
1649 |
* Free a back channel svc_sock. |
7652e5a09
|
1650 |
*/ |
1f11a034c
|
1651 |
static void svc_bc_sock_free(struct svc_xprt *xprt) |
7652e5a09
|
1652 |
{ |
778be232a
|
1653 |
if (xprt) |
7652e5a09
|
1654 1655 |
kfree(container_of(xprt, struct svc_sock, sk_xprt)); } |
9e00abc3c
|
1656 |
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ |