diff options
| -rw-r--r-- | include/linux/sunrpc/msg_prot.h | 1 | ||||
| -rw-r--r-- | include/linux/sunrpc/xprt.h | 3 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 8 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 395 |
4 files changed, 403 insertions, 4 deletions
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h index 77e624883393..c68a147939a6 100644 --- a/include/linux/sunrpc/msg_prot.h +++ b/include/linux/sunrpc/msg_prot.h | |||
| @@ -145,6 +145,7 @@ typedef __be32 rpc_fraghdr; | |||
| 145 | #define RPCBIND_NETID_TCP "tcp" | 145 | #define RPCBIND_NETID_TCP "tcp" |
| 146 | #define RPCBIND_NETID_UDP6 "udp6" | 146 | #define RPCBIND_NETID_UDP6 "udp6" |
| 147 | #define RPCBIND_NETID_TCP6 "tcp6" | 147 | #define RPCBIND_NETID_TCP6 "tcp6" |
| 148 | #define RPCBIND_NETID_LOCAL "local" | ||
| 148 | 149 | ||
| 149 | /* | 150 | /* |
| 150 | * Note that RFC 1833 does not put any size restrictions on the | 151 | * Note that RFC 1833 does not put any size restrictions on the |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a0f998c07c65..81cce3b3ee66 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
| @@ -141,7 +141,8 @@ enum xprt_transports { | |||
| 141 | XPRT_TRANSPORT_UDP = IPPROTO_UDP, | 141 | XPRT_TRANSPORT_UDP = IPPROTO_UDP, |
| 142 | XPRT_TRANSPORT_TCP = IPPROTO_TCP, | 142 | XPRT_TRANSPORT_TCP = IPPROTO_TCP, |
| 143 | XPRT_TRANSPORT_BC_TCP = IPPROTO_TCP | XPRT_TRANSPORT_BC, | 143 | XPRT_TRANSPORT_BC_TCP = IPPROTO_TCP | XPRT_TRANSPORT_BC, |
| 144 | XPRT_TRANSPORT_RDMA = 256 | 144 | XPRT_TRANSPORT_RDMA = 256, |
| 145 | XPRT_TRANSPORT_LOCAL = 257, | ||
| 145 | }; | 146 | }; |
| 146 | 147 | ||
| 147 | struct rpc_xprt { | 148 | struct rpc_xprt { |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 08ed49629b86..b84d7395535e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -28,7 +28,9 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
| 30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
| 31 | #include <linux/in.h> | ||
| 31 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
| 33 | #include <linux/un.h> | ||
| 32 | 34 | ||
| 33 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
| 34 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
| @@ -294,6 +296,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 294 | * up a string representation of the passed-in address. | 296 | * up a string representation of the passed-in address. |
| 295 | */ | 297 | */ |
| 296 | if (args->servername == NULL) { | 298 | if (args->servername == NULL) { |
| 299 | struct sockaddr_un *sun = | ||
| 300 | (struct sockaddr_un *)args->address; | ||
| 297 | struct sockaddr_in *sin = | 301 | struct sockaddr_in *sin = |
| 298 | (struct sockaddr_in *)args->address; | 302 | (struct sockaddr_in *)args->address; |
| 299 | struct sockaddr_in6 *sin6 = | 303 | struct sockaddr_in6 *sin6 = |
| @@ -301,6 +305,10 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 301 | 305 | ||
| 302 | servername[0] = '\0'; | 306 | servername[0] = '\0'; |
| 303 | switch (args->address->sa_family) { | 307 | switch (args->address->sa_family) { |
| 308 | case AF_LOCAL: | ||
| 309 | snprintf(servername, sizeof(servername), "%s", | ||
| 310 | sun->sun_path); | ||
| 311 | break; | ||
| 304 | case AF_INET: | 312 | case AF_INET: |
| 305 | snprintf(servername, sizeof(servername), "%pI4", | 313 | snprintf(servername, sizeof(servername), "%pI4", |
| 306 | &sin->sin_addr.s_addr); | 314 | &sin->sin_addr.s_addr); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 079366974e1f..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 | ||
| @@ -506,6 +527,60 @@ static inline void xs_encode_stream_record_marker(struct xdr_buf *buf) | |||
| 506 | } | 527 | } |
| 507 | 528 | ||
| 508 | /** | 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; | ||
