Commit 5185352c163a72cf969b2fbbfb89801b398896fd

Authored by Sage Weil
1 parent d79698da32

libceph: fix msgpool

There were several problems here:

 1- we weren't tagging allocations with the pool, so they were never
    returned to the pool.
 2- msgpool_put didn't add back to the mempool, even it were called.
 3- msgpool_release didn't clear the pool pointer, so it would have looped
    had #1 not been broken.

These may or may not have been responsible for #1136 or #1381 (BUG due to
non-empty mempool on umount).  I can't seem to trigger the crash now using
the method I was using before.

Signed-off-by: Sage Weil <sage@newdream.net>

Showing 1 changed file with 29 additions and 11 deletions Side-by-side Diff

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