diff options
-rw-r--r-- | net/sunrpc/xprtsock.c | 131 |
1 files changed, 72 insertions, 59 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 8295ae28391a..e8a5edf59912 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1323,6 +1323,35 @@ static inline void xs_reclassify_socket(struct socket *sock) | |||
1323 | } | 1323 | } |
1324 | #endif | 1324 | #endif |
1325 | 1325 | ||
1326 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
1327 | { | ||
1328 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
1329 | |||
1330 | if (!transport->inet) { | ||
1331 | struct sock *sk = sock->sk; | ||
1332 | |||
1333 | write_lock_bh(&sk->sk_callback_lock); | ||
1334 | |||
1335 | sk->sk_user_data = xprt; | ||
1336 | transport->old_data_ready = sk->sk_data_ready; | ||
1337 | transport->old_state_change = sk->sk_state_change; | ||
1338 | transport->old_write_space = sk->sk_write_space; | ||
1339 | sk->sk_data_ready = xs_udp_data_ready; | ||
1340 | sk->sk_write_space = xs_udp_write_space; | ||
1341 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1342 | sk->sk_allocation = GFP_ATOMIC; | ||
1343 | |||
1344 | xprt_set_connected(xprt); | ||
1345 | |||
1346 | /* Reset to new socket */ | ||
1347 | transport->sock = sock; | ||
1348 | transport->inet = sk; | ||
1349 | |||
1350 | write_unlock_bh(&sk->sk_callback_lock); | ||
1351 | } | ||
1352 | xs_udp_do_set_buffer_size(xprt); | ||
1353 | } | ||
1354 | |||
1326 | /** | 1355 | /** |
1327 | * xs_udp_connect_worker - set up a UDP socket | 1356 | * xs_udp_connect_worker - set up a UDP socket |
1328 | * @work: RPC transport to connect | 1357 | * @work: RPC transport to connect |
@@ -1357,29 +1386,7 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1357 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1386 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1358 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1387 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1359 | 1388 | ||
1360 | if (!transport->inet) { | 1389 | xs_udp_finish_connecting(xprt, sock); |
1361 | struct sock *sk = sock->sk; | ||
1362 | |||
1363 | write_lock_bh(&sk->sk_callback_lock); | ||
1364 | |||
1365 | sk->sk_user_data = xprt; | ||
1366 | transport->old_data_ready = sk->sk_data_ready; | ||
1367 | transport->old_state_change = sk->sk_state_change; | ||
1368 | transport->old_write_space = sk->sk_write_space; | ||
1369 | sk->sk_data_ready = xs_udp_data_ready; | ||
1370 | sk->sk_write_space = xs_udp_write_space; | ||
1371 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1372 | sk->sk_allocation = GFP_ATOMIC; | ||
1373 | |||
1374 | xprt_set_connected(xprt); | ||
1375 | |||
1376 | /* Reset to new socket */ | ||
1377 | transport->sock = sock; | ||
1378 | transport->inet = sk; | ||
1379 | |||
1380 | write_unlock_bh(&sk->sk_callback_lock); | ||
1381 | } | ||
1382 | xs_udp_do_set_buffer_size(xprt); | ||
1383 | status = 0; | 1390 | status = 0; |
1384 | out: | 1391 | out: |
1385 | xprt_wake_pending_tasks(xprt, status); | 1392 | xprt_wake_pending_tasks(xprt, status); |
@@ -1410,42 +1417,9 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | |||
1410 | result); | 1417 | result); |
1411 | } | 1418 | } |
1412 | 1419 | ||
1413 | /** | 1420 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
1414 | * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint | ||
1415 | * @work: RPC transport to connect | ||
1416 | * | ||
1417 | * Invoked by a work queue tasklet. | ||
1418 | */ | ||
1419 | static void xs_tcp_connect_worker(struct work_struct *work) | ||
1420 | { | 1421 | { |
1421 | struct sock_xprt *transport = | 1422 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
1422 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1423 | struct rpc_xprt *xprt = &transport->xprt; | ||
1424 | struct socket *sock = transport->sock; | ||
1425 | int err, status = -EIO; | ||
1426 | |||
1427 | if (xprt->shutdown || !xprt_bound(xprt)) | ||
1428 | goto out; | ||
1429 | |||
1430 | if (!sock) { | ||
1431 | /* start from scratch */ | ||
1432 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | ||
1433 | dprintk("RPC: can't create TCP transport " | ||
1434 | "socket (%d).\n", -err); | ||
1435 | goto out; | ||
1436 | } | ||
1437 | xs_reclassify_socket(sock); | ||
1438 | |||
1439 | if (xs_bind4(transport, sock)) { | ||
1440 | sock_release(sock); | ||
1441 | goto out; | ||
1442 | } | ||
1443 | } else | ||
1444 | /* "close" the socket, preserving the local port */ | ||
1445 | xs_tcp_reuse_connection(xprt); | ||
1446 | |||
1447 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1448 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
1449 | 1423 | ||
1450 | if (!transport->inet) { | 1424 | if (!transport->inet) { |
1451 | struct sock *sk = sock->sk; | 1425 | struct sock *sk = sock->sk; |
@@ -1479,8 +1453,47 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1479 | /* Tell the socket layer to start connecting... */ | 1453 | /* Tell the socket layer to start connecting... */ |
1480 | xprt->stat.connect_count++; | 1454 | xprt->stat.connect_count++; |
1481 | xprt->stat.connect_start = jiffies; | 1455 | xprt->stat.connect_start = jiffies; |
1482 | status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, | 1456 | return kernel_connect(sock, (struct sockaddr *) &xprt->addr, |
1483 | xprt->addrlen, O_NONBLOCK); | 1457 | xprt->addrlen, O_NONBLOCK); |
1458 | } | ||
1459 | |||
1460 | /** | ||
1461 | * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint | ||
1462 | * @work: RPC transport to connect | ||
1463 | * | ||
1464 | * Invoked by a work queue tasklet. | ||
1465 | */ | ||
1466 | static void xs_tcp_connect_worker(struct work_struct *work) | ||
1467 | { | ||
1468 | struct sock_xprt *transport = | ||
1469 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1470 | struct rpc_xprt *xprt = &transport->xprt; | ||
1471 | struct socket *sock = transport->sock; | ||
1472 | int err, status = -EIO; | ||
1473 | |||
1474 | if (xprt->shutdown || !xprt_bound(xprt)) | ||
1475 | goto out; | ||
1476 | |||
1477 | if (!sock) { | ||
1478 | /* start from scratch */ | ||
1479 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | ||
1480 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | ||
1481 | goto out; | ||
1482 | } | ||
1483 | xs_reclassify_socket(sock); | ||
1484 | |||
1485 | if (xs_bind4(transport, sock) < 0) { | ||
1486 | sock_release(sock); | ||
1487 | goto out; | ||
1488 | } | ||
1489 | } else | ||
1490 | /* "close" the socket, preserving the local port */ | ||
1491 | xs_tcp_reuse_connection(xprt); | ||
1492 | |||
1493 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1494 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
1495 | |||
1496 | status = xs_tcp_finish_connecting(xprt, sock); | ||
1484 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 1497 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1485 | xprt, -status, xprt_connected(xprt), | 1498 | xprt, -status, xprt_connected(xprt), |
1486 | sock->sk->sk_state); | 1499 | sock->sk->sk_state); |