diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 81 |
1 files changed, 41 insertions, 40 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index cc33c5880abb..4ae7eed7f617 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -235,6 +235,7 @@ struct sock_xprt { | |||
235 | * Connection of transports | 235 | * Connection of transports |
236 | */ | 236 | */ |
237 | struct delayed_work connect_worker; | 237 | struct delayed_work connect_worker; |
238 | struct sockaddr_storage addr; | ||
238 | unsigned short port; | 239 | unsigned short port; |
239 | 240 | ||
240 | /* | 241 | /* |
@@ -653,8 +654,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
653 | 654 | ||
654 | dprintk("RPC: xs_destroy xprt %p\n", xprt); | 655 | dprintk("RPC: xs_destroy xprt %p\n", xprt); |
655 | 656 | ||
656 | cancel_delayed_work(&transport->connect_worker); | 657 | cancel_rearming_delayed_work(&transport->connect_worker); |
657 | flush_scheduled_work(); | ||
658 | 658 | ||
659 | xprt_disconnect(xprt); | 659 | xprt_disconnect(xprt); |
660 | xs_close(xprt); | 660 | xs_close(xprt); |
@@ -1001,7 +1001,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1001 | /* Try to schedule an autoclose RPC calls */ | 1001 | /* Try to schedule an autoclose RPC calls */ |
1002 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1002 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); |
1003 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | 1003 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) |
1004 | schedule_work(&xprt->task_cleanup); | 1004 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
1005 | default: | 1005 | default: |
1006 | xprt_disconnect(xprt); | 1006 | xprt_disconnect(xprt); |
1007 | } | 1007 | } |
@@ -1146,31 +1146,36 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | |||
1146 | sap->sin_port = htons(port); | 1146 | sap->sin_port = htons(port); |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock) | 1149 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) |
1150 | { | 1150 | { |
1151 | struct sockaddr_in myaddr = { | 1151 | struct sockaddr_in myaddr = { |
1152 | .sin_family = AF_INET, | 1152 | .sin_family = AF_INET, |
1153 | }; | 1153 | }; |
1154 | struct sockaddr_in *sa; | ||
1154 | int err; | 1155 | int err; |
1155 | unsigned short port = transport->port; | 1156 | unsigned short port = transport->port; |
1156 | 1157 | ||
1158 | if (!transport->xprt.resvport) | ||
1159 | port = 0; | ||
1160 | sa = (struct sockaddr_in *)&transport->addr; | ||
1161 | myaddr.sin_addr = sa->sin_addr; | ||
1157 | do { | 1162 | do { |
1158 | myaddr.sin_port = htons(port); | 1163 | myaddr.sin_port = htons(port); |
1159 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1164 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, |
1160 | sizeof(myaddr)); | 1165 | sizeof(myaddr)); |
1166 | if (!transport->xprt.resvport) | ||
1167 | break; | ||
1161 | if (err == 0) { | 1168 | if (err == 0) { |
1162 | transport->port = port; | 1169 | transport->port = port; |
1163 | dprintk("RPC: xs_bindresvport bound to port %u\n", | 1170 | break; |
1164 | port); | ||
1165 | return 0; | ||
1166 | } | 1171 | } |
1167 | if (port <= xprt_min_resvport) | 1172 | if (port <= xprt_min_resvport) |
1168 | port = xprt_max_resvport; | 1173 | port = xprt_max_resvport; |
1169 | else | 1174 | else |
1170 | port--; | 1175 | port--; |
1171 | } while (err == -EADDRINUSE && port != transport->port); | 1176 | } while (err == -EADDRINUSE && port != transport->port); |
1172 | 1177 | dprintk("RPC: xs_bind "NIPQUAD_FMT":%u: %s (%d)\n", | |
1173 | dprintk("RPC: can't bind to reserved port (%d).\n", -err); | 1178 | NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err); |
1174 | return err; | 1179 | return err; |
1175 | } | 1180 | } |
1176 | 1181 | ||
@@ -1229,7 +1234,7 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1229 | } | 1234 | } |
1230 | xs_reclassify_socket(sock); | 1235 | xs_reclassify_socket(sock); |
1231 | 1236 | ||
1232 | if (xprt->resvport && xs_bindresvport(transport, sock) < 0) { | 1237 | if (xs_bind(transport, sock)) { |
1233 | sock_release(sock); | 1238 | sock_release(sock); |
1234 | goto out; | 1239 | goto out; |
1235 | } | 1240 | } |
@@ -1316,7 +1321,7 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1316 | } | 1321 | } |
1317 | xs_reclassify_socket(sock); | 1322 | xs_reclassify_socket(sock); |
1318 | 1323 | ||
1319 | if (xprt->resvport && xs_bindresvport(transport, sock) < 0) { | 1324 | if (xs_bind(transport, sock)) { |
1320 | sock_release(sock); | 1325 | sock_release(sock); |
1321 | goto out; | 1326 | goto out; |
1322 | } | 1327 | } |
@@ -1410,18 +1415,16 @@ static void xs_connect(struct rpc_task *task) | |||
1410 | dprintk("RPC: xs_connect delayed xprt %p for %lu " | 1415 | dprintk("RPC: xs_connect delayed xprt %p for %lu " |
1411 | "seconds\n", | 1416 | "seconds\n", |
1412 | xprt, xprt->reestablish_timeout / HZ); | 1417 | xprt, xprt->reestablish_timeout / HZ); |
1413 | schedule_delayed_work(&transport->connect_worker, | 1418 | queue_delayed_work(rpciod_workqueue, |
1414 | xprt->reestablish_timeout); | 1419 | &transport->connect_worker, |
1420 | xprt->reestablish_timeout); | ||
1415 | xprt->reestablish_timeout <<= 1; | 1421 | xprt->reestablish_timeout <<= 1; |
1416 | if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO) | 1422 | if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO) |
1417 | xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO; | 1423 | xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO; |
1418 | } else { | 1424 | } else { |
1419 | dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); | 1425 | dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); |
1420 | schedule_delayed_work(&transport->connect_worker, 0); | 1426 | queue_delayed_work(rpciod_workqueue, |
1421 | 1427 | &transport->connect_worker, 0); | |
1422 | /* flush_scheduled_work can sleep... */ | ||
1423 | if (!RPC_IS_ASYNC(task)) | ||
1424 | flush_scheduled_work(); | ||
1425 | } | 1428 | } |
1426 | } | 1429 | } |
1427 | 1430 | ||
@@ -1476,7 +1479,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1476 | .set_buffer_size = xs_udp_set_buffer_size, | 1479 | .set_buffer_size = xs_udp_set_buffer_size, |
1477 | .reserve_xprt = xprt_reserve_xprt_cong, | 1480 | .reserve_xprt = xprt_reserve_xprt_cong, |
1478 | .release_xprt = xprt_release_xprt_cong, | 1481 | .release_xprt = xprt_release_xprt_cong, |
1479 | .rpcbind = rpcb_getport, | 1482 | .rpcbind = rpcb_getport_async, |
1480 | .set_port = xs_set_port, | 1483 | .set_port = xs_set_port, |
1481 | .connect = xs_connect, | 1484 | .connect = xs_connect, |
1482 | .buf_alloc = rpc_malloc, | 1485 | .buf_alloc = rpc_malloc, |
@@ -1493,7 +1496,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1493 | static struct rpc_xprt_ops xs_tcp_ops = { | 1496 | static struct rpc_xprt_ops xs_tcp_ops = { |
1494 | .reserve_xprt = xprt_reserve_xprt, | 1497 | .reserve_xprt = xprt_reserve_xprt, |
1495 | .release_xprt = xs_tcp_release_xprt, | 1498 | .release_xprt = xs_tcp_release_xprt, |
1496 | .rpcbind = rpcb_getport, | 1499 | .rpcbind = rpcb_getport_async, |
1497 | .set_port = xs_set_port, | 1500 | .set_port = xs_set_port, |
1498 | .connect = xs_connect, | 1501 | .connect = xs_connect, |
1499 | .buf_alloc = rpc_malloc, | 1502 | .buf_alloc = rpc_malloc, |
@@ -1505,12 +1508,12 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1505 | .print_stats = xs_tcp_print_stats, | 1508 | .print_stats = xs_tcp_print_stats, |
1506 | }; | 1509 | }; |
1507 | 1510 | ||
1508 | static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size) | 1511 | static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size) |
1509 | { | 1512 | { |
1510 | struct rpc_xprt *xprt; | 1513 | struct rpc_xprt *xprt; |
1511 | struct sock_xprt *new; | 1514 | struct sock_xprt *new; |
1512 | 1515 | ||
1513 | if (addrlen > sizeof(xprt->addr)) { | 1516 | if (args->addrlen > sizeof(xprt->addr)) { |
1514 | dprintk("RPC: xs_setup_xprt: address too large\n"); | 1517 | dprintk("RPC: xs_setup_xprt: address too large\n"); |
1515 | return ERR_PTR(-EBADF); | 1518 | return ERR_PTR(-EBADF); |
1516 | } | 1519 | } |
@@ -1532,8 +1535,10 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns | |||
1532 | return ERR_PTR(-ENOMEM); | 1535 | return ERR_PTR(-ENOMEM); |
1533 | } | 1536 | } |
1534 | 1537 | ||
1535 | memcpy(&xprt->addr, addr, addrlen); | 1538 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); |
1536 | xprt->addrlen = addrlen; | 1539 | xprt->addrlen = args->addrlen; |
1540 | if (args->srcaddr) | ||
1541 | memcpy(&new->addr, args->srcaddr, args->addrlen); | ||
1537 | new->port = xs_get_random_port(); | 1542 | new->port = xs_get_random_port(); |
1538 | 1543 | ||
1539 | return xprt; | 1544 | return xprt; |
@@ -1541,22 +1546,20 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns | |||
1541 | 1546 | ||
1542 | /** | 1547 | /** |
1543 | * xs_setup_udp - Set up transport to use a UDP socket | 1548 | * xs_setup_udp - Set up transport to use a UDP socket |
1544 | * @addr: address of remote server | 1549 | * @args: rpc transport creation arguments |
1545 | * @addrlen: length of address in bytes | ||
1546 | * @to: timeout parameters | ||
1547 | * | 1550 | * |
1548 | */ | 1551 | */ |
1549 | struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) | 1552 | struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) |
1550 | { | 1553 | { |
1551 | struct rpc_xprt *xprt; | 1554 | struct rpc_xprt *xprt; |
1552 | struct sock_xprt *transport; | 1555 | struct sock_xprt *transport; |
1553 | 1556 | ||
1554 | xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries); | 1557 | xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries); |
1555 | if (IS_ERR(xprt)) | 1558 | if (IS_ERR(xprt)) |
1556 | return xprt; | 1559 | return xprt; |
1557 | transport = container_of(xprt, struct sock_xprt, xprt); | 1560 | transport = container_of(xprt, struct sock_xprt, xprt); |
1558 | 1561 | ||
1559 | if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0) | 1562 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) |
1560 | xprt_set_bound(xprt); | 1563 | xprt_set_bound(xprt); |
1561 | 1564 | ||
1562 | xprt->prot = IPPROTO_UDP; | 1565 | xprt->prot = IPPROTO_UDP; |
@@ -1572,8 +1575,8 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_ | |||
1572 | 1575 | ||
1573 | xprt->ops = &xs_udp_ops; | 1576 | xprt->ops = &xs_udp_ops; |
1574 | 1577 | ||
1575 | if (to) | 1578 | if (args->timeout) |
1576 | xprt->timeout = *to; | 1579 | xprt->timeout = *args->timeout; |
1577 | else | 1580 | else |
1578 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | 1581 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); |
1579 | 1582 | ||
@@ -1586,22 +1589,20 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_ | |||
1586 | 1589 | ||
1587 | /** | 1590 | /** |
1588 | * xs_setup_tcp - Set up transport to use a TCP socket | 1591 | * xs_setup_tcp - Set up transport to use a TCP socket |
1589 | * @addr: address of remote server | 1592 | * @args: rpc transport creation arguments |
1590 | * @addrlen: length of address in bytes | ||
1591 | * @to: timeout parameters | ||
1592 | * | 1593 | * |
1593 | */ | 1594 | */ |
1594 | struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) | 1595 | struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) |
1595 | { | 1596 | { |
1596 | struct rpc_xprt *xprt; | 1597 | struct rpc_xprt *xprt; |
1597 | struct sock_xprt *transport; | 1598 | struct sock_xprt *transport; |
1598 | 1599 | ||
1599 | xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries); | 1600 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); |
1600 | if (IS_ERR(xprt)) | 1601 | if (IS_ERR(xprt)) |
1601 | return xprt; | 1602 | return xprt; |
1602 | transport = container_of(xprt, struct sock_xprt, xprt); | 1603 | transport = container_of(xprt, struct sock_xprt, xprt); |
1603 | 1604 | ||
1604 | if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0) | 1605 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) |
1605 | xprt_set_bound(xprt); | 1606 | xprt_set_bound(xprt); |
1606 | 1607 | ||
1607 | xprt->prot = IPPROTO_TCP; | 1608 | xprt->prot = IPPROTO_TCP; |
@@ -1616,8 +1617,8 @@ struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_ | |||
1616 | 1617 | ||
1617 | xprt->ops = &xs_tcp_ops; | 1618 | xprt->ops = &xs_tcp_ops; |
1618 | 1619 | ||
1619 | if (to) | 1620 | if (args->timeout) |
1620 | xprt->timeout = *to; | 1621 | xprt->timeout = *args->timeout; |
1621 | else | 1622 | else |
1622 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | 1623 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); |
1623 | 1624 | ||