]> git.baikalelectronics.ru Git - kernel.git/commitdiff
dm stats: check for and propagate alloc_percpu failure
authorJiasheng Jiang <jiasheng@iscas.ac.cn>
Thu, 16 Mar 2023 06:55:06 +0000 (14:55 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Apr 2023 09:16:41 +0000 (11:16 +0200)
commit d3aa3e060c4a80827eb801fc448debc9daa7c46b upstream.

Check alloc_precpu()'s return value and return an error from
dm_stats_init() if it fails. Update alloc_dev() to fail if
dm_stats_init() does.

Otherwise, a NULL pointer dereference will occur in dm_stats_cleanup()
even if dm-stats isn't being actively used.

Fixes: 0da43f932b1b ("dm: add statistics support")
Cc: stable@vger.kernel.org
Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/dm-stats.c
drivers/md/dm-stats.h
drivers/md/dm.c

index ce6d3bce1b7b02180bd5ddf47ced339c29d5b957..0f42f4a7f38244a8c20a9264fa602815f60952de 100644 (file)
@@ -188,7 +188,7 @@ static int dm_stat_in_flight(struct dm_stat_shared *shared)
               atomic_read(&shared->in_flight[WRITE]);
 }
 
-void dm_stats_init(struct dm_stats *stats)
+int dm_stats_init(struct dm_stats *stats)
 {
        int cpu;
        struct dm_stats_last_position *last;
@@ -196,11 +196,16 @@ void dm_stats_init(struct dm_stats *stats)
        mutex_init(&stats->mutex);
        INIT_LIST_HEAD(&stats->list);
        stats->last = alloc_percpu(struct dm_stats_last_position);
+       if (!stats->last)
+               return -ENOMEM;
+
        for_each_possible_cpu(cpu) {
                last = per_cpu_ptr(stats->last, cpu);
                last->last_sector = (sector_t)ULLONG_MAX;
                last->last_rw = UINT_MAX;
        }
+
+       return 0;
 }
 
 void dm_stats_cleanup(struct dm_stats *stats)
index 2ddfae678f320f84776c772f1107da8eab485385..dcac11fce03bba613da83b35c22db732b19ed8af 100644 (file)
@@ -22,7 +22,7 @@ struct dm_stats_aux {
        unsigned long long duration_ns;
 };
 
-void dm_stats_init(struct dm_stats *st);
+int dm_stats_init(struct dm_stats *st);
 void dm_stats_cleanup(struct dm_stats *st);
 
 struct mapped_device;
index b58ff1a0fda7d1a6f1553c7c915b61d6bdf8a89c..771167ee552cde66ce1d92a9664d28030fe8d10a 100644 (file)
@@ -1994,7 +1994,9 @@ static struct mapped_device *alloc_dev(int minor)
        if (!md->bdev)
                goto bad;
 
-       dm_stats_init(&md->stats);
+       r = dm_stats_init(&md->stats);
+       if (r < 0)
+               goto bad;
 
        /* Populate the mapping, nobody knows we exist yet */
        spin_lock(&_minor_lock);