aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c242
1 files changed, 240 insertions, 2 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 62438f3a914d..bee415465754 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -32,6 +32,7 @@
32#include <linux/tcp.h> 32#include <linux/tcp.h>
33#include <linux/sunrpc/clnt.h> 33#include <linux/sunrpc/clnt.h>
34#include <linux/sunrpc/sched.h> 34#include <linux/sunrpc/sched.h>
35#include <linux/sunrpc/svcsock.h>
35#include <linux/sunrpc/xprtsock.h> 36#include <linux/sunrpc/xprtsock.h>
36#include <linux/file.h> 37#include <linux/file.h>
37#ifdef CONFIG_NFS_V4_1 38#ifdef CONFIG_NFS_V4_1
@@ -43,6 +44,7 @@
43#include <net/udp.h> 44#include <net/udp.h>
44#include <net/tcp.h> 45#include <net/tcp.h>
45 46
47#include "sunrpc.h"
46/* 48/*
47 * xprtsock tunables 49 * xprtsock tunables
48 */ 50 */
@@ -2098,6 +2100,134 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
2098 xprt->stat.bklog_u); 2100 xprt->stat.bklog_u);
2099} 2101}
2100 2102
2103/*
2104 * Allocate a bunch of pages for a scratch buffer for the rpc code. The reason
2105 * we allocate pages instead doing a kmalloc like rpc_malloc is because we want
2106 * to use the server side send routines.
2107 */
2108void *bc_malloc(struct rpc_task *task, size_t size)
2109{
2110 struct page *page;
2111 struct rpc_buffer *buf;
2112
2113 BUG_ON(size > PAGE_SIZE - sizeof(struct rpc_buffer));
2114 page = alloc_page(GFP_KERNEL);
2115
2116 if (!page)
2117 return NULL;
2118
2119 buf = page_address(page);
2120 buf->len = PAGE_SIZE;
2121
2122 return buf->data;
2123}
2124
2125/*
2126 * Free the space allocated in the bc_alloc routine
2127 */
2128void bc_free(void *buffer)
2129{
2130 struct rpc_buffer *buf;
2131
2132 if (!buffer)
2133 return;
2134
2135 buf = container_of(buffer, struct rpc_buffer, data);
2136 free_page((unsigned long)buf);
2137}
2138
2139/*
2140 * Use the svc_sock to send the callback. Must be called with svsk->sk_mutex
2141 * held. Borrows heavily from svc_tcp_sendto and xs_tcp_send_request.
2142 */
2143static int bc_sendto(struct rpc_rqst *req)
2144{
2145 int len;
2146 struct xdr_buf *xbufp = &req->rq_snd_buf;
2147 struct rpc_xprt *xprt = req->rq_xprt;
2148 struct sock_xprt *transport =
2149 container_of(xprt, struct sock_xprt, xprt);
2150 struct socket *sock = transport->sock;
2151 unsigned long headoff;
2152 unsigned long tailoff;
2153
2154 /*
2155 * Set up the rpc header and record marker stuff
2156 */
2157 xs_encode_tcp_record_marker(xbufp);
2158
2159 tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK;
2160 headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK;
2161 len = svc_send_common(sock, xbufp,
2162 virt_to_page(xbufp->head[0].iov_base), headoff,
2163 xbufp->tail[0].iov_base, tailoff);
2164
2165 if (len != xbufp->len) {
2166 printk(KERN_NOTICE "Error sending entire callback!\n");
2167 len = -EAGAIN;
2168 }
2169
2170 return len;
2171}
2172
2173/*
2174 * The send routine. Borrows from svc_send
2175 */
2176static int bc_send_request(struct rpc_task *task)
2177{
2178 struct rpc_rqst *req = task->tk_rqstp;
2179 struct svc_xprt *xprt;
2180 struct svc_sock *svsk;
2181 u32 len;
2182
2183 dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid));
2184 /*
2185 * Get the server socket associated with this callback xprt
2186 */
2187 xprt = req->rq_xprt->bc_xprt;
2188 svsk = container_of(xprt, struct svc_sock, sk_xprt);
2189
2190 /*
2191 * Grab the mutex to serialize data as the connection is shared
2192 * with the fore channel
2193 */
2194 if (!mutex_trylock(&xprt->xpt_mutex)) {
2195 rpc_sleep_on(&xprt->xpt_bc_pending, task, NULL);
2196 if (!mutex_trylock(&xprt->xpt_mutex))
2197 return -EAGAIN;
2198 rpc_wake_up_queued_task(&xprt->xpt_bc_pending, task);
2199 }
2200 if (test_bit(XPT_DEAD, &xprt->xpt_flags))
2201 len = -ENOTCONN;
2202 else
2203 len = bc_sendto(req);
2204 mutex_unlock(&xprt->xpt_mutex);
2205
2206 if (len > 0)
2207 len = 0;
2208
2209 return len;
2210}
2211
2212/*
2213 * The close routine. Since this is client initiated, we do nothing
2214 */
2215
2216static void bc_close(struct rpc_xprt *xprt)
2217{
2218 return;
2219}
2220
2221/*
2222 * The xprt destroy routine. Again, because this connection is client
2223 * initiated, we do nothing
2224 */
2225
2226static void bc_destroy(struct rpc_xprt *xprt)
2227{
2228 return;
2229}
2230
2101static struct rpc_xprt_ops xs_udp_ops = { 2231static struct rpc_xprt_ops xs_udp_ops = {
2102 .set_buffer_size = xs_udp_set_buffer_size, 2232 .set_buffer_size = xs_udp_set_buffer_size,
2103 .reserve_xprt = xprt_reserve_xprt_cong, 2233 .reserve_xprt = xprt_reserve_xprt_cong,
@@ -2134,6 +2264,22 @@ static struct rpc_xprt_ops xs_tcp_ops = {
2134 .print_stats = xs_tcp_print_stats, 2264 .print_stats = xs_tcp_print_stats,
2135}; 2265};
2136 2266
2267/*
2268 * The rpc_xprt_ops for the server backchannel
2269 */
2270
2271static struct rpc_xprt_ops bc_tcp_ops = {
2272 .reserve_xprt = xprt_reserve_xprt,
2273 .release_xprt = xprt_release_xprt,
2274 .buf_alloc = bc_malloc,
2275 .buf_free = bc_free,
2276 .send_request = bc_send_request,
2277 .set_retrans_timeout = xprt_set_retrans_timeout_def,
2278 .close = bc_close,
2279 .destroy = bc_destroy,
2280 .print_stats = xs_tcp_print_stats,
2281};
2282
2137static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, 2283static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
2138 unsigned int slot_table_size) 2284 unsigned int slot_table_size)
2139{ 2285{
@@ -2322,11 +2468,93 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
2322 return ERR_PTR(-EINVAL); 2468 return ERR_PTR(-EINVAL);
2323} 2469}
2324 2470
2471/**
2472 * xs_setup_bc_tcp - Set up transport to use a TCP backchannel socket
2473 * @args: rpc transport creation arguments
2474 *
2475 */
2476static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
2477{
2478 struct sockaddr *addr = args->dstaddr;
2479 struct rpc_xprt *xprt;
2480 struct sock_xprt *transport;
2481 struct svc_sock *bc_sock;
2482
2483 if (!args->bc_xprt)
2484 ERR_PTR(-EINVAL);
2485
2486 xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
2487 if (IS_ERR(xprt))
2488 return xprt;
2489 transport = container_of(xprt, struct sock_xprt, xprt);
2490
2491 xprt->prot = IPPROTO_TCP;
2492 xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
2493 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
2494 xprt->timeout = &xs_tcp_default_timeout;
2495
2496 /* backchannel */
2497 xprt_set_bound(xprt);
2498 xprt->bind_timeout = 0;
2499 xprt->connect_timeout = 0;
2500 xprt->reestablish_timeout = 0;
2501 xprt->idle_timeout = 0;
2502
2503 /*
2504 * The backchannel uses the same socket connection as the
2505 * forechannel
2506 */
2507 xprt->bc_xprt = args->bc_xprt;
2508 bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt);
2509 bc_sock->sk_bc_xprt = xprt;
2510 transport->sock = bc_sock->sk_sock;
2511 transport->inet = bc_sock->sk_sk;
2512
2513 xprt->ops = &bc_tcp_ops;
2514
2515 switch (addr->sa_family) {
2516 case AF_INET:
2517 xs_format_peer_addresses(xprt, "tcp",
2518 RPCBIND_NETID_TCP);
2519 break;
2520 case AF_INET6:
2521 xs_format_peer_addresses(xprt, "tcp",
2522 RPCBIND_NETID_TCP6);
2523 break;
2524 default:
2525 kfree(xprt);
2526 return ERR_PTR(-EAFNOSUPPORT);
2527 }
2528
2529 if (xprt_bound(xprt))
2530 dprintk("RPC: set up xprt to %s (port %s) via %s\n",
2531 xprt->address_strings[RPC_DISPLAY_ADDR],
2532 xprt->address_strings[RPC_DISPLAY_PORT],
2533 xprt->address_strings[RPC_DISPLAY_PROTO]);
2534 else
2535 dprintk("RPC: set up xprt to %s (autobind) via %s\n",
2536 xprt->address_strings[RPC_DISPLAY_ADDR],
2537 xprt->address_strings[RPC_DISPLAY_PROTO]);
2538
2539 /*
2540 * Since we don't want connections for the backchannel, we set
2541 * the xprt status to connected
2542 */
2543 xprt_set_connected(xprt);
2544
2545
2546 if (try_module_get(THIS_MODULE))
2547 return xprt;
2548 kfree(xprt->slot);
2549 kfree(xprt);
2550 return ERR_PTR(-EINVAL);
2551}
2552
2325static struct xprt_class xs_udp_transport = { 2553static struct xprt_class xs_udp_transport = {
2326 .list = LIST_HEAD_INIT(xs_udp_transport.list), 2554 .list = LIST_HEAD_INIT(xs_udp_transport.list),
2327 .name = "udp", 2555 .name = "udp",
2328 .owner = THIS_MODULE, 2556 .owner = THIS_MODULE,
2329 .ident = IPPROTO_UDP, 2557 .ident = XPRT_TRANSPORT_UDP,
2330 .setup = xs_setup_udp, 2558 .setup = xs_setup_udp,
2331}; 2559};
2332 2560
@@ -2334,10 +2562,18 @@ static struct xprt_class xs_tcp_transport = {
2334 .list = LIST_HEAD_INIT(xs_tcp_transport.list), 2562 .list = LIST_HEAD_INIT(xs_tcp_transport.list),
2335 .name = "tcp", 2563 .name = "tcp",
2336 .owner = THIS_MODULE, 2564 .owner = THIS_MODULE,
2337 .ident = IPPROTO_TCP, 2565 .ident = XPRT_TRANSPORT_TCP,
2338 .setup = xs_setup_tcp, 2566 .setup = xs_setup_tcp,
2339}; 2567};
2340 2568
2569static struct xprt_class xs_bc_tcp_transport = {
2570 .list = LIST_HEAD_INIT(xs_bc_tcp_transport.list),
2571 .name = "tcp NFSv4.1 backchannel",
2572 .owner = THIS_MODULE,
2573 .ident = XPRT_TRANSPORT_BC_TCP,
2574 .setup = xs_setup_bc_tcp,
2575};
2576
2341/** 2577/**
2342 * init_socket_xprt - set up xprtsock's sysctls, register with RPC client 2578 * init_socket_xprt - set up xprtsock's sysctls, register with RPC client
2343 * 2579 *
@@ -2351,6 +2587,7 @@ int init_socket_xprt(void)
2351 2587
2352 xprt_register_transport(&xs_udp_transport); 2588 xprt_register_transport(&xs_udp_transport);
2353 xprt_register_transport(&xs_tcp_transport); 2589 xprt_register_transport(&xs_tcp_transport);
2590 xprt_register_transport(&xs_bc_tcp_transport);
2354 2591
2355 return 0; 2592 return 0;
2356} 2593}
@@ -2370,6 +2607,7 @@ void cleanup_socket_xprt(void)
2370 2607
2371 xprt_unregister_transport(&xs_udp_transport); 2608 xprt_unregister_transport(&xs_udp_transport);
2372 xprt_unregister_transport(&xs_tcp_transport); 2609 xprt_unregister_transport(&xs_tcp_transport);
2610 xprt_unregister_transport(&xs_bc_tcp_transport);
2373} 2611}
2374 2612
2375static int param_set_uint_minmax(const char *val, struct kernel_param *kp, 2613static int param_set_uint_minmax(const char *val, struct kernel_param *kp,