1 #include <linux/ceph/ceph_debug.h> 2 3 #include <linux/err.h> 4 #include <linux/sched.h> 5 #include <linux/types.h> 6 #include <linux/vmalloc.h> 7 8 #include <linux/ceph/messenger.h> 9 #include <linux/ceph/msgpool.h> 10 11 static void *msgpool_alloc(gfp_t gfp_mask, void *arg) 12 { 13 struct ceph_msgpool *pool = arg; 14 struct ceph_msg *msg; 15 16 msg = ceph_msg_new(pool->type, pool->front_len, gfp_mask, true); 17 if (!msg) { 18 dout("msgpool_alloc %s failed\n", pool->name); 19 } else { 20 dout("msgpool_alloc %s %p\n", pool->name, msg); 21 msg->pool = pool; 22 } 23 return msg; 24 } 25 26 static void msgpool_free(void *element, void *arg) 27 { 28 struct ceph_msgpool *pool = arg; 29 struct ceph_msg *msg = element; 30 31 dout("msgpool_release %s %p\n", pool->name, msg); 32 msg->pool = NULL; 33 ceph_msg_put(msg); 34 } 35 36 int ceph_msgpool_init(struct ceph_msgpool *pool, int type, 37 int front_len, int size, bool blocking, const char *name) 38 { 39 dout("msgpool %s init\n", name); 40 pool->type = type; 41 pool->front_len = front_len; 42 pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool); 43 if (!pool->pool) 44 return -ENOMEM; 45 pool->name = name; 46 return 0; 47 } 48 49 void ceph_msgpool_destroy(struct ceph_msgpool *pool) 50 { 51 dout("msgpool %s destroy\n", pool->name); 52 mempool_destroy(pool->pool); 53 } 54 55 struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, 56 int front_len) 57 { 58 struct ceph_msg *msg; 59 60 if (front_len > pool->front_len) { 61 dout("msgpool_get %s need front %d, pool size is %d\n", 62 pool->name, front_len, pool->front_len); 63 WARN_ON(1); 64 65 /* try to alloc a fresh message */ 66 return ceph_msg_new(pool->type, front_len, GFP_NOFS, false); 67 } 68 69 msg = mempool_alloc(pool->pool, GFP_NOFS); 70 dout("msgpool_get %s %p\n", pool->name, msg); 71 return msg; 72 } 73 74 void ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg) 75 { 76 dout("msgpool_put %s %p\n", pool->name, msg); 77 78 /* reset msg front_len; user may have changed it */ 79 msg->front.iov_len = pool->front_len; 80 msg->hdr.front_len = cpu_to_le32(pool->front_len); 81 82 kref_init(&msg->kref); /* retake single ref */ 83 mempool_free(msg, pool->pool); 84 } 85