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:
parent
28bce06f17
commit
36988a3dda
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue