diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 567 |
1 files changed, 456 insertions, 111 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 282efd447a61..02298f529dad 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -13,10 +13,14 @@ | |||
13 | * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no> | 13 | * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no> |
14 | * | 14 | * |
15 | * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com> | 15 | * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com> |
16 | * | ||
17 | * IPv6 support contributed by Gilles Quillard, Bull Open Source, 2005. | ||
18 | * <gilles.quillard@bull.net> | ||
16 | */ | 19 | */ |
17 | 20 | ||
18 | #include <linux/types.h> | 21 | #include <linux/types.h> |
19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/module.h> | ||
20 | #include <linux/capability.h> | 24 | #include <linux/capability.h> |
21 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
22 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
@@ -28,6 +32,7 @@ | |||
28 | #include <linux/tcp.h> | 32 | #include <linux/tcp.h> |
29 | #include <linux/sunrpc/clnt.h> | 33 | #include <linux/sunrpc/clnt.h> |
30 | #include <linux/sunrpc/sched.h> | 34 | #include <linux/sunrpc/sched.h> |
35 | #include <linux/sunrpc/xprtsock.h> | ||
31 | #include <linux/file.h> | 36 | #include <linux/file.h> |
32 | 37 | ||
33 | #include <net/sock.h> | 38 | #include <net/sock.h> |
@@ -260,14 +265,29 @@ struct sock_xprt { | |||
260 | #define TCP_RCV_COPY_XID (1UL << 2) | 265 | #define TCP_RCV_COPY_XID (1UL << 2) |
261 | #define TCP_RCV_COPY_DATA (1UL << 3) | 266 | #define TCP_RCV_COPY_DATA (1UL << 3) |
262 | 267 | ||
263 | static void xs_format_peer_addresses(struct rpc_xprt *xprt) | 268 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) |
269 | { | ||
270 | return (struct sockaddr *) &xprt->addr; | ||
271 | } | ||
272 | |||
273 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) | ||
264 | { | 274 | { |
265 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | 275 | return (struct sockaddr_in *) &xprt->addr; |
276 | } | ||
277 | |||
278 | static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt) | ||
279 | { | ||
280 | return (struct sockaddr_in6 *) &xprt->addr; | ||
281 | } | ||
282 | |||
283 | static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) | ||
284 | { | ||
285 | struct sockaddr_in *addr = xs_addr_in(xprt); | ||
266 | char *buf; | 286 | char *buf; |
267 | 287 | ||
268 | buf = kzalloc(20, GFP_KERNEL); | 288 | buf = kzalloc(20, GFP_KERNEL); |
269 | if (buf) { | 289 | if (buf) { |
270 | snprintf(buf, 20, "%u.%u.%u.%u", | 290 | snprintf(buf, 20, NIPQUAD_FMT, |
271 | NIPQUAD(addr->sin_addr.s_addr)); | 291 | NIPQUAD(addr->sin_addr.s_addr)); |
272 | } | 292 | } |
273 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | 293 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; |
@@ -279,26 +299,123 @@ static void xs_format_peer_addresses(struct rpc_xprt *xprt) | |||
279 | } | 299 | } |
280 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | 300 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; |
281 | 301 | ||
282 | if (xprt->prot == IPPROTO_UDP) | 302 | buf = kzalloc(8, GFP_KERNEL); |
283 | xprt->address_strings[RPC_DISPLAY_PROTO] = "udp"; | 303 | if (buf) { |
284 | else | 304 | if (xprt->prot == IPPROTO_UDP) |
285 | xprt->address_strings[RPC_DISPLAY_PROTO] = "tcp"; | 305 | snprintf(buf, 8, "udp"); |
306 | else | ||
307 | snprintf(buf, 8, "tcp"); | ||
308 | } | ||
309 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
286 | 310 | ||
287 | buf = kzalloc(48, GFP_KERNEL); | 311 | buf = kzalloc(48, GFP_KERNEL); |
288 | if (buf) { | 312 | if (buf) { |
289 | snprintf(buf, 48, "addr=%u.%u.%u.%u port=%u proto=%s", | 313 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", |
290 | NIPQUAD(addr->sin_addr.s_addr), | 314 | NIPQUAD(addr->sin_addr.s_addr), |
291 | ntohs(addr->sin_port), | 315 | ntohs(addr->sin_port), |
292 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | 316 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); |
293 | } | 317 | } |
294 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | 318 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; |
319 | |||
320 | buf = kzalloc(10, GFP_KERNEL); | ||
321 | if (buf) { | ||
322 | snprintf(buf, 10, "%02x%02x%02x%02x", | ||
323 | NIPQUAD(addr->sin_addr.s_addr)); | ||
324 | } | ||
325 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
326 | |||
327 | buf = kzalloc(8, GFP_KERNEL); | ||
328 | if (buf) { | ||
329 | snprintf(buf, 8, "%4hx", | ||
330 | ntohs(addr->sin_port)); | ||
331 | } | ||
332 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
333 | |||
334 | buf = kzalloc(30, GFP_KERNEL); | ||
335 | if (buf) { | ||
336 | snprintf(buf, 30, NIPQUAD_FMT".%u.%u", | ||
337 | NIPQUAD(addr->sin_addr.s_addr), | ||
338 | ntohs(addr->sin_port) >> 8, | ||
339 | ntohs(addr->sin_port) & 0xff); | ||
340 | } | ||
341 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
342 | |||
343 | xprt->address_strings[RPC_DISPLAY_NETID] = | ||
344 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
345 | RPCBIND_NETID_UDP : RPCBIND_NETID_TCP, GFP_KERNEL); | ||
346 | } | ||
347 | |||
348 | static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) | ||
349 | { | ||
350 | struct sockaddr_in6 *addr = xs_addr_in6(xprt); | ||
351 | char *buf; | ||
352 | |||
353 | buf = kzalloc(40, GFP_KERNEL); | ||
354 | if (buf) { | ||
355 | snprintf(buf, 40, NIP6_FMT, | ||
356 | NIP6(addr->sin6_addr)); | ||
357 | } | ||
358 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | ||
359 | |||
360 | buf = kzalloc(8, GFP_KERNEL); | ||
361 | if (buf) { | ||
362 | snprintf(buf, 8, "%u", | ||
363 | ntohs(addr->sin6_port)); | ||
364 | } | ||
365 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | ||
366 | |||
367 | buf = kzalloc(8, GFP_KERNEL); | ||
368 | if (buf) { | ||
369 | if (xprt->prot == IPPROTO_UDP) | ||
370 | snprintf(buf, 8, "udp"); | ||
371 | else | ||
372 | snprintf(buf, 8, "tcp"); | ||
373 | } | ||
374 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
375 | |||
376 | buf = kzalloc(64, GFP_KERNEL); | ||
377 | if (buf) { | ||
378 | snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s", | ||
379 | NIP6(addr->sin6_addr), | ||
380 | ntohs(addr->sin6_port), | ||
381 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | ||
382 | } | ||
383 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | ||
384 | |||
385 | buf = kzalloc(36, GFP_KERNEL); | ||
386 | if (buf) { | ||
387 | snprintf(buf, 36, NIP6_SEQFMT, | ||
388 | NIP6(addr->sin6_addr)); | ||
389 | } | ||
390 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
391 | |||
392 | buf = kzalloc(8, GFP_KERNEL); | ||
393 | if (buf) { | ||
394 | snprintf(buf, 8, "%4hx", | ||
395 | ntohs(addr->sin6_port)); | ||
396 | } | ||
397 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
398 | |||
399 | buf = kzalloc(50, GFP_KERNEL); | ||
400 | if (buf) { | ||
401 | snprintf(buf, 50, NIP6_FMT".%u.%u", | ||
402 | NIP6(addr->sin6_addr), | ||
403 | ntohs(addr->sin6_port) >> 8, | ||
404 | ntohs(addr->sin6_port) & 0xff); | ||
405 | } | ||
406 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
407 | |||
408 | xprt->address_strings[RPC_DISPLAY_NETID] = | ||
409 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
410 | RPCBIND_NETID_UDP6 : RPCBIND_NETID_TCP6, GFP_KERNEL); | ||
295 | } | 411 | } |
296 | 412 | ||
297 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) | 413 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) |
298 | { | 414 | { |
299 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | 415 | int i; |
300 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | 416 | |
301 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | 417 | for (i = 0; i < RPC_DISPLAY_MAX; i++) |
418 | kfree(xprt->address_strings[i]); | ||
302 | } | 419 | } |
303 | 420 | ||
304 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) | 421 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) |
@@ -463,19 +580,20 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
463 | 580 | ||
464 | req->rq_xtime = jiffies; | 581 | req->rq_xtime = jiffies; |
465 | status = xs_sendpages(transport->sock, | 582 | status = xs_sendpages(transport->sock, |
466 | (struct sockaddr *) &xprt->addr, | 583 | xs_addr(xprt), |
467 | xprt->addrlen, xdr, | 584 | xprt->addrlen, xdr, |
468 | req->rq_bytes_sent); | 585 | req->rq_bytes_sent); |
469 | 586 | ||
470 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", | 587 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", |
471 | xdr->len - req->rq_bytes_sent, status); | 588 | xdr->len - req->rq_bytes_sent, status); |
472 | 589 | ||
473 | if (likely(status >= (int) req->rq_slen)) | 590 | if (status >= 0) { |
474 | return 0; | 591 | task->tk_bytes_sent += status; |
475 | 592 | if (status >= req->rq_slen) | |
476 | /* Still some bytes left; set up for a retry later. */ | 593 | return 0; |
477 | if (status > 0) | 594 | /* Still some bytes left; set up for a retry later. */ |
478 | status = -EAGAIN; | 595 | status = -EAGAIN; |
596 | } | ||
479 | 597 | ||
480 | switch (status) { | 598 | switch (status) { |
481 | case -ENETUNREACH: | 599 | case -ENETUNREACH: |
@@ -523,7 +641,8 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
523 | struct rpc_xprt *xprt = req->rq_xprt; | 641 | struct rpc_xprt *xprt = req->rq_xprt; |
524 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 642 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
525 | struct xdr_buf *xdr = &req->rq_snd_buf; | 643 | struct xdr_buf *xdr = &req->rq_snd_buf; |
526 | int status, retry = 0; | 644 | int status; |
645 | unsigned int retry = 0; | ||
527 | 646 | ||
528 | xs_encode_tcp_record_marker(&req->rq_snd_buf); | 647 | xs_encode_tcp_record_marker(&req->rq_snd_buf); |
529 | 648 | ||
@@ -661,6 +780,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
661 | xs_free_peer_addresses(xprt); | 780 | xs_free_peer_addresses(xprt); |
662 | kfree(xprt->slot); | 781 | kfree(xprt->slot); |
663 | kfree(xprt); | 782 | kfree(xprt); |
783 | module_put(THIS_MODULE); | ||
664 | } | 784 | } |
665 | 785 | ||
666 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | 786 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) |
@@ -1139,14 +1259,23 @@ static unsigned short xs_get_random_port(void) | |||
1139 | */ | 1259 | */ |
1140 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | 1260 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) |
1141 | { | 1261 | { |
1142 | struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr; | 1262 | struct sockaddr *addr = xs_addr(xprt); |
1143 | 1263 | ||
1144 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); | 1264 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); |
1145 | 1265 | ||
1146 | sap->sin_port = htons(port); | 1266 | switch (addr->sa_family) { |
1267 | case AF_INET: | ||
1268 | ((struct sockaddr_in *)addr)->sin_port = htons(port); | ||
1269 | break; | ||
1270 | case AF_INET6: | ||
1271 | ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); | ||
1272 | break; | ||
1273 | default: | ||
1274 | BUG(); | ||
1275 | } | ||
1147 | } | 1276 | } |
1148 | 1277 | ||
1149 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) | 1278 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) |
1150 | { | 1279 | { |
1151 | struct sockaddr_in myaddr = { | 1280 | struct sockaddr_in myaddr = { |
1152 | .sin_family = AF_INET, | 1281 | .sin_family = AF_INET, |
@@ -1174,8 +1303,42 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
1174 | else | 1303 | else |
1175 | port--; | 1304 | port--; |
1176 | } while (err == -EADDRINUSE && port != transport->port); | 1305 | } while (err == -EADDRINUSE && port != transport->port); |
1177 | dprintk("RPC: xs_bind "NIPQUAD_FMT":%u: %s (%d)\n", | 1306 | dprintk("RPC: %s "NIPQUAD_FMT":%u: %s (%d)\n", |
1178 | NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err); | 1307 | __FUNCTION__, NIPQUAD(myaddr.sin_addr), |
1308 | port, err ? "failed" : "ok", err); | ||
1309 | return err; | ||
1310 | } | ||
1311 | |||
1312 | static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | ||
1313 | { | ||
1314 | struct sockaddr_in6 myaddr = { | ||
1315 | .sin6_family = AF_INET6, | ||
1316 | }; | ||
1317 | struct sockaddr_in6 *sa; | ||
1318 | int err; | ||
1319 | unsigned short port = transport->port; | ||
1320 | |||
1321 | if (!transport->xprt.resvport) | ||
1322 | port = 0; | ||
1323 | sa = (struct sockaddr_in6 *)&transport->addr; | ||
1324 | myaddr.sin6_addr = sa->sin6_addr; | ||
1325 | do { | ||
1326 | myaddr.sin6_port = htons(port); | ||
1327 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | ||
1328 | sizeof(myaddr)); | ||
1329 | if (!transport->xprt.resvport) | ||
1330 | break; | ||
1331 | if (err == 0) { | ||
1332 | transport->port = port; | ||
1333 | break; | ||
1334 | } | ||
1335 | if (port <= xprt_min_resvport) | ||
1336 | port = xprt_max_resvport; | ||
1337 | else | ||
1338 | port--; | ||
1339 | } while (err == -EADDRINUSE && port != transport->port); | ||
1340 | dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n", | ||
1341 | NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err); | ||
1179 | return err; | 1342 | return err; |
1180 | } | 1343 | } |
1181 | 1344 | ||
@@ -1183,38 +1346,69 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
1183 | static struct lock_class_key xs_key[2]; | 1346 | static struct lock_class_key xs_key[2]; |
1184 | static struct lock_class_key xs_slock_key[2]; | 1347 | static struct lock_class_key xs_slock_key[2]; |
1185 | 1348 | ||
1186 | static inline void xs_reclassify_socket(struct socket *sock) | 1349 | static inline void xs_reclassify_socket4(struct socket *sock) |
1187 | { | 1350 | { |
1188 | struct sock *sk = sock->sk; | 1351 | struct sock *sk = sock->sk; |
1352 | |||
1189 | BUG_ON(sock_owned_by_user(sk)); | 1353 | BUG_ON(sock_owned_by_user(sk)); |
1190 | switch (sk->sk_family) { | 1354 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", |
1191 | case AF_INET: | 1355 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); |
1192 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS", | 1356 | } |
1193 | &xs_slock_key[0], "sk_lock-AF_INET-NFS", &xs_key[0]); | ||
1194 | break; | ||
1195 | 1357 | ||
1196 | case AF_INET6: | 1358 | static inline void xs_reclassify_socket6(struct socket *sock) |
1197 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFS", | 1359 | { |
1198 | &xs_slock_key[1], "sk_lock-AF_INET6-NFS", &xs_key[1]); | 1360 | struct sock *sk = sock->sk; |
1199 | break; | ||
1200 | 1361 | ||
1201 | default: | 1362 | BUG_ON(sock_owned_by_user(sk)); |
1202 | BUG(); | 1363 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", |
1203 | } | 1364 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); |
1204 | } | 1365 | } |
1205 | #else | 1366 | #else |
1206 | static inline void xs_reclassify_socket(struct socket *sock) | 1367 | static inline void xs_reclassify_socket4(struct socket *sock) |
1368 | { | ||
1369 | } | ||
1370 | |||
1371 | static inline void xs_reclassify_socket6(struct socket *sock) | ||
1207 | { | 1372 | { |
1208 | } | 1373 | } |
1209 | #endif | 1374 | #endif |
1210 | 1375 | ||
1376 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
1377 | { | ||
1378 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
1379 | |||
1380 | if (!transport->inet) { | ||
1381 | struct sock *sk = sock->sk; | ||
1382 | |||
1383 | write_lock_bh(&sk->sk_callback_lock); | ||
1384 | |||
1385 | sk->sk_user_data = xprt; | ||
1386 | transport->old_data_ready = sk->sk_data_ready; | ||
1387 | transport->old_state_change = sk->sk_state_change; | ||
1388 | transport->old_write_space = sk->sk_write_space; | ||
1389 | sk->sk_data_ready = xs_udp_data_ready; | ||
1390 | sk->sk_write_space = xs_udp_write_space; | ||
1391 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1392 | sk->sk_allocation = GFP_ATOMIC; | ||
1393 | |||
1394 | xprt_set_connected(xprt); | ||
1395 | |||
1396 | /* Reset to new socket */ | ||
1397 | transport->sock = sock; | ||
1398 | transport->inet = sk; | ||
1399 | |||
1400 | write_unlock_bh(&sk->sk_callback_lock); | ||
1401 | } | ||
1402 | xs_udp_do_set_buffer_size(xprt); | ||
1403 | } | ||
1404 | |||
1211 | /** | 1405 | /** |
1212 | * xs_udp_connect_worker - set up a UDP socket | 1406 | * xs_udp_connect_worker4 - set up a UDP socket |
1213 | * @work: RPC transport to connect | 1407 | * @work: RPC transport to connect |
1214 | * | 1408 | * |
1215 | * Invoked by a work queue tasklet. | 1409 | * Invoked by a work queue tasklet. |
1216 | */ | 1410 | */ |
1217 | static void xs_udp_connect_worker(struct work_struct *work) | 1411 | static void xs_udp_connect_worker4(struct work_struct *work) |
1218 | { | 1412 | { |
1219 | struct sock_xprt *transport = | 1413 | struct sock_xprt *transport = |
1220 | container_of(work, struct sock_xprt, connect_worker.work); | 1414 | container_of(work, struct sock_xprt, connect_worker.work); |
@@ -1232,9 +1426,9 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1232 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1426 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1233 | goto out; | 1427 | goto out; |
1234 | } | 1428 | } |
1235 | xs_reclassify_socket(sock); | 1429 | xs_reclassify_socket4(sock); |
1236 | 1430 | ||
1237 | if (xs_bind(transport, sock)) { | 1431 | if (xs_bind4(transport, sock)) { |
1238 | sock_release(sock); | 1432 | sock_release(sock); |
1239 | goto out; | 1433 | goto out; |
1240 | } | 1434 | } |
@@ -1242,29 +1436,48 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1242 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1436 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1243 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1437 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1244 | 1438 | ||
1245 | if (!transport->inet) { | 1439 | xs_udp_finish_connecting(xprt, sock); |
1246 | struct sock *sk = sock->sk; | 1440 | status = 0; |
1441 | out: | ||
1442 | xprt_wake_pending_tasks(xprt, status); | ||
1443 | xprt_clear_connecting(xprt); | ||
1444 | } | ||
1247 | 1445 | ||
1248 | write_lock_bh(&sk->sk_callback_lock); | 1446 | /** |
1447 | * xs_udp_connect_worker6 - set up a UDP socket | ||
1448 | * @work: RPC transport to connect | ||
1449 | * | ||
1450 | * Invoked by a work queue tasklet. | ||
1451 | */ | ||
1452 | static void xs_udp_connect_worker6(struct work_struct *work) | ||
1453 | { | ||
1454 | struct sock_xprt *transport = | ||
1455 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1456 | struct rpc_xprt *xprt = &transport->xprt; | ||
1457 | struct socket *sock = transport->sock; | ||
1458 | int err, status = -EIO; | ||
1249 | 1459 | ||
1250 | sk->sk_user_data = xprt; | 1460 | if (xprt->shutdown || !xprt_bound(xprt)) |
1251 | transport->old_data_ready = sk->sk_data_ready; | 1461 | goto out; |
1252 | transport->old_state_change = sk->sk_state_change; | ||
1253 | transport->old_write_space = sk->sk_write_space; | ||
1254 | sk->sk_data_ready = xs_udp_data_ready; | ||
1255 | sk->sk_write_space = xs_udp_write_space; | ||
1256 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1257 | sk->sk_allocation = GFP_ATOMIC; | ||
1258 | 1462 | ||
1259 | xprt_set_connected(xprt); | 1463 | /* Start by resetting any existing state */ |
1464 | xs_close(xprt); | ||
1260 | 1465 | ||
1261 | /* Reset to new socket */ | 1466 | if ((err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { |
1262 | transport->sock = sock; | 1467 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1263 | transport->inet = sk; | 1468 | goto out; |
1469 | } | ||
1470 | xs_reclassify_socket6(sock); | ||
1264 | 1471 | ||
1265 | write_unlock_bh(&sk->sk_callback_lock); | 1472 | if (xs_bind6(transport, sock) < 0) { |
1473 | sock_release(sock); | ||
1474 | goto out; | ||
1266 | } | 1475 | } |
1267 | xs_udp_do_set_buffer_size(xprt); | 1476 | |
1477 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1478 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
1479 | |||
1480 | xs_udp_finish_connecting(xprt, sock); | ||
1268 | status = 0; | 1481 | status = 0; |
1269 | out: | 1482 | out: |
1270 | xprt_wake_pending_tasks(xprt, status); | 1483 | xprt_wake_pending_tasks(xprt, status); |
@@ -1295,13 +1508,52 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | |||
1295 | result); | 1508 | result); |
1296 | } | 1509 | } |
1297 | 1510 | ||
1511 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
1512 | { | ||
1513 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
1514 | |||
1515 | if (!transport->inet) { | ||
1516 | struct sock *sk = sock->sk; | ||
1517 | |||
1518 | write_lock_bh(&sk->sk_callback_lock); | ||
1519 | |||
1520 | sk->sk_user_data = xprt; | ||
1521 | transport->old_data_ready = sk->sk_data_ready; | ||
1522 | transport->old_state_change = sk->sk_state_change; | ||
1523 | transport->old_write_space = sk->sk_write_space; | ||
1524 | sk->sk_data_ready = xs_tcp_data_ready; | ||
1525 | sk->sk_state_change = xs_tcp_state_change; | ||
1526 | sk->sk_write_space = xs_tcp_write_space; | ||
1527 | sk->sk_allocation = GFP_ATOMIC; | ||
1528 | |||
1529 | /* socket options */ | ||
1530 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | ||
1531 | sock_reset_flag(sk, SOCK_LINGER); | ||
1532 | tcp_sk(sk)->linger2 = 0; | ||
1533 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | ||
1534 | |||
1535 | xprt_clear_connected(xprt); | ||
1536 | |||
1537 | /* Reset to new socket */ | ||
1538 | transport->sock = sock; | ||
1539 | transport->inet = sk; | ||
1540 | |||
1541 | write_unlock_bh(&sk->sk_callback_lock); | ||
1542 | } | ||
1543 | |||
1544 | /* Tell the socket layer to start connecting... */ | ||
1545 | xprt->stat.connect_count++; | ||
1546 | xprt->stat.connect_start = jiffies; | ||
1547 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); | ||
1548 | } | ||
1549 | |||
1298 | /** | 1550 | /** |
1299 | * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint | 1551 | * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint |
1300 | * @work: RPC transport to connect | 1552 | * @work: RPC transport to connect |
1301 | * | 1553 | * |
1302 | * Invoked by a work queue tasklet. | 1554 | * Invoked by a work queue tasklet. |
1303 | */ | 1555 | */ |
1304 | static void xs_tcp_connect_worker(struct work_struct *work) | 1556 | static void xs_tcp_connect_worker4(struct work_struct *work) |
1305 | { | 1557 | { |
1306 | struct sock_xprt *transport = | 1558 | struct sock_xprt *transport = |
1307 | container_of(work, struct sock_xprt, connect_worker.work); | 1559 | container_of(work, struct sock_xprt, connect_worker.work); |
@@ -1315,13 +1567,12 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1315 | if (!sock) { | 1567 | if (!sock) { |
1316 | /* start from scratch */ | 1568 | /* start from scratch */ |
1317 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | 1569 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { |
1318 | dprintk("RPC: can't create TCP transport " | 1570 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); |
1319 | "socket (%d).\n", -err); | ||
1320 | goto out; | 1571 | goto out; |
1321 | } | 1572 | } |
1322 | xs_reclassify_socket(sock); | 1573 | xs_reclassify_socket4(sock); |
1323 | 1574 | ||
1324 | if (xs_bind(transport, sock)) { | 1575 | if (xs_bind4(transport, sock) < 0) { |
1325 | sock_release(sock); | 1576 | sock_release(sock); |
1326 | goto out; | 1577 | goto out; |
1327 | } | 1578 | } |
@@ -1332,43 +1583,70 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1332 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1583 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1333 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1584 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1334 | 1585 | ||
1335 | if (!transport->inet) { | 1586 | status = xs_tcp_finish_connecting(xprt, sock); |
1336 | struct sock *sk = sock->sk; | 1587 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1337 | 1588 | xprt, -status, xprt_connected(xprt), | |
1338 | write_lock_bh(&sk->sk_callback_lock); | 1589 | sock->sk->sk_state); |
1590 | if (status < 0) { | ||
1591 | switch (status) { | ||
1592 | case -EINPROGRESS: | ||
1593 | case -EALREADY: | ||
1594 | goto out_clear; | ||
1595 | case -ECONNREFUSED: | ||
1596 | case -ECONNRESET: | ||
1597 | /* retry with existing socket, after a delay */ | ||
1598 | break; | ||
1599 | default: | ||
1600 | /* get rid of existing socket, and retry */ | ||
1601 | xs_close(xprt); | ||
1602 | break; | ||
1603 | } | ||
1604 | } | ||
1605 | out: | ||
1606 | xprt_wake_pending_tasks(xprt, status); | ||
1607 | out_clear: | ||
1608 | xprt_clear_connecting(xprt); | ||
1609 | } | ||
1339 | 1610 | ||
1340 | sk->sk_user_data = xprt; | 1611 | /** |
1341 | transport->old_data_ready = sk->sk_data_ready; | 1612 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint |
1342 | transport->old_state_change = sk->sk_state_change; | 1613 | * @work: RPC transport to connect |
1343 | transport->old_write_space = sk->sk_write_space; | 1614 | * |
1344 | sk->sk_data_ready = xs_tcp_data_ready; | 1615 | * Invoked by a work queue tasklet. |
1345 | sk->sk_state_change = xs_tcp_state_change; | 1616 | */ |
1346 | sk->sk_write_space = xs_tcp_write_space; | 1617 | static void xs_tcp_connect_worker6(struct work_struct *work) |
1347 | sk->sk_allocation = GFP_ATOMIC; | 1618 | { |
1619 | struct sock_xprt *transport = | ||
1620 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1621 | struct rpc_xprt *xprt = &transport->xprt; | ||
1622 | struct socket *sock = transport->sock; | ||
1623 | int err, status = -EIO; | ||
1348 | 1624 | ||
1349 | /* socket options */ | 1625 | if (xprt->shutdown || !xprt_bound(xprt)) |
1350 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 1626 | goto out; |
1351 | sock_reset_flag(sk, SOCK_LINGER); | ||
1352 | tcp_sk(sk)->linger2 = 0; | ||
1353 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | ||
1354 | 1627 | ||
1355 | xprt_clear_connected(xprt); | 1628 | if (!sock) { |
1629 | /* start from scratch */ | ||
1630 | if ((err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | ||
1631 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | ||
1632 | goto out; | ||
1633 | } | ||
1634 | xs_reclassify_socket6(sock); | ||
1356 | 1635 | ||
1357 | /* Reset to new socket */ | 1636 | if (xs_bind6(transport, sock) < 0) { |
1358 | transport->sock = sock; | 1637 | sock_release(sock); |
1359 | transport->inet = sk; | 1638 | goto out; |
1639 | } | ||
1640 | } else | ||
1641 | /* "close" the socket, preserving the local port */ | ||
1642 | xs_tcp_reuse_connection(xprt); | ||
1360 | 1643 | ||
1361 | write_unlock_bh(&sk->sk_callback_lock); | 1644 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1362 | } | 1645 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1363 | 1646 | ||
1364 | /* Tell the socket layer to start connecting... */ | 1647 | status = xs_tcp_finish_connecting(xprt, sock); |
1365 | xprt->stat.connect_count++; | ||
1366 | xprt->stat.connect_start = jiffies; | ||
1367 | status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, | ||
1368 | xprt->addrlen, O_NONBLOCK); | ||
1369 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 1648 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1370 | xprt, -status, xprt_connected(xprt), | 1649 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); |
1371 | sock->sk->sk_state); | ||
1372 | if (status < 0) { | 1650 | if (status < 0) { |
1373 | switch (status) { | 1651 | switch (status) { |
1374 | case -EINPROGRESS: | 1652 | case -EINPROGRESS: |
@@ -1508,7 +1786,8 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1508 | .print_stats = xs_tcp_print_stats, | 1786 | .print_stats = xs_tcp_print_stats, |
1509 | }; | 1787 | }; |
1510 | 1788 | ||
1511 | static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size) | 1789 | static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, |
1790 | unsigned int slot_table_size) | ||
1512 | { | 1791 | { |
1513 | struct rpc_xprt *xprt; | 1792 | struct rpc_xprt *xprt; |
1514 | struct sock_xprt *new; | 1793 | struct sock_xprt *new; |
@@ -1549,8 +1828,9 @@ static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned | |||
1549 | * @args: rpc transport creation arguments | 1828 | * @args: rpc transport creation arguments |
1550 | * | 1829 | * |
1551 | */ | 1830 | */ |
1552 | struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | 1831 | struct rpc_xprt *xs_setup_udp(struct xprt_create *args) |
1553 | { | 1832 | { |
1833 | struct sockaddr *addr = args->dstaddr; | ||
1554 | struct rpc_xprt *xprt; | 1834 | struct rpc_xprt *xprt; |
1555 | struct sock_xprt *transport; | 1835 | struct sock_xprt *transport; |
1556 | 1836 | ||
@@ -1559,15 +1839,11 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
1559 | return xprt; | 1839 | return xprt; |
1560 | transport = container_of(xprt, struct sock_xprt, xprt); | 1840 | transport = container_of(xprt, struct sock_xprt, xprt); |
1561 | 1841 | ||
1562 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) | ||
1563 | xprt_set_bound(xprt); | ||
1564 | |||
1565 | xprt->prot = IPPROTO_UDP; | 1842 | xprt->prot = IPPROTO_UDP; |
1566 | xprt->tsh_size = 0; | 1843 | xprt->tsh_size = 0; |
1567 | /* XXX: header size can vary due to auth type, IPv6, etc. */ | 1844 | /* XXX: header size can vary due to auth type, IPv6, etc. */ |
1568 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); | 1845 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); |
1569 | 1846 | ||
1570 | INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker); | ||
1571 | xprt->bind_timeout = XS_BIND_TO; | 1847 | xprt->bind_timeout = XS_BIND_TO; |
1572 | xprt->connect_timeout = XS_UDP_CONN_TO; | 1848 | xprt->connect_timeout = XS_UDP_CONN_TO; |
1573 | xprt->reestablish_timeout = XS_UDP_REEST_TO; | 1849 | xprt->reestablish_timeout = XS_UDP_REEST_TO; |
@@ -1580,11 +1856,37 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
1580 | else | 1856 | else |
1581 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | 1857 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); |
1582 | 1858 | ||
1583 | xs_format_peer_addresses(xprt); | 1859 | switch (addr->sa_family) { |
1860 | case AF_INET: | ||
1861 | if (((struct sockaddr_in *)addr)->sin_port != htons(0)) | ||
1862 | xprt_set_bound(xprt); | ||
1863 | |||
1864 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
1865 | xs_udp_connect_worker4); | ||
1866 | xs_format_ipv4_peer_addresses(xprt); | ||
1867 | break; | ||
1868 | case AF_INET6: | ||
1869 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | ||
1870 | xprt_set_bound(xprt); | ||
1871 | |||
1872 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
1873 | xs_udp_connect_worker6); | ||
1874 | xs_format_ipv6_peer_addresses(xprt); | ||
1875 | break; | ||
1876 | default: | ||
1877 | kfree(xprt); | ||
1878 | return ERR_PTR(-EAFNOSUPPORT); | ||
1879 | } | ||
1880 | |||
1584 | dprintk("RPC: set up transport to address %s\n", | 1881 | dprintk("RPC: set up transport to address %s\n", |
1585 | xprt->address_strings[RPC_DISPLAY_ALL]); | 1882 | xprt->address_strings[RPC_DISPLAY_ALL]); |
1586 | 1883 | ||
1587 | return xprt; | 1884 | if (try_module_get(THIS_MODULE)) |
1885 | return xprt; | ||
1886 | |||
1887 | kfree(xprt->slot); | ||
1888 | kfree(xprt); | ||
1889 | return ERR_PTR(-EINVAL); | ||
1588 | } | 1890 | } |
1589 | 1891 | ||
1590 | /** | 1892 | /** |
@@ -1592,8 +1894,9 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
1592 | * @args: rpc transport creation arguments | 1894 | * @args: rpc transport creation arguments |
1593 | * | 1895 | * |
1594 | */ | 1896 | */ |
1595 | struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | 1897 | struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) |
1596 | { | 1898 | { |
1899 | struct sockaddr *addr = args->dstaddr; | ||
1597 | struct rpc_xprt *xprt; | 1900 | struct rpc_xprt *xprt; |
1598 | struct sock_xprt *transport; | 1901 | struct sock_xprt *transport; |
1599 | 1902 | ||
@@ -1602,14 +1905,10 @@ struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | |||
1602 | return xprt; | 1905 | return xprt; |
1603 | transport = container_of(xprt, struct sock_xprt, xprt); | 1906 | transport = container_of(xprt, struct sock_xprt, xprt); |
1604 | 1907 | ||
1605 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) | ||
1606 | xprt_set_bound(xprt); | ||
1607 | |||
1608 | xprt->prot = IPPROTO_TCP; | 1908 | xprt->prot = IPPROTO_TCP; |
1609 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | 1909 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); |
1610 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 1910 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
1611 | 1911 | ||
1612 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker); | ||
1613 | xprt->bind_timeout = XS_BIND_TO; | 1912 | xprt->bind_timeout = XS_BIND_TO; |
1614 | xprt->connect_timeout = XS_TCP_CONN_TO; | 1913 | xprt->connect_timeout = XS_TCP_CONN_TO; |
1615 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | 1914 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; |
@@ -1622,15 +1921,55 @@ struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | |||
1622 | else | 1921 | else |
1623 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | 1922 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); |
1624 | 1923 | ||
1625 | xs_format_peer_addresses(xprt); | 1924 | switch (addr->sa_family) { |
1925 | case AF_INET: | ||
1926 | if (((struct sockaddr_in *)addr)->sin_port != htons(0)) | ||
1927 | xprt_set_bound(xprt); | ||
1928 | |||
1929 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker4); | ||
1930 | xs_format_ipv4_peer_addresses(xprt); | ||
1931 | break; | ||
1932 | case AF_INET6: | ||
1933 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | ||
1934 | xprt_set_bound(xprt); | ||
1935 | |||
1936 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker6); | ||
1937 | xs_format_ipv6_peer_addresses(xprt); | ||
1938 | break; | ||
1939 | default: | ||
1940 | kfree(xprt); | ||
1941 | return ERR_PTR(-EAFNOSUPPORT); | ||
1942 | } | ||
1943 | |||
1626 | dprintk("RPC: set up transport to address %s\n", | 1944 | dprintk("RPC: set up transport to address %s\n", |
1627 | xprt->address_strings[RPC_DISPLAY_ALL]); | 1945 | xprt->address_strings[RPC_DISPLAY_ALL]); |
1628 | 1946 | ||
1629 | return xprt; | 1947 | if (try_module_get(THIS_MODULE)) |
1948 | return xprt; | ||
1949 | |||
1950 | kfree(xprt->slot); | ||
1951 | kfree(xprt); | ||
1952 | return ERR_PTR(-EINVAL); | ||
1630 | } | 1953 | } |
1631 | 1954 | ||
1955 | static struct xprt_class xs_udp_transport = { | ||
1956 | .list = LIST_HEAD_INIT(xs_udp_transport.list), | ||
1957 | .name = "udp", | ||
1958 | .owner = THIS_MODULE, | ||
1959 | .ident = IPPROTO_UDP, | ||
1960 | .setup = xs_setup_udp, | ||
1961 | }; | ||
1962 | |||
1963 | static struct xprt_class xs_tcp_transport = { | ||
1964 | .list = LIST_HEAD_INIT(xs_tcp_transport.list), | ||
1965 | .name = "tcp", | ||
1966 | .owner = THIS_MODULE, | ||
1967 | .ident = IPPROTO_TCP, | ||
1968 | .setup = xs_setup_tcp, | ||
1969 | }; | ||
1970 | |||
1632 | /** | 1971 | /** |
1633 | * init_socket_xprt - set up xprtsock's sysctls | 1972 | * init_socket_xprt - set up xprtsock's sysctls, register with RPC client |
1634 | * | 1973 | * |
1635 | */ | 1974 | */ |
1636 | int init_socket_xprt(void) | 1975 | int init_socket_xprt(void) |
@@ -1640,11 +1979,14 @@ int init_socket_xprt(void) | |||
1640 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | 1979 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
1641 | #endif | 1980 | #endif |
1642 | 1981 | ||
1982 | xprt_register_transport(&xs_udp_transport); | ||
1983 | xprt_register_transport(&xs_tcp_transport); | ||
1984 | |||
1643 | return 0; | 1985 | return 0; |
1644 | } | 1986 | } |
1645 | 1987 | ||
1646 | /** | 1988 | /** |
1647 | * cleanup_socket_xprt - remove xprtsock's sysctls | 1989 | * cleanup_socket_xprt - remove xprtsock's sysctls, unregister |
1648 | * | 1990 | * |
1649 | */ | 1991 | */ |
1650 | void cleanup_socket_xprt(void) | 1992 | void cleanup_socket_xprt(void) |
@@ -1655,4 +1997,7 @@ void cleanup_socket_xprt(void) | |||
1655 | sunrpc_table_header = NULL; | 1997 | sunrpc_table_header = NULL; |
1656 | } | 1998 | } |
1657 | #endif | 1999 | #endif |
2000 | |||
2001 | xprt_unregister_transport(&xs_udp_transport); | ||
2002 | xprt_unregister_transport(&xs_tcp_transport); | ||
1658 | } | 2003 | } |