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

Commit 5e96ee65 authored by Neil Brown's avatar Neil Brown
Browse files

Allow setting start point for requested check/repair



This makes it possible to just resync a small part of an array.
e.g. if a drive reports that it has questionable sectors,
a 'repair' of just the region covering those sectors will
cause them to be read and, if there is an error, re-written
with correct data.

Signed-off-by: default avatarNeil Brown <neilb@suse.de>
parent a0da84f3
Loading
Loading
Loading
Loading
+42 −5
Original line number Diff line number Diff line
@@ -278,6 +278,7 @@ static mddev_t * mddev_find(dev_t unit)
	init_waitqueue_head(&new->sb_wait);
	init_waitqueue_head(&new->recovery_wait);
	new->reshape_position = MaxSector;
	new->resync_min = 0;
	new->resync_max = MaxSector;
	new->level = LEVEL_NONE;

@@ -3074,6 +3075,36 @@ sync_completed_show(mddev_t *mddev, char *page)

static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);

static ssize_t
min_sync_show(mddev_t *mddev, char *page)
{
	return sprintf(page, "%llu\n",
		       (unsigned long long)mddev->resync_min);
}
static ssize_t
min_sync_store(mddev_t *mddev, const char *buf, size_t len)
{
	unsigned long long min;
	if (strict_strtoull(buf, 10, &min))
		return -EINVAL;
	if (min > mddev->resync_max)
		return -EINVAL;
	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
		return -EBUSY;

	/* Must be a multiple of chunk_size */
	if (mddev->chunk_size) {
		if (min & (sector_t)((mddev->chunk_size>>9)-1))
			return -EINVAL;
	}
	mddev->resync_min = min;

	return len;
}

static struct md_sysfs_entry md_min_sync =
__ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);

static ssize_t
max_sync_show(mddev_t *mddev, char *page)
{
@@ -3089,9 +3120,10 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
	if (strncmp(buf, "max", 3) == 0)
		mddev->resync_max = MaxSector;
	else {
		char *ep;
		unsigned long long max = simple_strtoull(buf, &ep, 10);
		if (ep == buf || (*ep != 0 && *ep != '\n'))
		unsigned long long max;
		if (strict_strtoull(buf, 10, &max))
			return -EINVAL;
		if (max < mddev->resync_min)
			return -EINVAL;
		if (max < mddev->resync_max &&
		    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3222,6 +3254,7 @@ static struct attribute *md_redundancy_attrs[] = {
	&md_sync_speed.attr,
	&md_sync_force_parallel.attr,
	&md_sync_completed.attr,
	&md_min_sync.attr,
	&md_max_sync.attr,
	&md_suspend_lo.attr,
	&md_suspend_hi.attr,
@@ -3777,6 +3810,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
		mddev->size = 0;
		mddev->raid_disks = 0;
		mddev->recovery_cp = 0;
		mddev->resync_min = 0;
		mddev->resync_max = MaxSector;
		mddev->reshape_position = MaxSector;
		mddev->external = 0;
@@ -5625,9 +5659,11 @@ void md_do_sync(mddev_t *mddev)
		max_sectors = mddev->resync_max_sectors;
		mddev->resync_mismatches = 0;
		/* we don't use the checkpoint if there's a bitmap */
		if (!mddev->bitmap &&
		    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
		if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
			j = mddev->resync_min;
		else if (!mddev->bitmap)
			j = mddev->recovery_cp;

	} else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
		max_sectors = mddev->size << 1;
	else {
@@ -5796,6 +5832,7 @@ void md_do_sync(mddev_t *mddev)

 skip:
	mddev->curr_resync = 0;
	mddev->resync_min = 0;
	mddev->resync_max = MaxSector;
	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
	wake_up(&resync_wait);
+2 −0
Original line number Diff line number Diff line
@@ -227,6 +227,8 @@ struct mddev_s
	atomic_t			recovery_active; /* blocks scheduled, but not written */
	wait_queue_head_t		recovery_wait;
	sector_t			recovery_cp;
	sector_t			resync_min;	/* user requested sync
							 * starts here */
	sector_t			resync_max;	/* resync should pause
							 * when it gets here */