imsm: FIX: core dump during imsm metadata writing

Wrong number of disks during metadata update causes core dump.  New
disks number based on internal mdmon information has to used for
calculation (not previously read from metadata).

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Adam Kwolek 2010-11-29 12:53:16 +11:00 committed by NeilBrown
parent 28bce06f17
commit 36988a3dda
1 changed files with 18 additions and 9 deletions

View File

@ -3484,8 +3484,9 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
return 0;
}
static int write_super_imsm(struct intel_super *super, int doclose)
static int write_super_imsm(struct supertype *st, int doclose)
{
struct intel_super *super = st->sb;
struct imsm_super *mpb = super->anchor;
struct dl *d;
__u32 generation;
@ -3493,6 +3494,7 @@ static int write_super_imsm(struct intel_super *super, int doclose)
int spares = 0;
int i;
__u32 mpb_size = sizeof(struct imsm_super) - sizeof(struct imsm_disk);
int num_disks = 0;
/* 'generation' is incremented everytime the metadata is written */
generation = __le32_to_cpu(mpb->generation_num);
@ -3505,21 +3507,28 @@ static int write_super_imsm(struct intel_super *super, int doclose)
if (mpb->orig_family_num == 0)
mpb->orig_family_num = mpb->family_num;
mpb_size += sizeof(struct imsm_disk) * mpb->num_disks;
for (d = super->disks; d; d = d->next) {
if (d->index == -1)
spares++;
else
else {
mpb->disk[d->index] = d->disk;
num_disks++;
}
}
for (d = super->missing; d; d = d->next)
for (d = super->missing; d; d = d->next) {
mpb->disk[d->index] = d->disk;
num_disks++;
}
mpb->num_disks = num_disks;
mpb_size += sizeof(struct imsm_disk) * mpb->num_disks;
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = __get_imsm_dev(mpb, i);
imsm_copy_dev(dev, get_imsm_dev(super, i));
mpb_size += sizeof_imsm_dev(dev, 0);
struct imsm_dev *dev2 = get_imsm_dev(super, i);
if (dev && dev2) {
imsm_copy_dev(dev, dev2);
mpb_size += sizeof_imsm_dev(dev, 0);
}
}
mpb_size += __le32_to_cpu(mpb->bbm_log_size);
mpb->mpb_size = __cpu_to_le32(mpb_size);
@ -3639,7 +3648,7 @@ static int write_init_super_imsm(struct supertype *st)
struct dl *d;
for (d = super->disks; d; d = d->next)
Kill(d->devname, NULL, 0, 1, 1);
return write_super_imsm(st->sb, 1);
return write_super_imsm(st, 1);
}
}
#endif
@ -4925,7 +4934,7 @@ static void imsm_sync_metadata(struct supertype *container)
if (!super->updates_pending)
return;
write_super_imsm(super, 0);
write_super_imsm(container, 0);
super->updates_pending = 0;
}