Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1dddda86 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Clean up allocation and freeing of back channel requests

parent 0f419791
Loading
Loading
Loading
Loading
+55 −40
Original line number Diff line number Diff line
@@ -67,6 +67,55 @@ static void xprt_free_allocation(struct rpc_rqst *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
 * 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)
{
	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;
	int i;

@@ -106,7 +153,7 @@ int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
	INIT_LIST_HEAD(&tmp_list);
	for (i = 0; i < min_reqs; i++) {
		/* 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) {
			printk(KERN_ERR "Failed to create bc rpc_rqst\n");
			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 */
		dprintk("RPC:       adding req= %p\n", req);
		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 @@ int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
	/*
	 * 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);
		xprt_free_allocation(req);
	}