diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-29 14:20:02 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-29 14:20:02 -0400 |
| commit | f1d1c9fa8f360990e263bdcb73e35ab6fbdc41fe (patch) | |
| tree | 91468535e200f890fd532d5cbb50df59035278e0 /net | |
| parent | 2ff55e98d6e662a4887d2c688a4ab2ae510a97df (diff) | |
| parent | 176e21ee2ec89cae8d45cf1a850ea45a45428fb8 (diff) | |
Merge branch 'nfs-for-2.6.40' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'nfs-for-2.6.40' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
SUNRPC: Support for RPC over AF_LOCAL transports
SUNRPC: Remove obsolete comment
SUNRPC: Use AF_LOCAL for rpcbind upcalls
SUNRPC: Clean up use of curly braces in switch cases
NFS: Revert NFSROOT default mount options
SUNRPC: Rename xs_encode_tcp_fragment_header()
nfs,rcu: convert call_rcu(nfs_free_delegation_callback) to kfree_rcu()
nfs41: Correct offset for LAYOUTCOMMIT
NFS: nfs_update_inode: print current and new inode size in debug output
NFSv4.1: Fix the handling of NFS4ERR_SEQ_MISORDERED errors
NFSv4: Handle expired stateids when the lease is still valid
SUNRPC: Deal with the lack of a SYN_SENT sk->sk_state_change callback...
Diffstat (limited to 'net')
| -rw-r--r-- | net/sunrpc/clnt.c | 29 | ||||
| -rw-r--r-- | net/sunrpc/rpcb_clnt.c | 97 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 435 |
4 files changed, 518 insertions, 45 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 8d83f9d48713..b84d7395535e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -13,10 +13,6 @@ | |||
| 13 | * and need to be refreshed, or when a packet was damaged in transit. | 13 | * and need to be refreshed, or when a packet was damaged in transit. |
| 14 | * This may be have to be moved to the VFS layer. | 14 | * This may be have to be moved to the VFS layer. |
| 15 | * | 15 | * |
| 16 | * NB: BSD uses a more intelligent approach to guessing when a request | ||
| 17 | * or reply has been lost by keeping the RTO estimate for each procedure. | ||
| 18 | * We currently make do with a constant timeout value. | ||
| 19 | * | ||
| 20 | * Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com> | 16 | * Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com> |
| 21 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> | 17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> |
| 22 | */ | 18 | */ |
| @@ -32,7 +28,9 @@ | |||
| 32 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 33 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
| 34 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
| 31 | #include <linux/in.h> | ||
| 35 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
| 33 | #include <linux/un.h> | ||
| 36 | 34 | ||
| 37 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
| 38 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
| @@ -298,22 +296,27 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 298 | * up a string representation of the passed-in address. | 296 | * up a string representation of the passed-in address. |
| 299 | */ | 297 | */ |
| 300 | if (args->servername == NULL) { | 298 | if (args->servername == NULL) { |
| 299 | struct sockaddr_un *sun = | ||
| 300 | (struct sockaddr_un *)args->address; | ||
| 301 | struct sockaddr_in *sin = | ||
| 302 | (struct sockaddr_in *)args->address; | ||
| 303 | struct sockaddr_in6 *sin6 = | ||
| 304 | (struct sockaddr_in6 *)args->address; | ||
| 305 | |||
| 301 | servername[0] = '\0'; | 306 | servername[0] = '\0'; |
| 302 | switch (args->address->sa_family) { | 307 | switch (args->address->sa_family) { |
| 303 | case AF_INET: { | 308 | case AF_LOCAL: |
| 304 | struct sockaddr_in *sin = | 309 | snprintf(servername, sizeof(servername), "%s", |
| 305 | (struct sockaddr_in *)args->address; | 310 | sun->sun_path); |
| 311 | break; | ||
| 312 | case AF_INET: | ||
| 306 | snprintf(servername, sizeof(servername), "%pI4", | 313 | snprintf(servername, sizeof(servername), "%pI4", |
| 307 | &sin->sin_addr.s_addr); | 314 | &sin->sin_addr.s_addr); |
| 308 | break; | 315 | break; |
| 309 | } | 316 | case AF_INET6: |
| 310 | case AF_INET6: { | ||
| 311 | struct sockaddr_in6 *sin = | ||
| 312 | (struct sockaddr_in6 *)args->address; | ||
| 313 | snprintf(servername, sizeof(servername), "%pI6", | 317 | snprintf(servername, sizeof(servername), "%pI6", |
| 314 | &sin->sin6_addr); | 318 | &sin6->sin6_addr); |
| 315 | break; | 319 | break; |
| 316 | } | ||
| 317 | default: | 320 | default: |
| 318 | /* caller wants default server name, but | 321 | /* caller wants default server name, but |
| 319 | * address family isn't recognized. */ | 322 | * address family isn't recognized. */ |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index c652e4cc9fe9..9a80a922c527 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <linux/socket.h> | 18 | #include <linux/socket.h> |
| 19 | #include <linux/un.h> | ||
| 19 | #include <linux/in.h> | 20 | #include <linux/in.h> |
| 20 | #include <linux/in6.h> | 21 | #include <linux/in6.h> |
| 21 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
| @@ -32,6 +33,8 @@ | |||
| 32 | # define RPCDBG_FACILITY RPCDBG_BIND | 33 | # define RPCDBG_FACILITY RPCDBG_BIND |
| 33 | #endif | 34 | #endif |
| 34 | 35 | ||
| 36 | #define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock" | ||
| 37 | |||
| 35 | #define RPCBIND_PROGRAM (100000u) | 38 | #define RPCBIND_PROGRAM (100000u) |
| 36 | #define RPCBIND_PORT (111u) | 39 | #define RPCBIND_PORT (111u) |
| 37 | 40 | ||
| @@ -158,20 +161,69 @@ static void rpcb_map_release(void *data) | |||
| 158 | kfree(map); | 161 | kfree(map); |
| 159 | } | 162 | } |
| 160 | 163 | ||
| 161 | static const struct sockaddr_in rpcb_inaddr_loopback = { | 164 | /* |
| 162 | .sin_family = AF_INET, | 165 | * Returns zero on success, otherwise a negative errno value |
| 163 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | 166 | * is returned. |
| 164 | .sin_port = htons(RPCBIND_PORT), | 167 | */ |
| 165 | }; | 168 | static int rpcb_create_local_unix(void) |
| 169 | { | ||
| 170 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { | ||
| 171 | .sun_family = AF_LOCAL, | ||
| 172 | .sun_path = RPCBIND_SOCK_PATHNAME, | ||
| 173 | }; | ||
| 174 | struct rpc_create_args args = { | ||
| 175 | .net = &init_net, | ||
| 176 | .protocol = XPRT_TRANSPORT_LOCAL, | ||
| 177 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, | ||
| 178 | .addrsize = sizeof(rpcb_localaddr_rpcbind), | ||
| 179 | .servername = "localhost", | ||
| 180 | .program = &rpcb_program, | ||
| 181 | .version = RPCBVERS_2, | ||
| 182 | .authflavor = RPC_AUTH_NULL, | ||
| 183 | }; | ||
| 184 | struct rpc_clnt *clnt, *clnt4; | ||
| 185 | int result = 0; | ||
| 186 | |||
| 187 | /* | ||
| 188 | * Because we requested an RPC PING at transport creation time, | ||
| 189 | * this works only if the user space portmapper is rpcbind, and | ||
| 190 | * it's listening on AF_LOCAL on the named socket. | ||
| 191 | */ | ||
| 192 | clnt = rpc_create(&args); | ||
| 193 | if (IS_ERR(clnt)) { | ||
| 194 | dprintk("RPC: failed to create AF_LOCAL rpcbind " | ||
| 195 | "client (errno %ld).\n", PTR_ERR(clnt)); | ||
| 196 | result = -PTR_ERR(clnt); | ||
| 197 | goto out; | ||
| 198 | } | ||
| 199 | |||
| 200 | clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); | ||
| 201 | if (IS_ERR(clnt4)) { | ||
| 202 | dprintk("RPC: failed to bind second program to " | ||
| 203 | "rpcbind v4 client (errno %ld).\n", | ||
| 204 | PTR_ERR(clnt4)); | ||
| 205 | clnt4 = NULL; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Protected by rpcb_create_local_mutex */ | ||
| 209 | rpcb_local_clnt = clnt; | ||
| 210 | rpcb_local_clnt4 = clnt4; | ||
| 166 | 211 | ||
| 167 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 212 | out: |
| 213 | return result; | ||
| 214 | } | ||
| 168 | 215 | ||
| 169 | /* | 216 | /* |
| 170 | * Returns zero on success, otherwise a negative errno value | 217 | * Returns zero on success, otherwise a negative errno value |
| 171 | * is returned. | 218 | * is returned. |
| 172 | */ | 219 | */ |
| 173 | static int rpcb_create_local(void) | 220 | static int rpcb_create_local_net(void) |
| 174 | { | 221 | { |
| 222 | static const struct sockaddr_in rpcb_inaddr_loopback = { | ||
| 223 | .sin_family = AF_INET, | ||
| 224 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | ||
| 225 | .sin_port = htons(RPCBIND_PORT), | ||
| 226 | }; | ||
| 175 | struct rpc_create_args args = { | 227 | struct rpc_create_args args = { |
| 176 | .net = &init_net, | 228 | .net = &init_net, |
| 177 | .protocol = XPRT_TRANSPORT_TCP, | 229 | .protocol = XPRT_TRANSPORT_TCP, |
| @@ -186,13 +238,6 @@ static int rpcb_create_local(void) | |||
| 186 | struct rpc_clnt *clnt, *clnt4; | 238 | struct rpc_clnt *clnt, *clnt4; |
| 187 | int result = 0; | 239 | int result = 0; |
| 188 | 240 | ||
| 189 | if (rpcb_local_clnt) | ||
| 190 | return result; | ||
| 191 | |||
| 192 | mutex_lock(&rpcb_create_local_mutex); | ||
| 193 | if (rpcb_local_clnt) | ||
| 194 | goto out; | ||
| 195 | |||
| 196 | clnt = rpc_create(&args); | 241 | clnt = rpc_create(&args); |
| 197 | if (IS_ERR(clnt)) { | 242 | if (IS_ERR(clnt)) { |
| 198 | dprintk("RPC: failed to create local rpcbind " | 243 | dprintk("RPC: failed to create local rpcbind " |
| @@ -214,10 +259,34 @@ static int rpcb_create_local(void) | |||
| 214 | clnt4 = NULL; | 259 | clnt4 = NULL; |
| 215 | } | 260 | } |
| 216 | 261 | ||
| 262 | /* Protected by rpcb_create_local_mutex */ | ||
| 217 | rpcb_local_clnt = clnt; | 263 | rpcb_local_clnt = clnt; |
| 218 | rpcb_local_clnt4 = clnt4; | 264 | rpcb_local_clnt4 = clnt4; |
| 219 | 265 | ||
| 220 | out: | 266 | out: |
| 267 | return result; | ||
| 268 | } | ||
| 269 | |||
| 270 | /* | ||
| 271 | * Returns zero on success, otherwise a negative errno value | ||
| 272 | * is returned. | ||
| 273 | */ | ||
| 274 | static int rpcb_create_local(void) | ||
| 275 | { | ||
| 276 | static DEFINE_MUTEX(rpcb_create_local_mutex); | ||
| 277 | int result = 0; | ||
| 278 | |||
| 279 | if (rpcb_local_clnt) | ||
| 280 | return result; | ||
| 281 | |||
| 282 | mutex_lock(&rpcb_create_local_mutex); | ||
| 283 | if (rpcb_local_clnt) | ||
| 284 | goto out; | ||
| 285 | |||
| 286 | if (rpcb_create_local_unix() != 0) | ||
| 287 | result = rpcb_create_local_net(); | ||
| 288 | |||
| 289 | out: | ||
| 221 | mutex_unlock(&rpcb_create_local_mutex); | 290 | mutex_unlock(&rpcb_create_local_mutex); |
| 222 | return result; | 291 | return result; |
| 223 | } | 292 | } |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 08e05a8ce025..2b90292e9505 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
| @@ -942,6 +942,8 @@ static void svc_unregister(const struct svc_serv *serv) | |||
| 942 | if (progp->pg_vers[i]->vs_hidden) | 942 | if (progp->pg_vers[i]->vs_hidden) |
| 943 | continue; | 943 | continue; |
| 944 | 944 | ||
| 945 | dprintk("svc: attempting to unregister %sv%u\n", | ||
| 946 | progp->pg_name, i); | ||
| 945 | __svc_unregister(progp->pg_prog, i, progp->pg_name); | 947 | __svc_unregister(progp->pg_prog, i, progp->pg_name); |
| 946 | } | 948 | } |
| 947 | } | 949 | } |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index bf005d3c65ef..72abb7358933 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
| 22 | #include <linux/string.h> | ||
| 22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 24 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include <linux/in.h> | 29 | #include <linux/in.h> |
| 29 | #include <linux/net.h> | 30 | #include <linux/net.h> |
| 30 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| 32 | #include <linux/un.h> | ||
| 31 | #include <linux/udp.h> | 33 | #include <linux/udp.h> |
| 32 | #include <linux/tcp.h> | 34 | #include <linux/tcp.h> |
| 33 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
| @@ -45,6 +47,9 @@ | |||
| 45 | #include <net/tcp.h> | 47 | #include <net/tcp.h> |
| 46 | 48 | ||
| 47 | #include "sunrpc.h" | 49 | #include "sunrpc.h" |
| 50 | |||
| 51 | static void xs_close(struct rpc_xprt *xprt); | ||
| 52 | |||
| 48 | /* | 53 | /* |
| 49 | * xprtsock tunables | 54 | * xprtsock tunables |
| 50 | */ | 55 | */ |
| @@ -261,6 +266,11 @@ static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) | |||
| 261 | return (struct sockaddr *) &xprt->addr; | 266 | return (struct sockaddr *) &xprt->addr; |
| 262 | } | 267 | } |
| 263 | 268 | ||
| 269 | static inline struct sockaddr_un *xs_addr_un(struct rpc_xprt *xprt) | ||
| 270 | { | ||
| 271 | return (struct sockaddr_un *) &xprt->addr; | ||
| 272 | } | ||
| 273 | |||
| 264 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) | 274 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) |
| 265 | { | 275 | { |
| 266 | return (struct sockaddr_in *) &xprt->addr; | 276 | return (struct sockaddr_in *) &xprt->addr; |
| @@ -276,23 +286,34 @@ static void xs_format_common_peer_addresses(struct rpc_xprt *xprt) | |||
| 276 | struct sockaddr *sap = xs_addr(xprt); | 286 | struct sockaddr *sap = xs_addr(xprt); |
| 277 | struct sockaddr_in6 *sin6; | 287 | struct sockaddr_in6 *sin6; |
| 278 | struct sockaddr_in *sin; | 288 | struct sockaddr_in *sin; |
| 289 | struct sockaddr_un *sun; | ||
| 279 | char buf[128]; | 290 | char buf[128]; |
| 280 | 291 | ||
| 281 | (void)rpc_ntop(sap, buf, sizeof(buf)); | ||
| 282 | xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL); | ||
| 283 | |||
| 284 | switch (sap->sa_family) { | 292 | switch (sap->sa_family) { |
| 293 | case AF_LOCAL: | ||
| 294 | sun = xs_addr_un(xprt); | ||
| 295 | strlcpy(buf, sun->sun_path, sizeof(buf)); | ||
| 296 | xprt->address_strings[RPC_DISPLAY_ADDR] = | ||
| 297 | kstrdup(buf, GFP_KERNEL); | ||
| 298 | break; | ||
| 285 | case AF_INET: | 299 | case AF_INET: |
| 300 | (void)rpc_ntop(sap, buf, sizeof(buf)); | ||
| 301 | xprt->address_strings[RPC_DISPLAY_ADDR] = | ||
| 302 | kstrdup(buf, GFP_KERNEL); | ||
| 286 | sin = xs_addr_in(xprt); | 303 | sin = xs_addr_in(xprt); |
| 287 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); | 304 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); |
| 288 | break; | 305 | break; |
| 289 | case AF_INET6: | 306 | case AF_INET6: |
| 307 | (void)rpc_ntop(sap, buf, sizeof(buf)); | ||
| 308 | xprt->address_strings[RPC_DISPLAY_ADDR] = | ||
| 309 | kstrdup(buf, GFP_KERNEL); | ||
| 290 | sin6 = xs_addr_in6(xprt); | 310 | sin6 = xs_addr_in6(xprt); |
| 291 | snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); | 311 | snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); |
| 292 | break; | 312 | break; |
| 293 | default: | 313 | default: |
| 294 | BUG(); | 314 | BUG(); |
| 295 | } | 315 | } |
| 316 | |||
| 296 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); | 317 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); |
| 297 | } | 318 | } |
| 298 | 319 | ||
| @@ -495,6 +516,70 @@ static int xs_nospace(struct rpc_task *task) | |||
| 495 | return ret; | 516 | return ret; |
| 496 | } | 517 | } |
| 497 | 518 | ||
| 519 | /* | ||
| 520 | * Construct a stream transport record marker in @buf. | ||
| 521 | */ | ||
| 522 | static inline void xs_encode_stream_record_marker(struct xdr_buf *buf) | ||
| 523 | { | ||
| 524 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | ||
| 525 | rpc_fraghdr *base = buf->head[0].iov_base; | ||
| 526 | *base = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | reclen); | ||
| 527 | } | ||
| 528 | |||
| 529 | /** | ||
| 530 | * xs_local_send_request - write an RPC request to an AF_LOCAL socket | ||
| 531 | * @task: RPC task that manages the state of an RPC request | ||
| 532 | * | ||
| 533 | * Return values: | ||
| 534 | * 0: The request has been sent | ||
| 535 | * EAGAIN: The socket was blocked, please call again later to | ||
| 536 | * complete the request | ||
| 537 | * ENOTCONN: Caller needs to invoke connect logic then call again | ||
| 538 | * other: Some other error occured, the request was not sent | ||
| 539 | */ | ||
| 540 | static int xs_local_send_request(struct rpc_task *task) | ||
| 541 | { | ||
| 542 | struct rpc_rqst *req = task->tk_rqstp; | ||
| 543 | struct rpc_xprt *xprt = req->rq_xprt; | ||
| 544 | struct sock_xprt *transport = | ||
| 545 | container_of(xprt, struct sock_xprt, xprt); | ||
| 546 | struct xdr_buf *xdr = &req->rq_snd_buf; | ||
| 547 | int status; | ||
| 548 | |||
| 549 | xs_encode_stream_record_marker(&req->rq_snd_buf); | ||
| 550 | |||
| 551 | xs_pktdump("packet data:", | ||
| 552 | req->rq_svec->iov_base, req->rq_svec->iov_len); | ||
| 553 | |||
| 554 | status = xs_sendpages(transport->sock, NULL, 0, | ||
| 555 | xdr, req->rq_bytes_sent); | ||
| 556 | dprintk("RPC: %s(%u) = %d\n", | ||
| 557 | __func__, xdr->len - req->rq_bytes_sent, status); | ||
| 558 | if (likely(status >= 0)) { | ||
| 559 | req->rq_bytes_sent += status; | ||
| 560 | req->rq_xmit_bytes_sent += status; | ||
| 561 | if (likely(req->rq_bytes_sent >= req->rq_slen)) { | ||
| 562 | req->rq_bytes_sent = 0; | ||
| 563 | return 0; | ||
| 564 | } | ||
| 565 | status = -EAGAIN; | ||
| 566 | } | ||
| 567 | |||
| 568 | switch (status) { | ||
| 569 | case -EAGAIN: | ||
| 570 | status = xs_nospace(task); | ||
| 571 | break; | ||
| 572 | default: | ||
| 573 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | ||
| 574 | -status); | ||
| 575 | case -EPIPE: | ||
| 576 | xs_close(xprt); | ||
| 577 | status = -ENOTCONN; | ||
| 578 | } | ||
| 579 | |||
| 580 | return status; | ||
| 581 | } | ||
| 582 | |||
| 498 | /** | 583 | /** |
| 499 | * xs_udp_send_request - write an RPC request to a UDP socket | 584 | * xs_udp_send_request - write an RPC request to a UDP socket |
| 500 | * @task: address of RPC task that manages the state of an RPC request | 585 | * @task: address of RPC task that manages the state of an RPC request |
| @@ -574,13 +659,6 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt) | |||
| 574 | kernel_sock_shutdown(sock, SHUT_WR); | 659 | kernel_sock_shutdown(sock, SHUT_WR); |
| 575 | } | 660 | } |
| 576 | 661 | ||
| 577 | static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | ||
| 578 | { | ||
| 579 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | ||
| 580 | rpc_fraghdr *base = buf->head[0].iov_base; | ||
| 581 | *base = htonl(RPC_LAST_STREAM_FRAGMENT | reclen); | ||
| 582 | } | ||
| 583 | |||
| 584 | /** | 662 | /** |
| 585 | * xs_tcp_send_request - write an RPC request to a TCP socket | 663 | * xs_tcp_send_request - write an RPC request to a TCP socket |
| 586 | * @task: address of RPC task that manages the state of an RPC request | 664 | * @task: address of RPC task that manages the state of an RPC request |
| @@ -603,7 +681,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 603 | struct xdr_buf *xdr = &req->rq_snd_buf; | 681 | struct xdr_buf *xdr = &req->rq_snd_buf; |
| 604 | int status; | 682 | int status; |
| 605 | 683 | ||
| 606 | xs_encode_tcp_record_marker(&req->rq_snd_buf); | 684 | xs_encode_stream_record_marker(&req->rq_snd_buf); |
| 607 | 685 | ||
| 608 | xs_pktdump("packet data:", | 686 | xs_pktdump("packet data:", |
| 609 | req->rq_svec->iov_base, | 687 | req->rq_svec->iov_base, |
| @@ -785,6 +863,88 @@ static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | |||
| 785 | return (struct rpc_xprt *) sk->sk_user_data; | 863 | return (struct rpc_xprt *) sk->sk_user_data; |
| 786 | } | 864 | } |
| 787 | 865 | ||
| 866 | static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | ||
| 867 | { | ||
| 868 | struct xdr_skb_reader desc = { | ||
| 869 | .skb = skb, | ||
| 870 | .offset = sizeof(rpc_fraghdr), | ||
| 871 | .count = skb->len - sizeof(rpc_fraghdr), | ||
| 872 | }; | ||
| 873 | |||
| 874 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0) | ||
| 875 | return -1; | ||
| 876 | if (desc.count) | ||
| 877 | return -1; | ||
| 878 | return 0; | ||
| 879 | } | ||
| 880 | |||
| 881 | /** | ||
| 882 | * xs_local_data_ready - "data ready" callback for AF_LOCAL sockets | ||
| 883 | * @sk: socket with data to read | ||
| 884 | * @len: how much data to read | ||
| 885 | * | ||
| 886 | * Currently this assumes we can read the whole reply in a single gulp. | ||
| 887 | */ | ||
| 888 | static void xs_local_data_ready(struct sock *sk, int len) | ||
| 889 | { | ||
| 890 | struct rpc_task *task; | ||
| 891 | struct rpc_xprt *xprt; | ||
| 892 | struct rpc_rqst *rovr; | ||
| 893 | struct sk_buff *skb; | ||
| 894 | int err, repsize, copied; | ||
| 895 | u32 _xid; | ||
| 896 | __be32 *xp; | ||
| 897 | |||
| 898 | read_lock_bh(&sk->sk_callback_lock); | ||
| 899 | dprintk("RPC: %s...\n", __func__); | ||
| 900 | xprt = xprt_from_sock(sk); | ||
| 901 | if (xprt == NULL) | ||
| 902 | goto out; | ||
| 903 | |||
| 904 | skb = skb_recv_datagram(sk, 0, 1, &err); | ||
| 905 | if (skb == NULL) | ||
| 906 | goto out; | ||
| 907 | |||
| 908 | if (xprt->shutdown) | ||
| 909 | goto dropit; | ||
| 910 | |||
| 911 | repsize = skb->len - sizeof(rpc_fraghdr); | ||
| 912 | if (repsize < 4) { | ||
| 913 | dprintk("RPC: impossible RPC reply size %d\n", repsize); | ||
| 914 | goto dropit; | ||
| 915 | } | ||
| 916 | |||
| 917 | /* Copy the XID from the skb... */ | ||
| 918 | xp = skb_header_pointer(skb, sizeof(rpc_fraghdr), sizeof(_xid), &_xid); | ||
| 919 | if (xp == NULL) | ||
| 920 | goto dropit; | ||
| 921 | |||
| 922 | /* Look up and lock the request corresponding to the given XID */ | ||
| 923 | spin_lock(&xprt->transport_lock); | ||
| 924 | rovr = xprt_lookup_rqst(xprt, *xp); | ||
| 925 | if (!rovr) | ||
| 926 | goto out_unlock; | ||
| 927 | task = rovr->rq_task; | ||
| 928 | |||
| 929 | copied = rovr->rq_private_buf.buflen; | ||
| 930 | if (copied > repsize) | ||
| 931 | copied = repsize; | ||
| 932 | |||
| 933 | if (xs_local_copy_to_xdr(&rovr->rq_private_buf, skb)) { | ||
| 934 | dprintk("RPC: sk_buff copy failed\n"); | ||
| 935 | goto out_unlock; | ||
| 936 | } | ||
| 937 | |||
| 938 | xprt_complete_rqst(task, copied); | ||
| 939 | |||
| 940 | out_unlock: | ||
| 941 | spin_unlock(&xprt->transport_lock); | ||
| 942 | dropit: | ||
| 943 | skb_free_datagram(sk, skb); | ||
| 944 | out: | ||
| 945 | read_unlock_bh(&sk->sk_callback_lock); | ||
| 946 | } | ||
| 947 | |||
| 788 | /** | 948 | /** |
| 789 | * xs_udp_data_ready - "data ready" callback for UDP sockets | 949 | * xs_udp_data_ready - "data ready" callback for UDP sockets |
| 790 | * @sk: socket with data to read | 950 | * @sk: socket with data to read |
| @@ -1344,7 +1504,6 @@ static void xs_tcp_state_change(struct sock *sk) | |||
| 1344 | case TCP_CLOSE_WAIT: | 1504 | case TCP_CLOSE_WAIT: |
| 1345 | /* The server initiated a shutdown of the socket */ | 1505 | /* The server initiated a shutdown of the socket */ |
| 1346 | xprt_force_disconnect(xprt); | 1506 | xprt_force_disconnect(xprt); |
| 1347 | case TCP_SYN_SENT: | ||
| 1348 | xprt->connect_cookie++; | 1507 | xprt->connect_cookie++; |
| 1349 | case TCP_CLOSING: | 1508 | case TCP_CLOSING: |
| 1350 | /* | 1509 | /* |
| @@ -1571,11 +1730,31 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
| 1571 | return err; | 1730 | return err; |
| 1572 | } | 1731 | } |
| 1573 | 1732 | ||
| 1733 | /* | ||
| 1734 | * We don't support autobind on AF_LOCAL sockets | ||
| 1735 | */ | ||
| 1736 | static void xs_local_rpcbind(struct rpc_task *task) | ||
| 1737 | { | ||
| 1738 | xprt_set_bound(task->tk_xprt); | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | static void xs_local_set_port(struct rpc_xprt *xprt, unsigned short port) | ||
| 1742 | { | ||
| 1743 | } | ||
| 1574 | 1744 | ||
| 1575 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 1745 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 1576 | static struct lock_class_key xs_key[2]; | 1746 | static struct lock_class_key xs_key[2]; |
| 1577 | static struct lock_class_key xs_slock_key[2]; | 1747 | static struct lock_class_key xs_slock_key[2]; |
| 1578 | 1748 | ||
| 1749 | static inline void xs_reclassify_socketu(struct socket *sock) | ||
| 1750 | { | ||
| 1751 | struct sock *sk = sock->sk; | ||
| 1752 | |||
| 1753 | BUG_ON(sock_owned_by_user(sk)); | ||
| 1754 | sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", | ||
| 1755 | &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); | ||
| 1756 | } | ||
| 1757 | |||
| 1579 | static inline void xs_reclassify_socket4(struct socket *sock) | 1758 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1580 | { | 1759 | { |
| 1581 | struct sock *sk = sock->sk; | 1760 | struct sock *sk = sock->sk; |
| @@ -1597,6 +1776,9 @@ static inline void xs_reclassify_socket6(struct socket *sock) | |||
| 1597 | static inline void xs_reclassify_socket(int family, struct socket *sock) | 1776 | static inline void xs_reclassify_socket(int family, struct socket *sock) |
| 1598 | { | 1777 | { |
| 1599 | switch (family) { | 1778 | switch (family) { |
| 1779 | case AF_LOCAL: | ||
| 1780 | xs_reclassify_socketu(sock); | ||
| 1781 | break; | ||
| 1600 | case AF_INET: | 1782 | case AF_INET: |
| 1601 | xs_reclassify_socket4(sock); | 1783 | xs_reclassify_socket4(sock); |
| 1602 | break; | 1784 | break; |
| @@ -1606,6 +1788,10 @@ static inline void xs_reclassify_socket(int family, struct socket *sock) | |||
| 1606 | } | 1788 | } |
| 1607 | } | 1789 | } |
| 1608 | #else | 1790 | #else |
| 1791 | static inline void xs_reclassify_socketu(struct socket *sock) | ||
| 1792 | { | ||
| 1793 | } | ||
| 1794 | |||
| 1609 | static inline void xs_reclassify_socket4(struct socket *sock) | 1795 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1610 | { | 1796 | { |
| 1611 | } | 1797 | } |
| @@ -1644,6 +1830,94 @@ out: | |||
| 1644 | return ERR_PTR(err); | 1830 | return ERR_PTR(err); |
| 1645 | } | 1831 | } |
| 1646 | 1832 | ||
| 1833 | static int xs_local_finish_connecting(struct rpc_xprt *xprt, | ||
| 1834 | struct socket *sock) | ||
| 1835 | { | ||
| 1836 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, | ||
| 1837 | xprt); | ||
| 1838 | |||
| 1839 | if (!transport->inet) { | ||
| 1840 | struct sock *sk = sock->sk; | ||
| 1841 | |||
| 1842 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1843 | |||
| 1844 | xs_save_old_callbacks(transport, sk); | ||
| 1845 | |||
| 1846 | sk->sk_user_data = xprt; | ||
| 1847 | sk->sk_data_ready = xs_local_data_ready; | ||
| 1848 | sk->sk_write_space = xs_udp_write_space; | ||
| 1849 | sk->sk_error_report = xs_error_report; | ||
| 1850 | sk->sk_allocation = GFP_ATOMIC; | ||
| 1851 | |||
| 1852 | xprt_clear_connected(xprt); | ||
| 1853 | |||
| 1854 | /* Reset to new socket */ | ||
| 1855 | transport->sock = sock; | ||
| 1856 | transport->inet = sk; | ||
| 1857 | |||
| 1858 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | /* Tell the socket layer to start connecting... */ | ||
| 1862 | xprt->stat.connect_count++; | ||
| 1863 | xprt->stat.connect_start = jiffies; | ||
| 1864 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, 0); | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | /** | ||
| 1868 | * xs_local_setup_socket - create AF_LOCAL socket, connect to a local endpoint | ||
| 1869 | * @xprt: RPC transport to connect | ||
| 1870 | * @transport: socket transport to connect | ||
| 1871 | * @create_sock: function to create a socket of the correct type | ||
| 1872 | * | ||
| 1873 | * Invoked by a work queue tasklet. | ||
| 1874 | */ | ||
| 1875 | static void xs_local_setup_socket(struct work_struct *work) | ||
| 1876 | { | ||
| 1877 | struct sock_xprt *transport = | ||
| 1878 | container_of(work, struct sock_xprt, connect_worker.work); | ||
| 1879 | struct rpc_xprt *xprt = &transport->xprt; | ||
| 1880 | struct socket *sock; | ||
| 1881 | int status = -EIO; | ||
| 1882 | |||
| 1883 | if (xprt->shutdown) | ||
| 1884 | goto out; | ||
| 1885 | |||
| 1886 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
| 1887 | status = __sock_create(xprt->xprt_net, AF_LOCAL, | ||
| 1888 | SOCK_STREAM, 0, &sock, 1); | ||
| 1889 | if (status < 0) { | ||
| 1890 | dprintk("RPC: can't create AF_LOCAL " | ||
| 1891 | "transport socket (%d).\n", -status); | ||
| 1892 | goto out; | ||
| 1893 | } | ||
| 1894 | xs_reclassify_socketu(sock); | ||
| 1895 | |||
| 1896 | dprintk("RPC: worker connecting xprt %p via AF_LOCAL to %s\n", | ||
| 1897 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 1898 | |||
| 1899 | status = xs_local_finish_connecting(xprt, sock); | ||
| 1900 | switch (status) { | ||
| 1901 | case 0: | ||
| 1902 | dprintk("RPC: xprt %p connected to %s\n", | ||
| 1903 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 1904 | xprt_set_connected(xprt); | ||
| 1905 | break; | ||
| 1906 | case -ENOENT: | ||
| 1907 | dprintk("RPC: xprt %p: socket %s does not exist\n", | ||
| 1908 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 1909 | break; | ||
| 1910 | default: | ||
| 1911 | printk(KERN_ERR "%s: unhandled error (%d) connecting to %s\n", | ||
| 1912 | __func__, -status, | ||
| 1913 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 1914 | } | ||
| 1915 | |||
| 1916 | out: | ||
| 1917 | xprt_clear_connecting(xprt); | ||
| 1918 | xprt_wake_pending_tasks(xprt, status); | ||
| 1919 | } | ||
| 1920 | |||
| 1647 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 1921 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
| 1648 | { | 1922 | { |
| 1649 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1923 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| @@ -1758,6 +2032,7 @@ static void xs_tcp_reuse_connection(struct sock_xprt *transport) | |||
| 1758 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 2032 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
| 1759 | { | 2033 | { |
| 1760 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 2034 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| 2035 | int ret = -ENOTCONN; | ||
| 1761 | 2036 | ||
| 1762 | if (!transport->inet) { | 2037 | if (!transport->inet) { |
| 1763 | struct sock *sk = sock->sk; | 2038 | struct sock *sk = sock->sk; |
| @@ -1789,12 +2064,22 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
| 1789 | } | 2064 | } |
| 1790 | 2065 | ||
| 1791 | if (!xprt_bound(xprt)) | 2066 | if (!xprt_bound(xprt)) |
| 1792 | return -ENOTCONN; | 2067 | goto out; |
| 1793 | 2068 | ||
| 1794 | /* Tell the socket layer to start connecting... */ | 2069 | /* Tell the socket layer to start connecting... */ |
| 1795 | xprt->stat.connect_count++; | 2070 | xprt->stat.connect_count++; |
| 1796 | xprt->stat.connect_start = jiffies; | 2071 | xprt->stat.connect_start = jiffies; |
| 1797 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); | 2072 | ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); |
| 2073 | switch (ret) { | ||
| 2074 | case 0: | ||
| 2075 | case -EINPROGRESS: | ||
| 2076 | /* SYN_SENT! */ | ||
| 2077 | xprt->connect_cookie++; | ||
| 2078 | if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) | ||
| 2079 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | ||
| 2080 | } | ||
| 2081 | out: | ||
| 2082 | return ret; | ||
| 1798 | } | 2083 | } |
| 1799 | 2084 | ||
| 1800 | /** | 2085 | /** |
| @@ -1917,6 +2202,32 @@ static void xs_connect(struct rpc_task *task) | |||
| 1917 | } | 2202 | } |
| 1918 | 2203 | ||
| 1919 | /** | 2204 | /** |
| 2205 | * xs_local_print_stats - display AF_LOCAL socket-specifc stats | ||
| 2206 | * @xprt: rpc_xprt struct containing statistics | ||
| 2207 | * @seq: output file | ||
| 2208 | * | ||
| 2209 | */ | ||
| 2210 | static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | ||
| 2211 | { | ||
| 2212 | long idle_time = 0; | ||
| 2213 | |||
| 2214 | if (xprt_connected(xprt)) | ||
| 2215 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | ||
| 2216 | |||
| 2217 | seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu " | ||
| 2218 | "%llu %llu\n", | ||
| 2219 | xprt->stat.bind_count, | ||
| 2220 | xprt->stat.connect_count, | ||
| 2221 | xprt->stat.connect_time, | ||
| 2222 | idle_time, | ||
| 2223 | xprt->stat.sends, | ||
| 2224 | xprt->stat.recvs, | ||
| 2225 | xprt->stat.bad_xids, | ||
| 2226 | xprt->stat.req_u, | ||
| 2227 | xprt->stat.bklog_u); | ||
| 2228 | } | ||
| 2229 | |||
| 2230 | /** | ||
| 1920 | * xs_udp_print_stats - display UDP socket-specifc stats | 2231 | * xs_udp_print_stats - display UDP socket-specifc stats |
| 1921 | * @xprt: rpc_xprt struct containing statistics | 2232 | * @xprt: rpc_xprt struct containing statistics |
| 1922 | * @seq: output file | 2233 | * @seq: output file |
| @@ -2014,10 +2325,7 @@ static int bc_sendto(struct rpc_rqst *req) | |||
| 2014 | unsigned long headoff; | 2325 | unsigned long headoff; |
| 2015 | unsigned long tailoff; | 2326 | unsigned long tailoff; |
| 2016 | 2327 | ||
| 2017 | /* | 2328 | xs_encode_stream_record_marker(xbufp); |
| 2018 | * Set up the rpc header and record marker stuff | ||
| 2019 | */ | ||
| 2020 | xs_encode_tcp_record_marker(xbufp); | ||
| 2021 | 2329 | ||
| 2022 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; | 2330 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; |
| 2023 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; | 2331 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; |
| @@ -2089,6 +2397,21 @@ static void bc_destroy(struct rpc_xprt *xprt) | |||
| 2089 | { | 2397 | { |
| 2090 | } | 2398 | } |
| 2091 | 2399 | ||
| 2400 | static struct rpc_xprt_ops xs_local_ops = { | ||
| 2401 | .reserve_xprt = xprt_reserve_xprt, | ||
| 2402 | .release_xprt = xs_tcp_release_xprt, | ||
| 2403 | .rpcbind = xs_local_rpcbind, | ||
| 2404 | .set_port = xs_local_set_port, | ||
| 2405 | .connect = xs_connect, | ||
| 2406 | .buf_alloc = rpc_malloc, | ||
| 2407 | .buf_free = rpc_free, | ||
| 2408 | .send_request = xs_local_send_request, | ||
| 2409 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | ||
| 2410 | .close = xs_close, | ||
| 2411 | .destroy = xs_destroy, | ||
| 2412 | .print_stats = xs_local_print_stats, | ||
| 2413 | }; | ||
| 2414 | |||
| 2092 | static struct rpc_xprt_ops xs_udp_ops = { | 2415 | static struct rpc_xprt_ops xs_udp_ops = { |
| 2093 | .set_buffer_size = xs_udp_set_buffer_size, | 2416 | .set_buffer_size = xs_udp_set_buffer_size, |
| 2094 | .reserve_xprt = xprt_reserve_xprt_cong, | 2417 | .reserve_xprt = xprt_reserve_xprt_cong, |
| @@ -2150,6 +2473,8 @@ static int xs_init_anyaddr(const int family, struct sockaddr *sap) | |||
| 2150 | }; | 2473 | }; |
| 2151 | 2474 | ||
| 2152 | switch (family) { | 2475 | switch (family) { |
| 2476 | case AF_LOCAL: | ||
| 2477 | break; | ||
| 2153 | case AF_INET: | 2478 | case AF_INET: |
| 2154 | memcpy(sap, &sin, sizeof(sin)); | 2479 | memcpy(sap, &sin, sizeof(sin)); |
| 2155 | break; | 2480 | break; |
| @@ -2197,6 +2522,70 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, | |||
| 2197 | return xprt; | 2522 | return xprt; |
| 2198 | } | 2523 | } |
| 2199 | 2524 | ||
| 2525 | static const struct rpc_timeout xs_local_default_timeout = { | ||
| 2526 | .to_initval = 10 * HZ, | ||
| 2527 | .to_maxval = 10 * HZ, | ||
| 2528 | .to_retries = 2, | ||
| 2529 | }; | ||
| 2530 | |||
| 2531 | /** | ||
| 2532 | * xs_setup_local - Set up transport to use an AF_LOCAL socket | ||
| 2533 | * @args: rpc transport creation arguments | ||
| 2534 | * | ||
| 2535 | * AF_LOCAL is a "tpi_cots_ord" transport, just like TCP | ||
| 2536 | */ | ||
| 2537 | static struct rpc_xprt *xs_setup_local(struct xprt_create *args) | ||
| 2538 | { | ||
| 2539 | struct sockaddr_un *sun = (struct sockaddr_un *)args->dstaddr; | ||
| 2540 | struct sock_xprt *transport; | ||
| 2541 | struct rpc_xprt *xprt; | ||
| 2542 | struct rpc_xprt *ret; | ||
| 2543 | |||
| 2544 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); | ||
| 2545 | if (IS_ERR(xprt)) | ||
| 2546 | return xprt; | ||
| 2547 | transport = container_of(xprt, struct sock_xprt, xprt); | ||
| 2548 | |||
| 2549 | xprt->prot = 0; | ||
| 2550 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | ||
| 2551 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | ||
| 2552 | |||
| 2553 | xprt->bind_timeout = XS_BIND_TO; | ||
| 2554 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | ||
| 2555 | xprt->idle_timeout = XS_IDLE_DISC_TO; | ||
| 2556 | |||
| 2557 | xprt->ops = &xs_local_ops; | ||
| 2558 | xprt->timeout = &xs_local_default_timeout; | ||
| 2559 | |||
| 2560 | switch (sun->sun_family) { | ||
| 2561 | case AF_LOCAL: | ||
| 2562 | if (sun->sun_path[0] != '/') { | ||
| 2563 | dprintk("RPC: bad AF_LOCAL address: %s\n", | ||
| 2564 | sun->sun_path); | ||
| 2565 | ret = ERR_PTR(-EINVAL); | ||
| 2566 | goto out_err; | ||
| 2567 | } | ||
| 2568 | xprt_set_bound(xprt); | ||
| 2569 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
| 2570 | xs_local_setup_socket); | ||
| 2571 | xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL); | ||
| 2572 | break; | ||
| 2573 | default: | ||
| 2574 | ret = ERR_PTR(-EAFNOSUPPORT); | ||
| 2575 | goto out_err; | ||
| 2576 | } | ||
| 2577 | |||
| 2578 | dprintk("RPC: set up xprt to %s via AF_LOCAL\n", | ||
| 2579 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 2580 | |||
| 2581 | if (try_module_get(THIS_MODULE)) | ||
| 2582 | return xprt; | ||
| 2583 | ret = ERR_PTR(-EINVAL); | ||
| 2584 | out_err: | ||
| 2585 | xprt_free(xprt); | ||
| 2586 | return ret; | ||
| 2587 | } | ||
| 2588 | |||
| 2200 | static const struct rpc_timeout xs_udp_default_timeout = { | 2589 | static const struct rpc_timeout xs_udp_default_timeout = { |
| 2201 | .to_initval = 5 * HZ, | 2590 | .to_initval = 5 * HZ, |
| 2202 | .to_maxval = 30 * HZ, | 2591 | .to_maxval = 30 * HZ, |
| @@ -2438,6 +2827,14 @@ out_err: | |||
| 2438 | return ret; | 2827 | return ret; |
| 2439 | } | 2828 | } |
| 2440 | 2829 | ||
| 2830 | static struct xprt_class xs_local_transport = { | ||
| 2831 | .list = LIST_HEAD_INIT(xs_local_transport.list), | ||
| 2832 | .name = "named UNIX socket", | ||
| 2833 | .owner = THIS_MODULE, | ||
| 2834 | .ident = XPRT_TRANSPORT_LOCAL, | ||
| 2835 | .setup = xs_setup_local, | ||
| 2836 | }; | ||
| 2837 | |||
| 2441 | static struct xprt_class xs_udp_transport = { | 2838 | static struct xprt_class xs_udp_transport = { |
| 2442 | .list = LIST_HEAD_INIT(xs_udp_transport.list), | 2839 | .list = LIST_HEAD_INIT(xs_udp_transport.list), |
| 2443 | .name = "udp", | 2840 | .name = "udp", |
| @@ -2473,6 +2870,7 @@ int init_socket_xprt(void) | |||
| 2473 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | 2870 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
| 2474 | #endif | 2871 | #endif |
| 2475 | 2872 | ||
| 2873 | xprt_register_transport(&xs_local_transport); | ||
| 2476 | xprt_register_transport(&xs_udp_transport); | 2874 | xprt_register_transport(&xs_udp_transport); |
| 2477 | xprt_register_transport(&xs_tcp_transport); | 2875 | xprt_register_transport(&xs_tcp_transport); |
| 2478 | xprt_register_transport(&xs_bc_tcp_transport); | 2876 | xprt_register_transport(&xs_bc_tcp_transport); |
| @@ -2493,6 +2891,7 @@ void cleanup_socket_xprt(void) | |||
| 2493 | } | 2891 | } |
| 2494 | #endif | 2892 | #endif |
| 2495 | 2893 | ||
| 2894 | xprt_unregister_transport(&xs_local_transport); | ||
| 2496 | xprt_unregister_transport(&xs_udp_transport); | 2895 | xprt_unregister_transport(&xs_udp_transport); |
| 2497 | xprt_unregister_transport(&xs_tcp_transport); | 2896 | xprt_unregister_transport(&xs_tcp_transport); |
| 2498 | xprt_unregister_transport(&xs_bc_tcp_transport); | 2897 | xprt_unregister_transport(&xs_bc_tcp_transport); |
