diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2006-10-17 14:44:27 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-06 10:46:34 -0500 |
commit | c8541ecdd5692bcfbcb5305cab9a873288d29175 (patch) | |
tree | 45714725337f22a5eb27cbe5b87c3b01f37c9490 | |
parent | e744cf2e3ab8535a8494a4cf0177de26f94586da (diff) |
SUNRPC: Make the transport-specific setup routine allocate rpc_xprt
Change the location where the rpc_xprt structure is allocated so each
transport implementation can allocate a private area from the same
chunk of memory.
Note also that xprt->ops->destroy, rather than xprt_destroy, is now
responsible for freeing rpc_xprt when the transport is destroyed.
Test plan:
Connectathon.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | include/linux/sunrpc/xprt.h | 4 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 31 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 73 |
3 files changed, 61 insertions, 47 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 0321fb53bd02..d7919010863d 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -265,8 +265,8 @@ void xprt_disconnect(struct rpc_xprt *xprt); | |||
265 | /* | 265 | /* |
266 | * Socket transport setup operations | 266 | * Socket transport setup operations |
267 | */ | 267 | */ |
268 | int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to); | 268 | struct rpc_xprt * xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to); |
269 | int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to); | 269 | struct rpc_xprt * xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to); |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * Reserved bit positions in xprt->state | 272 | * Reserved bit positions in xprt->state |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 80857470dc11..8cc2afa2942c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -891,39 +891,25 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i | |||
891 | */ | 891 | */ |
892 | struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to) | 892 | struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to) |
893 | { | 893 | { |
894 | int result; | ||
895 | struct rpc_xprt *xprt; | 894 | struct rpc_xprt *xprt; |
896 | struct rpc_rqst *req; | 895 | struct rpc_rqst *req; |
897 | 896 | ||
898 | if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) { | ||
899 | dprintk("RPC: xprt_create_transport: no memory\n"); | ||
900 | return ERR_PTR(-ENOMEM); | ||
901 | } | ||
902 | if (size <= sizeof(xprt->addr)) { | ||
903 | memcpy(&xprt->addr, ap, size); | ||
904 | xprt->addrlen = size; | ||
905 | } else { | ||
906 | kfree(xprt); | ||
907 | dprintk("RPC: xprt_create_transport: address too large\n"); | ||
908 | return ERR_PTR(-EBADF); | ||
909 | } | ||
910 | |||
911 | switch (proto) { | 897 | switch (proto) { |
912 | case IPPROTO_UDP: | 898 | case IPPROTO_UDP: |
913 | result = xs_setup_udp(xprt, to); | 899 | xprt = xs_setup_udp(ap, size, to); |
914 | break; | 900 | break; |
915 | case IPPROTO_TCP: | 901 | case IPPROTO_TCP: |
916 | result = xs_setup_tcp(xprt, to); | 902 | xprt = xs_setup_tcp(ap, size, to); |
917 | break; | 903 | break; |
918 | default: | 904 | default: |
919 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", | 905 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", |
920 | proto); | 906 | proto); |
921 | return ERR_PTR(-EIO); | 907 | return ERR_PTR(-EIO); |
922 | } | 908 | } |
923 | if (result) { | 909 | if (IS_ERR(xprt)) { |
924 | kfree(xprt); | 910 | dprintk("RPC: xprt_create_transport: failed, %ld\n", |
925 | dprintk("RPC: xprt_create_transport: failed, %d\n", result); | 911 | -PTR_ERR(xprt)); |
926 | return ERR_PTR(result); | 912 | return xprt; |
927 | } | 913 | } |
928 | 914 | ||
929 | kref_init(&xprt->kref); | 915 | kref_init(&xprt->kref); |
@@ -969,8 +955,11 @@ static void xprt_destroy(struct kref *kref) | |||
969 | dprintk("RPC: destroying transport %p\n", xprt); | 955 | dprintk("RPC: destroying transport %p\n", xprt); |
970 | xprt->shutdown = 1; | 956 | xprt->shutdown = 1; |
971 | del_timer_sync(&xprt->timer); | 957 | del_timer_sync(&xprt->timer); |
958 | |||
959 | /* | ||
960 | * Tear down transport state and free the rpc_xprt | ||
961 | */ | ||
972 | xprt->ops->destroy(xprt); | 962 | xprt->ops->destroy(xprt); |
973 | kfree(xprt); | ||
974 | } | 963 | } |
975 | 964 | ||
976 | /** | 965 | /** |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 25620851d4bf..ec3462f141b4 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -518,6 +518,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
518 | xs_close(xprt); | 518 | xs_close(xprt); |
519 | xs_free_peer_addresses(xprt); | 519 | xs_free_peer_addresses(xprt); |
520 | kfree(xprt->slot); | 520 | kfree(xprt->slot); |
521 | kfree(xprt); | ||
521 | } | 522 | } |
522 | 523 | ||
523 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | 524 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) |
@@ -1339,26 +1340,53 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1339 | .print_stats = xs_tcp_print_stats, | 1340 | .print_stats = xs_tcp_print_stats, |
1340 | }; | 1341 | }; |
1341 | 1342 | ||
1343 | static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size) | ||
1344 | { | ||
1345 | struct rpc_xprt *xprt; | ||
1346 | |||
1347 | if (addrlen > sizeof(xprt->addr)) { | ||
1348 | dprintk("RPC: xs_setup_xprt: address too large\n"); | ||
1349 | return ERR_PTR(-EBADF); | ||
1350 | } | ||
1351 | |||
1352 | xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL); | ||
1353 | if (xprt == NULL) { | ||
1354 | dprintk("RPC: xs_setup_xprt: couldn't allocate rpc_xprt\n"); | ||
1355 | return ERR_PTR(-ENOMEM); | ||
1356 | } | ||
1357 | |||
1358 | xprt->max_reqs = slot_table_size; | ||
1359 | xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL); | ||
1360 | if (xprt->slot == NULL) { | ||
1361 | kfree(xprt); | ||
1362 | dprintk("RPC: xs_setup_xprt: couldn't allocate slot table\n"); | ||
1363 | return ERR_PTR(-ENOMEM); | ||
1364 | } | ||
1365 | |||
1366 | memcpy(&xprt->addr, addr, addrlen); | ||
1367 | xprt->addrlen = addrlen; | ||
1368 | xprt->port = xs_get_random_port(); | ||
1369 | |||
1370 | return xprt; | ||
1371 | } | ||
1372 | |||
1342 | /** | 1373 | /** |
1343 | * xs_setup_udp - Set up transport to use a UDP socket | 1374 | * xs_setup_udp - Set up transport to use a UDP socket |
1344 | * @xprt: transport to set up | 1375 | * @addr: address of remote server |
1376 | * @addrlen: length of address in bytes | ||
1345 | * @to: timeout parameters | 1377 | * @to: timeout parameters |
1346 | * | 1378 | * |
1347 | */ | 1379 | */ |
1348 | int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) | 1380 | struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) |
1349 | { | 1381 | { |
1350 | size_t slot_table_size; | 1382 | struct rpc_xprt *xprt; |
1351 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | ||
1352 | 1383 | ||
1353 | xprt->max_reqs = xprt_udp_slot_table_entries; | 1384 | xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries); |
1354 | slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); | 1385 | if (IS_ERR(xprt)) |
1355 | xprt->slot = kzalloc(slot_table_size, GFP_KERNEL); | 1386 | return xprt; |
1356 | if (xprt->slot == NULL) | ||
1357 | return -ENOMEM; | ||
1358 | 1387 | ||
1359 | if (ntohs(addr->sin_port) != 0) | 1388 | if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0) |
1360 | xprt_set_bound(xprt); | 1389 | xprt_set_bound(xprt); |
1361 | xprt->port = xs_get_random_port(); | ||
1362 | 1390 | ||
1363 | xprt->prot = IPPROTO_UDP; | 1391 | xprt->prot = IPPROTO_UDP; |
1364 | xprt->tsh_size = 0; | 1392 | xprt->tsh_size = 0; |
@@ -1382,29 +1410,26 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1382 | dprintk("RPC: set up transport to address %s\n", | 1410 | dprintk("RPC: set up transport to address %s\n", |
1383 | xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); | 1411 | xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); |
1384 | 1412 | ||
1385 | return 0; | 1413 | return xprt; |
1386 | } | 1414 | } |
1387 | 1415 | ||
1388 | /** | 1416 | /** |
1389 | * xs_setup_tcp - Set up transport to use a TCP socket | 1417 | * xs_setup_tcp - Set up transport to use a TCP socket |
1390 | * @xprt: transport to set up | 1418 | * @addr: address of remote server |
1419 | * @addrlen: length of address in bytes | ||
1391 | * @to: timeout parameters | 1420 | * @to: timeout parameters |
1392 | * | 1421 | * |
1393 | */ | 1422 | */ |
1394 | int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) | 1423 | struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) |
1395 | { | 1424 | { |
1396 | size_t slot_table_size; | 1425 | struct rpc_xprt *xprt; |
1397 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | ||
1398 | 1426 | ||
1399 | xprt->max_reqs = xprt_tcp_slot_table_entries; | 1427 | xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries); |
1400 | slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); | 1428 | if (IS_ERR(xprt)) |
1401 | xprt->slot = kzalloc(slot_table_size, GFP_KERNEL); | 1429 | return xprt; |
1402 | if (xprt->slot == NULL) | ||
1403 | return -ENOMEM; | ||
1404 | 1430 | ||
1405 | if (ntohs(addr->sin_port) != 0) | 1431 | if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0) |
1406 | xprt_set_bound(xprt); | 1432 | xprt_set_bound(xprt); |
1407 | xprt->port = xs_get_random_port(); | ||
1408 | 1433 | ||
1409 | xprt->prot = IPPROTO_TCP; | 1434 | xprt->prot = IPPROTO_TCP; |
1410 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | 1435 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); |
@@ -1427,5 +1452,5 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1427 | dprintk("RPC: set up transport to address %s\n", | 1452 | dprintk("RPC: set up transport to address %s\n", |
1428 | xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); | 1453 | xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); |
1429 | 1454 | ||
1430 | return 0; | 1455 | return xprt; |
1431 | } | 1456 | } |