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

Commit 24dd469d authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[PATCH] md: allow a manual resync with md



You can trigger a 'check' with
  echo check > /sys/block/mdX/md/scan_mode
or a check-and-repair errors with
  echo repair > /sys/block/mdX/md/scan_mode

and read the current state from the same file.

Note: personalities need to know the different between 'check' and 'repair',
but don't yet.  Until they do, 'check' will be the same as 'repair' and will
just do a normal resync pass.

Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3f294f4f
Loading
Loading
Loading
Loading
+68 −9
Original line number Original line Diff line number Diff line
@@ -1714,9 +1714,60 @@ static struct md_sysfs_entry md_raid_disks = {
	.show = md_show_rdisks,
	.show = md_show_rdisks,
};
};


static ssize_t
md_show_scan(mddev_t *mddev, char *page)
{
	char *type = "none";
	if (mddev->recovery &
	    ((1<<MD_RECOVERY_RUNNING) || (1<<MD_RECOVERY_NEEDED))) {
		if (mddev->recovery & (1<<MD_RECOVERY_SYNC)) {
			if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
				type = "resync";
			else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
				type = "check";
			else
				type = "repair";
		} else
			type = "recover";
	}
	return sprintf(page, "%s\n", type);
}

static ssize_t
md_store_scan(mddev_t *mddev, const char *page, size_t len)
{
	int canscan=0;
	if (mddev->recovery &
	    ((1<<MD_RECOVERY_RUNNING) || (1<<MD_RECOVERY_NEEDED)))
		return -EBUSY;
	down(&mddev->reconfig_sem);
	if (mddev->pers && mddev->pers->sync_request)
		canscan=1;
	up(&mddev->reconfig_sem);
	if (!canscan)
		return -EINVAL;

	if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0)
		set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
	else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0)
		return -EINVAL;
	set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
	set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
	md_wakeup_thread(mddev->thread);
	return len;
}

static struct md_sysfs_entry md_scan_mode = {
	.attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR },
	.show = md_show_scan,
	.store = md_store_scan,
};

static struct attribute *md_default_attrs[] = {
static struct attribute *md_default_attrs[] = {
	&md_level.attr,
	&md_level.attr,
	&md_raid_disks.attr,
	&md_raid_disks.attr,
	&md_scan_mode.attr,
	NULL,
	NULL,
};
};


@@ -3855,7 +3906,8 @@ static void md_do_sync(mddev_t *mddev)


	is_mddev_idle(mddev); /* this also initializes IO event counters */
	is_mddev_idle(mddev); /* this also initializes IO event counters */
	/* we don't use the checkpoint if there's a bitmap */
	/* we don't use the checkpoint if there's a bitmap */
	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap)
	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap
	    && ! test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
		j = mddev->recovery_cp;
		j = mddev->recovery_cp;
	else
	else
		j = 0;
		j = 0;
@@ -4093,9 +4145,13 @@ void md_check_recovery(mddev_t *mddev)
			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
			goto unlock;
			goto unlock;
		}
		}
		if (mddev->recovery)
		/* Clear some bits that don't mean anything, but
			/* probably just the RECOVERY_NEEDED flag */
		 * might be left set
			mddev->recovery = 0;
		 */
		clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
		clear_bit(MD_RECOVERY_ERR, &mddev->recovery);
		clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
		clear_bit(MD_RECOVERY_DONE, &mddev->recovery);


		/* no recovery is running.
		/* no recovery is running.
		 * remove any failed drives, then
		 * remove any failed drives, then
@@ -4129,14 +4185,17 @@ void md_check_recovery(mddev_t *mddev)
				}
				}
		}
		}


		if (!spares && (mddev->recovery_cp == MaxSector )) {
		if (spares) {
			/* nothing we can do ... */
			clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
			clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
		} else if (mddev->recovery_cp < MaxSector) {
			set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
		} else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
			/* nothing to be done ... */
			goto unlock;
			goto unlock;
		}

		if (mddev->pers->sync_request) {
		if (mddev->pers->sync_request) {
			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
			if (!spares)
				set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
			if (spares && mddev->bitmap && ! mddev->bitmap->file) {
			if (spares && mddev->bitmap && ! mddev->bitmap->file) {
				/* We are adding a device or devices to an array
				/* We are adding a device or devices to an array
				 * which has the bitmap stored on all devices.
				 * which has the bitmap stored on all devices.
+4 −0
Original line number Original line Diff line number Diff line
@@ -182,6 +182,8 @@ struct mddev_s
	 * ERR:      and IO error was detected - abort the resync/recovery
	 * ERR:      and IO error was detected - abort the resync/recovery
	 * INTR:     someone requested a (clean) early abort.
	 * INTR:     someone requested a (clean) early abort.
	 * DONE:     thread is done and is waiting to be reaped
	 * DONE:     thread is done and is waiting to be reaped
	 * REQUEST:  user-space has requested a sync (used with SYNC)
	 * CHECK:    user-space request for for check-only, no repair
	 */
	 */
#define	MD_RECOVERY_RUNNING	0
#define	MD_RECOVERY_RUNNING	0
#define	MD_RECOVERY_SYNC	1
#define	MD_RECOVERY_SYNC	1
@@ -189,6 +191,8 @@ struct mddev_s
#define	MD_RECOVERY_INTR	3
#define	MD_RECOVERY_INTR	3
#define	MD_RECOVERY_DONE	4
#define	MD_RECOVERY_DONE	4
#define	MD_RECOVERY_NEEDED	5
#define	MD_RECOVERY_NEEDED	5
#define	MD_RECOVERY_REQUESTED	6
#define	MD_RECOVERY_CHECK	7
	unsigned long			recovery;
	unsigned long			recovery;


	int				in_sync;	/* know to not need resync */
	int				in_sync;	/* know to not need resync */