#define MPB_SECTOR_CNT 418
#define IMSM_RESERVED_SECTORS 4096
+#define SECT_PER_MB_SHIFT 11
/* Disk configuration info. */
#define IMSM_MAX_DEVICES 255
__u8 num_members; /* number of member disks */
__u8 num_domains; /* number of parity domains */
__u8 failed_disk_num; /* valid only when state is degraded */
- __u8 reserved[1];
+ __u8 ddf;
__u32 filler[7]; /* expansion area */
#define IMSM_ORD_REBUILD (1 << 24)
__u32 disk_ord_tbl[1]; /* disk_ord_tbl[num_members],
#define MIGR_VERIFY 2 /* analagous to echo check > sync_action */
#define MIGR_GEN_MIGR 3
#define MIGR_STATE_CHANGE 4
+#define MIGR_REPAIR 5
__u8 migr_type; /* Initializing, Rebuilding, ... */
__u8 dirty;
__u8 fs_state; /* fast-sync state for CnG (0xff == disabled) */
static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
#endif
+static __u8 migr_type(struct imsm_dev *dev)
+{
+ if (dev->vol.migr_type == MIGR_VERIFY &&
+ dev->status & DEV_VERIFY_AND_FIX)
+ return MIGR_REPAIR;
+ else
+ return dev->vol.migr_type;
+}
+
+static void set_migr_type(struct imsm_dev *dev, __u8 migr_type)
+{
+ /* for compatibility with older oroms convert MIGR_REPAIR, into
+ * MIGR_VERIFY w/ DEV_VERIFY_AND_FIX status
+ */
+ if (migr_type == MIGR_REPAIR) {
+ dev->vol.migr_type = MIGR_VERIFY;
+ dev->status |= DEV_VERIFY_AND_FIX;
+ } else {
+ dev->vol.migr_type = migr_type;
+ dev->status &= ~DEV_VERIFY_AND_FIX;
+ }
+}
+
static unsigned int sector_count(__u32 bytes)
{
return ((bytes + (512-1)) & (~(512-1))) / 512;
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", dev->vol.migr_state ? "migrating" : "idle");
- if (dev->vol.migr_state)
- printf(": %s", dev->vol.migr_type ? "rebuilding" : "initializing");
- printf("\n");
+ printf(" Migrate State : %s", dev->vol.migr_state ? "migrating" : "idle\n");
+ if (dev->vol.migr_state) {
+ if (migr_type(dev) == MIGR_INIT)
+ printf(": initializing\n");
+ else if (migr_type(dev) == MIGR_REBUILD)
+ printf(": rebuilding\n");
+ else if (migr_type(dev) == MIGR_VERIFY)
+ printf(": check\n");
+ else if (migr_type(dev) == MIGR_GEN_MIGR)
+ printf(": general migration\n");
+ else if (migr_type(dev) == MIGR_STATE_CHANGE)
+ printf(": state change\n");
+ else if (migr_type(dev) == MIGR_REPAIR)
+ printf(": repair\n");
+ else
+ printf(": <unknown:%d>\n", migr_type(dev));
+ }
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(" Signature : %x\n", __le32_to_cpu(log->signature));
printf(" Entry Count : %d\n", __le32_to_cpu(log->entry_count));
printf(" Spare Blocks : %d\n", __le32_to_cpu(log->reserved_spare_block_count));
- printf(" First Spare : %llx\n", __le64_to_cpu(log->first_spare_lba));
+ printf(" First Spare : %llx\n",
+ (unsigned long long) __le64_to_cpu(log->first_spare_lba));
}
for (i = 0; i < mpb->num_raid_devs; i++) {
struct mdinfo info;
}
}
-static void brief_examine_super_imsm(struct supertype *st)
+static void brief_examine_super_imsm(struct supertype *st, int verbose)
{
/* We just write a generic IMSM ARRAY entry */
struct mdinfo info;
getinfo_super_imsm(st, &info);
fname_from_uuid(st, &info, nbuf, ':');
- printf("ARRAY metadata=imsm auto=md UUID=%s\n", nbuf + 5);
for (i = 0; i < super->anchor->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
super->current_vol = i;
getinfo_super_imsm(st, &info);
fname_from_uuid(st, &info, nbuf1, ':');
- printf("ARRAY /dev/md/%.16s container=%s\n"
- " member=%d auto=mdp UUID=%s\n",
+ printf("ARRAY /dev/md/%.16s container=%s member=%d UUID=%s\n",
dev->volume, nbuf + 5, i, nbuf1 + 5);
}
+ printf("ARRAY metadata=imsm UUID=%s\n", nbuf + 5);
}
static void export_examine_super_imsm(struct supertype *st)
info->array.utime = 0;
info->array.chunk_size = __le16_to_cpu(map->blocks_per_strip) << 9;
info->array.state = !dev->vol.dirty;
+ info->custom_array_size = __le32_to_cpu(dev->size_high);
+ info->custom_array_size <<= 32;
+ info->custom_array_size |= __le32_to_cpu(dev->size_low);
info->disk.major = 0;
info->disk.minor = 0;
if (map->map_state == IMSM_T_STATE_UNINITIALIZED || dev->vol.dirty)
info->resync_start = 0;
else if (dev->vol.migr_state)
- info->resync_start = __le32_to_cpu(dev->vol.curr_migr_unit);
+ /* FIXME add curr_migr_unit to resync_start conversion */
+ info->resync_start = 0;
else
info->resync_start = ~0ULL;
* 1/ Idle (migr_state=0 map0state=normal||unitialized||degraded||failed)
* 2/ Initialize (migr_state=1 migr_type=MIGR_INIT map0state=normal
* map1state=unitialized)
- * 3/ Verify (Resync) (migr_state=1 migr_type=MIGR_REBUILD map0state=normal
+ * 3/ Repair (Resync) (migr_state=1 migr_type=MIGR_REPAIR map0state=normal
* map1state=normal)
* 4/ Rebuild (migr_state=1 migr_type=MIGR_REBUILD map0state=normal
* map1state=degraded)
struct imsm_map *src = get_imsm_map(dev, 0);
dev->vol.migr_state = 1;
- dev->vol.migr_type = migr_type;
+ set_migr_type(dev, migr_type);
dev->vol.curr_migr_unit = 0;
dest = get_imsm_map(dev, 1);
if (st->subarray[0]) {
if (atoi(st->subarray) <= super->anchor->num_raid_devs)
super->current_vol = atoi(st->subarray);
- else
+ else {
+ free_imsm(super);
return 1;
+ }
}
*sbp = super;
if (load_super_imsm_all(st, fd, &st->sb, devname, 1) == 0)
return 0;
#endif
- if (st->subarray[0])
- return 1; /* FIXME */
+
+ free_super_imsm(st);
super = alloc_super(0);
if (!super) {
return rv;
}
+ if (st->subarray[0]) {
+ if (atoi(st->subarray) <= super->anchor->num_raid_devs)
+ super->current_vol = atoi(st->subarray);
+ else {
+ free_imsm(super);
+ return 1;
+ }
+ }
+
st->sb = super;
if (st->ss == NULL) {
st->ss = &super_imsm;
array_blocks = calc_array_size(info->level, info->raid_disks,
info->layout, info->chunk_size,
info->size*2);
+ /* round array size down to closest MB */
+ array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
+
dev->size_low = __cpu_to_le32((__u32) array_blocks);
dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32));
dev->status = __cpu_to_le32(0);
dev->reserved_blocks = __cpu_to_le32(0);
vol = &dev->vol;
vol->migr_state = 0;
- vol->migr_type = MIGR_INIT;
+ set_migr_type(dev, MIGR_INIT);
vol->dirty = 0;
vol->curr_migr_unit = 0;
map = get_imsm_map(dev, 0);
map->failed_disk_num = ~0;
map->map_state = info->level ? IMSM_T_STATE_UNINITIALIZED :
IMSM_T_STATE_NORMAL;
+ map->ddf = 1;
if (info->level == 1 && info->raid_disks > 2) {
fprintf(stderr, Name": imsm does not support more than 2 disks"
"in a raid1 volume\n");
return 0;
}
+
+ map->raid_level = info->level;
if (info->level == 10) {
map->raid_level = 1;
map->num_domains = info->raid_disks / 2;
- } else {
- map->raid_level = info->level;
+ } else if (info->level == 1)
+ map->num_domains = info->raid_disks;
+ else
map->num_domains = 1;
- }
+
num_data_stripes = info_to_num_data_stripes(info, map->num_domains);
map->num_data_stripes = __cpu_to_le32(num_data_stripes);
struct mdinfo *this;
int slot;
+ /* do not publish arrays that are in the middle of an
+ * unsupported migration
+ */
+ if (dev->vol.migr_state &&
+ (migr_type(dev) == MIGR_GEN_MIGR ||
+ migr_type(dev) == MIGR_STATE_CHANGE)) {
+ fprintf(stderr, Name ": cannot assemble volume '%.16s':"
+ " unsupported migration in progress\n",
+ dev->volume);
+ continue;
+ }
+
this = malloc(sizeof(*this));
memset(this, 0, sizeof(*this));
this->next = rest;
info_d = malloc(sizeof(*info_d));
if (!info_d) {
fprintf(stderr, Name ": failed to allocate disk"
- " for volume %s\n", (char *) dev->volume);
+ " for volume %.16s\n", dev->volume);
free(this);
this = rest;
break;
if (!dev->vol.migr_state)
return 0;
- if (dev->vol.migr_type == MIGR_INIT)
+ if (migr_type(dev) == MIGR_INIT ||
+ migr_type(dev) == MIGR_REPAIR)
return 1;
migr_map = get_imsm_map(dev, 1);
if (!dev->vol.migr_state)
return 0;
- if (dev->vol.migr_type != MIGR_REBUILD)
+ if (migr_type(dev) != MIGR_REBUILD)
return 0;
migr_map = get_imsm_map(dev, 1);
disk->status |= FAILED_DISK;
set_imsm_ord_tbl_ent(map, slot, idx | IMSM_ORD_REBUILD);
- if (map->failed_disk_num == ~0)
+ if (~map->failed_disk_num == 0)
map->failed_disk_num = slot;
return 1;
}
} else if (!is_resyncing(dev) && !failed) {
/* mark the start of the init process if nothing is failed */
dprintf("imsm: mark resync start (%llu)\n", a->resync_start);
- if (map->map_state == IMSM_T_STATE_NORMAL)
- migrate(dev, IMSM_T_STATE_NORMAL, MIGR_REBUILD);
- else
+ if (map->map_state == IMSM_T_STATE_UNINITIALIZED)
migrate(dev, IMSM_T_STATE_NORMAL, MIGR_INIT);
+ else
+ migrate(dev, IMSM_T_STATE_NORMAL, MIGR_REPAIR);
super->updates_pending++;
}
- /* check if we can update the migration checkpoint */
- if (dev->vol.migr_state &&
- __le32_to_cpu(dev->vol.curr_migr_unit) != a->resync_start) {
- dprintf("imsm: checkpoint migration (%llu)\n", a->resync_start);
- dev->vol.curr_migr_unit = __cpu_to_le32(a->resync_start);
- super->updates_pending++;
- }
+ /* FIXME check if we can update curr_migr_unit from resync_start */
/* mark dirty / clean */
if (dev->vol.dirty != !consistent) {