mem-buf-msgq: Reduce buffer free complexity

Reuse the same buffer for each message in mem_buf_msgq_recv_fn()
instead of allocating a new one for each message, and freeing it
in a dozen different locations depending on what type of message it
is.

If a consumer of the message needs to defer its work to a workqueue,
it must allocate a new copy of the message.

Change-Id: Ia5583bc7dc9937211f25624f7a679d34fe8fb521
Signed-off-by: Patrick Daly <quic_pdaly@quicinc.com>
This commit is contained in:
Patrick Daly 2022-05-27 12:33:38 -07:00 committed by Chris Goldsworthy
parent 0f6efbf911
commit 63bddcd463
2 changed files with 22 additions and 18 deletions

View File

@ -445,6 +445,7 @@ static void mem_buf_alloc_req_work(struct work_struct *work)
}
resp_msg = mem_buf_construct_alloc_resp(req_msg, ret, hdl);
kfree(rmt_msg->msg);
kfree(rmt_msg);
if (IS_ERR(resp_msg))
@ -510,7 +511,6 @@ static int mem_buf_alloc_resp_hdlr(void *hdlr_data, void *msg_buf, size_t size,
trace_receive_alloc_resp_msg(alloc_resp);
if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER)) {
kfree(msg_buf);
return -EPERM;
}
@ -521,23 +521,26 @@ static int mem_buf_alloc_resp_hdlr(void *hdlr_data, void *msg_buf, size_t size,
membuf->memparcel_hdl = get_alloc_resp_hdl(alloc_resp);
}
kfree(msg_buf);
return ret;
}
/* Functions invoked when treating allocation requests to other VMs. */
static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *buf, size_t size)
static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *_buf, size_t size)
{
struct mem_buf_rmt_msg *rmt_msg;
void *buf;
if (!(mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) {
kfree(buf);
return;
}
rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL);
if (!rmt_msg) {
kfree(buf);
if (!rmt_msg)
return;
buf = kmemdup(_buf, size, GFP_KERNEL);
if (!buf) {
kfree(rmt_msg);
return;
}
@ -547,18 +550,22 @@ static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *buf, size_t size)
queue_work(mem_buf_wq, &rmt_msg->work);
}
static void mem_buf_relinquish_hdlr(void *hdlr_data, void *buf, size_t size)
static void mem_buf_relinquish_hdlr(void *hdlr_data, void *_buf, size_t size)
{
struct mem_buf_rmt_msg *rmt_msg;
void *buf;
if (!(mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) {
kfree(buf);
return;
}
rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL);
if (!rmt_msg) {
kfree(buf);
if (!rmt_msg)
return;
buf = kmemdup(_buf, size, GFP_KERNEL);
if (!buf) {
kfree(rmt_msg);
return;
}

View File

@ -310,7 +310,6 @@ static void mem_buf_process_alloc_resp(struct mem_buf_msgq_desc *desc, void *buf
if (!alloc_resp->ret) {
desc->msgq_ops->relinquish_memparcel_hdl(desc->hdlr_data, hdr->txn_id,
alloc_resp->hdl);
kfree(buf);
}
} else {
txn->txn_ret = desc->msgq_ops->alloc_resp_hdlr(desc->hdlr_data, buf, size,
@ -328,7 +327,6 @@ static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_
if (size < sizeof(*hdr) || hdr->msg_size != size) {
pr_err("%s: message received is not of a proper size: 0x%lx\n",
__func__, size);
kfree(buf);
return;
}
@ -345,7 +343,6 @@ static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_
default:
pr_err("%s: received message of unknown type: %d\n", __func__,
hdr->msg_type);
kfree(buf);
}
}
@ -367,20 +364,20 @@ static int mem_buf_msgq_recv_fn(void *data)
size_t size;
int ret;
while (!kthread_should_stop()) {
buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
if (!buf)
continue;
buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
if (!buf)
return -ENOMEM;
while (!kthread_should_stop()) {
ret = gh_msgq_recv(desc->msgq_hdl, buf, GH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0);
if (ret < 0) {
kfree(buf);
pr_err_ratelimited("%s failed to receive message rc: %d\n", __func__, ret);
} else {
mem_buf_process_msg(desc, buf, size);
}
}
kfree(buf);
return 0;
}