]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
md/md-bitmap: hold 'reconfig_mutex' in backlog_store()
authorYu Kuai <yukuai3@huawei.com>
Thu, 6 Jul 2023 08:37:27 +0000 (16:37 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Sep 2023 07:48:15 +0000 (09:48 +0200)
[ Upstream commit 44abfa6a95df425c0660d56043020b67e6d93ab8 ]

Several reasons why 'reconfig_mutex' should be held:

1) rdev_for_each() is not safe to be called without the lock, because
   rdev can be removed concurrently.
2) mddev_destroy_serial_pool() and mddev_create_serial_pool() should not
   be called concurrently.
3) mddev_suspend() from mddev_destroy/create_serial_pool() should be
   protected by the lock.

Fixes: 10c92fca636e ("md-bitmap: create and destroy wb_info_pool with the change of backlog")
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Link: https://lore.kernel.org/r/20230706083727.608914-3-yukuai1@huaweicloud.com
Signed-off-by: Song Liu <song@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/md/md-bitmap.c

index 4934d8f0cf11a40755602a70be9d22c55e3bae95..ba6b4819d37e4a164fc886ab321d3a03d746f664 100644 (file)
@@ -2504,6 +2504,10 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
        if (backlog > COUNTER_MAX)
                return -EINVAL;
 
+       rv = mddev_lock(mddev);
+       if (rv)
+               return rv;
+
        /*
         * Without write mostly device, it doesn't make sense to set
         * backlog for max_write_behind.
@@ -2517,6 +2521,7 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
        if (!has_write_mostly) {
                pr_warn_ratelimited("%s: can't set backlog, no write mostly device available\n",
                                    mdname(mddev));
+               mddev_unlock(mddev);
                return -EINVAL;
        }
 
@@ -2532,6 +2537,8 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
        }
        if (old_mwb != backlog)
                md_bitmap_update_sb(mddev->bitmap);
+
+       mddev_unlock(mddev);
        return len;
 }