Skip to content

Commit

Permalink
md/raid10: fix memleak for 'conf->bio_split'
Browse files Browse the repository at this point in the history
[ Upstream commit c9ac2ac ]

In the error path of raid10_run(), 'conf' need be freed, however,
'conf->bio_split' is missed and memory will be leaked.

Since there are 3 places to free 'conf', factor out a helper to fix the
problem.

Fixes: fc9977d ("md/raid10: simplify the splitting of requests.")
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20230310073855.1337560-6-yukuai1@huaweicloud.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Yu Kuai authored and gregkh committed May 11, 2023
1 parent 4f82e7e commit e2fec8d
Showing 1 changed file with 17 additions and 20 deletions.
37 changes: 17 additions & 20 deletions drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -4015,6 +4015,20 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
return nc*fc;
}

static void raid10_free_conf(struct r10conf *conf)
{
if (!conf)
return;

mempool_exit(&conf->r10bio_pool);
kfree(conf->mirrors);
kfree(conf->mirrors_old);
kfree(conf->mirrors_new);
safe_put_page(conf->tmppage);
bioset_exit(&conf->bio_split);
kfree(conf);
}

static struct r10conf *setup_conf(struct mddev *mddev)
{
struct r10conf *conf = NULL;
Expand Down Expand Up @@ -4097,13 +4111,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
return conf;

out:
if (conf) {
mempool_exit(&conf->r10bio_pool);
kfree(conf->mirrors);
safe_put_page(conf->tmppage);
bioset_exit(&conf->bio_split);
kfree(conf);
}
raid10_free_conf(conf);
return ERR_PTR(err);
}

Expand Down Expand Up @@ -4294,26 +4302,15 @@ static int raid10_run(struct mddev *mddev)

out_free_conf:
md_unregister_thread(&mddev->thread);
mempool_exit(&conf->r10bio_pool);
safe_put_page(conf->tmppage);
kfree(conf->mirrors);
kfree(conf);
raid10_free_conf(conf);
mddev->private = NULL;
out:
return -EIO;
}

static void raid10_free(struct mddev *mddev, void *priv)
{
struct r10conf *conf = priv;

mempool_exit(&conf->r10bio_pool);
safe_put_page(conf->tmppage);
kfree(conf->mirrors);
kfree(conf->mirrors_old);
kfree(conf->mirrors_new);
bioset_exit(&conf->bio_split);
kfree(conf);
raid10_free_conf(priv);
}

static void raid10_quiesce(struct mddev *mddev, int quiesce)
Expand Down

0 comments on commit e2fec8d

Please sign in to comment.