From 9794b146fa7b93f8ab74fb62d67fdefad760769f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 16 Feb 2010 15:53:32 -0800 Subject: ceph: fix memory leak when destroying osdmap with pg_temp mappings Also move _lookup_pg_mapping into a helper. Signed-off-by: Sage Weil --- fs/ceph/osdmap.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'fs/ceph/osdmap.c') diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c index a6afe3836f7..443fdcdb19c 100644 --- a/fs/ceph/osdmap.c +++ b/fs/ceph/osdmap.c @@ -321,8 +321,13 @@ void ceph_osdmap_destroy(struct ceph_osdmap *map) dout("osdmap_destroy %p\n", map); if (map->crush) crush_destroy(map->crush); - while (!RB_EMPTY_ROOT(&map->pg_temp)) - rb_erase(rb_first(&map->pg_temp), &map->pg_temp); + while (!RB_EMPTY_ROOT(&map->pg_temp)) { + struct ceph_pg_mapping *pg = + rb_entry(rb_first(&map->pg_temp), + struct ceph_pg_mapping, node); + rb_erase(&pg->node, &map->pg_temp); + kfree(pg); + } kfree(map->osd_state); kfree(map->osd_weight); kfree(map->pg_pool); @@ -367,7 +372,8 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, int max) } /* - * Insert a new pg_temp mapping + * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid + * to a set of osds) */ static int pgid_cmp(struct ceph_pg l, struct ceph_pg r) { @@ -406,6 +412,26 @@ static int __insert_pg_mapping(struct ceph_pg_mapping *new, return 0; } +static struct ceph_pg_mapping *__lookup_pg_mapping(struct rb_root *root, + struct ceph_pg pgid) +{ + struct rb_node *n = root->rb_node; + struct ceph_pg_mapping *pg; + int c; + + while (n) { + pg = rb_entry(n, struct ceph_pg_mapping, node); + c = pgid_cmp(pgid, pg->pgid); + if (c < 0) + n = n->rb_left; + else if (c > 0) + n = n->rb_right; + else + return pg; + } + return NULL; +} + /* * decode a full map. */ @@ -870,26 +896,17 @@ int ceph_calc_object_layout(struct ceph_object_layout *ol, static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, int *osds, int *num) { - struct rb_node *n = osdmap->pg_temp.rb_node; struct ceph_pg_mapping *pg; struct ceph_pg_pool_info *pool; int ruleno; unsigned poolid, ps, pps; int preferred; - int c; /* pg_temp? */ - while (n) { - pg = rb_entry(n, struct ceph_pg_mapping, node); - c = pgid_cmp(pgid, pg->pgid); - if (c < 0) - n = n->rb_left; - else if (c > 0) - n = n->rb_right; - else { - *num = pg->len; - return pg->osds; - } + pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid); + if (pg) { + *num = pg->len; + return pg->osds; } /* crush */ -- cgit v1.2.3