[PATCH 0/5] imsm support for raid0->raid5 migration

[PATCH 0/5] imsm support for raid0->raid5 migration

am 04.05.2011 17:10:33 von unknown

Migration r0->r5 once again; with a fix comming from your comment.

The following series implements support for raid0->raid5 migration for IMSM
metadata. These patches blocks opposite direction of migration.
Code mostly bases on patches sent to you by Adam Kwolek. I have incorporated
your remarks and I tested it quite extensively for comformity with IMSM
standard. I have also removed opposite direction, as it is just not supported
right now.

Note:
Please do not include these patches on 'master' branch, as they are supposed
to be a part of next minor mdadm version (ie. mdadm 3.2.2). I think good place
for it is devel-3.2. Master should be reserved just for bug/stability fixes
for previous release.
---

Przemyslaw Czarnowski (5):
imsm: prepare update for level migrations reshape
imsm: fix: disable migration from raid5->raid0
imsm: prepare memory for level migration update
imsm: process update for raid level migrations
imsm: add new chunk size to metadata update


super-intel.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 330 insertions(+), 7 deletions(-)

--
Best Regards,
Przemyslaw Czarnowski
--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

[PATCH 1/5] imsm: prepare update for level migrations reshape

am 04.05.2011 17:11:07 von unknown

Introducing raid0->raid5 level migration metadata update structure
is prepared for future use.

Adding spare device is required to hold additional raid5 parity.
Mdadm just checks for spares, but it is not included in update.
If there are no spares available, abort. Otherwise we will create
degraded array what should be not allowed.
Mdmon will decide what spare device is used for parity.

Signed-off-by: Adam Kwolek
Signed-off-by: Przemyslaw Czarnowski
---
super-intel.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index 83135a6..6f41180 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -305,6 +305,7 @@ enum imsm_update_type {
update_rename_array,
update_add_remove_disk,
update_reshape_container_disks,
+ update_reshape_migration,
update_takeover
};

@@ -340,6 +341,20 @@ struct imsm_update_reshape {
enum imsm_update_type type;
int old_raid_disks;
int new_raid_disks;
+
+ int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
+};
+
+struct imsm_update_reshape_migration {
+ enum imsm_update_type type;
+ int old_raid_disks;
+ int new_raid_disks;
+ /* fields for array migration changes
+ */
+ int subdev;
+ int new_level;
+ int new_layout;
+
int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
};

@@ -6337,6 +6352,9 @@ static void imsm_process_update(struct supertype *st,
super->updates_pending++;
break;
}
+ case update_reshape_migration: {
+ break;
+ }
case update_activate_spare: {
struct imsm_update_activate_spare *u = (void *) update->buf;
struct imsm_dev *dev = get_imsm_dev(super, u->array);
@@ -6730,6 +6748,9 @@ static void imsm_prepare_update(struct supertype *st,
dprintf("New anchor length is %llu\n", (unsigned long long)len);
break;
}
+ case update_reshape_migration: {
+ break;
+ }
case update_create_array: {
struct imsm_update_create_array *u = (void *) update->buf;
struct intel_dev *dv;
@@ -7105,6 +7126,70 @@ abort:
return 0;
}

+/********************************************************** ********************
+ * function: imsm_create_metadata_update_for_migration()
+ * Creates update for IMSM array.
+ *
+ ************************************************************ ******************/
+static int imsm_create_metadata_update_for_migration(
+ struct supertype *st,
+ struct geo_params *geo,
+ struct imsm_update_reshape_migration **updatep)
+{
+ struct intel_super *super = st->sb;
+ int update_memory_size = 0;
+ struct imsm_update_reshape_migration *u = NULL;
+ struct imsm_dev *dev;
+ int previous_level = -1;
+
+ dprintf("imsm_create_metadata_update_for_migration(enter)"
+ " New Level = %i\n", geo->level);
+
+ /* size of all update data without anchor */
+ update_memory_size = sizeof(struct imsm_update_reshape_migration);
+
+ u = calloc(1, update_memory_size);
+ if (u == NULL) {
+ dprintf("error: cannot get memory for "
+ "imsm_create_metadata_update_for_migration\n");
+ return 0;
+ }
+ u->type = update_reshape_migration;
+ u->subdev = super->current_vol;
+ u->new_level = geo->level;
+ u->new_layout = geo->layout;
+ u->new_raid_disks = u->old_raid_disks = geo->raid_disks;
+ u->new_disks[0] = -1;
+
+ dev = get_imsm_dev(super, u->subdev);
+ if (dev) {
+ struct imsm_map *map;
+
+ map = get_imsm_map(dev, 0);
+ if (map)
+ previous_level = map->raid_level;
+ }
+ if ((geo->level == 5) && (previous_level == 0)) {
+ struct mdinfo *spares = NULL;
+
+ u->new_raid_disks++;
+ spares = get_spares_for_grow(st);
+ if ((spares == NULL) || (spares->array.spare_disks < 1)) {
+ free(u);
+ sysfs_free(spares);
+ update_memory_size = 0;
+ dprintf("error: cannot get spare device "
+ "for requested migration");
+ return 0;
+ }
+ sysfs_free(spares);
+ }
+ dprintf("imsm: reshape update preparation : OK\n");
+ *updatep = u;
+
+ return update_memory_size;
+}
+
static void imsm_update_metadata_locally(struct supertype *st,
void *buf, int len)
{
@@ -7393,9 +7478,26 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
case CH_TAKEOVER:
ret_val = imsm_takeover(st, &geo);
break;
- case CH_MIGRATION:
+ case CH_MIGRATION: {
+ struct imsm_update_reshape_migration *u = NULL;
+ int len =
+ imsm_create_metadata_update_for_migration(
+ st, &geo, &u);
+ if (len < 1) {
+ dprintf("imsm: "
+ "Cannot prepare update\n");
+ break;
+ }
ret_val = 0;
- break;
+ /* 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:
ret_val = 1;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

[PATCH 2/5] imsm: fix: disable migration from raid5->raid0

am 04.05.2011 17:11:41 von unknown

it is not supported yet, so start such transition is improper.

Signed-off-by: Przemyslaw Czarnowski
---
super-intel.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index 6f41180..a7d880b 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -7247,10 +7247,6 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
check_devs = 1;
}
break;
- case 5:
- if (geo->level == 0)
- change = CH_MIGRATION;
- break;
case 10:
if (geo->level == 0) {
change = CH_TAKEOVER;

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

[PATCH 3/5] imsm: prepare memory for level migration update

am 04.05.2011 17:12:14 von unknown

When level is changed from raid0 to raid5 memory is required for replace device
smaller device/array object.
This memory is allocated in manager context in prepare_update()

Prepare_update() is called in manager context so memory allocation are
allowed here. This allows us to look for spare devices for meta update.

Signed-off-by: Adam Kwolek
Signed-off-by: Przemyslaw Czarnowski
---
super-intel.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index a7d880b..c6f8f6d 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6651,6 +6651,8 @@ static void imsm_process_update(struct supertype *st,
}
}

+static struct mdinfo *get_spares_for_grow(struct supertype *st);
+
static void imsm_prepare_update(struct supertype *st,
struct metadata_update *update)
{
@@ -6749,6 +6751,90 @@ static void imsm_prepare_update(struct supertype *st,
break;
}
case update_reshape_migration: {
+ /* for migration level 0->5 we need to add disks
+ * so the same as for container operation we will copy
+ * device to the bigger location.
+ * in memory prepared device and new disk area are prepared
+ * for usage in process update
+ */
+ struct imsm_update_reshape_migration *u = (void *)update->buf;
+ struct intel_dev *id;
+ void **space_tail = (void **)&update->space_list;
+ int size;
+ void *s;
+ int current_level = -1;
+
+ dprintf("imsm: imsm_prepare_update() for update_reshape\n");
+
+ /* add space for bigger array in update
+ */
+ for (id = super->devlist; id; id = id->next) {
+ if (id->index == (unsigned)u->subdev) {
+ size = sizeof_imsm_dev(id->dev, 1);
+ if (u->new_raid_disks > u->old_raid_disks)
+ size += sizeof(__u32)*2*
+ (u->new_raid_disks - u->old_raid_disks);
+ s = malloc(size);
+ if (!s)
+ break;
+ *space_tail = s;
+ space_tail = s;
+ *space_tail = NULL;
+ break;
+ }
+ }
+ if (update->space_list == NULL)
+ break;
+
+ /* add space for disk in update
+ */
+ size = sizeof(struct dl);
+ s = malloc(size);
+ if (!s) {
+ free(update->space_list);
+ update->space_list = NULL;
+ break;
+ }
+ *space_tail = s;
+ space_tail = s;
+ *space_tail = NULL;
+
+ /* add spare device to update
+ */
+ for (id = super->devlist ; id; id = id->next)
+ if (id->index == (unsigned)u->subdev) {
+ struct imsm_dev *dev;
+ struct imsm_map *map;
+
+ dev = get_imsm_dev(super, u->subdev);
+ map = get_imsm_map(dev, 0);
+ current_level = map->raid_level;
+ break;
+ }
+ if ((u->new_level == 5) && (u->new_level != current_level)) {
+ struct mdinfo *spares;
+
+ spares = get_spares_for_grow(st);
+ if (spares) {
+ struct dl *dl;
+ struct mdinfo *dev;
+
+ dev = spares->devs;
+ if (dev) {
+ u->new_disks[0] =
+ makedev(dev->disk.major,
+ dev->disk.minor);
+ dl = get_disk_super(super,
+ dev->disk.major,
+ dev->disk.minor);
+ dl->index = u->old_raid_disks;
+ dev = dev->next;
+ }
+ sysfs_free(spares);
+ }
+ }
+ len = disks_to_mpb_size(u->new_raid_disks);
+ dprintf("New anchor length is %llu\n", (unsigned long long)len);
break;
}
case update_create_array: {

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

[PATCH 4/5] imsm: process update for raid level migrations

am 04.05.2011 17:12:48 von unknown

Received update and prepared memory is processed to update imsm metadata.

Signed-off-by: Adam Kwolek
Signed-off-by: Przemyslaw Czarnowski
---
super-intel.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 122 insertions(+), 1 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index c6f8f6d..d00364f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6088,6 +6088,124 @@ static int add_remove_disk_update(struct intel_super *super)
return check_degraded;
}

+
+static int apply_reshape_migration_update(struct imsm_update_reshape_migration *u,
+ struct intel_super *super,
+ void ***space_list)
+{
+ struct intel_dev *id;
+ void **tofree = NULL;
+ int ret_val = 0;
+
+ dprintf("apply_reshape_migration_update()\n");
+ if ((u->subdev < 0) ||
+ (u->subdev > 1)) {
+ dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev);
+ return ret_val;
+ }
+ if ((space_list == NULL) || (*space_list == NULL)) {
+ dprintf("imsm: Error: Memory is not allocated\n");
+ 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;
+ struct imsm_dev *new_dev =
+ (struct imsm_dev *)*space_list;
+ struct imsm_map *migr_map = get_imsm_map(dev, 1);
+ int to_state;
+ struct dl *new_disk;
+
+ if (new_dev == NULL)
+ return ret_val;
+ *space_list = **space_list;
+ memcpy(new_dev, dev, sizeof_imsm_dev(dev, 0));
+ map = get_imsm_map(new_dev, 0);
+ if (migr_map) {
+ dprintf("imsm: Error: migration in progress");
+ return ret_val;
+ }
+
+ to_state = map->map_state;
+ if ((u->new_level == 5) && (map->raid_level == 0)) {
+ map->num_members++;
+ /* this should not happen */
+ if (u->new_disks[0] < 0) {
+ map->failed_disk_num =
+ map->num_members - 1;
+ to_state = IMSM_T_STATE_DEGRADED;
+ } else
+ to_state = IMSM_T_STATE_NORMAL;
+ }
+ migrate(new_dev, to_state, MIGR_GEN_MIGR);
+ if (u->new_level > -1)
+ map->raid_level = u->new_level;
+ migr_map = get_imsm_map(new_dev, 1);
+ if ((u->new_level == 5) &&
+ (migr_map->raid_level == 0)) {
+ int ord = map->num_members - 1;
+ migr_map->num_members--;
+ if (u->new_disks[0] < 0)
+ ord |= IMSM_ORD_REBUILD;
+ set_imsm_ord_tbl_ent(map,
+ map->num_members - 1,
+ ord);
+ }
+ id->dev = new_dev;
+ tofree = (void **)dev;
+
+ /* add disk
+ */
+ if ((u->new_level != 5) ||
+ (migr_map->raid_level != 0) ||
+ (migr_map->raid_level == map->raid_level))
+ goto skip_disk_add;
+
+ if (u->new_disks[0] >= 0) {
+ /* use passes spare
+ */
+ new_disk = get_disk_super(super,
+ major(u->new_disks[0]),
+ minor(u->new_disks[0]));
+ dprintf("imsm: new disk for reshape is: %i:%i "
+ "(%p, index = %i)\n",
+ major(u->new_disks[0]),
+ minor(u->new_disks[0]),
+ new_disk, new_disk->index);
+ if (new_disk == NULL)
+ goto error_disk_add;
+
+ new_disk->index = map->num_members - 1;
+ /* slot to fill in autolayout
+ */
+ new_disk->raiddisk = new_disk->index;
+ new_disk->disk.status |= CONFIGURED_DISK;
+ new_disk->disk.status &= ~SPARE_DISK;
+ } else
+ goto error_disk_add;
+
+skip_disk_add:
+ *tofree = *space_list;
+ /* calculate new size
+ */
+ imsm_set_array_size(new_dev);
+
+ ret_val = 1;
+ }
+ }
+
+ if (tofree)
+ *space_list = tofree;
+ return ret_val;
+
+error_disk_add:
+ dprintf("Error: imsm: Cannot find disk.\n");
+ return ret_val;
+}
+
+
static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
struct intel_super *super,
void ***space_list)
@@ -6353,6 +6471,10 @@ static void imsm_process_update(struct supertype *st,
break;
}
case update_reshape_migration: {
+ struct imsm_update_reshape_migration *u = (void *)update->buf;
+ if (apply_reshape_migration_update(
+ u, super, &update->space_list))
+ super->updates_pending++;
break;
}
case update_activate_spare: {
@@ -6381,7 +6503,6 @@ static void imsm_process_update(struct supertype *st,
}

super->updates_pending++;
-
/* count failures (excluding rebuilds and the victim)
* to determine map[0] state
*/

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

[PATCH 5/5] imsm: add new chunk size to metadata update

am 04.05.2011 17:13:22 von unknown

Put information about new chunk size change in to migration metadata
update allowing simultaneous level change and re-striping.

Signed-off-by: Adam Kwolek
Signed-off-by: Przemyslaw Czarnowski
---
super-intel.c | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index d00364f..e1e55c8 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -354,6 +354,7 @@ struct imsm_update_reshape_migration {
int subdev;
int new_level;
int new_layout;
+ int new_chunksize;

int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
};
@@ -6156,6 +6157,12 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
id->dev = new_dev;
tofree = (void **)dev;

+ /* update chunk size
+ */
+ if (u->new_chunksize > 0)
+ map->blocks_per_strip =
+ __cpu_to_le16(u->new_chunksize * 2);
+
/* add disk
*/
if ((u->new_level != 5) ||
@@ -7367,14 +7374,25 @@ static int imsm_create_metadata_update_for_migration(
u->new_layout = geo->layout;
u->new_raid_disks = u->old_raid_disks = geo->raid_disks;
u->new_disks[0] = -1;
+ u->new_chunksize = -1;

dev = get_imsm_dev(super, u->subdev);
if (dev) {
struct imsm_map *map;

map = get_imsm_map(dev, 0);
- if (map)
+ if (map) {
+ int current_chunk_size =
+ __le16_to_cpu(map->blocks_per_strip) / 2;
+
+ if (geo->chunksize != current_chunk_size) {
+ u->new_chunksize = geo->chunksize / 1024;
+ dprintf("imsm: "
+ "chunk size change from %i to %i\n",
+ current_chunk_size, u->new_chunksize);
+ }
previous_level = map->raid_level;
+ }
}
if ((geo->level == 5) && (previous_level == 0)) {
struct mdinfo *spares = NULL;

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

Re: [PATCH 0/5] imsm support for raid0->raid5 migration

am 09.05.2011 04:03:28 von NeilBrown

On Wed, 04 May 2011 17:10:33 +0200 Przemyslaw Czarnowski
wrote:

> Migration r0->r5 once again; with a fix comming from your comment.
>
> The following series implements support for raid0->raid5 migration for IMSM
> metadata. These patches blocks opposite direction of migration.
> Code mostly bases on patches sent to you by Adam Kwolek. I have incorporated
> your remarks and I tested it quite extensively for comformity with IMSM
> standard. I have also removed opposite direction, as it is just not supported
> right now.
>
> Note:
> Please do not include these patches on 'master' branch, as they are supposed
> to be a part of next minor mdadm version (ie. mdadm 3.2.2). I think good place
> for it is devel-3.2. Master should be reserved just for bug/stability fixes
> for previous release.

I have applied these patches, and in fact I have applied them to 'master'
because that if where I think they belong. Eventually 3.2.2 will be whatever
is on 'master' at that time.

I might create a devel-3.3 at some stage to do some brand new development,
but these patches are just a continuation of what went into 3.2 and 3.2.1 so
I think this is where they belong.

Thanks,
NeilBrown

> ---
>
> Przemyslaw Czarnowski (5):
> imsm: prepare update for level migrations reshape
> imsm: fix: disable migration from raid5->raid0
> imsm: prepare memory for level migration update
> imsm: process update for raid level migrations
> imsm: add new chunk size to metadata update
>
>
> super-intel.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 330 insertions(+), 7 deletions(-)
>

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html