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

Commit 08a02ecd authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

md: allow reshape_position for md arrays to be set via sysfs



"reshape_position" records how much progress has been made on a "reshape"
(adding drives, changing layout or chunksize).

When it is set, the number of drives, layout and chunksize can have
two possible values, an old an a new.

So allow these different values to be visible, and allow both old and new to
be set: Set the old ones first, then the reshape_position, then the new
values.

Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 42b9bebe
Loading
Loading
Loading
Loading
+44 −28
Original line number Diff line number Diff line
@@ -178,6 +178,21 @@ All md devices contain:
     The size should be at least PAGE_SIZE (4k) and should be a power
     of 2.  This can only be set while assembling an array

  layout
     The "layout" for the array for the particular level.  This is
     simply a number that is interpretted differently by different
     levels.  It can be written while assembling an array.

  reshape_position
     This is either "none" or a sector number within the devices of
     the array where "reshape" is up to.  If this is set, the three
     attributes mentioned above (raid_disks, chunk_size, layout) can
     potentially have 2 values, an old and a new value.  If these
     values differ, reading the attribute returns
        new (old)
     and writing will effect the 'new' value, leaving the 'old'
     unchanged.

  component_size
     For arrays with data redundancy (i.e. not raid0, linear, faulty,
     multipath), all components must be the same size - or at least
@@ -193,11 +208,6 @@ All md devices contain:
     1.2 (newer format in varying locations) or "none" indicating that
     the kernel isn't managing metadata at all.

  layout
     The "layout" for the array for the particular level.  This is
     simply a number that is interpretted differently by different
     levels.  It can be written while assembling an array.

  resync_start
     The point at which resync should start.  If no resync is needed,
     this will be a very large number.  At array creation it will
@@ -259,29 +269,6 @@ All md devices contain:
         like active, but no writes have been seen for a while (safe_mode_delay).


   sync_speed_min
   sync_speed_max
     This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
     however they only apply to the particular array.
     If no value has been written to these, of if the word 'system'
     is written, then the system-wide value is used.  If a value,
     in kibibytes-per-second is written, then it is used.
     When the files are read, they show the currently active value
     followed by "(local)" or "(system)" depending on whether it is
     a locally set or system-wide value.

   sync_completed
     This shows the number of sectors that have been completed of
     whatever the current sync_action is, followed by the number of
     sectors in total that could need to be processed.  The two
     numbers are separated by a '/'  thus effectively showing one
     value, a fraction of the process that is complete.

   sync_speed
     This shows the current actual speed, in K/sec, of the current
     sync_action.  It is averaged over the last 30 seconds.


As component devices are added to an md array, they appear in the 'md'
directory as new directories named
      dev-XXX
@@ -412,6 +399,35 @@ also have
      Note that the numbers are 'bit' numbers, not 'block' numbers.
      They should be scaled by the bitmap_chunksize.

   sync_speed_min
   sync_speed_max
     This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
     however they only apply to the particular array.
     If no value has been written to these, of if the word 'system'
     is written, then the system-wide value is used.  If a value,
     in kibibytes-per-second is written, then it is used.
     When the files are read, they show the currently active value
     followed by "(local)" or "(system)" depending on whether it is
     a locally set or system-wide value.

   sync_completed
     This shows the number of sectors that have been completed of
     whatever the current sync_action is, followed by the number of
     sectors in total that could need to be processed.  The two
     numbers are separated by a '/'  thus effectively showing one
     value, a fraction of the process that is complete.

   sync_speed
     This shows the current actual speed, in K/sec, of the current
     sync_action.  It is averaged over the last 30 seconds.

   suspend_lo
   suspend_hi
     The two values, given as numbers of sectors, indicate a range
     within the array where IO will be blocked.  This is currently
     only supported for raid4/5/6.


Each active md device may also have attributes specific to the
personality module that manages it.
These are specific to the implementation of the module and could
+63 −7
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ static mddev_t * mddev_find(dev_t unit)
	atomic_set(&new->active, 1);
	spin_lock_init(&new->write_lock);
	init_waitqueue_head(&new->sb_wait);
	new->reshape_position = MaxSector;

	new->queue = blk_alloc_queue(GFP_KERNEL);
	if (!new->queue) {
@@ -2242,6 +2243,10 @@ static ssize_t
layout_show(mddev_t *mddev, char *page)
{
	/* just a number, not meaningful for all levels */
	if (mddev->reshape_position != MaxSector &&
	    mddev->layout != mddev->new_layout)
		return sprintf(page, "%d (%d)\n",
			       mddev->new_layout, mddev->layout);
	return sprintf(page, "%d\n", mddev->layout);
}

@@ -2250,12 +2255,15 @@ layout_store(mddev_t *mddev, const char *buf, size_t len)
{
	char *e;
	unsigned long n = simple_strtoul(buf, &e, 10);
	if (mddev->pers)
		return -EBUSY;

	if (!*buf || (*e && *e != '\n'))
		return -EINVAL;

	if (mddev->pers)
		return -EBUSY;
	if (mddev->reshape_position != MaxSector)
		mddev->new_layout = n;
	else
		mddev->layout = n;
	return len;
}
@@ -2268,6 +2276,10 @@ raid_disks_show(mddev_t *mddev, char *page)
{
	if (mddev->raid_disks == 0)
		return 0;
	if (mddev->reshape_position != MaxSector &&
	    mddev->delta_disks != 0)
		return sprintf(page, "%d (%d)\n", mddev->raid_disks,
			       mddev->raid_disks - mddev->delta_disks);
	return sprintf(page, "%d\n", mddev->raid_disks);
}

@@ -2285,7 +2297,11 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len)

	if (mddev->pers)
		rv = update_raid_disks(mddev, n);
	else
	else if (mddev->reshape_position != MaxSector) {
		int olddisks = mddev->raid_disks - mddev->delta_disks;
		mddev->delta_disks = n - olddisks;
		mddev->raid_disks = n;
	} else
		mddev->raid_disks = n;
	return rv ? rv : len;
}
@@ -2295,6 +2311,10 @@ __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store);
static ssize_t
chunk_size_show(mddev_t *mddev, char *page)
{
	if (mddev->reshape_position != MaxSector &&
	    mddev->chunk_size != mddev->new_chunk)
		return sprintf(page, "%d (%d)\n", mddev->new_chunk,
			       mddev->chunk_size);
	return sprintf(page, "%d\n", mddev->chunk_size);
}

@@ -2305,11 +2325,14 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
	char *e;
	unsigned long n = simple_strtoul(buf, &e, 10);

	if (mddev->pers)
		return -EBUSY;
	if (!*buf || (*e && *e != '\n'))
		return -EINVAL;

	if (mddev->pers)
		return -EBUSY;
	else if (mddev->reshape_position != MaxSector)
		mddev->new_chunk = n;
	else
		mddev->chunk_size = n;
	return len;
}
@@ -2896,6 +2919,37 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry md_suspend_hi =
__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);

static ssize_t
reshape_position_show(mddev_t *mddev, char *page)
{
	if (mddev->reshape_position != MaxSector)
		return sprintf(page, "%llu\n",
			       (unsigned long long)mddev->reshape_position);
	strcpy(page, "none\n");
	return 5;
}

static ssize_t
reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
{
	char *e;
	unsigned long long new = simple_strtoull(buf, &e, 10);
	if (mddev->pers)
		return -EBUSY;
	if (buf == e || (*e && *e != '\n'))
		return -EINVAL;
	mddev->reshape_position = new;
	mddev->delta_disks = 0;
	mddev->new_level = mddev->level;
	mddev->new_layout = mddev->layout;
	mddev->new_chunk = mddev->chunk_size;
	return len;
}

static struct md_sysfs_entry md_reshape_position =
__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
       reshape_position_store);


static struct attribute *md_default_attrs[] = {
	&md_level.attr,
@@ -2908,6 +2962,7 @@ static struct attribute *md_default_attrs[] = {
	&md_new_device.attr,
	&md_safe_delay.attr,
	&md_array_state.attr,
	&md_reshape_position.attr,
	NULL,
};

@@ -3446,6 +3501,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
		mddev->size = 0;
		mddev->raid_disks = 0;
		mddev->recovery_cp = 0;
		mddev->reshape_position = MaxSector;

	} else if (mddev->pers)
		printk(KERN_INFO "md: %s switched to read-only mode.\n",