aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorRahul Iyer <iyer@netapp.com>2009-09-10 10:32:28 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-09-11 15:04:16 -0400
commit4cfc7e6019caa3e97d2a81c48c8d575d7b38d751 (patch)
tree8dced61360d385b115da94f9a4fd5f8d635c296d /net/sunrpc/xprtsock.c
parent6951867b9967066eda090f46ad91ce69e0ead611 (diff)
nfsd41: sunrpc: Added rpc server-side backchannel handling
When the call direction is a reply, copy the xid and call direction into the req->rq_private_buf.head[0].iov_base otherwise rpc_verify_header returns rpc_garbage. Signed-off-by: Rahul Iyer <iyer@netapp.com> Signed-off-by: Mike Sager <sager@netapp.com> Signed-off-by: Marc Eshel <eshel@almaden.ibm.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com> Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [get rid of CONFIG_NFSD_V4_1] [sunrpc: refactoring of svc_tcp_recvfrom] [nfsd41: sunrpc: create common send routine for the fore and the back channels] [nfsd41: sunrpc: Use free_page() to free server backchannel pages] [nfsd41: sunrpc: Document server backchannel locking] [nfsd41: sunrpc: remove bc_connect_worker()] [nfsd41: sunrpc: Define xprt_server_backchannel()[ [nfsd41: sunrpc: remove bc_close and bc_init_auto_disconnect dummy functions] [nfsd41: sunrpc: eliminate unneeded switch statement in xs_setup_tcp()] [nfsd41: sunrpc: Don't auto close the server backchannel connection] [nfsd41: sunrpc: Remove unused functions] Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfsd41: change bc_sock to bc_xprt] [nfsd41: sunrpc: move struct rpc_buffer def into a common header file] [nfsd41: sunrpc: use rpc_sleep in bc_send_request so not to block on mutex] [removed cosmetic changes] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [sunrpc: add new xprt class for nfsv4.1 backchannel] [sunrpc: v2.1 change handling of auto_close and init_auto_disconnect operations for the nfsv4.1 backchannel] Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> [reverted more cosmetic leftovers] [got rid of xprt_server_backchannel] [separated "nfsd41: sunrpc: add new xprt class for nfsv4.1 backchannel"] Signed-off-by: Benny Halevy <bhalevy@panasas.com> Cc: Trond Myklebust <trond.myklebust@netapp.com> [sunrpc: change idle timeout value for the backchannel] Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Acked-by: Trond Myklebust <trond.myklebust@netapp.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 62438f3a914d..d9a2b815714e 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{