[PATCH 07/31] imsm: FIX: core dump during imsm metadata writing
am 09.11.2010 18:00:55 von adam.kwolekWrong 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
---
mdadm/mdadm/super-intel.c | 27 ++++++++++++++++++---------
1 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/mdadm/mdadm/super-intel.c b/mdadm/mdadm/super-intel.c index ffb4c33..100a19c 100644
--- a/mdadm/mdadm/super-intel.c
+++ b/mdadm/mdadm/super-intel.c
@@ -3510,8 +3510,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;
@@ -3519,6 +3520,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);
@@ -3531,21 +3533,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); @@ -3665,7 +3674,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
@@ -4938,7 +4947,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;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html