aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c81
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
1149static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock) 1149static 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 = {
1493static struct rpc_xprt_ops xs_tcp_ops = { 1496static 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
1508static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size) 1511static 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 */
1549struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) 1552struct 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 */
1594struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) 1595struct 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