diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
| -rw-r--r-- | net/sunrpc/svcsock.c | 157 |
1 files changed, 52 insertions, 105 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 998aa8c1807c..03827cef1fa7 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -59,7 +59,7 @@ | |||
| 59 | 59 | ||
| 60 | 60 | ||
| 61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, | 61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
| 62 | int *errp, int flags); | 62 | int flags); |
| 63 | static void svc_udp_data_ready(struct sock *, int); | 63 | static void svc_udp_data_ready(struct sock *, int); |
| 64 | static int svc_udp_recvfrom(struct svc_rqst *); | 64 | static int svc_udp_recvfrom(struct svc_rqst *); |
| 65 | static int svc_udp_sendto(struct svc_rqst *); | 65 | static int svc_udp_sendto(struct svc_rqst *); |
| @@ -305,57 +305,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) | |||
| 305 | return len; | 305 | return len; |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /** | ||
| 309 | * svc_sock_names - construct a list of listener names in a string | ||
| 310 | * @serv: pointer to RPC service | ||
| 311 | * @buf: pointer to a buffer to fill in with socket names | ||
| 312 | * @buflen: size of the buffer to be filled | ||
| 313 | * @toclose: pointer to '\0'-terminated C string containing the name | ||
| 314 | * of a listener to be closed | ||
| 315 | * | ||
| 316 | * Fills in @buf with a '\n'-separated list of names of listener | ||
| 317 | * sockets. If @toclose is not NULL, the socket named by @toclose | ||
| 318 | * is closed, and is not included in the output list. | ||
| 319 | * | ||
| 320 | * Returns positive length of the socket name string, or a negative | ||
| 321 | * errno value on error. | ||
| 322 | */ | ||
| 323 | int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, | ||
| 324 | const char *toclose) | ||
| 325 | { | ||
| 326 | struct svc_sock *svsk, *closesk = NULL; | ||
| 327 | int len = 0; | ||
| 328 | |||
| 329 | if (!serv) | ||
| 330 | return 0; | ||
| 331 | |||
| 332 | spin_lock_bh(&serv->sv_lock); | ||
| 333 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { | ||
| 334 | int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); | ||
| 335 | if (onelen < 0) { | ||
| 336 | len = onelen; | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | if (toclose && strcmp(toclose, buf + len) == 0) { | ||
| 340 | closesk = svsk; | ||
| 341 | svc_xprt_get(&closesk->sk_xprt); | ||
| 342 | } else | ||
| 343 | len += onelen; | ||
| 344 | } | ||
| 345 | spin_unlock_bh(&serv->sv_lock); | ||
| 346 | |||
| 347 | if (closesk) { | ||
| 348 | /* Should unregister with portmap, but you cannot | ||
| 349 | * unregister just one protocol... | ||
| 350 | */ | ||
| 351 | svc_close_xprt(&closesk->sk_xprt); | ||
| 352 | svc_xprt_put(&closesk->sk_xprt); | ||
| 353 | } else if (toclose) | ||
| 354 | return -ENOENT; | ||
| 355 | return len; | ||
| 356 | } | ||
| 357 | EXPORT_SYMBOL_GPL(svc_sock_names); | ||
| 358 | |||
| 359 | /* | 308 | /* |
| 360 | * Check input queue length | 309 | * Check input queue length |
| 361 | */ | 310 | */ |
| @@ -598,11 +547,9 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 598 | dprintk("svc: recvfrom returned error %d\n", -err); | 547 | dprintk("svc: recvfrom returned error %d\n", -err); |
| 599 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 548 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 600 | } | 549 | } |
| 601 | return -EAGAIN; | 550 | return 0; |
| 602 | } | 551 | } |
| 603 | len = svc_addr_len(svc_addr(rqstp)); | 552 | len = svc_addr_len(svc_addr(rqstp)); |
| 604 | if (len == 0) | ||
| 605 | return -EAFNOSUPPORT; | ||
| 606 | rqstp->rq_addrlen = len; | 553 | rqstp->rq_addrlen = len; |
| 607 | if (skb->tstamp.tv64 == 0) { | 554 | if (skb->tstamp.tv64 == 0) { |
| 608 | skb->tstamp = ktime_get_real(); | 555 | skb->tstamp = ktime_get_real(); |
| @@ -620,10 +567,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 620 | if (!svc_udp_get_dest_address(rqstp, cmh)) { | 567 | if (!svc_udp_get_dest_address(rqstp, cmh)) { |
| 621 | net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", | 568 | net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", |
| 622 | cmh->cmsg_level, cmh->cmsg_type); | 569 | cmh->cmsg_level, cmh->cmsg_type); |
| 623 | out_free: | 570 | goto out_free; |
| 624 | trace_kfree_skb(skb, svc_udp_recvfrom); | ||
| 625 | skb_free_datagram_locked(svsk->sk_sk, skb); | ||
| 626 | return 0; | ||
| 627 | } | 571 | } |
| 628 | rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); | 572 | rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); |
| 629 | 573 | ||
| @@ -662,6 +606,10 @@ out_free: | |||
| 662 | serv->sv_stats->netudpcnt++; | 606 | serv->sv_stats->netudpcnt++; |
| 663 | 607 | ||
| 664 | return len; | 608 | return len; |
| 609 | out_free: | ||
| 610 | trace_kfree_skb(skb, svc_udp_recvfrom); | ||
| 611 | skb_free_datagram_locked(svsk->sk_sk, skb); | ||
| 612 | return 0; | ||
| 665 | } | 613 | } |
| 666 | 614 | ||
| 667 | static int | 615 | static int |
| @@ -900,8 +848,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) | |||
| 900 | */ | 848 | */ |
| 901 | newsock->sk->sk_sndtimeo = HZ*30; | 849 | newsock->sk->sk_sndtimeo = HZ*30; |
| 902 | 850 | ||
| 903 | if (!(newsvsk = svc_setup_socket(serv, newsock, &err, | 851 | newsvsk = svc_setup_socket(serv, newsock, |
| 904 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) | 852 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)); |
| 853 | if (IS_ERR(newsvsk)) | ||
| 905 | goto failed; | 854 | goto failed; |
| 906 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); | 855 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); |
| 907 | err = kernel_getsockname(newsock, sin, &slen); | 856 | err = kernel_getsockname(newsock, sin, &slen); |
| @@ -1174,13 +1123,13 @@ error: | |||
| 1174 | if (len != -EAGAIN) | 1123 | if (len != -EAGAIN) |
| 1175 | goto err_other; | 1124 | goto err_other; |
| 1176 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); | 1125 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); |
| 1177 | return -EAGAIN; | 1126 | return 0; |
| 1178 | err_other: | 1127 | err_other: |
| 1179 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", | 1128 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", |
| 1180 | svsk->sk_xprt.xpt_server->sv_name, -len); | 1129 | svsk->sk_xprt.xpt_server->sv_name, -len); |
| 1181 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1130 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
| 1182 | err_noclose: | 1131 | err_noclose: |
| 1183 | return -EAGAIN; /* record not complete */ | 1132 | return 0; /* record not complete */ |
| 1184 | } | 1133 | } |
| 1185 | 1134 | ||
| 1186 | /* | 1135 | /* |
| @@ -1383,29 +1332,29 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs); | |||
| 1383 | */ | 1332 | */ |
| 1384 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | 1333 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, |
| 1385 | struct socket *sock, | 1334 | struct socket *sock, |
| 1386 | int *errp, int flags) | 1335 | int flags) |
| 1387 | { | 1336 | { |
| 1388 | struct svc_sock *svsk; | 1337 | struct svc_sock *svsk; |
| 1389 | struct sock *inet; | 1338 | struct sock *inet; |
| 1390 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); | 1339 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
| 1340 | int err = 0; | ||
| 1391 | 1341 | ||
| 1392 | dprintk("svc: svc_setup_socket %p\n", sock); | 1342 | dprintk("svc: svc_setup_socket %p\n", sock); |
| 1393 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { | 1343 | svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); |
| 1394 | *errp = -ENOMEM; | 1344 | if (!svsk) |
| 1395 | return NULL; | 1345 | return ERR_PTR(-ENOMEM); |
| 1396 | } | ||
| 1397 | 1346 | ||
| 1398 | inet = sock->sk; | 1347 | inet = sock->sk; |
| 1399 | 1348 | ||
| 1400 | /* Register socket with portmapper */ | 1349 | /* Register socket with portmapper */ |
| 1401 | if (*errp >= 0 && pmap_register) | 1350 | if (pmap_register) |
| 1402 | *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, | 1351 | err = svc_register(serv, sock_net(sock->sk), inet->sk_family, |
| 1403 | inet->sk_protocol, | 1352 | inet->sk_protocol, |
| 1404 | ntohs(inet_sk(inet)->inet_sport)); | 1353 | ntohs(inet_sk(inet)->inet_sport)); |
| 1405 | 1354 | ||
| 1406 | if (*errp < 0) { | 1355 | if (err < 0) { |
| 1407 | kfree(svsk); | 1356 | kfree(svsk); |
| 1408 | return NULL; | 1357 | return ERR_PTR(err); |
| 1409 | } | 1358 | } |
| 1410 | 1359 | ||
| 1411 | inet->sk_user_data = svsk; | 1360 | inet->sk_user_data = svsk; |
| @@ -1450,42 +1399,38 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, | |||
| 1450 | int err = 0; | 1399 | int err = 0; |
| 1451 | struct socket *so = sockfd_lookup(fd, &err); | 1400 | struct socket *so = sockfd_lookup(fd, &err); |
| 1452 | struct svc_sock *svsk = NULL; | 1401 | struct svc_sock *svsk = NULL; |
| 1402 | struct sockaddr_storage addr; | ||
| 1403 | struct sockaddr *sin = (struct sockaddr *)&addr; | ||
| 1404 | int salen; | ||
| 1453 | 1405 | ||
| 1454 | if (!so) | 1406 | if (!so) |
| 1455 | return err; | 1407 | return err; |
| 1408 | err = -EAFNOSUPPORT; | ||
| 1456 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) | 1409 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) |
| 1457 | err = -EAFNOSUPPORT; | 1410 | goto out; |
| 1458 | else if (so->sk->sk_protocol != IPPROTO_TCP && | 1411 | err = -EPROTONOSUPPORT; |
| 1412 | if (so->sk->sk_protocol != IPPROTO_TCP && | ||
| 1459 | so->sk->sk_protocol != IPPROTO_UDP) | 1413 | so->sk->sk_protocol != IPPROTO_UDP) |
| 1460 | err = -EPROTONOSUPPORT; | 1414 | goto out; |
| 1461 | else if (so->state > SS_UNCONNECTED) | 1415 | err = -EISCONN; |
| 1462 | err = -EISCONN; | 1416 | if (so->state > SS_UNCONNECTED) |
| 1463 | else { | 1417 | goto out; |
| 1464 | if (!try_module_get(THIS_MODULE)) | 1418 | err = -ENOENT; |
| 1465 | err = -ENOENT; | 1419 | if (!try_module_get(THIS_MODULE)) |
| 1466 | else | 1420 | goto out; |
| 1467 | svsk = svc_setup_socket(serv, so, &err, | 1421 | svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS); |
| 1468 | SVC_SOCK_DEFAULTS); | 1422 | if (IS_ERR(svsk)) { |
| 1469 | if (svsk) { | 1423 | module_put(THIS_MODULE); |
| 1470 | struct sockaddr_storage addr; | 1424 | err = PTR_ERR(svsk); |
| 1471 | struct sockaddr *sin = (struct sockaddr *)&addr; | 1425 | goto out; |
| 1472 | int salen; | ||
| 1473 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
| 1474 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
| 1475 | clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); | ||
| 1476 | spin_lock_bh(&serv->sv_lock); | ||
| 1477 | list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks); | ||
| 1478 | spin_unlock_bh(&serv->sv_lock); | ||
| 1479 | svc_xprt_received(&svsk->sk_xprt); | ||
| 1480 | err = 0; | ||
| 1481 | } else | ||
| 1482 | module_put(THIS_MODULE); | ||
| 1483 | } | ||
| 1484 | if (err) { | ||
| 1485 | sockfd_put(so); | ||
| 1486 | return err; | ||
| 1487 | } | 1426 | } |
| 1427 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
| 1428 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
| 1429 | svc_add_new_perm_xprt(serv, &svsk->sk_xprt); | ||
| 1488 | return svc_one_sock_name(svsk, name_return, len); | 1430 | return svc_one_sock_name(svsk, name_return, len); |
| 1431 | out: | ||
| 1432 | sockfd_put(so); | ||
| 1433 | return err; | ||
| 1489 | } | 1434 | } |
| 1490 | EXPORT_SYMBOL_GPL(svc_addsock); | 1435 | EXPORT_SYMBOL_GPL(svc_addsock); |
| 1491 | 1436 | ||
| @@ -1563,11 +1508,13 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
| 1563 | goto bummer; | 1508 | goto bummer; |
| 1564 | } | 1509 | } |
| 1565 | 1510 | ||
| 1566 | if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { | 1511 | svsk = svc_setup_socket(serv, sock, flags); |
| 1567 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); | 1512 | if (IS_ERR(svsk)) { |
| 1568 | return (struct svc_xprt *)svsk; | 1513 | error = PTR_ERR(svsk); |
| 1514 | goto bummer; | ||
| 1569 | } | 1515 | } |
| 1570 | 1516 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); | |
| 1517 | return (struct svc_xprt *)svsk; | ||
| 1571 | bummer: | 1518 | bummer: |
| 1572 | dprintk("svc: svc_create_socket error = %d\n", -error); | 1519 | dprintk("svc: svc_create_socket error = %d\n", -error); |
| 1573 | sock_release(sock); | 1520 | sock_release(sock); |
