0001
0002 #include <linux/ceph/ceph_debug.h>
0003
0004 #include <linux/err.h>
0005 #include <linux/sched.h>
0006 #include <linux/types.h>
0007 #include <linux/vmalloc.h>
0008
0009 #include <linux/ceph/messenger.h>
0010 #include <linux/ceph/msgpool.h>
0011
0012 static void *msgpool_alloc(gfp_t gfp_mask, void *arg)
0013 {
0014 struct ceph_msgpool *pool = arg;
0015 struct ceph_msg *msg;
0016
0017 msg = ceph_msg_new2(pool->type, pool->front_len, pool->max_data_items,
0018 gfp_mask, true);
0019 if (!msg) {
0020 dout("msgpool_alloc %s failed\n", pool->name);
0021 } else {
0022 dout("msgpool_alloc %s %p\n", pool->name, msg);
0023 msg->pool = pool;
0024 }
0025 return msg;
0026 }
0027
0028 static void msgpool_free(void *element, void *arg)
0029 {
0030 struct ceph_msgpool *pool = arg;
0031 struct ceph_msg *msg = element;
0032
0033 dout("msgpool_release %s %p\n", pool->name, msg);
0034 msg->pool = NULL;
0035 ceph_msg_put(msg);
0036 }
0037
0038 int ceph_msgpool_init(struct ceph_msgpool *pool, int type,
0039 int front_len, int max_data_items, int size,
0040 const char *name)
0041 {
0042 dout("msgpool %s init\n", name);
0043 pool->type = type;
0044 pool->front_len = front_len;
0045 pool->max_data_items = max_data_items;
0046 pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool);
0047 if (!pool->pool)
0048 return -ENOMEM;
0049 pool->name = name;
0050 return 0;
0051 }
0052
0053 void ceph_msgpool_destroy(struct ceph_msgpool *pool)
0054 {
0055 dout("msgpool %s destroy\n", pool->name);
0056 mempool_destroy(pool->pool);
0057 }
0058
0059 struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, int front_len,
0060 int max_data_items)
0061 {
0062 struct ceph_msg *msg;
0063
0064 if (front_len > pool->front_len ||
0065 max_data_items > pool->max_data_items) {
0066 pr_warn_ratelimited("%s need %d/%d, pool %s has %d/%d\n",
0067 __func__, front_len, max_data_items, pool->name,
0068 pool->front_len, pool->max_data_items);
0069 WARN_ON_ONCE(1);
0070
0071
0072 return ceph_msg_new2(pool->type, front_len, max_data_items,
0073 GFP_NOFS, false);
0074 }
0075
0076 msg = mempool_alloc(pool->pool, GFP_NOFS);
0077 dout("msgpool_get %s %p\n", pool->name, msg);
0078 return msg;
0079 }
0080
0081 void ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg)
0082 {
0083 dout("msgpool_put %s %p\n", pool->name, msg);
0084
0085
0086 msg->front.iov_len = pool->front_len;
0087 msg->hdr.front_len = cpu_to_le32(pool->front_len);
0088
0089 msg->data_length = 0;
0090 msg->num_data_items = 0;
0091
0092 kref_init(&msg->kref);
0093 mempool_free(msg, pool->pool);
0094 }