Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ebc0be7 authored by NeilBrown's avatar NeilBrown
Browse files

md: Be more careful about clearing flags bit in ->recovery



Setting ->recovery to 0 is generally not a good idea as it could clear
bits that shouldn't be cleared.  In particular, MD_RECOVERY_FROZEN
should only be cleared on explicit request from user-space.

So when we need to clear things, just clear the bits that need
clearing.

As there are a few different places which reap a resync process - and
some do an incomplte job - factor out the code for doing the from
md_check_recovery and call that function instead of open coding part
of it.

Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Reported-by: default avatarJonathan Brassow <jbrassow@redhat.com>
parent defad61a
Loading
Loading
Loading
Loading
+49 −37
Original line number Original line Diff line number Diff line
@@ -3746,6 +3746,8 @@ action_show(mddev_t *mddev, char *page)
	return sprintf(page, "%s\n", type);
	return sprintf(page, "%s\n", type);
}
}


static void reap_sync_thread(mddev_t *mddev);

static ssize_t
static ssize_t
action_store(mddev_t *mddev, const char *page, size_t len)
action_store(mddev_t *mddev, const char *page, size_t len)
{
{
@@ -3760,9 +3762,7 @@ action_store(mddev_t *mddev, const char *page, size_t len)
	if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
	if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
		if (mddev->sync_thread) {
		if (mddev->sync_thread) {
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
			md_unregister_thread(mddev->sync_thread);
			reap_sync_thread(mddev);
			mddev->sync_thread = NULL;
			mddev->recovery = 0;
		}
		}
	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
@@ -4709,8 +4709,7 @@ static void __md_stop_writes(mddev_t *mddev)
	if (mddev->sync_thread) {
	if (mddev->sync_thread) {
		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
		md_unregister_thread(mddev->sync_thread);
		reap_sync_thread(mddev);
		mddev->sync_thread = NULL;
	}
	}


	del_timer_sync(&mddev->safemode_timer);
	del_timer_sync(&mddev->safemode_timer);
@@ -7044,6 +7043,45 @@ static int remove_and_add_spares(mddev_t *mddev)
	}
	}
	return spares;
	return spares;
}
}

static void reap_sync_thread(mddev_t *mddev)
{
	mdk_rdev_t *rdev;

	/* resync has finished, collect result */
	md_unregister_thread(mddev->sync_thread);
	mddev->sync_thread = NULL;
	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
		/* success...*/
		/* activate any spares */
		if (mddev->pers->spare_active(mddev))
			sysfs_notify(&mddev->kobj, NULL,
				     "degraded");
	}
	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
	    mddev->pers->finish_reshape)
		mddev->pers->finish_reshape(mddev);
	md_update_sb(mddev, 1);

	/* if array is no-longer degraded, then any saved_raid_disk
	 * information must be scrapped
	 */
	if (!mddev->degraded)
		list_for_each_entry(rdev, &mddev->disks, same_set)
			rdev->saved_raid_disk = -1;

	clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
	clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
	clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
	clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
	/* flag recovery needed just to double check */
	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
	sysfs_notify_dirent_safe(mddev->sysfs_action);
	md_new_event(mddev);
}

/*
/*
 * This routine is regularly called by all per-raid-array threads to
 * This routine is regularly called by all per-raid-array threads to
 * deal with generic issues like resync and super-block update.
 * deal with generic issues like resync and super-block update.
@@ -7068,9 +7106,6 @@ static int remove_and_add_spares(mddev_t *mddev)
 */
 */
void md_check_recovery(mddev_t *mddev)
void md_check_recovery(mddev_t *mddev)
{
{
	mdk_rdev_t *rdev;


	if (mddev->bitmap)
	if (mddev->bitmap)
		bitmap_daemon_work(mddev);
		bitmap_daemon_work(mddev);


@@ -7138,34 +7173,7 @@ void md_check_recovery(mddev_t *mddev)
			goto unlock;
			goto unlock;
		}
		}
		if (mddev->sync_thread) {
		if (mddev->sync_thread) {
			/* resync has finished, collect result */
			reap_sync_thread(mddev);
			md_unregister_thread(mddev->sync_thread);
			mddev->sync_thread = NULL;
			if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
			    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
				/* success...*/
				/* activate any spares */
				if (mddev->pers->spare_active(mddev))
					sysfs_notify(&mddev->kobj, NULL,
						     "degraded");
			}
			if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
			    mddev->pers->finish_reshape)
				mddev->pers->finish_reshape(mddev);
			md_update_sb(mddev, 1);

			/* if array is no-longer degraded, then any saved_raid_disk
			 * information must be scrapped
			 */
			if (!mddev->degraded)
				list_for_each_entry(rdev, &mddev->disks, same_set)
					rdev->saved_raid_disk = -1;

			mddev->recovery = 0;
			/* flag recovery needed just to double check */
			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
			sysfs_notify_dirent_safe(mddev->sysfs_action);
			md_new_event(mddev);
			goto unlock;
			goto unlock;
		}
		}
		/* Set RUNNING before clearing NEEDED to avoid
		/* Set RUNNING before clearing NEEDED to avoid
@@ -7223,7 +7231,11 @@ void md_check_recovery(mddev_t *mddev)
					" thread...\n", 
					" thread...\n", 
					mdname(mddev));
					mdname(mddev));
				/* leave the spares where they are, it shouldn't hurt */
				/* leave the spares where they are, it shouldn't hurt */
				mddev->recovery = 0;
				clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
				clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
				clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
				clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
				clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
			} else
			} else
				md_wakeup_thread(mddev->sync_thread);
				md_wakeup_thread(mddev->sync_thread);
			sysfs_notify_dirent_safe(mddev->sysfs_action);
			sysfs_notify_dirent_safe(mddev->sysfs_action);