diff options
author | Sage Weil <sage@newdream.net> | 2011-08-09 17:48:11 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-08-09 18:26:17 -0400 |
commit | 5185352c163a72cf969b2fbbfb89801b398896fd (patch) | |
tree | 1b90d4b7ec1b3b117a43c3c6980c9140bb4b2097 /net | |
parent | d79698da32b317e96216236f265a9b72b78ae568 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/msgpool.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c index d5f2d97ac05c..1f4cb30a42c5 100644 --- a/net/ceph/msgpool.c +++ b/net/ceph/msgpool.c | |||
@@ -7,27 +7,37 @@ | |||
7 | 7 | ||
8 | #include <linux/ceph/msgpool.h> | 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 | struct ceph_msgpool *pool = arg; | 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); | 15 | msg = ceph_msg_new(0, pool->front_len, gfp_mask); |
16 | if (!p) | 16 | if (!msg) { |
17 | pr_err("msgpool %s alloc failed\n", pool->name); | 17 | dout("msgpool_alloc %s failed\n", pool->name); |
18 | return p; | 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 | int ceph_msgpool_init(struct ceph_msgpool *pool, | 35 | int ceph_msgpool_init(struct ceph_msgpool *pool, |
27 | int front_len, int size, bool blocking, const char *name) | 36 | int front_len, int size, bool blocking, const char *name) |
28 | { | 37 | { |
38 | dout("msgpool %s init\n", name); | ||
29 | pool->front_len = front_len; | 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 | if (!pool->pool) | 41 | if (!pool->pool) |
32 | return -ENOMEM; | 42 | return -ENOMEM; |
33 | pool->name = name; | 43 | pool->name = name; |
@@ -36,14 +46,17 @@ int ceph_msgpool_init(struct ceph_msgpool *pool, | |||
36 | 46 | ||
37 | void ceph_msgpool_destroy(struct ceph_msgpool *pool) | 47 | void ceph_msgpool_destroy(struct ceph_msgpool *pool) |
38 | { | 48 | { |
49 | dout("msgpool %s destroy\n", pool->name); | ||
39 | mempool_destroy(pool->pool); | 50 | mempool_destroy(pool->pool); |
40 | } | 51 | } |
41 | 52 | ||
42 | struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, | 53 | struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, |
43 | int front_len) | 54 | int front_len) |
44 | { | 55 | { |
56 | struct ceph_msg *msg; | ||
57 | |||
45 | if (front_len > pool->front_len) { | 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 | pool->name, front_len, pool->front_len); | 60 | pool->name, front_len, pool->front_len); |
48 | WARN_ON(1); | 61 | WARN_ON(1); |
49 | 62 | ||
@@ -51,14 +64,19 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, | |||
51 | return ceph_msg_new(0, front_len, GFP_NOFS); | 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 | void ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg) | 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 | /* reset msg front_len; user may have changed it */ | 76 | /* reset msg front_len; user may have changed it */ |
60 | msg->front.iov_len = pool->front_len; | 77 | msg->front.iov_len = pool->front_len; |
61 | msg->hdr.front_len = cpu_to_le32(pool->front_len); | 78 | msg->hdr.front_len = cpu_to_le32(pool->front_len); |
62 | 79 | ||
63 | kref_init(&msg->kref); /* retake single ref */ | 80 | kref_init(&msg->kref); /* retake single ref */ |
81 | mempool_free(msg, pool->pool); | ||
64 | } | 82 | } |