Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6460f68 authored by Yu Kuai's avatar Yu Kuai Committed by Greg Kroah-Hartman
Browse files

md/raid10: fix memleak for 'conf->bio_split'



[ Upstream commit c9ac2acde53f5385de185bccf6aaa91cf9ac1541 ]

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: fc9977dd ("md/raid10: simplify the splitting of requests.")
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20230310073855.1337560-6-yukuai1@huaweicloud.com


Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 8c5d5d7f
Loading
Loading
Loading
Loading
+17 −20
Original line number Diff line number Diff line
@@ -3635,6 +3635,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;
@@ -3717,13 +3731,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);
}

@@ -3937,10 +3945,7 @@ 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;
@@ -3948,15 +3953,7 @@ static int raid10_run(struct mddev *mddev)

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)