imsm: fix handling of the 'migr_state' and 'migr_type' bits

The option-rom and the Matrix driver mark resyncs/rebuilds with the
migrate state bits.  Update sizeof_imsm_dev to allow allocation of
imsm_dev entries large enough to grow if migr_state is later set.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2008-08-09 20:28:24 -07:00
parent a965f303c7
commit 3393c6af8b
1 changed files with 54 additions and 23 deletions

View File

@ -290,7 +290,10 @@ struct imsm_map *get_imsm_map(struct imsm_dev *dev, int second_map)
}
static size_t sizeof_imsm_dev(struct imsm_dev *dev)
/* return the size of the device.
* migr_state increases the returned size if map[0] were to be duplicated
*/
static size_t sizeof_imsm_dev(struct imsm_dev *dev, int migr_state)
{
size_t size = sizeof(*dev) - sizeof(struct imsm_map) +
sizeof_imsm_map(get_imsm_map(dev, 0));
@ -298,6 +301,8 @@ static size_t sizeof_imsm_dev(struct imsm_dev *dev)
/* migrating means an additional map */
if (dev->vol.migr_state)
size += sizeof_imsm_map(get_imsm_map(dev, 1));
else if (migr_state)
size += sizeof_imsm_map(get_imsm_map(dev, 0));
return size;
}
@ -318,7 +323,7 @@ static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
if (i == index)
return _mpb + offset;
else
offset += sizeof_imsm_dev(_mpb + offset);
offset += sizeof_imsm_dev(_mpb + offset, 0);
return NULL;
}
@ -439,9 +444,17 @@ static void print_imsm_dev(struct imsm_dev *dev, int index)
printf(" Chunk Size : %u KiB\n",
__le16_to_cpu(map->blocks_per_strip) / 2);
printf(" Reserved : %d\n", __le32_to_cpu(dev->reserved_blocks));
printf(" Migrate State : %s\n", dev->vol.migr_state ? "migrating" : "idle");
printf(" Migrate State : %s", dev->vol.migr_state ? "migrating" : "idle");
if (dev->vol.migr_state)
printf(": %s", dev->vol.migr_type ? "rebuilding" : "initializing");
printf("\n");
printf(" Map State : %s", map_state_str[map->map_state]);
if (dev->vol.migr_state) {
struct imsm_map *map = get_imsm_map(dev, 1);
printf(", %s", map_state_str[map->map_state]);
}
printf("\n");
printf(" Dirty State : %s\n", dev->vol.dirty ? "dirty" : "clean");
printf(" Map State : %s\n", map_state_str[map->map_state]);
}
static void print_imsm_disk(struct imsm_super *mpb, int index)
@ -922,7 +935,15 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src)
{
memcpy(dest, src, sizeof_imsm_dev(src));
memcpy(dest, src, sizeof_imsm_dev(src, 0));
}
static void dup_map(struct imsm_dev *dev)
{
struct imsm_map *dest = get_imsm_map(dev, 1);
struct imsm_map *src = get_imsm_map(dev, 0);
memcpy(dest, src, sizeof_imsm_map(src));
}
static int parse_raid_devices(struct intel_super *super)
@ -934,7 +955,7 @@ static int parse_raid_devices(struct intel_super *super)
for (i = 0; i < super->anchor->num_raid_devs; i++) {
struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i);
len = sizeof_imsm_dev(dev_iter);
len = sizeof_imsm_dev(dev_iter, 1);
dev_new = malloc(len);
if (!dev_new)
return 1;
@ -1659,7 +1680,7 @@ static int write_init_super_imsm(struct supertype *st)
}
len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev);
len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev, 0);
u = malloc(len);
if (!u) {
fprintf(stderr, "%s: failed to allocate update buffer\n",
@ -2063,7 +2084,8 @@ static __u8 imsm_check_degraded(struct intel_super *super, int n, int failed)
struct imsm_map *map = get_imsm_map(dev, 0);
if (!failed)
return map->map_state;
return map->map_state == IMSM_T_STATE_UNINITIALIZED ?
IMSM_T_STATE_UNINITIALIZED : IMSM_T_STATE_NORMAL;
switch (get_imsm_raid_level(map)) {
case 0:
@ -2144,32 +2166,39 @@ static void imsm_set_array_state(struct active_array *a, int consistent)
int failed;
__u8 map_state;
failed = imsm_count_failed(super, map);
map_state = imsm_check_degraded(super, inst, failed);
if (a->resync_start == ~0ULL) {
failed = imsm_count_failed(super, map);
map_state = imsm_check_degraded(super, inst, failed);
/* complete recovery or initial resync */
if (!failed)
map_state = IMSM_T_STATE_NORMAL;
if (map->map_state != map_state) {
dprintf("imsm: map_state %d: %d\n",
inst, map_state);
map->map_state = map_state;
super->updates_pending++;
}
/* complete resync */
if (!dirty && dev->vol.dirty) {
dprintf("imsm: mark 'clean'\n");
dev->vol.dirty = 0;
if (dev->vol.migr_state) {
dprintf("imsm: mark resync complete\n");
dev->vol.migr_state = 0;
dev->vol.migr_type = 0;
super->updates_pending++;
}
} else if (!dev->vol.migr_state) {
dprintf("imsm: mark '%s' (%llu)\n",
failed ? "rebuild" : "initializing", a->resync_start);
/* mark that we are rebuilding */
map->map_state = failed ? map_state : IMSM_T_STATE_NORMAL;
dev->vol.migr_state = 1;
dev->vol.migr_type = failed ? 1 : 0;
dup_map(dev);
super->updates_pending++;
}
/* mark dirty */
if (dirty && !dev->vol.dirty) {
dprintf("imsm: mark 'dirty' (%llu)\n", a->resync_start);
dev->vol.dirty = 1;
/* mark dirty / clean */
if (dirty != dev->vol.dirty) {
dprintf("imsm: mark '%s' (%llu)\n",
dirty ? "dirty" : "clean", a->resync_start);
dev->vol.dirty = dirty;
super->updates_pending++;
}
}
@ -2230,6 +2259,8 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
if (working == a->info.array.raid_disks) {
map->map_state = IMSM_T_STATE_NORMAL;
dev->vol.migr_state = 0;
dev->vol.migr_type = 0;
super->updates_pending++;
}
}
@ -2659,7 +2690,7 @@ static void imsm_prepare_update(struct supertype *st,
switch (type) {
case update_create_array: {
struct imsm_update_create_array *u = (void *) update->buf;
size_t len = sizeof_imsm_dev(&u->dev);
size_t len = sizeof_imsm_dev(&u->dev, 1);
update->space = malloc(len);
break;