]> git.baikalelectronics.ru Git - kernel.git/commitdiff
md/raid10: fix memleak for 'conf->bio_split'
authorYu Kuai <yukuai3@huawei.com>
Fri, 10 Mar 2023 07:38:54 +0000 (15:38 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 May 2023 09:35:43 +0000 (11:35 +0200)
[ 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: 6527563a687f ("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>
drivers/md/raid10.c

index dd91385a3526f7fc8b2e1e43b48f4e5ec541c783..68447e152505797c213e4f011da124d8b1a05ab7 100644 (file)
@@ -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 @@ out:
 
 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)