[pnfs] [PATCH 06/10] nfs41: New backchannel_rqst.c file.
Ricardo Labiaga
ricardo.labiaga at netapp.com
Wed Jan 2 19:01:47 EST 2008
This file contains the code to setup the callback xprt on the client side.
It allocates/ destroys the preallocated memory structures used to process
backchannel requests. Since callbacks are not expected to cause significant
latency, only one callback is handled at a time.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga at netapp.com>
---
net/sunrpc/backchannel_rqst.c | 133 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 133 insertions(+), 0 deletions(-)
create mode 100644 net/sunrpc/backchannel_rqst.c
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
new file mode 100644
index 0000000..5eff7a2
--- /dev/null
+++ b/net/sunrpc/backchannel_rqst.c
@@ -0,0 +1,133 @@
+/*
+ * This file is distributed under GPL. Please see Documentation/COPYING for
+ * details.
+ *
+ * Author: Rahul Iyer <iyer at netapp.com>
+ * Ricardo Labiaga <ricardo.labiaga at netapp.com>
+ */
+
+#include <linux/tcp.h>
+#include <linux/sunrpc/xprt.h>
+
+#ifdef RPC_DEBUG
+# undef RPC_DEBUG_DATA
+# define RPCDBG_FACILITY RPCDBG_TRANS
+#endif
+
+#if defined(CONFIG_NFS_V4_1)
+
+int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
+{
+ struct page *page_priv = NULL, *page_snd = NULL;
+ struct xdr_buf *xbufp = NULL;
+
+ BUG_ON(min_reqs > 1); /* We only prealloate buffers for one slot */
+ dprintk("RPC: setup backchannel transport\n");
+
+ /* Pre-allocate one backchannel rpc_rqst */
+ xprt->bc_rpc_rqst = kmalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
+ if (xprt->bc_rpc_rqst == NULL) {
+ printk(KERN_ERR "Failed to create backchannel rpc_rqst\n");
+ goto out_free;
+ }
+ xprt->bc_rpc_rqst->rq_xprt = xprt;
+
+ /* Preallocate one XDR private buffer */
+ page_priv = alloc_page(GFP_KERNEL);
+ if (page_priv == NULL) {
+ printk(KERN_ERR "Failed to create backchannel priv xbuf\n");
+ goto out_free;
+ }
+ xbufp = &xprt->bc_rpc_rqst->rq_private_buf;
+ xbufp->head[0].iov_base = page_address(page_priv);
+ xbufp->head[0].iov_len = PAGE_SIZE;
+ xbufp->tail[0].iov_len = 0;
+ xbufp->page_len = 0;
+ xbufp->len = PAGE_SIZE;
+ xbufp->buflen = PAGE_SIZE;
+
+ /* Preallocate one XDR send buffer */
+ page_snd = alloc_page(GFP_KERNEL);
+ if (page_snd == NULL) {
+ printk(KERN_ERR "Failed to create backchannel snd xbuf\n");
+ goto out_free;
+ }
+
+ xbufp = &xprt->bc_rpc_rqst->rq_snd_buf;
+ xbufp->head[0].iov_base = page_address(page_snd);
+ xbufp->head[0].iov_len = 0;
+ xbufp->tail[0].iov_len = 0;
+ xbufp->page_len = 0;
+ xbufp->len = 0;
+ xbufp->buflen = PAGE_SIZE;
+
+ dprintk("RPC: setup backchannel transport done\n");
+ return 0;
+
+out_free:
+ kfree(page_snd);
+ kfree(page_priv);
+ kfree(xprt->bc_rpc_rqst);
+
+ dprintk("RPC: setup backchannel transport failed\n");
+ return -1;
+}
+EXPORT_SYMBOL(xprt_setup_backchannel);
+
+void xprt_destroy_backchannel(struct rpc_xprt *xprt)
+{
+ struct rpc_rqst *req = xprt->bc_rpc_rqst;
+ struct xdr_buf *xbufp;
+
+ dprintk("RPC: destroy backchannel transport\n");
+ /*
+ * Any of these can be NULL if the user hit ^C
+ */
+ if (req == NULL)
+ return; /* Nothing to do */
+ xbufp = &req->rq_private_buf;
+ if (xbufp)
+ kfree(xbufp->head[0].iov_base);
+ xbufp = &req->rq_snd_buf;
+ if (xbufp)
+ kfree(xbufp->head[0].iov_base);
+ kfree(xprt->bc_rpc_rqst);
+}
+EXPORT_SYMBOL(xprt_destroy_backchannel);
+
+/*
+ * A single rpc_rqst structure has been preallocated during the backchannel
+ * setup. Buffer space for the send and private XDR buffers has been
+ * preallocated as well. Use xprt_alloc_bc_request to allocate this
+ * space for this request. Use xprt_free_bc_request to return it.
+ *
+ * Returns the rpc_rqst if it's not in use, otherwise NULL.
+ */
+struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
+{
+ struct rpc_rqst *req;
+
+ dprintk("RPC: allocate a backchannel request\n");
+ req = test_and_set_bit(RPC_BC_PREALLOC_IN_USE, &xprt->bc_flags) ?
+ NULL : xprt->bc_rpc_rqst;
+
+ dprintk("RPC: backchannel req=%p\n", req);
+ return req;
+}
+
+/*
+ * Return the preallocated rpc_rqst structure and XDR buffers
+ */
+void xprt_free_bc_request(struct rpc_rqst *req)
+{
+ struct rpc_xprt *xprt = req->rq_xprt;
+ dprintk("RPC: free backchannel req=%p\n", req);
+
+ smp_mb__before_clear_bit();
+ clear_bit(RPC_BC_PREALLOC_IN_USE, &xprt->bc_flags);
+ smp_mb__after_clear_bit();
+
+}
+EXPORT_SYMBOL(xprt_free_bc_request);
+
+#endif /* CONFIG_NFS_V4_1 */
--
1.5.3.3
More information about the pNFS
mailing list