|
@@ -67,6 +67,55 @@ static void xprt_free_allocation(struct rpc_rqst *req)
|
|
kfree(req);
|
|
kfree(req);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int xprt_alloc_xdr_buf(struct xdr_buf *buf, gfp_t gfp_flags)
|
|
|
|
+{
|
|
|
|
+ struct page *page;
|
|
|
|
+ /* Preallocate one XDR receive buffer */
|
|
|
|
+ page = alloc_page(gfp_flags);
|
|
|
|
+ if (page == NULL)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ buf->head[0].iov_base = page_address(page);
|
|
|
|
+ buf->head[0].iov_len = PAGE_SIZE;
|
|
|
|
+ buf->tail[0].iov_base = NULL;
|
|
|
|
+ buf->tail[0].iov_len = 0;
|
|
|
|
+ buf->page_len = 0;
|
|
|
|
+ buf->len = 0;
|
|
|
|
+ buf->buflen = PAGE_SIZE;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static
|
|
|
|
+struct rpc_rqst *xprt_alloc_bc_req(struct rpc_xprt *xprt, gfp_t gfp_flags)
|
|
|
|
+{
|
|
|
|
+ struct rpc_rqst *req;
|
|
|
|
+
|
|
|
|
+ /* Pre-allocate one backchannel rpc_rqst */
|
|
|
|
+ req = kzalloc(sizeof(*req), gfp_flags);
|
|
|
|
+ if (req == NULL)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ req->rq_xprt = xprt;
|
|
|
|
+ INIT_LIST_HEAD(&req->rq_list);
|
|
|
|
+ INIT_LIST_HEAD(&req->rq_bc_list);
|
|
|
|
+
|
|
|
|
+ /* Preallocate one XDR receive buffer */
|
|
|
|
+ if (xprt_alloc_xdr_buf(&req->rq_rcv_buf, gfp_flags) < 0) {
|
|
|
|
+ printk(KERN_ERR "Failed to create bc receive xbuf\n");
|
|
|
|
+ goto out_free;
|
|
|
|
+ }
|
|
|
|
+ req->rq_rcv_buf.len = PAGE_SIZE;
|
|
|
|
+
|
|
|
|
+ /* Preallocate one XDR send buffer */
|
|
|
|
+ if (xprt_alloc_xdr_buf(&req->rq_snd_buf, gfp_flags) < 0) {
|
|
|
|
+ printk(KERN_ERR "Failed to create bc snd xbuf\n");
|
|
|
|
+ goto out_free;
|
|
|
|
+ }
|
|
|
|
+ return req;
|
|
|
|
+out_free:
|
|
|
|
+ xprt_free_allocation(req);
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Preallocate up to min_reqs structures and related buffers for use
|
|
* Preallocate up to min_reqs structures and related buffers for use
|
|
* by the backchannel. This function can be called multiple times
|
|
* by the backchannel. This function can be called multiple times
|
|
@@ -87,9 +136,7 @@ static void xprt_free_allocation(struct rpc_rqst *req)
|
|
*/
|
|
*/
|
|
int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
|
|
int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
|
|
{
|
|
{
|
|
- struct page *page_rcv = NULL, *page_snd = NULL;
|
|
|
|
- struct xdr_buf *xbufp = NULL;
|
|
|
|
- struct rpc_rqst *req, *tmp;
|
|
|
|
|
|
+ struct rpc_rqst *req;
|
|
struct list_head tmp_list;
|
|
struct list_head tmp_list;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
@@ -106,7 +153,7 @@ int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
|
|
INIT_LIST_HEAD(&tmp_list);
|
|
INIT_LIST_HEAD(&tmp_list);
|
|
for (i = 0; i < min_reqs; i++) {
|
|
for (i = 0; i < min_reqs; i++) {
|
|
/* Pre-allocate one backchannel rpc_rqst */
|
|
/* Pre-allocate one backchannel rpc_rqst */
|
|
- req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
|
|
|
|
|
|
+ req = xprt_alloc_bc_req(xprt, GFP_KERNEL);
|
|
if (req == NULL) {
|
|
if (req == NULL) {
|
|
printk(KERN_ERR "Failed to create bc rpc_rqst\n");
|
|
printk(KERN_ERR "Failed to create bc rpc_rqst\n");
|
|
goto out_free;
|
|
goto out_free;
|
|
@@ -115,41 +162,6 @@ int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
|
|
/* Add the allocated buffer to the tmp list */
|
|
/* Add the allocated buffer to the tmp list */
|
|
dprintk("RPC: adding req= %p\n", req);
|
|
dprintk("RPC: adding req= %p\n", req);
|
|
list_add(&req->rq_bc_pa_list, &tmp_list);
|
|
list_add(&req->rq_bc_pa_list, &tmp_list);
|
|
-
|
|
|
|
- req->rq_xprt = xprt;
|
|
|
|
- INIT_LIST_HEAD(&req->rq_list);
|
|
|
|
- INIT_LIST_HEAD(&req->rq_bc_list);
|
|
|
|
-
|
|
|
|
- /* Preallocate one XDR receive buffer */
|
|
|
|
- page_rcv = alloc_page(GFP_KERNEL);
|
|
|
|
- if (page_rcv == NULL) {
|
|
|
|
- printk(KERN_ERR "Failed to create bc receive xbuf\n");
|
|
|
|
- goto out_free;
|
|
|
|
- }
|
|
|
|
- xbufp = &req->rq_rcv_buf;
|
|
|
|
- xbufp->head[0].iov_base = page_address(page_rcv);
|
|
|
|
- xbufp->head[0].iov_len = PAGE_SIZE;
|
|
|
|
- xbufp->tail[0].iov_base = NULL;
|
|
|
|
- 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 bc snd xbuf\n");
|
|
|
|
- goto out_free;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- xbufp = &req->rq_snd_buf;
|
|
|
|
- xbufp->head[0].iov_base = page_address(page_snd);
|
|
|
|
- xbufp->head[0].iov_len = 0;
|
|
|
|
- xbufp->tail[0].iov_base = NULL;
|
|
|
|
- xbufp->tail[0].iov_len = 0;
|
|
|
|
- xbufp->page_len = 0;
|
|
|
|
- xbufp->len = 0;
|
|
|
|
- xbufp->buflen = PAGE_SIZE;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -167,7 +179,10 @@ out_free:
|
|
/*
|
|
/*
|
|
* Memory allocation failed, free the temporary list
|
|
* Memory allocation failed, free the temporary list
|
|
*/
|
|
*/
|
|
- list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) {
|
|
|
|
|
|
+ while (!list_empty(&tmp_list)) {
|
|
|
|
+ req = list_first_entry(&tmp_list,
|
|
|
|
+ struct rpc_rqst,
|
|
|
|
+ rq_bc_pa_list);
|
|
list_del(&req->rq_bc_pa_list);
|
|
list_del(&req->rq_bc_pa_list);
|
|
xprt_free_allocation(req);
|
|
xprt_free_allocation(req);
|
|
}
|
|
}
|