From: mwilck@arcor.de Date: Fri, 1 Mar 2013 22:28:23 +0000 (+0100) Subject: DDF: use existing locations for primary and secondary DDF structure X-Git-Tag: mdadm-3.3-rc1~115 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=097bcf005780ddf0bb9169b8b7c4330a8c603799;p=thirdparty%2Fmdadm.git DDF: use existing locations for primary and secondary DDF structure Some RAID BIOSes apparently use hard-coded LBA offsets (presumably from the end of the disk) for the primary and secondary DDF structure, ignoring the values given in the DDF anchor. This is broken BIOS behavior, but it will cause any changes made by MD (e.g. setting the init_state flag after a full initialization) to be "forgotten" after the next reboot. This patch fixes this by using the exiting LBA locations if available. Verified that this fixes MD+LSI Mega Software RAID BIOS. Signed-off-by: Martin Wilck Signed-off-by: NeilBrown --- diff --git a/super-ddf.c b/super-ddf.c index 38af9132..dfbd5510 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -421,6 +421,9 @@ struct ddf_super { char *devname; int fd; unsigned long long size; /* sectors */ + unsigned long long primary_lba; /* sectors */ + unsigned long long secondary_lba; /* sectors */ + unsigned long long workspace_lba; /* sectors */ int pdnum; /* index in ->phys */ struct spare_assign *spare; void *mdupdate; /* hold metadata update */ @@ -668,6 +671,13 @@ static int load_ddf_local(int fd, struct ddf_super *super, dl->size = 0; if (get_dev_size(fd, devname, &dsize)) dl->size = dsize >> 9; + /* If the disks have different sizes, the LBAs will differ + * between phys disks. + * At this point here, the values in super->active must be valid + * for this phys disk. */ + dl->primary_lba = super->active->primary_lba; + dl->secondary_lba = super->active->secondary_lba; + dl->workspace_lba = super->active->workspace_lba; dl->spare = NULL; for (i = 0 ; i < super->max_part ; i++) dl->vlist[i] = NULL; @@ -2422,9 +2432,21 @@ static int __write_init_super_ddf(struct supertype *st) */ get_dev_size(fd, NULL, &size); size /= 512; - ddf->anchor.workspace_lba = __cpu_to_be64(size - 32*1024*2); - ddf->anchor.primary_lba = __cpu_to_be64(size - 16*1024*2); - ddf->anchor.secondary_lba = __cpu_to_be64(size - 31*1024*2); + if (d->workspace_lba != 0) + ddf->anchor.workspace_lba = d->workspace_lba; + else + ddf->anchor.workspace_lba = + __cpu_to_be64(size - 32*1024*2); + if (d->primary_lba != 0) + ddf->anchor.primary_lba = d->primary_lba; + else + ddf->anchor.primary_lba = + __cpu_to_be64(size - 16*1024*2); + if (d->secondary_lba != 0) + ddf->anchor.secondary_lba = d->secondary_lba; + else + ddf->anchor.secondary_lba = + __cpu_to_be64(size - 32*1024*2); ddf->anchor.seq = __cpu_to_be32(1); memcpy(&ddf->primary, &ddf->anchor, 512); memcpy(&ddf->secondary, &ddf->anchor, 512);