18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/ceph/ceph_debug.h> 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/err.h> 58c2ecf20Sopenharmony_ci#include <linux/sched.h> 68c2ecf20Sopenharmony_ci#include <linux/types.h> 78c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/ceph/messenger.h> 108c2ecf20Sopenharmony_ci#include <linux/ceph/msgpool.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic void *msgpool_alloc(gfp_t gfp_mask, void *arg) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci struct ceph_msgpool *pool = arg; 158c2ecf20Sopenharmony_ci struct ceph_msg *msg; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci msg = ceph_msg_new2(pool->type, pool->front_len, pool->max_data_items, 188c2ecf20Sopenharmony_ci gfp_mask, true); 198c2ecf20Sopenharmony_ci if (!msg) { 208c2ecf20Sopenharmony_ci dout("msgpool_alloc %s failed\n", pool->name); 218c2ecf20Sopenharmony_ci } else { 228c2ecf20Sopenharmony_ci dout("msgpool_alloc %s %p\n", pool->name, msg); 238c2ecf20Sopenharmony_ci msg->pool = pool; 248c2ecf20Sopenharmony_ci } 258c2ecf20Sopenharmony_ci return msg; 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void msgpool_free(void *element, void *arg) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct ceph_msgpool *pool = arg; 318c2ecf20Sopenharmony_ci struct ceph_msg *msg = element; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci dout("msgpool_release %s %p\n", pool->name, msg); 348c2ecf20Sopenharmony_ci msg->pool = NULL; 358c2ecf20Sopenharmony_ci ceph_msg_put(msg); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ciint ceph_msgpool_init(struct ceph_msgpool *pool, int type, 398c2ecf20Sopenharmony_ci int front_len, int max_data_items, int size, 408c2ecf20Sopenharmony_ci const char *name) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci dout("msgpool %s init\n", name); 438c2ecf20Sopenharmony_ci pool->type = type; 448c2ecf20Sopenharmony_ci pool->front_len = front_len; 458c2ecf20Sopenharmony_ci pool->max_data_items = max_data_items; 468c2ecf20Sopenharmony_ci pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool); 478c2ecf20Sopenharmony_ci if (!pool->pool) 488c2ecf20Sopenharmony_ci return -ENOMEM; 498c2ecf20Sopenharmony_ci pool->name = name; 508c2ecf20Sopenharmony_ci return 0; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_civoid ceph_msgpool_destroy(struct ceph_msgpool *pool) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci dout("msgpool %s destroy\n", pool->name); 568c2ecf20Sopenharmony_ci mempool_destroy(pool->pool); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistruct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, int front_len, 608c2ecf20Sopenharmony_ci int max_data_items) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct ceph_msg *msg; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (front_len > pool->front_len || 658c2ecf20Sopenharmony_ci max_data_items > pool->max_data_items) { 668c2ecf20Sopenharmony_ci pr_warn_ratelimited("%s need %d/%d, pool %s has %d/%d\n", 678c2ecf20Sopenharmony_ci __func__, front_len, max_data_items, pool->name, 688c2ecf20Sopenharmony_ci pool->front_len, pool->max_data_items); 698c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* try to alloc a fresh message */ 728c2ecf20Sopenharmony_ci return ceph_msg_new2(pool->type, front_len, max_data_items, 738c2ecf20Sopenharmony_ci GFP_NOFS, false); 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci msg = mempool_alloc(pool->pool, GFP_NOFS); 778c2ecf20Sopenharmony_ci dout("msgpool_get %s %p\n", pool->name, msg); 788c2ecf20Sopenharmony_ci return msg; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_civoid ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci dout("msgpool_put %s %p\n", pool->name, msg); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* reset msg front_len; user may have changed it */ 868c2ecf20Sopenharmony_ci msg->front.iov_len = pool->front_len; 878c2ecf20Sopenharmony_ci msg->hdr.front_len = cpu_to_le32(pool->front_len); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci msg->data_length = 0; 908c2ecf20Sopenharmony_ci msg->num_data_items = 0; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci kref_init(&msg->kref); /* retake single ref */ 938c2ecf20Sopenharmony_ci mempool_free(msg, pool->pool); 948c2ecf20Sopenharmony_ci} 95