/* internal representation of IMSM metadata */
struct intel_super {
union {
- struct imsm_super *mpb;
- void *buf;
+ void *buf; /* O_DIRECT buffer for reading/writing metadata */
+ struct imsm_super *anchor; /* immovable parameters */
};
+ size_t len; /* size of the 'buf' allocation */
int updates_pending; /* count of pending updates for mdmon */
int creating_imsm; /* flag to indicate container creation */
int current_vol; /* index of raid device undergoing creation */
+ #define IMSM_MAX_DISKS 6
+ struct imsm_disk *disk_tbl[IMSM_MAX_DISKS];
+ #define IMSM_MAX_RAID_DEVS 2
+ struct imsm_dev *dev_tbl[IMSM_MAX_RAID_DEVS];
struct dl {
struct dl *next;
int index;
return &mpb->sig[MPB_SIG_LEN];
}
-static struct imsm_disk *get_imsm_disk(struct imsm_super *mpb, __u8 index)
+/* retrieve a disk directly from the anchor when the anchor is known to be
+ * up-to-date, currently only at load time
+ */
+static struct imsm_disk *__get_imsm_disk(struct imsm_super *mpb, __u8 index)
{
- if (index > mpb->num_disks - 1)
+ if (index >= mpb->num_disks)
return NULL;
return &mpb->disk[index];
}
-static __u32 gen_imsm_checksum(struct imsm_super *mpb)
+static struct imsm_disk *get_imsm_disk(struct intel_super *super, __u8 index)
+{
+ if (index >= super->anchor->num_disks)
+ return NULL;
+ return super->disk_tbl[index];
+}
+
+/* generate a checksum directly from the anchor when the anchor is known to be
+ * up-to-date, currently only at load or write_super after coalescing
+ */
+static __u32 __gen_imsm_checksum(struct imsm_super *mpb)
{
__u32 end = mpb->mpb_size / sizeof(end);
__u32 *p = (__u32 *) mpb;
return size;
}
-static struct imsm_dev *get_imsm_dev(struct imsm_super *mpb, __u8 index)
+static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
{
int offset;
int i;
void *_mpb = mpb;
- if (index > mpb->num_raid_devs - 1)
+ if (index >= mpb->num_raid_devs)
return NULL;
/* devices start after all disks */
return NULL;
}
+static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index)
+{
+ if (index >= super->anchor->num_raid_devs)
+ return NULL;
+ return super->dev_tbl[index];
+}
+
static __u32 get_imsm_disk_idx(struct imsm_map *map, int slot)
{
__u32 *ord_tbl = &map->disk_ord_tbl[slot];
static struct extent *get_extents(struct intel_super *super, struct dl *dl)
{
/* find a list of used extents on the given physical device */
- struct imsm_super *mpb = super->mpb;
struct imsm_disk *disk;
struct extent *rv, *e;
int i, j;
int memberships = 0;
- disk = get_imsm_disk(mpb, dl->index);
+ disk = get_imsm_disk(super, dl->index);
if (!disk)
return NULL;
- for (i = 0; i < mpb->num_raid_devs; i++) {
- struct imsm_dev *dev = get_imsm_dev(mpb, i);
+ for (i = 0; i < super->anchor->num_raid_devs; i++) {
+ struct imsm_dev *dev = get_imsm_dev(super, i);
struct imsm_map *map = dev->vol.map;
for (j = 0; j < map->num_members; j++) {
return NULL;
e = rv;
- for (i = 0; i < mpb->num_raid_devs; i++) {
- struct imsm_dev *dev = get_imsm_dev(mpb, i);
+ for (i = 0; i < super->anchor->num_raid_devs; i++) {
+ struct imsm_dev *dev = get_imsm_dev(super, i);
struct imsm_map *map = dev->vol.map;
for (j = 0; j < map->num_members; j++) {
static void print_imsm_disk(struct imsm_super *mpb, int index)
{
- struct imsm_disk *disk = get_imsm_disk(mpb, index);
+ struct imsm_disk *disk = __get_imsm_disk(mpb, index);
char str[MAX_RAID_SERIAL_LEN];
__u32 s;
__u64 sz;
static void examine_super_imsm(struct supertype *st, char *homehost)
{
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
char str[MAX_SIGNATURE_LENGTH];
int i;
__u32 sum;
printf(" Generation : %08x\n", __le32_to_cpu(mpb->generation_num));
sum = __le32_to_cpu(mpb->check_sum);
printf(" Checksum : %08x %s\n", sum,
- gen_imsm_checksum(mpb) == sum ? "correct" : "incorrect");
+ __gen_imsm_checksum(mpb) == sum ? "correct" : "incorrect");
printf(" MPB Sectors : %d\n", mpb_sectors(mpb));
printf(" Disks : %d\n", mpb->num_disks);
printf(" RAID Devices : %d\n", mpb->num_raid_devs);
print_imsm_disk(mpb, super->disks->index);
for (i = 0; i < mpb->num_raid_devs; i++)
- print_imsm_dev(get_imsm_dev(mpb, i), super->disks->index);
+ print_imsm_dev(__get_imsm_dev(mpb, i), super->disks->index);
for (i = 0; i < mpb->num_disks; i++) {
if (i == super->disks->index)
continue;
static void brief_examine_super_imsm(struct supertype *st)
{
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
printf("ARRAY /dev/imsm family=%08x metadata=external:imsm\n",
- __le32_to_cpu(mpb->family_num));
+ __le32_to_cpu(super->anchor->family_num));
}
static void detail_super_imsm(struct supertype *st, char *homehost)
static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
{
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
- struct imsm_dev *dev = get_imsm_dev(mpb, super->current_vol);
+ struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
struct imsm_map *map = &dev->vol.map[0];
info->container_member = super->current_vol;
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
{
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
struct imsm_disk *disk;
__u32 s;
getinfo_super_imsm_volume(st, info);
return;
}
- info->array.raid_disks = mpb->num_disks;
+ info->array.raid_disks = super->anchor->num_disks;
info->array.level = LEVEL_CONTAINER;
info->array.layout = 0;
info->array.md_minor = -1;
info->disk.state = 0;
if (super->disks) {
- disk = get_imsm_disk(mpb, super->disks->index);
+ disk = get_imsm_disk(super, super->disks->index);
if (!disk) {
info->disk.number = -1;
info->disk.raid_disk = -1;
return 0;
}
- if (memcmp(first->mpb->sig, sec->mpb->sig, MAX_SIGNATURE_LENGTH) != 0)
+ if (memcmp(first->anchor->sig, sec->anchor->sig, MAX_SIGNATURE_LENGTH) != 0)
return 3;
- if (first->mpb->family_num != sec->mpb->family_num)
+ if (first->anchor->family_num != sec->anchor->family_num)
return 3;
- if (first->mpb->mpb_size != sec->mpb->mpb_size)
+ if (first->anchor->mpb_size != sec->anchor->mpb_size)
return 3;
- if (first->mpb->check_sum != sec->mpb->check_sum)
+ if (first->anchor->check_sum != sec->anchor->check_sum)
return 3;
return 0;
static int
load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
{
- struct imsm_super *mpb = super->mpb;
struct dl *dl;
struct stat stb;
struct imsm_disk *disk;
int i;
dl = malloc(sizeof(*dl));
- if (!dl) {
+ disk = malloc(sizeof(*disk));
+ if (!dl || !disk) {
if (devname)
fprintf(stderr,
Name ": failed to allocate disk buffer for %s\n",
devname);
+ if (disk)
+ free(disk);
+ if (dl)
+ free(dl);
return 2;
}
memset(dl, 0, sizeof(*dl));
+ memset(disk, 0, sizeof(*disk));
fstat(fd, &stb);
dl->major = major(stb.st_rdev);
return 2;
/* look up this disk's index */
- for (i = 0; i < mpb->num_disks; i++) {
- disk = get_imsm_disk(mpb, i);
+ for (i = 0; i < super->anchor->num_disks; i++) {
+ struct imsm_disk *disk_iter;
+
+ disk_iter = __get_imsm_disk(super->anchor, i);
- if (memcmp(disk->serial, dl->serial, MAX_RAID_SERIAL_LEN) == 0)
+ if (memcmp(disk_iter->serial, dl->serial,
+ MAX_RAID_SERIAL_LEN) == 0) {
+ *disk = *disk_iter;
+ super->disk_tbl[i] = disk;
+ dl->index = i;
break;
+ }
}
- if (i > mpb->num_disks - 1) {
+ if (i == super->anchor->num_disks) {
if (devname)
fprintf(stderr,
Name ": failed to match serial \'%s\' for %s\n",
dl->serial, devname);
+ free(disk);
return 0;
}
- dl->index = i;
+ return 0;
+}
+
+static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src)
+{
+ int i;
+
+ *dest = *src;
+
+ for (i = 0; i < src->vol.map[0].num_members; i++)
+ dest->vol.map[0].disk_ord_tbl[i] = src->vol.map[0].disk_ord_tbl[i];
+
+ if (!src->vol.migr_state)
+ return;
+
+ dest->vol.map[1] = src->vol.map[1];
+ for (i = 0; i < src->vol.map[1].num_members; i++)
+ dest->vol.map[1].disk_ord_tbl[i] = src->vol.map[1].disk_ord_tbl[i];
+}
+
+static int parse_raid_devices(struct intel_super *super)
+{
+ int i;
+ struct imsm_dev *dev_new;
+ size_t len;
+
+ 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);
+ dev_new = malloc(len);
+ if (!dev_new)
+ return 1;
+ imsm_copy_dev(dev_new, dev_iter);
+ super->dev_tbl[i] = dev_new;
+ }
return 0;
}
static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
{
unsigned long long dsize;
- size_t len, mpb_size;
unsigned long long sectors;
struct stat;
struct imsm_super *anchor;
__u32 check_sum;
+ int rc;
get_dev_size(fd, NULL, &dsize);
return 1;
}
- len = 512;
- if (posix_memalign((void**)&anchor, 512, len) != 0) {
+ if (posix_memalign((void**)&anchor, 512, 512) != 0) {
if (devname)
fprintf(stderr,
Name ": Failed to allocate imsm anchor buffer"
" on %s\n", devname);
return 1;
}
- if (read(fd, anchor, len) != len) {
+ if (read(fd, anchor, 512) != 512) {
if (devname)
fprintf(stderr,
Name ": Cannot read anchor block on %s: %s\n",
return 2;
}
- mpb_size = __le32_to_cpu(anchor->mpb_size);
- mpb_size = ROUND_UP(mpb_size, 512);
- if (posix_memalign(&super->buf, 512, mpb_size) != 0) {
+ super->len = __le32_to_cpu(anchor->mpb_size);
+ super->len = ROUND_UP(anchor->mpb_size, 512);
+ if (posix_memalign(&super->buf, 512, super->len) != 0) {
if (devname)
fprintf(stderr,
Name ": unable to allocate %zu byte mpb buffer\n",
- mpb_size);
+ super->len);
free(anchor);
return 2;
}
- memcpy(super->buf, anchor, len);
+ memcpy(super->buf, anchor, 512);
sectors = mpb_sectors(anchor) - 1;
free(anchor);
- if (!sectors)
- return load_imsm_disk(fd, super, devname, 0);
+ if (!sectors) {
+ rc = load_imsm_disk(fd, super, devname, 0);
+ if (rc == 0)
+ rc = parse_raid_devices(super);
+ return rc;
+ }
/* read the extended mpb */
if (lseek64(fd, dsize - (512 * (2 + sectors)), SEEK_SET) < 0) {
return 1;
}
- len = mpb_size - 512;
- if (read(fd, super->buf + 512, len) != len) {
+ if (read(fd, super->buf + 512, super->len - 512) != super->len - 512) {
if (devname)
fprintf(stderr,
Name ": Cannot read extended mpb on %s: %s\n",
return 2;
}
- check_sum = gen_imsm_checksum(super->mpb);
- if (check_sum != __le32_to_cpu(super->mpb->check_sum)) {
+ check_sum = __gen_imsm_checksum(super->anchor);
+ if (check_sum != __le32_to_cpu(super->anchor->check_sum)) {
if (devname)
fprintf(stderr,
Name ": IMSM checksum %x != %x on %s\n",
- check_sum, __le32_to_cpu(super->mpb->check_sum),
+ check_sum, __le32_to_cpu(super->anchor->check_sum),
devname);
return 2;
}
- return load_imsm_disk(fd, super, devname, 0);
+ rc = load_imsm_disk(fd, super, devname, 0);
+ if (rc == 0)
+ rc = parse_raid_devices(super);
+ return rc;
}
static void free_imsm_disks(struct intel_super *super)
{
+ int i;
+
while (super->disks) {
struct dl *d = super->disks;
free(d->devname);
free(d);
}
+ for (i = 0; i < IMSM_MAX_DISKS; i++)
+ if (super->disk_tbl[i]) {
+ free(super->disk_tbl[i]);
+ super->disk_tbl[i] = NULL;
+ }
}
static void free_imsm(struct intel_super *super)
{
- if (super->mpb)
- free(super->mpb);
+ int i;
+
+ if (super->buf)
+ free(super->buf);
free_imsm_disks(super);
+ for (i = 0; i < IMSM_MAX_RAID_DEVS; i++)
+ if (super->dev_tbl[i])
+ free(super->dev_tbl[i]);
free(super);
}
if (!keep_fd)
close(dfd);
if (rv == 0) {
- gen = __le32_to_cpu(super->mpb->generation_num);
+ gen = __le32_to_cpu(super->anchor->generation_num);
if (!best || gen > bestgen) {
bestgen = gen;
best = sd;
}
if (st->subarray[0]) {
- if (atoi(st->subarray) <= super->mpb->num_raid_devs)
+ if (atoi(st->subarray) <= super->anchor->num_raid_devs)
super->current_vol = atoi(st->subarray);
else
return 1;
* so st->sb is already set.
*/
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
struct imsm_dev *dev;
struct imsm_vol *vol;
struct imsm_map *map;
memcpy(mpb_new, mpb, size_old);
free(mpb);
mpb = mpb_new;
- super->mpb = mpb_new;
+ super->anchor = mpb_new;
mpb->mpb_size = __cpu_to_le32(size_new);
memset(mpb_new + size_old, 0, size_round - size_old);
}
super->current_vol = idx;
sprintf(st->subarray, "%d", idx);
- mpb->num_raid_devs++;
- dev = get_imsm_dev(mpb, idx);
+ dev = malloc(sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
+ if (!dev) {
+ fprintf(stderr, Name": could not allocate raid device\n");
+ return 0;
+ }
strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
array_blocks = calc_array_size(info->level, info->raid_disks,
info->layout, info->chunk_size,
vol->migr_type = 0;
vol->dirty = 0;
for (i = 0; i < idx; i++) {
- struct imsm_dev *prev = get_imsm_dev(mpb, i);
+ struct imsm_dev *prev = get_imsm_dev(super, i);
struct imsm_map *pmap = &prev->vol.map[0];
offset += __le32_to_cpu(pmap->blocks_per_member);
/* initialized in add_to_super */
map->disk_ord_tbl[i] = __cpu_to_le32(0);
}
+ mpb->num_raid_devs++;
+ super->dev_tbl[super->current_vol] = dev;
return 1;
}
int fd, char *devname)
{
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
struct dl *dl;
struct imsm_dev *dev;
struct imsm_map *map;
struct imsm_disk *disk;
__u32 status;
- dev = get_imsm_dev(mpb, super->current_vol);
+ dev = get_imsm_dev(super, super->current_vol);
map = &dev->vol.map[0];
for (dl = super->disks; dl ; dl = dl->next)
map->disk_ord_tbl[dk->number] = __cpu_to_le32(dl->index);
- disk = get_imsm_disk(mpb, dl->index);
+ disk = get_imsm_disk(super, dl->index);
status = CONFIGURED_DISK | USABLE_DISK;
disk->status = __cpu_to_le32(status);
}
int fd, char *devname)
{
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
struct imsm_disk *disk;
struct dl *dd;
unsigned long long size;
fstat(fd, &stb);
dd = malloc(sizeof(*dd));
- if (!dd) {
+ disk = malloc(sizeof(*disk));
+ if (!dd || !disk) {
fprintf(stderr,
Name ": malloc failed %s:%d.\n", __func__, __LINE__);
+ if (!dd)
+ free(dd);
+ if (!disk)
+ free(disk);
abort();
}
memset(dd, 0, sizeof(*dd));
+ memset(disk, 0, sizeof(*disk));
dd->major = major(stb.st_rdev);
dd->minor = minor(stb.st_rdev);
dd->index = dk->number;
if (rv) {
fprintf(stderr,
Name ": failed to retrieve scsi serial, aborting\n");
+ free(dd);
+ free(disk);
abort();
}
if (mpb->num_disks <= dk->number)
mpb->num_disks = dk->number + 1;
- disk = get_imsm_disk(mpb, dk->number);
get_dev_size(fd, NULL, &size);
size /= 512;
status = USABLE_DISK | SPARE_DISK;
disk->scsi_id = __cpu_to_le32(id);
else
disk->scsi_id = __cpu_to_le32(0);
+ super->disk_tbl[dd->index] = disk;
/* update the family number if we are creating a container */
- if (super->creating_imsm)
- mpb->family_num = __cpu_to_le32(gen_imsm_checksum(mpb));
+ if (super->creating_imsm) {
+ disk = __get_imsm_disk(mpb, dd->index);
+ *disk = *super->disk_tbl[dd->index]; /* copy in new disk */
+ mpb->family_num = __cpu_to_le32(__gen_imsm_checksum(mpb));
+ }
super->disks = dd;
}
static int write_super_imsm(struct intel_super *super, int doclose)
{
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
struct dl *d;
__u32 generation;
__u32 sum;
+ int i;
/* 'generation' is incremented everytime the metadata is written */
generation = __le32_to_cpu(mpb->generation_num);
generation++;
mpb->generation_num = __cpu_to_le32(generation);
+ for (i = 0; i < mpb->num_disks; i++)
+ mpb->disk[i] = *super->disk_tbl[i];
+ for (i = 0; i < mpb->num_raid_devs; i++) {
+ struct imsm_dev *dev = __get_imsm_dev(mpb, i);
+
+ imsm_copy_dev(dev, super->dev_tbl[i]);
+ }
+
/* recalculate checksum */
- sum = gen_imsm_checksum(mpb);
+ sum = __gen_imsm_checksum(mpb);
mpb->check_sum = __cpu_to_le32(sum);
for (d = super->disks; d ; d = d->next) {
size_t len;
struct imsm_update_create_array *u;
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
struct imsm_dev *dev;
- struct imsm_map *map;
struct dl *d;
if (super->current_vol < 0 ||
- !(dev = get_imsm_dev(mpb, super->current_vol))) {
+ !(dev = get_imsm_dev(super, super->current_vol))) {
fprintf(stderr, "%s: could not determine sub-array\n",
__func__);
return 1;
}
- map = &dev->vol.map[0];
- len = sizeof(*u) + sizeof(__u32) * (map->num_members - 1);
+ len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev);
u = malloc(len);
if (!u) {
fprintf(stderr, "%s: failed to allocate update buffer\n",
u->type = update_create_array;
u->dev_idx = super->current_vol;
- memcpy(&u->dev, dev, sizeof(*dev));
- memcpy(u->dev.vol.map[0].disk_ord_tbl, map->disk_ord_tbl,
- sizeof(__u32) * map->num_members);
+ imsm_copy_dev(&u->dev, dev);
append_metadata_update(st, u, len);
for (d = super->disks; d ; d = d->next) {
* and create appropriate device mdinfo.
*/
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
struct mdinfo *rest = NULL;
int i;
for (i = 0; i < mpb->num_raid_devs; i++) {
- struct imsm_dev *dev = get_imsm_dev(mpb, i);
+ struct imsm_dev *dev = get_imsm_dev(super, i);
struct imsm_vol *vol = &dev->vol;
struct imsm_map *map = vol->map;
struct mdinfo *this;
info_d->next = this->devs;
this->devs = info_d;
- disk = get_imsm_disk(mpb, idx);
+ disk = get_imsm_disk(super, idx);
s = __le32_to_cpu(disk->status);
info_d->disk.number = d->index;
char *inst)
{
struct intel_super *super = c->sb;
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
- if (atoi(inst) + 1 > mpb->num_raid_devs) {
+ if (atoi(inst) >= mpb->num_raid_devs) {
fprintf(stderr, "%s: subarry index %d, out of range\n",
__func__, atoi(inst));
return -ENODEV;
return 0;
}
-static __u8 imsm_check_degraded(struct imsm_super *mpb, int n, int failed)
+static __u8 imsm_check_degraded(struct intel_super *super, int n, int failed)
{
- struct imsm_dev *dev = get_imsm_dev(mpb, n);
+ struct imsm_dev *dev = get_imsm_dev(super, n);
struct imsm_map *map = dev->vol.map;
if (!failed)
for (i = 0; i < map->num_members; i++) {
int idx = get_imsm_disk_idx(map, i);
- struct imsm_disk *disk = get_imsm_disk(mpb, idx);
+ struct imsm_disk *disk = get_imsm_disk(super, idx);
if (__le32_to_cpu(disk->status) & FAILED_DISK)
failed++;
return map->map_state;
}
-static int imsm_count_failed(struct imsm_super *mpb, struct imsm_map *map)
+static int imsm_count_failed(struct intel_super *super, struct imsm_map *map)
{
int i;
int failed = 0;
for (i = 0; i < map->num_members; i++) {
int idx = get_imsm_disk_idx(map, i);
- disk = get_imsm_disk(mpb, idx);
+ disk = get_imsm_disk(super, idx);
if (__le32_to_cpu(disk->status) & FAILED_DISK)
failed++;
}
{
int inst = a->info.container_member;
struct intel_super *super = a->container->sb;
- struct imsm_dev *dev = get_imsm_dev(super->mpb, inst);
+ struct imsm_dev *dev = get_imsm_dev(super, inst);
struct imsm_map *map = &dev->vol.map[0];
int dirty = !consistent;
int failed;
__u8 map_state;
if (a->resync_start == ~0ULL) {
- failed = imsm_count_failed(super->mpb, map);
- map_state = imsm_check_degraded(super->mpb, inst, failed);
+ failed = imsm_count_failed(super, map);
+ map_state = imsm_check_degraded(super, inst, failed);
if (!failed)
map_state = IMSM_T_STATE_NORMAL;
if (map->map_state != map_state) {
{
int inst = a->info.container_member;
struct intel_super *super = a->container->sb;
- struct imsm_dev *dev = get_imsm_dev(super->mpb, inst);
+ struct imsm_dev *dev = get_imsm_dev(super, inst);
struct imsm_map *map = dev->vol.map;
struct imsm_disk *disk;
__u32 status;
dprintf("imsm: set_disk %d:%x\n", n, state);
- disk = get_imsm_disk(super->mpb, get_imsm_disk_idx(map, n));
+ disk = get_imsm_disk(super, get_imsm_disk_idx(map, n));
/* check for new failures */
status = __le32_to_cpu(disk->status);
* degraded / failed status
*/
if (new_failure && map->map_state != IMSM_T_STATE_FAILED)
- failed = imsm_count_failed(super->mpb, map);
+ failed = imsm_count_failed(super, map);
/* determine map_state based on failed or in_sync count */
if (failed)
- map->map_state = imsm_check_degraded(super->mpb, inst, failed);
+ map->map_state = imsm_check_degraded(super, inst, failed);
else if (map->map_state == IMSM_T_STATE_DEGRADED) {
struct mdinfo *d;
int working = 0;
static int store_imsm_mpb(int fd, struct intel_super *super)
{
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
__u32 mpb_size = __le32_to_cpu(mpb->mpb_size);
unsigned long long dsize;
unsigned long long sectors;
*/
struct intel_super *super = a->container->sb;
- struct imsm_super *mpb = super->mpb;
int inst = a->info.container_member;
- struct imsm_dev *dev = get_imsm_dev(mpb, inst);
+ struct imsm_dev *dev = get_imsm_dev(super, inst);
struct imsm_map *map = dev->vol.map;
int failed = a->info.array.raid_disks;
struct mdinfo *rv = NULL;
dprintf("imsm: activate spare: inst=%d failed=%d (%d) level=%d\n",
inst, failed, a->info.array.raid_disks, a->info.array.level);
- if (imsm_check_degraded(mpb, inst, failed) != IMSM_T_STATE_DEGRADED)
+ if (imsm_check_degraded(super, inst, failed) != IMSM_T_STATE_DEGRADED)
return NULL;
/* For each slot, if it is not working, find a spare */
continue;
/* is this unused device marked as a spare? */
- disk = get_imsm_disk(mpb, dl->index);
+ disk = get_imsm_disk(super, dl->index);
if (!(__le32_to_cpu(disk->status) & SPARE_DISK))
continue;
* flag
*/
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->mpb;
+ struct imsm_super *mpb = super->anchor;
enum imsm_update_type type = *(enum imsm_update_type *) update->buf;
switch (type) {
case update_activate_spare: {
struct imsm_update_activate_spare *u = (void *) update->buf;
- struct imsm_dev *dev = get_imsm_dev(mpb, u->array);
+ struct imsm_dev *dev = get_imsm_dev(super, u->array);
struct imsm_map *map = &dev->vol.map[0];
struct active_array *a;
struct imsm_disk *disk;
victim = get_imsm_disk_idx(map, u->slot);
map->disk_ord_tbl[u->slot] = __cpu_to_le32(u->disk_idx);
- disk = get_imsm_disk(mpb, u->disk_idx);
+ disk = get_imsm_disk(super, u->disk_idx);
status = __le32_to_cpu(disk->status);
status |= CONFIGURED_DISK;
disk->status = __cpu_to_le32(status);
for (a = st->arrays; a; a = a->next) {
int inst = a->info.container_member;
- dev = get_imsm_dev(mpb, inst);
+ dev = get_imsm_dev(super, inst);
map = &dev->vol.map[0];
if (map->raid_level > 0)
members |= 1 << inst;
/* count arrays using the victim in the metadata */
found = 0;
for (a = st->arrays; a ; a = a->next) {
- dev = get_imsm_dev(mpb, a->info.container_member);
+ dev = get_imsm_dev(super, a->info.container_member);
map = &dev->vol.map[0];
for (i = 0; i < map->num_members; i++)
if (victim == get_imsm_disk_idx(map, i))
/* clear some flags if the victim is no longer being
* utilized anywhere
*/
- disk = get_imsm_disk(mpb, victim);
+ disk = get_imsm_disk(super, victim);
if (!found) {
status = __le32_to_cpu(disk->status);
status &= ~(CONFIGURED_DISK | USABLE_DISK);
* overalpping disks
*/
for (i = 0; i < mpb->num_raid_devs; i++) {
- dev = get_imsm_dev(mpb, i);
+ dev = get_imsm_dev(super, i);
map = &dev->vol.map[0];
start = __le32_to_cpu(map->pba_of_lba0);
end = start + __le32_to_cpu(map->blocks_per_member);
return;
}
+ /* check that prepare update was successful */
+ if (!update->space) {
+ dprintf("%s: prepare update failed\n", __func__);
+ return;
+ }
+
super->updates_pending++;
+ dev = update->space;
+ update->space = NULL;
+ imsm_copy_dev(dev, &u->dev);
+ super->dev_tbl[u->dev_idx] = dev;
mpb->num_raid_devs++;
- dev = get_imsm_dev(mpb, u->dev_idx);
- memcpy(dev, &u->dev, sizeof(*dev));
- map = &dev->vol.map[0];
- memcpy(map->disk_ord_tbl, new_map->disk_ord_tbl,
- sizeof(__u32) * new_map->num_members);
/* fix up flags, if arrays overlap then the drives can not be
* spares
struct imsm_disk *disk;
__u32 status;
- disk = get_imsm_disk(mpb, get_imsm_disk_idx(map, i));
+ disk = get_imsm_disk(super, get_imsm_disk_idx(map, i));
status = __le32_to_cpu(disk->status);
status |= CONFIGURED_DISK;
if (overlap)
static void imsm_prepare_update(struct supertype *st,
struct metadata_update *update)
{
- /* Allocate space to hold a new mpb if necessary. We currently
- * allocate enough to hold 2 subarrays for the given number of disks.
- * This may not be sufficient iff reshaping.
+ /**
+ * Allocate space to hold new disk entries, raid-device entries or a
+ * new mpb if necessary. We currently maintain an mpb large enough to
+ * hold 2 subarrays for the given number of disks. This may not be
+ * sufficient when reshaping.
*
* FIX ME handle the reshape case.
*
* will start using the new pointer and the manager can continue to use
* the old value until check_update_queue() runs.
*/
+ enum imsm_update_type type = *(enum imsm_update_type *) update->buf;
+
+ switch (type) {
+ case update_create_array: {
+ struct imsm_update_create_array *u = (void *) update->buf;
+ size_t len = sizeof_imsm_dev(&u->dev);
+
+ update->space = malloc(len);
+ break;
+ default:
+ break;
+ }
+ }
return;
}