Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Generalize the RPC buffer release API

xprtrdma needs to allocate the Call and Reply buffers separately.
TBH, the reliance on using a single buffer for the pair of XDR
buffers is transport implementation-specific.

Instead of passing just the rq_buffer into the buf_free method, pass
the task structure and let buf_free take care of freeing both
XDR buffers at once.

There's a micro-optimization here. In the common case, both
xprt_release and the transport's buf_free method were checking if
rq_buffer was NULL. Now the check is done only once per RPC.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Chuck Lever and committed by
Anna Schumaker
3435c74a 5fe6eaa1

+20 -31
+1 -1
include/linux/sunrpc/sched.h
··· 240 240 void rpc_wake_up_status(struct rpc_wait_queue *, int); 241 241 void rpc_delay(struct rpc_task *, unsigned long); 242 242 int rpc_malloc(struct rpc_task *); 243 - void rpc_free(void *); 243 + void rpc_free(struct rpc_task *); 244 244 int rpciod_up(void); 245 245 void rpciod_down(void); 246 246 int __rpc_wait_for_completion_task(struct rpc_task *task, wait_bit_action_f *);
+1 -1
include/linux/sunrpc/xprt.h
··· 128 128 void (*set_port)(struct rpc_xprt *xprt, unsigned short port); 129 129 void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task); 130 130 int (*buf_alloc)(struct rpc_task *task); 131 - void (*buf_free)(void *buffer); 131 + void (*buf_free)(struct rpc_task *task); 132 132 int (*send_request)(struct rpc_task *task); 133 133 void (*set_retrans_timeout)(struct rpc_task *task); 134 134 void (*timer)(struct rpc_xprt *xprt, struct rpc_task *task);
+4 -6
net/sunrpc/sched.c
··· 896 896 EXPORT_SYMBOL_GPL(rpc_malloc); 897 897 898 898 /** 899 - * rpc_free - free buffer allocated via rpc_malloc 900 - * @buffer: buffer to free 899 + * rpc_free - free RPC buffer resources allocated via rpc_malloc 900 + * @task: RPC task 901 901 * 902 902 */ 903 - void rpc_free(void *buffer) 903 + void rpc_free(struct rpc_task *task) 904 904 { 905 + void *buffer = task->tk_rqstp->rq_buffer; 905 906 size_t size; 906 907 struct rpc_buffer *buf; 907 - 908 - if (!buffer) 909 - return; 910 908 911 909 buf = container_of(buffer, struct rpc_buffer, data); 912 910 size = buf->len;
+1 -1
net/sunrpc/xprt.c
··· 1295 1295 xprt_schedule_autodisconnect(xprt); 1296 1296 spin_unlock_bh(&xprt->transport_lock); 1297 1297 if (req->rq_buffer) 1298 - xprt->ops->buf_free(req->rq_buffer); 1298 + xprt->ops->buf_free(task); 1299 1299 xprt_inject_disconnect(xprt); 1300 1300 if (req->rq_cred != NULL) 1301 1301 put_rpccred(req->rq_cred);
+1 -1
net/sunrpc/xprtrdma/svc_rdma_backchannel.c
··· 186 186 } 187 187 188 188 static void 189 - xprt_rdma_bc_free(void *buffer) 189 + xprt_rdma_bc_free(struct rpc_task *task) 190 190 { 191 191 /* No-op: ctxt and page have already been freed. */ 192 192 }
+10 -16
net/sunrpc/xprtrdma/transport.c
··· 523 523 out: 524 524 dprintk("RPC: %s: size %zd, request 0x%p\n", __func__, size, req); 525 525 req->rl_connect_cookie = 0; /* our reserved value */ 526 - req->rl_task = task; 527 526 rqst->rq_buffer = req->rl_sendbuf->rg_base; 528 527 return 0; 529 528 ··· 570 571 return -ENOMEM; 571 572 } 572 573 573 - /* 574 - * This function returns all RDMA resources to the pool. 574 + /** 575 + * xprt_rdma_free - release resources allocated by xprt_rdma_allocate 576 + * @task: RPC task 577 + * 578 + * Caller guarantees rqst->rq_buffer is non-NULL. 575 579 */ 576 580 static void 577 - xprt_rdma_free(void *buffer) 581 + xprt_rdma_free(struct rpc_task *task) 578 582 { 579 - struct rpcrdma_req *req; 580 - struct rpcrdma_xprt *r_xprt; 581 - struct rpcrdma_regbuf *rb; 583 + struct rpc_rqst *rqst = task->tk_rqstp; 584 + struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt); 585 + struct rpcrdma_req *req = rpcr_to_rdmar(rqst); 582 586 583 - if (buffer == NULL) 584 - return; 585 - 586 - rb = container_of(buffer, struct rpcrdma_regbuf, rg_base[0]); 587 - req = rb->rg_owner; 588 587 if (req->rl_backchannel) 589 588 return; 590 - 591 - r_xprt = container_of(req->rl_buffer, struct rpcrdma_xprt, rx_buf); 592 589 593 590 dprintk("RPC: %s: called on 0x%p\n", __func__, req->rl_reply); 594 591 595 592 r_xprt->rx_ia.ri_ops->ro_unmap_safe(r_xprt, req, 596 - !RPC_IS_ASYNC(req->rl_task)); 597 - 593 + !RPC_IS_ASYNC(task)); 598 594 rpcrdma_buffer_put(req); 599 595 } 600 596
-1
net/sunrpc/xprtrdma/xprt_rdma.h
··· 283 283 struct list_head rl_free; 284 284 unsigned int rl_niovs; 285 285 unsigned int rl_connect_cookie; 286 - struct rpc_task *rl_task; 287 286 struct rpcrdma_buffer *rl_buffer; 288 287 struct rpcrdma_rep *rl_reply;/* holder for reply buffer */ 289 288 struct ib_sge rl_send_iov[RPCRDMA_MAX_IOVS];
+2 -4
net/sunrpc/xprtsock.c
··· 2560 2560 /* 2561 2561 * Free the space allocated in the bc_alloc routine 2562 2562 */ 2563 - static void bc_free(void *buffer) 2563 + static void bc_free(struct rpc_task *task) 2564 2564 { 2565 + void *buffer = task->tk_rqstp->rq_buffer; 2565 2566 struct rpc_buffer *buf; 2566 - 2567 - if (!buffer) 2568 - return; 2569 2567 2570 2568 buf = container_of(buffer, struct rpc_buffer, data); 2571 2569 free_page((unsigned long)buf);