Commit dd3bd170 authored by Guoqing Jiang's avatar Guoqing Jiang Committed by Jialin Zhang
Browse files

md: unlock mddev before reap sync_thread in action_store

mainline inclusion
from mainline-v6.0-rc1
commit 9dfbdafd
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6OMCC
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc3&id=9dfbdafda3b34e262e43e786077bab8e476a89d1



--------------------------------

Since the bug which commit 8b48ec23 ("md: don't unregister sync_thread
with reconfig_mutex held") fixed is related with action_store path, other
callers which reap sync_thread didn't need to be changed.

Let's pull md_unregister_thread from md_reap_sync_thread, then fix previous
bug with belows.

1. unlock mddev before md_reap_sync_thread in action_store.
2. save reshape_position before unlock, then restore it to ensure position
   not changed accidentally by others.

Signed-off-by: default avatarGuoqing Jiang <guoqing.jiang@linux.dev>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarHou Tao <houtao1@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parent 7058c39d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3693,6 +3693,7 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
	if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
		if (mddev->sync_thread) {
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
			md_unregister_thread(&mddev->sync_thread);
			md_reap_sync_thread(mddev);
		}
	} else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
+17 −2
Original line number Diff line number Diff line
@@ -4872,6 +4872,19 @@ action_store(struct mddev *mddev, const char *page, size_t len)
			if (work_pending(&mddev->del_work))
				flush_workqueue(md_misc_wq);
			if (mddev->sync_thread) {
				sector_t save_rp = mddev->reshape_position;

				mddev_unlock(mddev);
				set_bit(MD_RECOVERY_INTR, &mddev->recovery);
				md_unregister_thread(&mddev->sync_thread);
				mddev_lock_nointr(mddev);
				/*
				 * set RECOVERY_INTR again and restore reshape
				 * position in case others changed them after
				 * got lock, eg, reshape_position_store and
				 * md_check_recovery.
				 */
				mddev->reshape_position = save_rp;
				set_bit(MD_RECOVERY_INTR, &mddev->recovery);
				md_reap_sync_thread(mddev);
			}
@@ -6251,6 +6264,7 @@ static void __md_stop_writes(struct mddev *mddev)
		flush_workqueue(md_misc_wq);
	if (mddev->sync_thread) {
		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
		md_unregister_thread(&mddev->sync_thread);
		md_reap_sync_thread(mddev);
	}

@@ -9321,6 +9335,7 @@ void md_check_recovery(struct mddev *mddev)
			 * ->spare_active and clear saved_raid_disk
			 */
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
			md_unregister_thread(&mddev->sync_thread);
			md_reap_sync_thread(mddev);
			clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
			clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -9356,6 +9371,7 @@ void md_check_recovery(struct mddev *mddev)
			goto unlock;
		}
		if (mddev->sync_thread) {
			md_unregister_thread(&mddev->sync_thread);
			md_reap_sync_thread(mddev);
			goto unlock;
		}
@@ -9435,8 +9451,7 @@ void md_reap_sync_thread(struct mddev *mddev)
	sector_t old_dev_sectors = mddev->dev_sectors;
	bool is_reshaped = false;

	/* resync has finished, collect result */
	md_unregister_thread(&mddev->sync_thread);
	/* sync_thread should be unregistered, collect result */
	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
	    mddev->degraded != mddev->raid_disks) {