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>
Thu, 11 May 2023 14:03:23 +0000 (23:03 +0900)
[ 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: fc9977dd069e ("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 e2bd0f8..c861db5 100644 (file)
@@ -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;
@@ -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);
 }
 
@@ -4294,10 +4302,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;
@@ -4305,15 +4310,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)