imsm: refactor mpb handling into parse and coalesce
Maintaining a single global buffer is unwieldly when extending/rewriting sections of the metadata. Parse the metadata into component data structures upon reading and coalesce to a coherent buffer before writing. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
16ddab0daf
commit
949c47a0fa
358
super-intel.c
358
super-intel.c
|
@ -127,12 +127,17 @@ static unsigned int mpb_sectors(struct imsm_super *mpb)
|
||||||
/* internal representation of IMSM metadata */
|
/* internal representation of IMSM metadata */
|
||||||
struct intel_super {
|
struct intel_super {
|
||||||
union {
|
union {
|
||||||
struct imsm_super *mpb;
|
void *buf; /* O_DIRECT buffer for reading/writing metadata */
|
||||||
void *buf;
|
struct imsm_super *anchor; /* immovable parameters */
|
||||||
};
|
};
|
||||||
|
size_t len; /* size of the 'buf' allocation */
|
||||||
int updates_pending; /* count of pending updates for mdmon */
|
int updates_pending; /* count of pending updates for mdmon */
|
||||||
int creating_imsm; /* flag to indicate container creation */
|
int creating_imsm; /* flag to indicate container creation */
|
||||||
int current_vol; /* index of raid device undergoing 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 {
|
||||||
struct dl *next;
|
struct dl *next;
|
||||||
int index;
|
int index;
|
||||||
|
@ -201,14 +206,27 @@ static __u8 *get_imsm_version(struct imsm_super *mpb)
|
||||||
return &mpb->sig[MPB_SIG_LEN];
|
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 NULL;
|
||||||
return &mpb->disk[index];
|
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 end = mpb->mpb_size / sizeof(end);
|
||||||
__u32 *p = (__u32 *) mpb;
|
__u32 *p = (__u32 *) mpb;
|
||||||
|
@ -236,13 +254,13 @@ static size_t sizeof_imsm_dev(struct imsm_dev *dev)
|
||||||
return size;
|
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 offset;
|
||||||
int i;
|
int i;
|
||||||
void *_mpb = mpb;
|
void *_mpb = mpb;
|
||||||
|
|
||||||
if (index > mpb->num_raid_devs - 1)
|
if (index >= mpb->num_raid_devs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* devices start after all disks */
|
/* devices start after all disks */
|
||||||
|
@ -257,6 +275,13 @@ static struct imsm_dev *get_imsm_dev(struct imsm_super *mpb, __u8 index)
|
||||||
return NULL;
|
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)
|
static __u32 get_imsm_disk_idx(struct imsm_map *map, int slot)
|
||||||
{
|
{
|
||||||
__u32 *ord_tbl = &map->disk_ord_tbl[slot];
|
__u32 *ord_tbl = &map->disk_ord_tbl[slot];
|
||||||
|
@ -291,18 +316,17 @@ static int cmp_extent(const void *av, const void *bv)
|
||||||
static struct extent *get_extents(struct intel_super *super, struct dl *dl)
|
static struct extent *get_extents(struct intel_super *super, struct dl *dl)
|
||||||
{
|
{
|
||||||
/* find a list of used extents on the given physical device */
|
/* find a list of used extents on the given physical device */
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
struct extent *rv, *e;
|
struct extent *rv, *e;
|
||||||
int i, j;
|
int i, j;
|
||||||
int memberships = 0;
|
int memberships = 0;
|
||||||
|
|
||||||
disk = get_imsm_disk(mpb, dl->index);
|
disk = get_imsm_disk(super, dl->index);
|
||||||
if (!disk)
|
if (!disk)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
for (i = 0; i < super->anchor->num_raid_devs; i++) {
|
||||||
struct imsm_dev *dev = get_imsm_dev(mpb, i);
|
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||||
struct imsm_map *map = dev->vol.map;
|
struct imsm_map *map = dev->vol.map;
|
||||||
|
|
||||||
for (j = 0; j < map->num_members; j++) {
|
for (j = 0; j < map->num_members; j++) {
|
||||||
|
@ -317,8 +341,8 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
|
||||||
return NULL;
|
return NULL;
|
||||||
e = rv;
|
e = rv;
|
||||||
|
|
||||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
for (i = 0; i < super->anchor->num_raid_devs; i++) {
|
||||||
struct imsm_dev *dev = get_imsm_dev(mpb, i);
|
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||||
struct imsm_map *map = dev->vol.map;
|
struct imsm_map *map = dev->vol.map;
|
||||||
|
|
||||||
for (j = 0; j < map->num_members; j++) {
|
for (j = 0; j < map->num_members; j++) {
|
||||||
|
@ -379,7 +403,7 @@ static void print_imsm_dev(struct imsm_dev *dev, int index)
|
||||||
|
|
||||||
static void print_imsm_disk(struct imsm_super *mpb, int index)
|
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];
|
char str[MAX_RAID_SERIAL_LEN];
|
||||||
__u32 s;
|
__u32 s;
|
||||||
__u64 sz;
|
__u64 sz;
|
||||||
|
@ -405,7 +429,7 @@ static void print_imsm_disk(struct imsm_super *mpb, int index)
|
||||||
static void examine_super_imsm(struct supertype *st, char *homehost)
|
static void examine_super_imsm(struct supertype *st, char *homehost)
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
struct imsm_super *mpb = super->anchor;
|
||||||
char str[MAX_SIGNATURE_LENGTH];
|
char str[MAX_SIGNATURE_LENGTH];
|
||||||
int i;
|
int i;
|
||||||
__u32 sum;
|
__u32 sum;
|
||||||
|
@ -418,13 +442,13 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
|
||||||
printf(" Generation : %08x\n", __le32_to_cpu(mpb->generation_num));
|
printf(" Generation : %08x\n", __le32_to_cpu(mpb->generation_num));
|
||||||
sum = __le32_to_cpu(mpb->check_sum);
|
sum = __le32_to_cpu(mpb->check_sum);
|
||||||
printf(" Checksum : %08x %s\n", 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(" MPB Sectors : %d\n", mpb_sectors(mpb));
|
||||||
printf(" Disks : %d\n", mpb->num_disks);
|
printf(" Disks : %d\n", mpb->num_disks);
|
||||||
printf(" RAID Devices : %d\n", mpb->num_raid_devs);
|
printf(" RAID Devices : %d\n", mpb->num_raid_devs);
|
||||||
print_imsm_disk(mpb, super->disks->index);
|
print_imsm_disk(mpb, super->disks->index);
|
||||||
for (i = 0; i < mpb->num_raid_devs; i++)
|
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++) {
|
for (i = 0; i < mpb->num_disks; i++) {
|
||||||
if (i == super->disks->index)
|
if (i == super->disks->index)
|
||||||
continue;
|
continue;
|
||||||
|
@ -435,10 +459,9 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
|
||||||
static void brief_examine_super_imsm(struct supertype *st)
|
static void brief_examine_super_imsm(struct supertype *st)
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
|
|
||||||
printf("ARRAY /dev/imsm family=%08x metadata=external:imsm\n",
|
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 detail_super_imsm(struct supertype *st, char *homehost)
|
||||||
|
@ -510,8 +533,7 @@ static int imsm_level_to_layout(int level)
|
||||||
static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
|
static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
|
||||||
struct imsm_dev *dev = get_imsm_dev(mpb, super->current_vol);
|
|
||||||
struct imsm_map *map = &dev->vol.map[0];
|
struct imsm_map *map = &dev->vol.map[0];
|
||||||
|
|
||||||
info->container_member = super->current_vol;
|
info->container_member = super->current_vol;
|
||||||
|
@ -538,7 +560,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
|
||||||
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
|
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
__u32 s;
|
__u32 s;
|
||||||
|
|
||||||
|
@ -546,7 +567,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
|
||||||
getinfo_super_imsm_volume(st, info);
|
getinfo_super_imsm_volume(st, info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info->array.raid_disks = mpb->num_disks;
|
info->array.raid_disks = super->anchor->num_disks;
|
||||||
info->array.level = LEVEL_CONTAINER;
|
info->array.level = LEVEL_CONTAINER;
|
||||||
info->array.layout = 0;
|
info->array.layout = 0;
|
||||||
info->array.md_minor = -1;
|
info->array.md_minor = -1;
|
||||||
|
@ -563,7 +584,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
|
||||||
info->disk.state = 0;
|
info->disk.state = 0;
|
||||||
|
|
||||||
if (super->disks) {
|
if (super->disks) {
|
||||||
disk = get_imsm_disk(mpb, super->disks->index);
|
disk = get_imsm_disk(super, super->disks->index);
|
||||||
if (!disk) {
|
if (!disk) {
|
||||||
info->disk.number = -1;
|
info->disk.number = -1;
|
||||||
info->disk.raid_disk = -1;
|
info->disk.raid_disk = -1;
|
||||||
|
@ -667,13 +688,13 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
|
||||||
return 0;
|
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;
|
return 3;
|
||||||
if (first->mpb->family_num != sec->mpb->family_num)
|
if (first->anchor->family_num != sec->anchor->family_num)
|
||||||
return 3;
|
return 3;
|
||||||
if (first->mpb->mpb_size != sec->mpb->mpb_size)
|
if (first->anchor->mpb_size != sec->anchor->mpb_size)
|
||||||
return 3;
|
return 3;
|
||||||
if (first->mpb->check_sum != sec->mpb->check_sum)
|
if (first->anchor->check_sum != sec->anchor->check_sum)
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -750,7 +771,6 @@ static int imsm_read_serial(int fd, char *devname,
|
||||||
static int
|
static int
|
||||||
load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
|
load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
|
||||||
{
|
{
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
struct dl *dl;
|
struct dl *dl;
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
|
@ -758,14 +778,20 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dl = malloc(sizeof(*dl));
|
dl = malloc(sizeof(*dl));
|
||||||
if (!dl) {
|
disk = malloc(sizeof(*disk));
|
||||||
|
if (!dl || !disk) {
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": failed to allocate disk buffer for %s\n",
|
Name ": failed to allocate disk buffer for %s\n",
|
||||||
devname);
|
devname);
|
||||||
|
if (disk)
|
||||||
|
free(disk);
|
||||||
|
if (dl)
|
||||||
|
free(dl);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
memset(dl, 0, sizeof(*dl));
|
memset(dl, 0, sizeof(*dl));
|
||||||
|
memset(disk, 0, sizeof(*disk));
|
||||||
|
|
||||||
fstat(fd, &stb);
|
fstat(fd, &stb);
|
||||||
dl->major = major(stb.st_rdev);
|
dl->major = major(stb.st_rdev);
|
||||||
|
@ -781,22 +807,65 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
/* look up this disk's index */
|
/* look up this disk's index */
|
||||||
for (i = 0; i < mpb->num_disks; i++) {
|
for (i = 0; i < super->anchor->num_disks; i++) {
|
||||||
disk = get_imsm_disk(mpb, i);
|
struct imsm_disk *disk_iter;
|
||||||
|
|
||||||
if (memcmp(disk->serial, dl->serial, MAX_RAID_SERIAL_LEN) == 0)
|
disk_iter = __get_imsm_disk(super->anchor, i);
|
||||||
|
|
||||||
|
if (memcmp(disk_iter->serial, dl->serial,
|
||||||
|
MAX_RAID_SERIAL_LEN) == 0) {
|
||||||
|
*disk = *disk_iter;
|
||||||
|
super->disk_tbl[i] = disk;
|
||||||
|
dl->index = i;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > mpb->num_disks - 1) {
|
if (i == super->anchor->num_disks) {
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": failed to match serial \'%s\' for %s\n",
|
Name ": failed to match serial \'%s\' for %s\n",
|
||||||
dl->serial, devname);
|
dl->serial, devname);
|
||||||
|
free(disk);
|
||||||
return 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -807,11 +876,11 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
|
||||||
static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
|
static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
|
||||||
{
|
{
|
||||||
unsigned long long dsize;
|
unsigned long long dsize;
|
||||||
size_t len, mpb_size;
|
|
||||||
unsigned long long sectors;
|
unsigned long long sectors;
|
||||||
struct stat;
|
struct stat;
|
||||||
struct imsm_super *anchor;
|
struct imsm_super *anchor;
|
||||||
__u32 check_sum;
|
__u32 check_sum;
|
||||||
|
int rc;
|
||||||
|
|
||||||
get_dev_size(fd, NULL, &dsize);
|
get_dev_size(fd, NULL, &dsize);
|
||||||
|
|
||||||
|
@ -823,15 +892,14 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = 512;
|
if (posix_memalign((void**)&anchor, 512, 512) != 0) {
|
||||||
if (posix_memalign((void**)&anchor, 512, len) != 0) {
|
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": Failed to allocate imsm anchor buffer"
|
Name ": Failed to allocate imsm anchor buffer"
|
||||||
" on %s\n", devname);
|
" on %s\n", devname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (read(fd, anchor, len) != len) {
|
if (read(fd, anchor, 512) != 512) {
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": Cannot read anchor block on %s: %s\n",
|
Name ": Cannot read anchor block on %s: %s\n",
|
||||||
|
@ -848,22 +916,26 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpb_size = __le32_to_cpu(anchor->mpb_size);
|
super->len = __le32_to_cpu(anchor->mpb_size);
|
||||||
mpb_size = ROUND_UP(mpb_size, 512);
|
super->len = ROUND_UP(anchor->mpb_size, 512);
|
||||||
if (posix_memalign(&super->buf, 512, mpb_size) != 0) {
|
if (posix_memalign(&super->buf, 512, super->len) != 0) {
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": unable to allocate %zu byte mpb buffer\n",
|
Name ": unable to allocate %zu byte mpb buffer\n",
|
||||||
mpb_size);
|
super->len);
|
||||||
free(anchor);
|
free(anchor);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
memcpy(super->buf, anchor, len);
|
memcpy(super->buf, anchor, 512);
|
||||||
|
|
||||||
sectors = mpb_sectors(anchor) - 1;
|
sectors = mpb_sectors(anchor) - 1;
|
||||||
free(anchor);
|
free(anchor);
|
||||||
if (!sectors)
|
if (!sectors) {
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* read the extended mpb */
|
/* read the extended mpb */
|
||||||
if (lseek64(fd, dsize - (512 * (2 + sectors)), SEEK_SET) < 0) {
|
if (lseek64(fd, dsize - (512 * (2 + sectors)), SEEK_SET) < 0) {
|
||||||
|
@ -874,8 +946,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = mpb_size - 512;
|
if (read(fd, super->buf + 512, super->len - 512) != super->len - 512) {
|
||||||
if (read(fd, super->buf + 512, len) != len) {
|
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": Cannot read extended mpb on %s: %s\n",
|
Name ": Cannot read extended mpb on %s: %s\n",
|
||||||
|
@ -883,21 +954,26 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_sum = gen_imsm_checksum(super->mpb);
|
check_sum = __gen_imsm_checksum(super->anchor);
|
||||||
if (check_sum != __le32_to_cpu(super->mpb->check_sum)) {
|
if (check_sum != __le32_to_cpu(super->anchor->check_sum)) {
|
||||||
if (devname)
|
if (devname)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": IMSM checksum %x != %x on %s\n",
|
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);
|
devname);
|
||||||
return 2;
|
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)
|
static void free_imsm_disks(struct intel_super *super)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
while (super->disks) {
|
while (super->disks) {
|
||||||
struct dl *d = super->disks;
|
struct dl *d = super->disks;
|
||||||
|
|
||||||
|
@ -908,13 +984,23 @@ static void free_imsm_disks(struct intel_super *super)
|
||||||
free(d->devname);
|
free(d->devname);
|
||||||
free(d);
|
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)
|
static void free_imsm(struct intel_super *super)
|
||||||
{
|
{
|
||||||
if (super->mpb)
|
int i;
|
||||||
free(super->mpb);
|
|
||||||
|
if (super->buf)
|
||||||
|
free(super->buf);
|
||||||
free_imsm_disks(super);
|
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);
|
free(super);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,7 +1068,7 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
|
||||||
if (!keep_fd)
|
if (!keep_fd)
|
||||||
close(dfd);
|
close(dfd);
|
||||||
if (rv == 0) {
|
if (rv == 0) {
|
||||||
gen = __le32_to_cpu(super->mpb->generation_num);
|
gen = __le32_to_cpu(super->anchor->generation_num);
|
||||||
if (!best || gen > bestgen) {
|
if (!best || gen > bestgen) {
|
||||||
bestgen = gen;
|
bestgen = gen;
|
||||||
best = sd;
|
best = sd;
|
||||||
|
@ -1029,7 +1115,7 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st->subarray[0]) {
|
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);
|
super->current_vol = atoi(st->subarray);
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1119,7 +1205,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
* so st->sb is already set.
|
* so st->sb is already set.
|
||||||
*/
|
*/
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
struct imsm_super *mpb = super->anchor;
|
||||||
struct imsm_dev *dev;
|
struct imsm_dev *dev;
|
||||||
struct imsm_vol *vol;
|
struct imsm_vol *vol;
|
||||||
struct imsm_map *map;
|
struct imsm_map *map;
|
||||||
|
@ -1149,14 +1235,17 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
memcpy(mpb_new, mpb, size_old);
|
memcpy(mpb_new, mpb, size_old);
|
||||||
free(mpb);
|
free(mpb);
|
||||||
mpb = mpb_new;
|
mpb = mpb_new;
|
||||||
super->mpb = mpb_new;
|
super->anchor = mpb_new;
|
||||||
mpb->mpb_size = __cpu_to_le32(size_new);
|
mpb->mpb_size = __cpu_to_le32(size_new);
|
||||||
memset(mpb_new + size_old, 0, size_round - size_old);
|
memset(mpb_new + size_old, 0, size_round - size_old);
|
||||||
}
|
}
|
||||||
super->current_vol = idx;
|
super->current_vol = idx;
|
||||||
sprintf(st->subarray, "%d", idx);
|
sprintf(st->subarray, "%d", idx);
|
||||||
mpb->num_raid_devs++;
|
dev = malloc(sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
|
||||||
dev = get_imsm_dev(mpb, idx);
|
if (!dev) {
|
||||||
|
fprintf(stderr, Name": could not allocate raid device\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
|
strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
|
||||||
array_blocks = calc_array_size(info->level, info->raid_disks,
|
array_blocks = calc_array_size(info->level, info->raid_disks,
|
||||||
info->layout, info->chunk_size,
|
info->layout, info->chunk_size,
|
||||||
|
@ -1170,7 +1259,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
vol->migr_type = 0;
|
vol->migr_type = 0;
|
||||||
vol->dirty = 0;
|
vol->dirty = 0;
|
||||||
for (i = 0; i < idx; i++) {
|
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];
|
struct imsm_map *pmap = &prev->vol.map[0];
|
||||||
|
|
||||||
offset += __le32_to_cpu(pmap->blocks_per_member);
|
offset += __le32_to_cpu(pmap->blocks_per_member);
|
||||||
|
@ -1199,6 +1288,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
/* initialized in add_to_super */
|
/* initialized in add_to_super */
|
||||||
map->disk_ord_tbl[i] = __cpu_to_le32(0);
|
map->disk_ord_tbl[i] = __cpu_to_le32(0);
|
||||||
}
|
}
|
||||||
|
mpb->num_raid_devs++;
|
||||||
|
super->dev_tbl[super->current_vol] = dev;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1251,14 +1342,13 @@ static void add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
int fd, char *devname)
|
int fd, char *devname)
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
struct dl *dl;
|
struct dl *dl;
|
||||||
struct imsm_dev *dev;
|
struct imsm_dev *dev;
|
||||||
struct imsm_map *map;
|
struct imsm_map *map;
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
__u32 status;
|
__u32 status;
|
||||||
|
|
||||||
dev = get_imsm_dev(mpb, super->current_vol);
|
dev = get_imsm_dev(super, super->current_vol);
|
||||||
map = &dev->vol.map[0];
|
map = &dev->vol.map[0];
|
||||||
|
|
||||||
for (dl = super->disks; dl ; dl = dl->next)
|
for (dl = super->disks; dl ; dl = dl->next)
|
||||||
|
@ -1270,7 +1360,7 @@ static void add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
|
|
||||||
map->disk_ord_tbl[dk->number] = __cpu_to_le32(dl->index);
|
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;
|
status = CONFIGURED_DISK | USABLE_DISK;
|
||||||
disk->status = __cpu_to_le32(status);
|
disk->status = __cpu_to_le32(status);
|
||||||
}
|
}
|
||||||
|
@ -1279,7 +1369,7 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
int fd, char *devname)
|
int fd, char *devname)
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
struct imsm_super *mpb = super->anchor;
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
struct dl *dd;
|
struct dl *dd;
|
||||||
unsigned long long size;
|
unsigned long long size;
|
||||||
|
@ -1294,12 +1384,18 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
|
|
||||||
fstat(fd, &stb);
|
fstat(fd, &stb);
|
||||||
dd = malloc(sizeof(*dd));
|
dd = malloc(sizeof(*dd));
|
||||||
if (!dd) {
|
disk = malloc(sizeof(*disk));
|
||||||
|
if (!dd || !disk) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": malloc failed %s:%d.\n", __func__, __LINE__);
|
Name ": malloc failed %s:%d.\n", __func__, __LINE__);
|
||||||
|
if (!dd)
|
||||||
|
free(dd);
|
||||||
|
if (!disk)
|
||||||
|
free(disk);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
memset(dd, 0, sizeof(*dd));
|
memset(dd, 0, sizeof(*dd));
|
||||||
|
memset(disk, 0, sizeof(*disk));
|
||||||
dd->major = major(stb.st_rdev);
|
dd->major = major(stb.st_rdev);
|
||||||
dd->minor = minor(stb.st_rdev);
|
dd->minor = minor(stb.st_rdev);
|
||||||
dd->index = dk->number;
|
dd->index = dk->number;
|
||||||
|
@ -1310,13 +1406,14 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
if (rv) {
|
if (rv) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
Name ": failed to retrieve scsi serial, aborting\n");
|
Name ": failed to retrieve scsi serial, aborting\n");
|
||||||
|
free(dd);
|
||||||
|
free(disk);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpb->num_disks <= dk->number)
|
if (mpb->num_disks <= dk->number)
|
||||||
mpb->num_disks = dk->number + 1;
|
mpb->num_disks = dk->number + 1;
|
||||||
|
|
||||||
disk = get_imsm_disk(mpb, dk->number);
|
|
||||||
get_dev_size(fd, NULL, &size);
|
get_dev_size(fd, NULL, &size);
|
||||||
size /= 512;
|
size /= 512;
|
||||||
status = USABLE_DISK | SPARE_DISK;
|
status = USABLE_DISK | SPARE_DISK;
|
||||||
|
@ -1327,10 +1424,14 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
disk->scsi_id = __cpu_to_le32(id);
|
disk->scsi_id = __cpu_to_le32(id);
|
||||||
else
|
else
|
||||||
disk->scsi_id = __cpu_to_le32(0);
|
disk->scsi_id = __cpu_to_le32(0);
|
||||||
|
super->disk_tbl[dd->index] = disk;
|
||||||
|
|
||||||
/* update the family number if we are creating a container */
|
/* update the family number if we are creating a container */
|
||||||
if (super->creating_imsm)
|
if (super->creating_imsm) {
|
||||||
mpb->family_num = __cpu_to_le32(gen_imsm_checksum(mpb));
|
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;
|
super->disks = dd;
|
||||||
}
|
}
|
||||||
|
@ -1339,18 +1440,27 @@ static int store_imsm_mpb(int fd, struct intel_super *super);
|
||||||
|
|
||||||
static int write_super_imsm(struct intel_super *super, int doclose)
|
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;
|
struct dl *d;
|
||||||
__u32 generation;
|
__u32 generation;
|
||||||
__u32 sum;
|
__u32 sum;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* 'generation' is incremented everytime the metadata is written */
|
/* 'generation' is incremented everytime the metadata is written */
|
||||||
generation = __le32_to_cpu(mpb->generation_num);
|
generation = __le32_to_cpu(mpb->generation_num);
|
||||||
generation++;
|
generation++;
|
||||||
mpb->generation_num = __cpu_to_le32(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 */
|
/* recalculate checksum */
|
||||||
sum = gen_imsm_checksum(mpb);
|
sum = __gen_imsm_checksum(mpb);
|
||||||
mpb->check_sum = __cpu_to_le32(sum);
|
mpb->check_sum = __cpu_to_le32(sum);
|
||||||
|
|
||||||
for (d = super->disks; d ; d = d->next) {
|
for (d = super->disks; d ; d = d->next) {
|
||||||
|
@ -1375,21 +1485,18 @@ static int write_init_super_imsm(struct supertype *st)
|
||||||
size_t len;
|
size_t len;
|
||||||
struct imsm_update_create_array *u;
|
struct imsm_update_create_array *u;
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
struct imsm_dev *dev;
|
struct imsm_dev *dev;
|
||||||
struct imsm_map *map;
|
|
||||||
struct dl *d;
|
struct dl *d;
|
||||||
|
|
||||||
if (super->current_vol < 0 ||
|
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",
|
fprintf(stderr, "%s: could not determine sub-array\n",
|
||||||
__func__);
|
__func__);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
map = &dev->vol.map[0];
|
len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev);
|
||||||
len = sizeof(*u) + sizeof(__u32) * (map->num_members - 1);
|
|
||||||
u = malloc(len);
|
u = malloc(len);
|
||||||
if (!u) {
|
if (!u) {
|
||||||
fprintf(stderr, "%s: failed to allocate update buffer\n",
|
fprintf(stderr, "%s: failed to allocate update buffer\n",
|
||||||
|
@ -1399,9 +1506,7 @@ static int write_init_super_imsm(struct supertype *st)
|
||||||
|
|
||||||
u->type = update_create_array;
|
u->type = update_create_array;
|
||||||
u->dev_idx = super->current_vol;
|
u->dev_idx = super->current_vol;
|
||||||
memcpy(&u->dev, dev, sizeof(*dev));
|
imsm_copy_dev(&u->dev, dev);
|
||||||
memcpy(u->dev.vol.map[0].disk_ord_tbl, map->disk_ord_tbl,
|
|
||||||
sizeof(__u32) * map->num_members);
|
|
||||||
append_metadata_update(st, u, len);
|
append_metadata_update(st, u, len);
|
||||||
|
|
||||||
for (d = super->disks; d ; d = d->next) {
|
for (d = super->disks; d ; d = d->next) {
|
||||||
|
@ -1674,12 +1779,12 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
|
||||||
* and create appropriate device mdinfo.
|
* and create appropriate device mdinfo.
|
||||||
*/
|
*/
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
struct imsm_super *mpb = super->anchor;
|
||||||
struct mdinfo *rest = NULL;
|
struct mdinfo *rest = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < mpb->num_raid_devs; 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_vol *vol = &dev->vol;
|
||||||
struct imsm_map *map = vol->map;
|
struct imsm_map *map = vol->map;
|
||||||
struct mdinfo *this;
|
struct mdinfo *this;
|
||||||
|
@ -1737,7 +1842,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
|
||||||
info_d->next = this->devs;
|
info_d->next = this->devs;
|
||||||
this->devs = info_d;
|
this->devs = info_d;
|
||||||
|
|
||||||
disk = get_imsm_disk(mpb, idx);
|
disk = get_imsm_disk(super, idx);
|
||||||
s = __le32_to_cpu(disk->status);
|
s = __le32_to_cpu(disk->status);
|
||||||
|
|
||||||
info_d->disk.number = d->index;
|
info_d->disk.number = d->index;
|
||||||
|
@ -1766,9 +1871,9 @@ static int imsm_open_new(struct supertype *c, struct active_array *a,
|
||||||
char *inst)
|
char *inst)
|
||||||
{
|
{
|
||||||
struct intel_super *super = c->sb;
|
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",
|
fprintf(stderr, "%s: subarry index %d, out of range\n",
|
||||||
__func__, atoi(inst));
|
__func__, atoi(inst));
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1779,9 +1884,9 @@ static int imsm_open_new(struct supertype *c, struct active_array *a,
|
||||||
return 0;
|
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;
|
struct imsm_map *map = dev->vol.map;
|
||||||
|
|
||||||
if (!failed)
|
if (!failed)
|
||||||
|
@ -1811,7 +1916,7 @@ static __u8 imsm_check_degraded(struct imsm_super *mpb, int n, int failed)
|
||||||
|
|
||||||
for (i = 0; i < map->num_members; i++) {
|
for (i = 0; i < map->num_members; i++) {
|
||||||
int idx = get_imsm_disk_idx(map, 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)
|
if (__le32_to_cpu(disk->status) & FAILED_DISK)
|
||||||
failed++;
|
failed++;
|
||||||
|
@ -1839,7 +1944,7 @@ static __u8 imsm_check_degraded(struct imsm_super *mpb, int n, int failed)
|
||||||
return map->map_state;
|
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 i;
|
||||||
int failed = 0;
|
int failed = 0;
|
||||||
|
@ -1848,7 +1953,7 @@ static int imsm_count_failed(struct imsm_super *mpb, struct imsm_map *map)
|
||||||
for (i = 0; i < map->num_members; i++) {
|
for (i = 0; i < map->num_members; i++) {
|
||||||
int idx = get_imsm_disk_idx(map, 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)
|
if (__le32_to_cpu(disk->status) & FAILED_DISK)
|
||||||
failed++;
|
failed++;
|
||||||
}
|
}
|
||||||
|
@ -1860,15 +1965,15 @@ static void imsm_set_array_state(struct active_array *a, int consistent)
|
||||||
{
|
{
|
||||||
int inst = a->info.container_member;
|
int inst = a->info.container_member;
|
||||||
struct intel_super *super = a->container->sb;
|
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];
|
struct imsm_map *map = &dev->vol.map[0];
|
||||||
int dirty = !consistent;
|
int dirty = !consistent;
|
||||||
int failed;
|
int failed;
|
||||||
__u8 map_state;
|
__u8 map_state;
|
||||||
|
|
||||||
if (a->resync_start == ~0ULL) {
|
if (a->resync_start == ~0ULL) {
|
||||||
failed = imsm_count_failed(super->mpb, map);
|
failed = imsm_count_failed(super, map);
|
||||||
map_state = imsm_check_degraded(super->mpb, inst, failed);
|
map_state = imsm_check_degraded(super, inst, failed);
|
||||||
if (!failed)
|
if (!failed)
|
||||||
map_state = IMSM_T_STATE_NORMAL;
|
map_state = IMSM_T_STATE_NORMAL;
|
||||||
if (map->map_state != map_state) {
|
if (map->map_state != map_state) {
|
||||||
|
@ -1892,7 +1997,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
|
||||||
{
|
{
|
||||||
int inst = a->info.container_member;
|
int inst = a->info.container_member;
|
||||||
struct intel_super *super = a->container->sb;
|
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_map *map = dev->vol.map;
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
__u32 status;
|
__u32 status;
|
||||||
|
@ -1908,7 +2013,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
|
||||||
|
|
||||||
dprintf("imsm: set_disk %d:%x\n", n, state);
|
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 */
|
/* check for new failures */
|
||||||
status = __le32_to_cpu(disk->status);
|
status = __le32_to_cpu(disk->status);
|
||||||
|
@ -1923,11 +2028,11 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
|
||||||
* degraded / failed status
|
* degraded / failed status
|
||||||
*/
|
*/
|
||||||
if (new_failure && map->map_state != IMSM_T_STATE_FAILED)
|
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 */
|
/* determine map_state based on failed or in_sync count */
|
||||||
if (failed)
|
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) {
|
else if (map->map_state == IMSM_T_STATE_DEGRADED) {
|
||||||
struct mdinfo *d;
|
struct mdinfo *d;
|
||||||
int working = 0;
|
int working = 0;
|
||||||
|
@ -1945,7 +2050,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
|
||||||
|
|
||||||
static int store_imsm_mpb(int fd, struct intel_super *super)
|
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);
|
__u32 mpb_size = __le32_to_cpu(mpb->mpb_size);
|
||||||
unsigned long long dsize;
|
unsigned long long dsize;
|
||||||
unsigned long long sectors;
|
unsigned long long sectors;
|
||||||
|
@ -2001,9 +2106,8 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct intel_super *super = a->container->sb;
|
struct intel_super *super = a->container->sb;
|
||||||
struct imsm_super *mpb = super->mpb;
|
|
||||||
int inst = a->info.container_member;
|
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;
|
struct imsm_map *map = dev->vol.map;
|
||||||
int failed = a->info.array.raid_disks;
|
int failed = a->info.array.raid_disks;
|
||||||
struct mdinfo *rv = NULL;
|
struct mdinfo *rv = NULL;
|
||||||
|
@ -2026,7 +2130,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
|
||||||
|
|
||||||
dprintf("imsm: activate spare: inst=%d failed=%d (%d) level=%d\n",
|
dprintf("imsm: activate spare: inst=%d failed=%d (%d) level=%d\n",
|
||||||
inst, failed, a->info.array.raid_disks, a->info.array.level);
|
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;
|
return NULL;
|
||||||
|
|
||||||
/* For each slot, if it is not working, find a spare */
|
/* For each slot, if it is not working, find a spare */
|
||||||
|
@ -2061,7 +2165,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* is this unused device marked as a spare? */
|
/* 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))
|
if (!(__le32_to_cpu(disk->status) & SPARE_DISK))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -2189,13 +2293,13 @@ static void imsm_process_update(struct supertype *st,
|
||||||
* flag
|
* flag
|
||||||
*/
|
*/
|
||||||
struct intel_super *super = st->sb;
|
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;
|
enum imsm_update_type type = *(enum imsm_update_type *) update->buf;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case update_activate_spare: {
|
case update_activate_spare: {
|
||||||
struct imsm_update_activate_spare *u = (void *) update->buf;
|
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 imsm_map *map = &dev->vol.map[0];
|
||||||
struct active_array *a;
|
struct active_array *a;
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
|
@ -2221,7 +2325,7 @@ static void imsm_process_update(struct supertype *st,
|
||||||
|
|
||||||
victim = get_imsm_disk_idx(map, u->slot);
|
victim = get_imsm_disk_idx(map, u->slot);
|
||||||
map->disk_ord_tbl[u->slot] = __cpu_to_le32(u->disk_idx);
|
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 = __le32_to_cpu(disk->status);
|
||||||
status |= CONFIGURED_DISK;
|
status |= CONFIGURED_DISK;
|
||||||
disk->status = __cpu_to_le32(status);
|
disk->status = __cpu_to_le32(status);
|
||||||
|
@ -2232,7 +2336,7 @@ static void imsm_process_update(struct supertype *st,
|
||||||
for (a = st->arrays; a; a = a->next) {
|
for (a = st->arrays; a; a = a->next) {
|
||||||
int inst = a->info.container_member;
|
int inst = a->info.container_member;
|
||||||
|
|
||||||
dev = get_imsm_dev(mpb, inst);
|
dev = get_imsm_dev(super, inst);
|
||||||
map = &dev->vol.map[0];
|
map = &dev->vol.map[0];
|
||||||
if (map->raid_level > 0)
|
if (map->raid_level > 0)
|
||||||
members |= 1 << inst;
|
members |= 1 << inst;
|
||||||
|
@ -2254,7 +2358,7 @@ static void imsm_process_update(struct supertype *st,
|
||||||
/* count arrays using the victim in the metadata */
|
/* count arrays using the victim in the metadata */
|
||||||
found = 0;
|
found = 0;
|
||||||
for (a = st->arrays; a ; a = a->next) {
|
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];
|
map = &dev->vol.map[0];
|
||||||
for (i = 0; i < map->num_members; i++)
|
for (i = 0; i < map->num_members; i++)
|
||||||
if (victim == get_imsm_disk_idx(map, i))
|
if (victim == get_imsm_disk_idx(map, i))
|
||||||
|
@ -2264,7 +2368,7 @@ static void imsm_process_update(struct supertype *st,
|
||||||
/* clear some flags if the victim is no longer being
|
/* clear some flags if the victim is no longer being
|
||||||
* utilized anywhere
|
* utilized anywhere
|
||||||
*/
|
*/
|
||||||
disk = get_imsm_disk(mpb, victim);
|
disk = get_imsm_disk(super, victim);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
status = __le32_to_cpu(disk->status);
|
status = __le32_to_cpu(disk->status);
|
||||||
status &= ~(CONFIGURED_DISK | USABLE_DISK);
|
status &= ~(CONFIGURED_DISK | USABLE_DISK);
|
||||||
|
@ -2313,7 +2417,7 @@ static void imsm_process_update(struct supertype *st,
|
||||||
* overalpping disks
|
* overalpping disks
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
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];
|
map = &dev->vol.map[0];
|
||||||
start = __le32_to_cpu(map->pba_of_lba0);
|
start = __le32_to_cpu(map->pba_of_lba0);
|
||||||
end = start + __le32_to_cpu(map->blocks_per_member);
|
end = start + __le32_to_cpu(map->blocks_per_member);
|
||||||
|
@ -2331,13 +2435,18 @@ static void imsm_process_update(struct supertype *st,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check that prepare update was successful */
|
||||||
|
if (!update->space) {
|
||||||
|
dprintf("%s: prepare update failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
super->updates_pending++;
|
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++;
|
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
|
/* fix up flags, if arrays overlap then the drives can not be
|
||||||
* spares
|
* spares
|
||||||
|
@ -2346,7 +2455,7 @@ static void imsm_process_update(struct supertype *st,
|
||||||
struct imsm_disk *disk;
|
struct imsm_disk *disk;
|
||||||
__u32 status;
|
__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 = __le32_to_cpu(disk->status);
|
||||||
status |= CONFIGURED_DISK;
|
status |= CONFIGURED_DISK;
|
||||||
if (overlap)
|
if (overlap)
|
||||||
|
@ -2361,9 +2470,11 @@ static void imsm_process_update(struct supertype *st,
|
||||||
static void imsm_prepare_update(struct supertype *st,
|
static void imsm_prepare_update(struct supertype *st,
|
||||||
struct metadata_update *update)
|
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.
|
* Allocate space to hold new disk entries, raid-device entries or a
|
||||||
* This may not be sufficient iff reshaping.
|
* 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.
|
* FIX ME handle the reshape case.
|
||||||
*
|
*
|
||||||
|
@ -2372,6 +2483,19 @@ static void imsm_prepare_update(struct supertype *st,
|
||||||
* will start using the new pointer and the manager can continue to use
|
* will start using the new pointer and the manager can continue to use
|
||||||
* the old value until check_update_queue() runs.
|
* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue