All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] imsm: volume expand
@ 2012-04-13 14:51 Adam Kwolek
  2012-04-13 14:51 ` [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for Raid1/10 Adam Kwolek
  2012-04-17  2:56 ` [PATCH 00/14] imsm: volume expand NeilBrown
  0 siblings, 2 replies; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:51 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

This patch series introduces the possibility to increase volume size using
existing free space in container without adding spare disks to imsm metadata.

Adam Kwolek (14):
  imsm: FIX: Update function imsm_num_data_members() for Raid1/10
  imsm: FIX: Add volume size expand support to imsm_analyze_change()
  imsm: Add new metadata update for volume size expansion
  imsm: Execute size change for external metatdata
  FIX: Support metadata changes rollback
  imsm: FIX: Support metadata changes rollback
  FIX: Extend size of raid0 array
  FIX: Respect metadata size limitations
  FIX: Detect error and rollback metadata
  imsm: Add function imsm_get_free_size()
  imsm: Support setting max size for size change operation
  imsm: FIX: Component size alignment check
  FIX: Size change is possible as standalone change only
  FIX: Assembled second array is in read only state during reshape

 Assemble.c    |   29 ++++--
 Grow.c        |  163 ++++++++++++++++++++++-------
 mdadm.h       |    4 +
 super-intel.c |  318 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 438 insertions(+), 76 deletions(-)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for Raid1/10
  2012-04-13 14:51 [PATCH 00/14] imsm: volume expand Adam Kwolek
@ 2012-04-13 14:51 ` Adam Kwolek
  2012-04-13 14:51   ` [PATCH 02/14] imsm: FIX: Add volume size expand support to imsm_analyze_change() Adam Kwolek
  2012-04-17  2:56 ` [PATCH 00/14] imsm: volume expand NeilBrown
  1 sibling, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:51 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Function imsm_num_data_members() returns wrong value for raid 1 and 10.
It returns all data member but it should return number of unique data
members (excluding mirror devices)

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index b087b32..3aabcc0 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2032,9 +2032,11 @@ static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map)
 
 	switch (get_imsm_raid_level(map)) {
 	case 0:
+		return map->num_members;
+		break;
 	case 1:
 	case 10:
-		return map->num_members;
+		return map->num_members/2;
 	case 5:
 		return map->num_members - 1;
 	default:
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/14] imsm: FIX: Add volume size expand support to imsm_analyze_change()
  2012-04-13 14:51 ` [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for Raid1/10 Adam Kwolek
@ 2012-04-13 14:51   ` Adam Kwolek
  2012-04-13 14:51     ` [PATCH 03/14] imsm: Add new metadata update for volume size expansion Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:51 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Patch adds ability to function imsm_analyze_change() for:
1. Detect size change request for volume operation.
2. Check and correct size for change.
3. Set new change kind to CH_ARRAY_SIZE

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index 3aabcc0..b657249 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -405,6 +405,7 @@ struct extent {
 enum imsm_reshape_type {
 	CH_TAKEOVER,
 	CH_MIGRATION,
+	CH_ARRAY_SIZE,
 };
 
 /* definition of messages passed to imsm_process_update */
@@ -9728,6 +9729,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 	int devNumChange = 0;
 	/* imsm compatible layout value for array geometry verification */
 	int imsm_layout = -1;
+	int data_disks;
+	struct imsm_dev *dev;
+	struct intel_super *super;
+	long long current_size;
 
 	getinfo_super_imsm_volume(st, &info, NULL);
 	if ((geo->level != info.array.level) &&
@@ -9809,6 +9814,47 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 		geo->chunksize = info.array.chunk_size;
 
 	chunk = geo->chunksize / 1024;
+
+	super = st->sb;
+	dev = get_imsm_dev(super, super->current_vol);
+	data_disks = imsm_num_data_members(dev , MAP_0);
+	/* compute current size in K per disk member
+	 */
+	current_size = info.custom_array_size / 2 / data_disks;
+
+	if ((current_size != geo->size) && (geo->size > 0)) {
+		if (change != -1) {
+			fprintf(stderr,
+				Name " Error. Size change should be the only "
+				"one at a time.\n");
+			change = -1;
+			goto analyse_change_exit;
+		}
+		if ((super->current_vol + 1) != super->anchor->num_raid_devs) {
+			fprintf(stderr,
+				Name " Error. The last volume in container "
+				"can be expanded only (%i/%i).\n",
+				super->current_vol, st->devnum);
+			goto analyse_change_exit;
+		}
+		geo->size *= 2;
+		/* round size due to metadata compatibility
+		 */
+		geo->size = (geo->size >> SECT_PER_MB_SHIFT)
+			    << SECT_PER_MB_SHIFT;
+		dprintf("Prepare update for size change to %llu\n", geo->size );
+		if (current_size >= geo->size) {
+			fprintf(stderr,
+				Name " Error. Size expanssion is supported only"
+				" (current size is %llu, requested size "
+				"/rounded/ is %llu).\n",
+				current_size, geo->size);
+			goto analyse_change_exit;
+		}
+		geo->size *= data_disks;
+		geo->raid_disks = dev->vol.map->num_members;
+		change = CH_ARRAY_SIZE;
+	}
 	if (!validate_geometry_imsm(st,
 				    geo->level,
 				    imsm_layout,
@@ -9978,6 +10024,11 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
 				free(u);
 		}
 		break;
+		case CH_ARRAY_SIZE: {
+			/* ToDo: Prepare metadata update here
+			 */
+		}
+		break;
 		default:
 			ret_val = 1;
 		}
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/14] imsm: Add new metadata update for volume size expansion
  2012-04-13 14:51   ` [PATCH 02/14] imsm: FIX: Add volume size expand support to imsm_analyze_change() Adam Kwolek
@ 2012-04-13 14:51     ` Adam Kwolek
  2012-04-13 14:51       ` [PATCH 04/14] imsm: Execute size change for external metatdata Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:51 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Add new meatdata update type imsm_update_size_change, and update metadata
for volume size expansion operation.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |  132 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 124 insertions(+), 8 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index b657249..9220318 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -419,6 +419,7 @@ enum imsm_update_type {
 	update_reshape_migration,
 	update_takeover,
 	update_general_migration_checkpoint,
+	update_size_change,
 };
 
 struct imsm_update_activate_spare {
@@ -471,6 +472,12 @@ struct imsm_update_reshape_migration {
 	int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
 };
 
+struct imsm_update_size_change {
+	enum imsm_update_type type;
+	int subdev;
+	long long new_size;
+};
+
 struct imsm_update_general_migration_checkpoint {
 	enum imsm_update_type type;
 	__u32 curr_migr_unit;
@@ -6976,7 +6983,8 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
 	super->updates_pending++;
 }
 
-static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
+static unsigned long long imsm_set_array_size(struct imsm_dev *dev,
+					      long long new_size)
 {
 	int used_disks = imsm_num_data_members(dev, MAP_0);
 	unsigned long long array_blocks;
@@ -6995,8 +7003,17 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
 
 	/* set array size in metadata
 	 */
-	map = get_imsm_map(dev, MAP_0);
-	array_blocks = blocks_per_member(map) * used_disks;
+	if (new_size <= 0) {
+		/* OLCE size change is caused by added disks
+		 */
+		map = get_imsm_map(dev, MAP_0);
+		array_blocks = blocks_per_member(map) * used_disks;
+	} else {
+		/* Online Volume Size Change
+		 * Using  available free space
+		 */
+		array_blocks = new_size;
+	}
 
 	/* round array size down to closest MB
 	 */
@@ -7053,7 +7070,7 @@ static void imsm_progress_container_reshape(struct intel_super *super)
 		memcpy(map2, map, copy_map_size);
 		map2->num_members = prev_num_members;
 
-		imsm_set_array_size(dev);
+		imsm_set_array_size(dev, -1);
 		super->clean_migration_record_by_mdmon = 1;
 		super->updates_pending++;
 	}
@@ -7943,7 +7960,7 @@ skip_disk_add:
 			*tofree = *space_list;
 			/* calculate new size
 			 */
-			imsm_set_array_size(new_dev);
+			imsm_set_array_size(new_dev, -1);
 
 			ret_val = 1;
 		}
@@ -7958,6 +7975,44 @@ error_disk_add:
 	return ret_val;
 }
 
+static int apply_size_change_update(struct imsm_update_size_change *u,
+		struct intel_super *super)
+{
+	struct intel_dev *id;
+	int ret_val = 0;
+
+	dprintf("apply_size_change_update()\n");
+	if ((u->subdev < 0) ||
+	    (u->subdev > 1)) {
+		dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev);
+		return ret_val;
+	}
+
+	for (id = super->devlist ; id; id = id->next) {
+		if (id->index == (unsigned)u->subdev) {
+			struct imsm_dev *dev = get_imsm_dev(super, u->subdev);
+			struct imsm_map *map = get_imsm_map(dev, MAP_0);
+			int used_disks = imsm_num_data_members(dev, MAP_0);
+			unsigned long long blocks_per_member;
+
+			/* calculate new size
+			 */
+			blocks_per_member = u->new_size / used_disks;
+			dprintf("imsm: apply_size_change_update(size: %llu, "
+				"blocks per member: %llu)\n",
+				u->new_size, blocks_per_member);
+			set_blocks_per_member(map, blocks_per_member);
+			imsm_set_array_size(dev, u->new_size);
+
+			ret_val = 1;
+			break;
+		}
+	}
+
+	return ret_val;
+}
+
+
 static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
 				       struct intel_super *super,
 				       struct active_array *active_array)
@@ -8157,7 +8212,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
 			newmap = get_imsm_map(newdev, MAP_1);
 			memcpy(newmap, oldmap, sizeof_imsm_map(oldmap));
 
-			imsm_set_array_size(newdev);
+			imsm_set_array_size(newdev, -1);
 		}
 
 		sp = (void **)id->dev;
@@ -8365,6 +8420,12 @@ static void imsm_process_update(struct supertype *st,
 			super->updates_pending++;
 		break;
 	}
+	case update_size_change: {
+		struct imsm_update_size_change *u = (void *)update->buf;
+		if (apply_size_change_update(u, super))
+			super->updates_pending++;
+		break;
+	}
 	case update_activate_spare: {
 		struct imsm_update_activate_spare *u = (void *) update->buf; 
 		if (apply_update_activate_spare(u, super, st->arrays))
@@ -8759,6 +8820,9 @@ static void imsm_prepare_update(struct supertype *st,
 		dprintf("New anchor length is %llu\n", (unsigned long long)len);
 		break;
 	}
+	case update_size_change: {
+		break;
+	}
 	case update_create_array: {
 		struct imsm_update_create_array *u = (void *) update->buf;
 		struct intel_dev *dv;
@@ -9616,6 +9680,43 @@ abort:
 	return 0;
 }
 
+
+/******************************************************************************
+ * function: imsm_create_metadata_update_for_size_change()
+ *           Creates update for IMSM array for array size change.
+ *
+ ******************************************************************************/
+static int imsm_create_metadata_update_for_size_change(
+				struct supertype *st,
+				struct geo_params *geo,
+				struct imsm_update_size_change **updatep)
+{
+	struct intel_super *super = st->sb;
+	int update_memory_size = 0;
+	struct imsm_update_size_change *u = NULL;
+
+	dprintf("imsm_create_metadata_update_for_size_change(enter)"
+		" New size = %llu\n", geo->size);
+
+	/* size of all update data without anchor */
+	update_memory_size = sizeof(struct imsm_update_size_change);
+
+	u = calloc(1, update_memory_size);
+	if (u == NULL) {
+		dprintf("error: cannot get memory for "
+			"imsm_create_metadata_update_for_size_change\n");
+		return 0;
+	}
+	u->type = update_size_change;
+	u->subdev = super->current_vol;
+	u->new_size = geo->size;
+
+	dprintf("imsm: reshape update preparation : OK\n");
+	*updatep = u;
+
+	return update_memory_size;
+}
+
 /******************************************************************************
  * function: imsm_create_metadata_update_for_migration()
  *           Creates update for IMSM array.
@@ -10025,8 +10126,23 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
 		}
 		break;
 		case CH_ARRAY_SIZE: {
-			/* ToDo: Prepare metadata update here
-			 */
+			struct imsm_update_size_change *u = NULL;
+			int len =
+				imsm_create_metadata_update_for_size_change(
+					st, &geo, &u);
+			if (len < 1) {
+				dprintf("imsm: "
+					"Cannot prepare update\n");
+				break;
+			}
+			ret_val = 0;
+			/* update metadata locally */
+			imsm_update_metadata_locally(st, u, len);
+			/* and possibly remotely */
+			if (st->update_tail)
+				append_metadata_update(st, u, len);
+			else
+				free(u);
 		}
 		break;
 		default:
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/14] imsm: Execute size change for external metatdata
  2012-04-13 14:51     ` [PATCH 03/14] imsm: Add new metadata update for volume size expansion Adam Kwolek
@ 2012-04-13 14:51       ` Adam Kwolek
  2012-04-13 14:51         ` [PATCH 05/14] FIX: Support metadata changes rollback Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:51 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

For external metatdata ioctl doesn't set new size. Set new size using sysfs.
Put code for size change in to function to re-use the same code as during
On-line Capacity Expansion

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Grow.c |   78 ++++++++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/Grow.c b/Grow.c
index e3ef8d4..5fd44aa 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1386,6 +1386,44 @@ char *analyse_change(struct mdinfo *info, struct reshape *re)
 	return NULL;
 }
 
+static int set_array_size(struct supertype *st, struct mdinfo *sra,
+			  char *text_version)
+{
+	struct mdinfo *info;
+	char *subarray;
+	int ret_val = -1;
+
+	if ((st == NULL) || (sra == NULL))
+		return ret_val;
+
+	if (text_version == NULL)
+		text_version = sra->text_version;
+	subarray = strchr(text_version+1, '/')+1;
+	info = st->ss->container_content(st, subarray);
+	if (info) {
+		unsigned long long current_size = 0;
+		unsigned long long new_size =
+			info->custom_array_size/2;
+
+		if (sysfs_get_ll(sra, NULL, "array_size", &current_size) == 0 &&
+		    new_size > current_size) {
+			if (sysfs_set_num(sra, NULL, "array_size", new_size)
+					< 0)
+				dprintf("Error: Cannot set array size");
+			else {
+				ret_val = 0;
+				dprintf("Array size changed");
+			}
+			dprintf(" from %llu to %llu.\n",
+				current_size, new_size);
+		}
+		sysfs_free(info);
+	} else
+		dprintf("Error: set_array_size(): info pointer in NULL\n");
+
+	return ret_val;
+}
+
 static int reshape_array(char *container, int fd, char *devname,
 			 struct supertype *st, struct mdinfo *info,
 			 int force, struct mddev_dev *devlist,
@@ -1636,7 +1674,6 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 				"2TB per device\n");
 			size = min_csize;
 		}
-
 		array.size = size;
 		if (array.size != size) {
 			/* got truncated to 32bit, write to
@@ -1647,8 +1684,14 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 						   "component_size", size);
 			else
 				rv = -1;
-		} else
+		} else {
 			rv = ioctl(fd, SET_ARRAY_INFO, &array);
+			/* manage array size when it is managed externally
+			 */
+			if ((rv == 0) && st->ss->external)
+				rv = set_array_size(st, sra, sra->text_version);
+		}
+
 		if (rv != 0) {
 			int err = errno;
 
@@ -2507,35 +2550,8 @@ started:
 	 */
 	if (reshape.before.data_disks !=
 	    reshape.after.data_disks &&
-	    info->custom_array_size) {
-		struct mdinfo *info2;
-		char *subarray = strchr(info->text_version+1, '/')+1;
-
-		info2 = st->ss->container_content(st, subarray);
-		if (info2) {
-			unsigned long long current_size = 0;
-			unsigned long long new_size =
-				info2->custom_array_size/2;
-
-			if (sysfs_get_ll(sra,
-					 NULL,
-					 "array_size",
-					 &current_size) == 0 &&
-			    new_size > current_size) {
-				if (sysfs_set_num(sra, NULL,
-						  "array_size", new_size)
-				    < 0)
-					dprintf("Error: Cannot"
-						" set array size");
-				else
-					dprintf("Array size "
-						"changed");
-				dprintf(" from %llu to %llu.\n",
-					current_size, new_size);
-			}
-			sysfs_free(info2);
-		}
-	}
+	    info->custom_array_size)
+		set_array_size(st, info, info->text_version);
 
 	if (info->new_level != reshape.level) {
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/14] FIX: Support metadata changes rollback
  2012-04-13 14:51       ` [PATCH 04/14] imsm: Execute size change for external metatdata Adam Kwolek
@ 2012-04-13 14:51         ` Adam Kwolek
  2012-04-13 14:52           ` [PATCH 06/14] imsm: " Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:51 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Function reshape_super() guards metadata changes.
It is used to apply changes rollback in error case also.
As change (apply and rollback) can be not bi-directional reshape_super()
has to know if current action is metadata change that should be guarded
using metadata restrictions, or this is metadata rollback change
executed due to error occurrence.

In second case change has to be unconditional.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Grow.c        |   16 ++++++++++------
 mdadm.h       |    4 ++++
 super-intel.c |    2 +-
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/Grow.c b/Grow.c
index 5fd44aa..8c7bafc 100644
--- a/Grow.c
+++ b/Grow.c
@@ -650,7 +650,7 @@ static void wait_reshape(struct mdinfo *sra)
 static int reshape_super(struct supertype *st, long long size, int level,
 			 int layout, int chunksize, int raid_disks,
 			 int delta_disks, char *backup_file, char *dev,
-			 int verbose)
+			 int direction, int verbose)
 {
 	/* nothing extra to check in the native case */
 	if (!st->ss->external)
@@ -664,7 +664,7 @@ static int reshape_super(struct supertype *st, long long size, int level,
 
 	return st->ss->reshape_super(st, size, level, layout, chunksize,
 				     raid_disks, delta_disks, backup_file, dev,
-				     verbose);
+				     direction, verbose);
 }
 
 static void sync_metadata(struct supertype *st)
@@ -1631,7 +1631,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 			orig_size = array.size;
 
 		if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL,
-				  devname, !quiet)) {
+				  devname, APPLY_METADATA_CHANGES, !quiet)) {
 			rv = 1;
 			goto release;
 		}
@@ -1697,7 +1697,9 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 
 			/* restore metadata */
 			if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
-					  UnSet, NULL, devname, !quiet) == 0)
+					  UnSet, NULL, devname,
+					  ROLLBACK_METADATA_CHANGES,
+					  !quiet) == 0)
 				sync_metadata(st);
 			fprintf(stderr, Name ": Cannot set device size for %s: %s\n",
 				devname, strerror(err));
@@ -1909,7 +1911,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 		if (reshape_super(st, info.component_size, info.new_level,
 				  info.new_layout, info.new_chunk,
 				  info.array.raid_disks, info.delta_disks,
-				  backup_file, devname, quiet)) {
+				  backup_file, devname, APPLY_METADATA_CHANGES,
+				  quiet)) {
 			rv = 1;
 			goto release;
 		}
@@ -2608,7 +2611,8 @@ int reshape_container(char *container, char *devname,
 	    reshape_super(st, -1, info->new_level,
 			  info->new_layout, info->new_chunk,
 			  info->array.raid_disks, info->delta_disks,
-			  backup_file, devname, quiet)) {
+			  backup_file, devname, APPLY_METADATA_CHANGES,
+			  quiet)) {
 		unfreeze(st);
 		return 1;
 	}
diff --git a/mdadm.h b/mdadm.h
index 9f58800..686d4b4 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -740,9 +740,13 @@ extern struct superswitch {
 	 * initialized to indicate if reshape is being performed at the
 	 * container or subarray level
 	 */
+#define APPLY_METADATA_CHANGES		1
+#define ROLLBACK_METADATA_CHANGES	0
+
 	int (*reshape_super)(struct supertype *st, long long size, int level,
 			     int layout, int chunksize, int raid_disks,
 			     int delta_disks, char *backup, char *dev,
+			     int direction,
 			     int verbose); /* optional */
 	int (*manage_reshape)( /* optional */
 		int afd, struct mdinfo *sra, struct reshape *reshape,
diff --git a/super-intel.c b/super-intel.c
index 9220318..62aeeb3 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -10020,7 +10020,7 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo)
 static int imsm_reshape_super(struct supertype *st, long long size, int level,
 			      int layout, int chunksize, int raid_disks,
 			      int delta_disks, char *backup, char *dev,
-			      int verbose)
+			      int direction, int verbose)
 {
 	int ret_val = 1;
 	struct geo_params geo;
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/14] imsm: FIX: Support metadata changes rollback
  2012-04-13 14:51         ` [PATCH 05/14] FIX: Support metadata changes rollback Adam Kwolek
@ 2012-04-13 14:52           ` Adam Kwolek
  2012-04-13 14:52             ` [PATCH 07/14] FIX: Extend size of raid0 array Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Add metadata rollback specific code for imsm.
Let reshape_super() ability to differentiate metadata apply and rollback
actions.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |   56 ++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index 62aeeb3..2a050fc 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -9472,7 +9472,8 @@ static int imsm_find_array_minor_by_subdev(int subdev, int container, int *minor
 
 static int imsm_reshape_is_allowed_on_container(struct supertype *st,
 						struct geo_params *geo,
-						int *old_raid_disks)
+						int *old_raid_disks,
+						int direction)
 {
 	/* currently we only support increasing the number of devices
 	 * for a container.  This increases the number of device for each
@@ -9496,6 +9497,12 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
 		return ret_val;
 	}
 
+	if (direction == ROLLBACK_METADATA_CHANGES) {
+		dprintf("imsm: Metadata changes rollback is not supported for "
+			"container operation.\n");
+		return ret_val;
+	}
+
 	info = container_content_imsm(st, NULL);
 	for (member = info; member; member = member->next) {
 		int result;
@@ -9816,11 +9823,13 @@ static void imsm_update_metadata_locally(struct supertype *st,
 * Function:	imsm_analyze_change
 * Description:	Function analyze change for single volume
 * 		and validate if transition is supported
-* Parameters:	Geometry parameters, supertype structure
+* Parameters:	Geometry parameters, supertype structure,
+*		metadata change direction (apply/rollback)
 * Returns:	Operation type code on success, -1 if fail
 ****************************************************************************/
 enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
-					   struct geo_params *geo)
+					   struct geo_params *geo,
+					   int direction)
 {
 	struct mdinfo info;
 	int change = -1;
@@ -9939,18 +9948,24 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 			goto analyse_change_exit;
 		}
 		geo->size *= 2;
-		/* round size due to metadata compatibility
-		 */
-		geo->size = (geo->size >> SECT_PER_MB_SHIFT)
-			    << SECT_PER_MB_SHIFT;
-		dprintf("Prepare update for size change to %llu\n", geo->size );
-		if (current_size >= geo->size) {
-			fprintf(stderr,
-				Name " Error. Size expanssion is supported only"
-				" (current size is %llu, requested size "
-				"/rounded/ is %llu).\n",
-				current_size, geo->size);
-			goto analyse_change_exit;
+		if ((direction == ROLLBACK_METADATA_CHANGES)) {
+			/* accept size for rollback only
+			*/
+		} else {
+			/* round size due to metadata compatibility
+			*/
+			geo->size = (geo->size >> SECT_PER_MB_SHIFT)
+				    << SECT_PER_MB_SHIFT;
+			dprintf("Prepare update for size change to %llu\n",
+				geo->size );
+			if (current_size >= geo->size) {
+				fprintf(stderr,
+					Name " Error. Size expanssion is "
+					"supported only (current size is %llu, "
+					"requested size /rounded/ is %llu).\n",
+					current_size, geo->size);
+				goto analyse_change_exit;
+			}
 		}
 		geo->size *= data_disks;
 		geo->raid_disks = dev->vol.map->num_members;
@@ -9980,7 +9995,12 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 	}
 
 analyse_change_exit:
-
+	if ((direction == ROLLBACK_METADATA_CHANGES) &&
+	     ((change == CH_MIGRATION) || (change == CH_TAKEOVER))) {
+		dprintf("imsm: Metadata changes rollback is not supported for "
+			"migration and takeover operations.\n");
+		change = -1;
+	}
 	return change;
 }
 
@@ -10051,7 +10071,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
 		int old_raid_disks = 0;
 
 		if (imsm_reshape_is_allowed_on_container(
-			    st, &geo, &old_raid_disks)) {
+			    st, &geo, &old_raid_disks, direction)) {
 			struct imsm_update_reshape *u = NULL;
 			int len;
 
@@ -10100,7 +10120,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
 			goto exit_imsm_reshape_super;
 		}
 		super->current_vol = dev->index;
-		change = imsm_analyze_change(st, &geo);
+		change = imsm_analyze_change(st, &geo, direction);
 		switch (change) {
 		case CH_TAKEOVER:
 			ret_val = imsm_takeover(st, &geo);
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/14] FIX: Extend size of raid0 array
  2012-04-13 14:52           ` [PATCH 06/14] imsm: " Adam Kwolek
@ 2012-04-13 14:52             ` Adam Kwolek
  2012-04-13 14:52               ` [PATCH 08/14] FIX: Respect metadata size limitations Adam Kwolek
  2012-04-17  2:52               ` [PATCH 07/14] FIX: Extend size of raid0 array NeilBrown
  0 siblings, 2 replies; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

For raid0, takeover operation is required for size change.
Add takeover to degraded raid4 before size change and back to raid0 after.
Array information has to be read again from md after takeover.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Grow.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/Grow.c b/Grow.c
index 8c7bafc..e8f6554 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 		long long orig_size = get_component_size(fd)/2;
 		long long min_csize;
 		struct mdinfo *mdi;
+		int raid0_takeover = 0;
 
 		if (orig_size == 0)
 			orig_size = array.size;
@@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 				"2TB per device\n");
 			size = min_csize;
 		}
+		if (st->ss->external) {
+			if (sra->array.level == 0) {
+				rv = sysfs_set_str(sra, NULL, "level",
+						   "raid5");
+				if (!rv) {
+					raid0_takeover = 1;
+					/* get array parametes after takeover
+					 * to chane one parameter at time only
+					 */
+					rv = ioctl(fd, GET_ARRAY_INFO, &array);
+				}
+			}
+			/* make sure mdmon is
+			 * aware of the new level */
+			if (!mdmon_running(st->container_dev))
+				start_mdmon(st->container_dev);
+			ping_monitor(container);
+			if (mdmon_running(st->container_dev) &&
+					st->update_tail == NULL)
+				st->update_tail = &st->updates;
+		}
+
 		array.size = size;
 		if (array.size != size) {
 			/* got truncated to 32bit, write to
@@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 				rv = -1;
 		} else {
 			rv = ioctl(fd, SET_ARRAY_INFO, &array);
+
 			/* manage array size when it is managed externally
 			 */
 			if ((rv == 0) && st->ss->external)
 				rv = set_array_size(st, sra, sra->text_version);
 		}
 
+		if (raid0_takeover) {
+			/* do not recync non-existing parity,
+			 * we will drop it anyway
+			 */
+			sysfs_set_str(sra, NULL, "sync_action", "idle");
+			/* go back to raid0, drop parity disk
+			 */
+			sysfs_set_str(sra, NULL, "level", "raid0");
+			ioctl(fd, GET_ARRAY_INFO, &array);
+		}
+
 		if (rv != 0) {
 			int err = errno;
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/14] FIX: Respect metadata size limitations
  2012-04-13 14:52             ` [PATCH 07/14] FIX: Extend size of raid0 array Adam Kwolek
@ 2012-04-13 14:52               ` Adam Kwolek
  2012-04-13 14:52                 ` [PATCH 09/14] FIX: Detect error and rollback metadata Adam Kwolek
  2012-04-17  2:52               ` [PATCH 07/14] FIX: Extend size of raid0 array NeilBrown
  1 sibling, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

When reshape_super() updates metadata with new size, due to some metadata
limitations saved value can be different than requested value by user.
Update size (read it from metadata) for setting it in md.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Grow.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/Grow.c b/Grow.c
index e8f6554..86d1020 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1637,6 +1637,27 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 			goto release;
 		}
 		sync_metadata(st);
+		if (st->ss->external) {
+			/* metadata can have size limitation
+			 * update size value according to metadata information
+			 */
+			struct mdinfo *sizeinfo =
+				st->ss->container_content(st, subarray);
+			if (sizeinfo) {
+				unsigned long long new_size =
+					sizeinfo->custom_array_size/2;
+				int data_disks = get_data_disks(
+						sizeinfo->array.level,
+						sizeinfo->array.layout,
+						sizeinfo->array.raid_disks);
+				new_size /= data_disks;
+				dprintf("Metadata size correction from %llu to "
+					"%llu (%llu)\n", orig_size, new_size,
+					new_size * data_disks);
+				size = new_size;
+				sysfs_free(sizeinfo);
+			}
+		}
 
 		/* Update the size of each member device in case
 		 * they have been resized.  This will never reduce
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/14] FIX: Detect error and rollback metadata
  2012-04-13 14:52               ` [PATCH 08/14] FIX: Respect metadata size limitations Adam Kwolek
@ 2012-04-13 14:52                 ` Adam Kwolek
  2012-04-13 14:52                   ` [PATCH 10/14] imsm: Add function imsm_get_free_size() Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Some setting size error cases were not detected.
When error occurs, stop setting new size action and rollback metadata
changes.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Grow.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/Grow.c b/Grow.c
index 86d1020..1b45199 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1665,9 +1665,12 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 		 * understands '0' to mean 'max'.
 		 */
 		min_csize = 0;
+		rv = 0;
 		for (mdi = sra->devs; mdi; mdi = mdi->next) {
-			if (sysfs_set_num(sra, mdi, "size", size) < 0)
+			if (sysfs_set_num(sra, mdi, "size", size) < 0) {
+				rv = 1;
 				break;
+			}
 			if (array.not_persistent == 0 &&
 			    array.major_version == 0 &&
 			    get_linux_version() < 3001000) {
@@ -1682,11 +1685,16 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 				}
 			}
 		}
+		if (rv) {
+			fprintf(stderr, Name ": Cannot set size on "
+				"array members.\n");
+			goto size_change_error;
+		}
 		if (min_csize && size > min_csize) {
 			fprintf(stderr, Name ": Cannot safely make this array "
 				"use more than 2TB per device on this kernel.\n");
 			rv = 1;
-			goto release;
+			goto size_change_error;
 		}
 		if (min_csize && size == 0) {
 			/* Don't let the kernel choose a size - it will get
@@ -1748,6 +1756,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 			ioctl(fd, GET_ARRAY_INFO, &array);
 		}
 
+size_change_error:
 		if (rv != 0) {
 			int err = errno;
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/14] imsm: Add function imsm_get_free_size()
  2012-04-13 14:52                 ` [PATCH 09/14] FIX: Detect error and rollback metadata Adam Kwolek
@ 2012-04-13 14:52                   ` Adam Kwolek
  2012-04-13 14:52                     ` [PATCH 11/14] imsm: Support setting max size for size change operation Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Add function imsm_imsm_get_free_size() using part of code from function
reserve_space().

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |   25 ++++++++++++++++++++++++-
 1 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index 2a050fc..7161fc5 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6110,7 +6110,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
 	return 1;
 }
 
-static int reserve_space(struct supertype *st, int raiddisks,
+static int imsm_get_free_size(struct supertype *st, int raiddisks,
 			 unsigned long long size, int chunk,
 			 unsigned long long *freesize)
 {
@@ -6188,9 +6188,32 @@ static int reserve_space(struct supertype *st, int raiddisks,
 
 	*freesize = size;
 
+	dprintf("imsm: imsm_get_free_size() returns : %llu\n", size);
+
 	return 1;
 }
 
+static int reserve_space(struct supertype *st, int raiddisks,
+			 unsigned long long size, int chunk,
+			 unsigned long long *freesize)
+{
+	struct intel_super *super = st->sb;
+	struct dl *dl;
+	int cnt;
+	int rv = 0;
+
+	rv = imsm_get_free_size(st, raiddisks, size, chunk, freesize);
+	if (rv) {
+		cnt = 0;
+		for (dl = super->disks; dl; dl = dl->next)
+			if (dl->e)
+				dl->raiddisk = cnt++;
+		rv = 1;
+	}
+
+	return rv;
+}
+
 static int validate_geometry_imsm(struct supertype *st, int level, int layout,
 				  int raiddisks, int *chunk, unsigned long long size,
 				  char *dev, unsigned long long *freesize,
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/14] imsm: Support setting max size for size change operation
  2012-04-13 14:52                   ` [PATCH 10/14] imsm: Add function imsm_get_free_size() Adam Kwolek
@ 2012-04-13 14:52                     ` Adam Kwolek
  2012-04-13 14:52                       ` [PATCH 12/14] imsm: FIX: Component size alignment check Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Add support for setting max size for size change operation using
imsm_get_free_size() function for computing maximum available space.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index 7161fc5..d9c293c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -9955,7 +9955,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 	 */
 	current_size = info.custom_array_size / 2 / data_disks;
 
-	if ((current_size != geo->size) && (geo->size > 0)) {
+	if ((current_size != geo->size) && (geo->size >= 0)) {
 		if (change != -1) {
 			fprintf(stderr,
 				Name " Error. Size change should be the only "
@@ -9970,7 +9970,27 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 				super->current_vol, st->devnum);
 			goto analyse_change_exit;
 		}
-		geo->size *= 2;
+		if (geo->size == 0) {
+			/* requested size change to the maximum available size
+			 */
+			unsigned long long freesize;
+			int rv;
+
+			rv =  imsm_get_free_size(st, dev->vol.map->num_members,
+						 0, chunk, &freesize);
+			if (rv == 0) {
+				fprintf(stderr, Name " Error. Cannot find "
+					"maximum available space.\n");
+				change = -1;
+				goto analyse_change_exit;
+			}
+			geo->size = freesize + current_size;
+
+			/* round to chunk size */
+			geo->size &= ~(chunk-1);
+		} else
+			geo->size *= 2;
+
 		if ((direction == ROLLBACK_METADATA_CHANGES)) {
 			/* accept size for rollback only
 			*/
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/14] imsm: FIX: Component size alignment check
  2012-04-13 14:52                     ` [PATCH 11/14] imsm: Support setting max size for size change operation Adam Kwolek
@ 2012-04-13 14:52                       ` Adam Kwolek
  2012-04-13 14:52                         ` [PATCH 13/14] FIX: Size change is possible as standalone change only Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Put currently existing code for alignment correction in to function
imsm_component_size_aligment_check() and use it for align component size
to chunk size during volume size expansion operation.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 super-intel.c |   68 ++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index d9c293c..6d0e0c4 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2454,6 +2454,32 @@ int imsm_reshape_blocks_arrays_changes(struct intel_super *super)
 	}
 	return rv;
 }
+static unsigned long long imsm_component_size_aligment_check(int level,
+					      int chunk_size,
+					      unsigned long long component_size)
+{
+	unsigned int component_size_alligment;
+
+	/* check component size aligment
+	*/
+	component_size_alligment = component_size % (chunk_size/512);
+
+	dprintf("imsm_component_size_aligment_check(Level: %i, "
+		"chunk_size = %i, component_size = %llu), "
+		"component_size_alligment = %u\n",
+		level, chunk_size, component_size,
+		component_size_alligment);
+
+	if (component_size_alligment && (level != 1) && (level != UnSet)) {
+		dprintf("imsm: reported component size alligned from %llu ",
+			component_size);
+		component_size -= component_size_alligment;
+		dprintf("to %llu (%i).\n",
+			component_size, component_size_alligment);
+	}
+
+	return component_size;
+}
 
 static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap)
 {
@@ -2465,7 +2491,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
 	struct imsm_map *map_to_analyse = map;
 	struct dl *dl;
 	char *devname;
-	unsigned int component_size_alligment;
 	int map_disks = info->array.raid_disks;
 
 	memset(info, 0, sizeof(*info));
@@ -2548,19 +2573,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
 	info->data_offset	  = pba_of_lba0(map_to_analyse);
 	info->component_size	  = blocks_per_member(map_to_analyse);
 
-	/* check component size aligment
-	 */
-	component_size_alligment =
-		info->component_size % (info->array.chunk_size/512);
-
-	if (component_size_alligment &&
-	    (info->array.level != 1) && (info->array.level != UnSet)) {
-		dprintf("imsm: reported component size alligned from %llu ",
-			info->component_size);
-		info->component_size -= component_size_alligment;
-		dprintf("to %llu (%i).\n",
-			info->component_size, component_size_alligment);
-	}
+	info->component_size = imsm_component_size_aligment_check(
+							info->array.level,
+							info->array.chunk_size,
+							info->component_size);
 
 	memset(info->uuid, 0, sizeof(info->uuid));
 	info->recovery_start = MaxSector;
@@ -9951,9 +9967,18 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 	super = st->sb;
 	dev = get_imsm_dev(super, super->current_vol);
 	data_disks = imsm_num_data_members(dev , MAP_0);
-	/* compute current size in K per disk member
+	/* compute current size per disk member
 	 */
-	current_size = info.custom_array_size / 2 / data_disks;
+	current_size = info.custom_array_size / data_disks;
+
+	if (geo->size > 0) {
+		/* align component size
+		 */
+		geo->size = imsm_component_size_aligment_check(
+				    get_imsm_raid_level(dev->vol.map),
+				    chunk * 1024,
+				    geo->size * 2);
+	}
 
 	if ((current_size != geo->size) && (geo->size >= 0)) {
 		if (change != -1) {
@@ -9986,10 +10011,13 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 			}
 			geo->size = freesize + current_size;
 
-			/* round to chunk size */
-			geo->size &= ~(chunk-1);
-		} else
-			geo->size *= 2;
+			/* align component size
+			 */
+			geo->size = imsm_component_size_aligment_check(
+					      get_imsm_raid_level(dev->vol.map),
+					      chunk * 1024,
+					      geo->size);
+		}
 
 		if ((direction == ROLLBACK_METADATA_CHANGES)) {
 			/* accept size for rollback only
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/14] FIX: Size change is possible as standalone change only
  2012-04-13 14:52                       ` [PATCH 12/14] imsm: FIX: Component size alignment check Adam Kwolek
@ 2012-04-13 14:52                         ` Adam Kwolek
  2012-04-13 14:52                           ` [PATCH 14/14] FIX: Assembled second array is in read only state during reshape Adam Kwolek
  0 siblings, 1 reply; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

Size change is possible as standalone change only. To make sure size change
is not requested pass '-1' as size parameter.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Grow.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Grow.c b/Grow.c
index 1b45199..389992e 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1973,7 +1973,7 @@ size_change_error:
 		/* Impose these changes on a single array.  First
 		 * check that the metadata is OK with the change. */
 
-		if (reshape_super(st, info.component_size, info.new_level,
+		if (reshape_super(st, -1, info.new_level,
 				  info.new_layout, info.new_chunk,
 				  info.array.raid_disks, info.delta_disks,
 				  backup_file, devname, APPLY_METADATA_CHANGES,
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 14/14] FIX: Assembled second array is in read only state during reshape
  2012-04-13 14:52                         ` [PATCH 13/14] FIX: Size change is possible as standalone change only Adam Kwolek
@ 2012-04-13 14:52                           ` Adam Kwolek
  0 siblings, 0 replies; 20+ messages in thread
From: Adam Kwolek @ 2012-04-13 14:52 UTC (permalink / raw)
  To: neilb
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska, Adam Kwolek

When arrays using external metadata are assembled, and one of array
in container is under reshape, second array will remain in read only
state (not auto read only). It is caused by array fact that array
is frozen and mdmon doesn't has opportunity to switch array in r/w mode.

Freezing not reshaped array just after it is being assembled allows mdmon
to enable it for writing.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
 Assemble.c |   29 +++++++++++++++++++++--------
 1 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/Assemble.c b/Assemble.c
index 23695e7..080993d 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1558,6 +1558,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
 	int expansion = 0;
 	struct map_ent *map = NULL;
 	int old_raid_disks;
+	int start_reshape;
 
 	sysfs_init(content, mdfd, 0);
 
@@ -1569,7 +1570,17 @@ int assemble_container_content(struct supertype *st, int mdfd,
 			return 1;
 		}
 
-	if (st->ss->external && content->recovery_blocked)
+	/* There are two types of reshape: container wide or sub-array specific
+	 * Check if metadata requests blocking container wide reshapes
+	 */
+	start_reshape = (content->reshape_active &&
+		!((content->reshape_active == CONTAINER_RESHAPE) &&
+		(content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE))));
+
+	/* Block subarray here if it is under reshape now
+	 * Do not allow for any changes in this array
+	 */
+	if (st->ss->external && content->recovery_blocked && start_reshape)
 		block_subarray(content);
 
 	if (sra)
@@ -1595,14 +1606,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
 		 (working + preexist + expansion) >=
 			content->array.working_disks) {
 		int err;
-		int start_reshape;
 
-		/* There are two types of reshape: container wide or sub-array specific
-		 * Check if metadata requests blocking container wide reshapes
-		 */
-		start_reshape = (content->reshape_active &&
-				 !((content->reshape_active == CONTAINER_RESHAPE) &&
-				   (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE))));
 		if (start_reshape) {
 			int spare = content->array.raid_disks + expansion;
 			if (restore_backup(st, content,
@@ -1646,6 +1650,15 @@ int assemble_container_content(struct supertype *st, int mdfd,
 		}
 		if (!err)
 			sysfs_set_safemode(content, content->safe_mode_delay);
+
+		/* Block subarray here if it is not reshaped now
+		 * It has be blocked a little later to allow mdmon to switch in
+		 * in to R/W state
+		 */
+		if (st->ss->external && content->recovery_blocked &&
+		    !start_reshape)
+			block_subarray(content);
+
 		if (verbose >= 0) {
 			if (err)
 				fprintf(stderr, Name
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 07/14] FIX: Extend size of raid0 array
  2012-04-13 14:52             ` [PATCH 07/14] FIX: Extend size of raid0 array Adam Kwolek
  2012-04-13 14:52               ` [PATCH 08/14] FIX: Respect metadata size limitations Adam Kwolek
@ 2012-04-17  2:52               ` NeilBrown
  2012-04-19 15:09                 ` Dorau, Lukasz
  1 sibling, 1 reply; 20+ messages in thread
From: NeilBrown @ 2012-04-17  2:52 UTC (permalink / raw)
  To: Adam Kwolek
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska

[-- Attachment #1: Type: text/plain, Size: 2974 bytes --]

On Fri, 13 Apr 2012 16:52:01 +0200 Adam Kwolek <adam.kwolek@intel.com> wrote:

> For raid0, takeover operation is required for size change.
> Add takeover to degraded raid4 before size change and back to raid0 after.
> Array information has to be read again from md after takeover.
> 
> Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
> ---
>  Grow.c |   35 +++++++++++++++++++++++++++++++++++
>  1 files changed, 35 insertions(+), 0 deletions(-)
> 
> diff --git a/Grow.c b/Grow.c
> index 8c7bafc..e8f6554 100644
> --- a/Grow.c
> +++ b/Grow.c
> @@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
>  		long long orig_size = get_component_size(fd)/2;
>  		long long min_csize;
>  		struct mdinfo *mdi;
> +		int raid0_takeover = 0;
>  
>  		if (orig_size == 0)
>  			orig_size = array.size;
> @@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
>  				"2TB per device\n");
>  			size = min_csize;
>  		}
> +		if (st->ss->external) {
> +			if (sra->array.level == 0) {
> +				rv = sysfs_set_str(sra, NULL, "level",
> +						   "raid5");
> +				if (!rv) {
> +					raid0_takeover = 1;
> +					/* get array parametes after takeover
> +					 * to chane one parameter at time only
> +					 */
> +					rv = ioctl(fd, GET_ARRAY_INFO, &array);
> +				}
> +			}
> +			/* make sure mdmon is
> +			 * aware of the new level */
> +			if (!mdmon_running(st->container_dev))
> +				start_mdmon(st->container_dev);
> +			ping_monitor(container);
> +			if (mdmon_running(st->container_dev) &&
> +					st->update_tail == NULL)
> +				st->update_tail = &st->updates;
> +		}
> +
>  		array.size = size;
>  		if (array.size != size) {
>  			/* got truncated to 32bit, write to
> @@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
>  				rv = -1;
>  		} else {
>  			rv = ioctl(fd, SET_ARRAY_INFO, &array);
> +
>  			/* manage array size when it is managed externally
>  			 */
>  			if ((rv == 0) && st->ss->external)
>  				rv = set_array_size(st, sra, sra->text_version);
>  		}
>  
> +		if (raid0_takeover) {
> +			/* do not recync non-existing parity,
> +			 * we will drop it anyway
> +			 */
> +			sysfs_set_str(sra, NULL, "sync_action", "idle");

This is probably ineffective.  If the array thinks it needs to resync, then
just setting it to 'idle' will only stop in temporarily.  It will immediately
start syncing again.

However given that it is a RAID5 array which is degraded, it shouldn't try to
resync at all.

So:  does it still work if you remove this line?  If so, could you send a
patch to remove it?
If not - we should work out why.

Thanks,
NeilBrown


> +			/* go back to raid0, drop parity disk
> +			 */
> +			sysfs_set_str(sra, NULL, "level", "raid0");
> +			ioctl(fd, GET_ARRAY_INFO, &array);
> +		}
> +
>  		if (rv != 0) {
>  			int err = errno;
>  


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 00/14] imsm: volume expand
  2012-04-13 14:51 [PATCH 00/14] imsm: volume expand Adam Kwolek
  2012-04-13 14:51 ` [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for Raid1/10 Adam Kwolek
@ 2012-04-17  2:56 ` NeilBrown
  1 sibling, 0 replies; 20+ messages in thread
From: NeilBrown @ 2012-04-17  2:56 UTC (permalink / raw)
  To: Adam Kwolek
  Cc: linux-raid, dan.j.williams, ed.ciechanowski, grzegorz.grabowski,
	maciej.patelczyk, anna.czarnowska

[-- Attachment #1: Type: text/plain, Size: 1338 bytes --]

On Fri, 13 Apr 2012 16:51:54 +0200 Adam Kwolek <adam.kwolek@intel.com> wrote:

> This patch series introduces the possibility to increase volume size using
> existing free space in container without adding spare disks to imsm metadata.
> 
> Adam Kwolek (14):
>   imsm: FIX: Update function imsm_num_data_members() for Raid1/10
>   imsm: FIX: Add volume size expand support to imsm_analyze_change()
>   imsm: Add new metadata update for volume size expansion
>   imsm: Execute size change for external metatdata
>   FIX: Support metadata changes rollback
>   imsm: FIX: Support metadata changes rollback
>   FIX: Extend size of raid0 array
>   FIX: Respect metadata size limitations
>   FIX: Detect error and rollback metadata
>   imsm: Add function imsm_get_free_size()
>   imsm: Support setting max size for size change operation
>   imsm: FIX: Component size alignment check
>   FIX: Size change is possible as standalone change only
>   FIX: Assembled second array is in read only state during reshape
> 
>  Assemble.c    |   29 ++++--
>  Grow.c        |  163 ++++++++++++++++++++++-------
>  mdadm.h       |    4 +
>  super-intel.c |  318 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  4 files changed, 438 insertions(+), 76 deletions(-)


Thanks,
I've applied these patches.

NeilBrown


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH 07/14] FIX: Extend size of raid0 array
  2012-04-17  2:52               ` [PATCH 07/14] FIX: Extend size of raid0 array NeilBrown
@ 2012-04-19 15:09                 ` Dorau, Lukasz
  2012-04-19 21:23                   ` NeilBrown
  0 siblings, 1 reply; 20+ messages in thread
From: Dorau, Lukasz @ 2012-04-19 15:09 UTC (permalink / raw)
  To: NeilBrown
  Cc: linux-raid, Williams, Dan J, Ciechanowski, Ed, Patelczyk, Maciej,
	Danecki, Jacek, Kwolek, Adam

On Tuesday, April 17, 2012 4:53 AM NeilBrown wrote:
> 
> On Fri, 13 Apr 2012 16:52:01 +0200 Adam Kwolek <adam.kwolek@intel.com>
> wrote:
> 
> > For raid0, takeover operation is required for size change.
> > Add takeover to degraded raid4 before size change and back to raid0 after.
> > Array information has to be read again from md after takeover.
> >
> > Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
> > ---
> >  Grow.c |   35 +++++++++++++++++++++++++++++++++++
> >  1 files changed, 35 insertions(+), 0 deletions(-)
> >
> > diff --git a/Grow.c b/Grow.c
> > index 8c7bafc..e8f6554 100644
> > --- a/Grow.c
> > +++ b/Grow.c
> > @@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int
> quiet, char *backup_file,
> >  		long long orig_size = get_component_size(fd)/2;
> >  		long long min_csize;
> >  		struct mdinfo *mdi;
> > +		int raid0_takeover = 0;
> >
> >  		if (orig_size == 0)
> >  			orig_size = array.size;
> > @@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int
> quiet, char *backup_file,
> >  				"2TB per device\n");
> >  			size = min_csize;
> >  		}
> > +		if (st->ss->external) {
> > +			if (sra->array.level == 0) {
> > +				rv = sysfs_set_str(sra, NULL, "level",
> > +						   "raid5");
> > +				if (!rv) {
> > +					raid0_takeover = 1;
> > +					/* get array parametes after takeover
> > +					 * to chane one parameter at time
> only
> > +					 */
> > +					rv = ioctl(fd, GET_ARRAY_INFO,
> &array);
> > +				}
> > +			}
> > +			/* make sure mdmon is
> > +			 * aware of the new level */
> > +			if (!mdmon_running(st->container_dev))
> > +				start_mdmon(st->container_dev);
> > +			ping_monitor(container);
> > +			if (mdmon_running(st->container_dev) &&
> > +					st->update_tail == NULL)
> > +				st->update_tail = &st->updates;
> > +		}
> > +
> >  		array.size = size;
> >  		if (array.size != size) {
> >  			/* got truncated to 32bit, write to
> > @@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd, int
> quiet, char *backup_file,
> >  				rv = -1;
> >  		} else {
> >  			rv = ioctl(fd, SET_ARRAY_INFO, &array);
> > +
> >  			/* manage array size when it is managed externally
> >  			 */
> >  			if ((rv == 0) && st->ss->external)
> >  				rv = set_array_size(st, sra, sra->text_version);
> >  		}
> >
> > +		if (raid0_takeover) {
> > +			/* do not recync non-existing parity,
> > +			 * we will drop it anyway
> > +			 */
> > +			sysfs_set_str(sra, NULL, "sync_action", "idle");
> 
> This is probably ineffective.  If the array thinks it needs to resync, then
> just setting it to 'idle' will only stop in temporarily.  It will immediately
> start syncing again.
> 
> However given that it is a RAID5 array which is degraded, it shouldn't try to
> resync at all.
> 
> So:  does it still work if you remove this line?  If so, could you send a
> patch to remove it?
> If not - we should work out why.
> 

It doesn't work without this line.
The N-disks raid0 changes to degraded (N+1)-disks raid5 (N of N+1 disks) 
in /proc/mdstat after size extension, however the metadata on all disks is correct.

Regards,
Lukasz
 
> 
> > +			/* go back to raid0, drop parity disk
> > +			 */
> > +			sysfs_set_str(sra, NULL, "level", "raid0");
> > +			ioctl(fd, GET_ARRAY_INFO, &array);
> > +		}
> > +
> >  		if (rv != 0) {
> >  			int err = errno;
> >


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 07/14] FIX: Extend size of raid0 array
  2012-04-19 15:09                 ` Dorau, Lukasz
@ 2012-04-19 21:23                   ` NeilBrown
  2012-04-20  8:48                     ` Dorau, Lukasz
  0 siblings, 1 reply; 20+ messages in thread
From: NeilBrown @ 2012-04-19 21:23 UTC (permalink / raw)
  To: Dorau, Lukasz
  Cc: linux-raid, Williams, Dan J, Ciechanowski, Ed, Patelczyk, Maciej,
	Danecki, Jacek, Kwolek, Adam

[-- Attachment #1: Type: text/plain, Size: 3679 bytes --]

On Thu, 19 Apr 2012 15:09:45 +0000 "Dorau, Lukasz" <lukasz.dorau@intel.com>
wrote:

> On Tuesday, April 17, 2012 4:53 AM NeilBrown wrote:
> > 
> > On Fri, 13 Apr 2012 16:52:01 +0200 Adam Kwolek <adam.kwolek@intel.com>
> > wrote:
> > 
> > > For raid0, takeover operation is required for size change.
> > > Add takeover to degraded raid4 before size change and back to raid0 after.
> > > Array information has to be read again from md after takeover.
> > >
> > > Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
> > > ---
> > >  Grow.c |   35 +++++++++++++++++++++++++++++++++++
> > >  1 files changed, 35 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/Grow.c b/Grow.c
> > > index 8c7bafc..e8f6554 100644
> > > --- a/Grow.c
> > > +++ b/Grow.c
> > > @@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int
> > quiet, char *backup_file,
> > >  		long long orig_size = get_component_size(fd)/2;
> > >  		long long min_csize;
> > >  		struct mdinfo *mdi;
> > > +		int raid0_takeover = 0;
> > >
> > >  		if (orig_size == 0)
> > >  			orig_size = array.size;
> > > @@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int
> > quiet, char *backup_file,
> > >  				"2TB per device\n");
> > >  			size = min_csize;
> > >  		}
> > > +		if (st->ss->external) {
> > > +			if (sra->array.level == 0) {
> > > +				rv = sysfs_set_str(sra, NULL, "level",
> > > +						   "raid5");
> > > +				if (!rv) {
> > > +					raid0_takeover = 1;
> > > +					/* get array parametes after takeover
> > > +					 * to chane one parameter at time
> > only
> > > +					 */
> > > +					rv = ioctl(fd, GET_ARRAY_INFO,
> > &array);
> > > +				}
> > > +			}
> > > +			/* make sure mdmon is
> > > +			 * aware of the new level */
> > > +			if (!mdmon_running(st->container_dev))
> > > +				start_mdmon(st->container_dev);
> > > +			ping_monitor(container);
> > > +			if (mdmon_running(st->container_dev) &&
> > > +					st->update_tail == NULL)
> > > +				st->update_tail = &st->updates;
> > > +		}
> > > +
> > >  		array.size = size;
> > >  		if (array.size != size) {
> > >  			/* got truncated to 32bit, write to
> > > @@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd, int
> > quiet, char *backup_file,
> > >  				rv = -1;
> > >  		} else {
> > >  			rv = ioctl(fd, SET_ARRAY_INFO, &array);
> > > +
> > >  			/* manage array size when it is managed externally
> > >  			 */
> > >  			if ((rv == 0) && st->ss->external)
> > >  				rv = set_array_size(st, sra, sra->text_version);
> > >  		}
> > >
> > > +		if (raid0_takeover) {
> > > +			/* do not recync non-existing parity,
> > > +			 * we will drop it anyway
> > > +			 */
> > > +			sysfs_set_str(sra, NULL, "sync_action", "idle");
> > 
> > This is probably ineffective.  If the array thinks it needs to resync, then
> > just setting it to 'idle' will only stop in temporarily.  It will immediately
> > start syncing again.
> > 
> > However given that it is a RAID5 array which is degraded, it shouldn't try to
> > resync at all.
> > 
> > So:  does it still work if you remove this line?  If so, could you send a
> > patch to remove it?
> > If not - we should work out why.
> > 
> 
> It doesn't work without this line.
> The N-disks raid0 changes to degraded (N+1)-disks raid5 (N of N+1 disks) 
> in /proc/mdstat after size extension, however the metadata on all disks is correct.
> 

In that case I suspect that fact that it works with the line is racy and it
could sometimes fail.  Setting "sync_action" to "frozen" would be safer.
Can you confirm that also works?  I'd feel more comfortable about that.

NeilBrown


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH 07/14] FIX: Extend size of raid0 array
  2012-04-19 21:23                   ` NeilBrown
@ 2012-04-20  8:48                     ` Dorau, Lukasz
  0 siblings, 0 replies; 20+ messages in thread
From: Dorau, Lukasz @ 2012-04-20  8:48 UTC (permalink / raw)
  To: NeilBrown
  Cc: linux-raid, Williams, Dan J, Ciechanowski, Ed, Patelczyk, Maciej,
	Danecki, Jacek, Kwolek, Adam

On Thursday, April 19, 2012 11:24 PM NeilBrown <neilb@suse.de> wrote:
> 
> On Thu, 19 Apr 2012 15:09:45 +0000 "Dorau, Lukasz"
> <lukasz.dorau@intel.com>
> wrote:
> 
> > On Tuesday, April 17, 2012 4:53 AM NeilBrown wrote:
> > >
> > > On Fri, 13 Apr 2012 16:52:01 +0200 Adam Kwolek
> <adam.kwolek@intel.com>
> > > wrote:
> > >
> > > > For raid0, takeover operation is required for size change.
> > > > Add takeover to degraded raid4 before size change and back to raid0
> after.
> > > > Array information has to be read again from md after takeover.
> > > >
> > > > Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
> > > > ---
> > > >  Grow.c |   35 +++++++++++++++++++++++++++++++++++
> > > >  1 files changed, 35 insertions(+), 0 deletions(-)
> > > >
> > > > diff --git a/Grow.c b/Grow.c
> > > > index 8c7bafc..e8f6554 100644
> > > > --- a/Grow.c
> > > > +++ b/Grow.c
> > > > @@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int
> > > quiet, char *backup_file,
> > > >  		long long orig_size = get_component_size(fd)/2;
> > > >  		long long min_csize;
> > > >  		struct mdinfo *mdi;
> > > > +		int raid0_takeover = 0;
> > > >
> > > >  		if (orig_size == 0)
> > > >  			orig_size = array.size;
> > > > @@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int
> > > quiet, char *backup_file,
> > > >  				"2TB per device\n");
> > > >  			size = min_csize;
> > > >  		}
> > > > +		if (st->ss->external) {
> > > > +			if (sra->array.level == 0) {
> > > > +				rv = sysfs_set_str(sra, NULL, "level",
> > > > +						   "raid5");
> > > > +				if (!rv) {
> > > > +					raid0_takeover = 1;
> > > > +					/* get array parametes after takeover
> > > > +					 * to chane one parameter at time
> > > only
> > > > +					 */
> > > > +					rv = ioctl(fd, GET_ARRAY_INFO,
> > > &array);
> > > > +				}
> > > > +			}
> > > > +			/* make sure mdmon is
> > > > +			 * aware of the new level */
> > > > +			if (!mdmon_running(st->container_dev))
> > > > +				start_mdmon(st->container_dev);
> > > > +			ping_monitor(container);
> > > > +			if (mdmon_running(st->container_dev) &&
> > > > +					st->update_tail == NULL)
> > > > +				st->update_tail = &st->updates;
> > > > +		}
> > > > +
> > > >  		array.size = size;
> > > >  		if (array.size != size) {
> > > >  			/* got truncated to 32bit, write to
> > > > @@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd,
> int
> > > quiet, char *backup_file,
> > > >  				rv = -1;
> > > >  		} else {
> > > >  			rv = ioctl(fd, SET_ARRAY_INFO, &array);
> > > > +
> > > >  			/* manage array size when it is managed externally
> > > >  			 */
> > > >  			if ((rv == 0) && st->ss->external)
> > > >  				rv = set_array_size(st, sra, sra->text_version);
> > > >  		}
> > > >
> > > > +		if (raid0_takeover) {
> > > > +			/* do not recync non-existing parity,
> > > > +			 * we will drop it anyway
> > > > +			 */
> > > > +			sysfs_set_str(sra, NULL, "sync_action", "idle");
> > >
> > > This is probably ineffective.  If the array thinks it needs to resync, then
> > > just setting it to 'idle' will only stop in temporarily.  It will immediately
> > > start syncing again.
> > >
> > > However given that it is a RAID5 array which is degraded, it shouldn't try
> to
> > > resync at all.
> > >
> > > So:  does it still work if you remove this line?  If so, could you send a
> > > patch to remove it?
> > > If not - we should work out why.
> > >
> >
> > It doesn't work without this line.
> > The N-disks raid0 changes to degraded (N+1)-disks raid5 (N of N+1 disks)
> > in /proc/mdstat after size extension, however the metadata on all disks is
> correct.
> >
> 
> In that case I suspect that fact that it works with the line is racy and it
> could sometimes fail.  Setting "sync_action" to "frozen" would be safer.
> Can you confirm that also works?  I'd feel more comfortable about that.
> 

You're right. I've checked it on another machine and it sometimes fails.
I've also checked that with "sync_action" set to "frozen" it works.
I'll send the patch soon.

Regards,
Lukasz




^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-04-20  8:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-13 14:51 [PATCH 00/14] imsm: volume expand Adam Kwolek
2012-04-13 14:51 ` [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for Raid1/10 Adam Kwolek
2012-04-13 14:51   ` [PATCH 02/14] imsm: FIX: Add volume size expand support to imsm_analyze_change() Adam Kwolek
2012-04-13 14:51     ` [PATCH 03/14] imsm: Add new metadata update for volume size expansion Adam Kwolek
2012-04-13 14:51       ` [PATCH 04/14] imsm: Execute size change for external metatdata Adam Kwolek
2012-04-13 14:51         ` [PATCH 05/14] FIX: Support metadata changes rollback Adam Kwolek
2012-04-13 14:52           ` [PATCH 06/14] imsm: " Adam Kwolek
2012-04-13 14:52             ` [PATCH 07/14] FIX: Extend size of raid0 array Adam Kwolek
2012-04-13 14:52               ` [PATCH 08/14] FIX: Respect metadata size limitations Adam Kwolek
2012-04-13 14:52                 ` [PATCH 09/14] FIX: Detect error and rollback metadata Adam Kwolek
2012-04-13 14:52                   ` [PATCH 10/14] imsm: Add function imsm_get_free_size() Adam Kwolek
2012-04-13 14:52                     ` [PATCH 11/14] imsm: Support setting max size for size change operation Adam Kwolek
2012-04-13 14:52                       ` [PATCH 12/14] imsm: FIX: Component size alignment check Adam Kwolek
2012-04-13 14:52                         ` [PATCH 13/14] FIX: Size change is possible as standalone change only Adam Kwolek
2012-04-13 14:52                           ` [PATCH 14/14] FIX: Assembled second array is in read only state during reshape Adam Kwolek
2012-04-17  2:52               ` [PATCH 07/14] FIX: Extend size of raid0 array NeilBrown
2012-04-19 15:09                 ` Dorau, Lukasz
2012-04-19 21:23                   ` NeilBrown
2012-04-20  8:48                     ` Dorau, Lukasz
2012-04-17  2:56 ` [PATCH 00/14] imsm: volume expand NeilBrown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.