From 7f798aca5bb643c8489a855996d40913d21c7722 Mon Sep 17 00:00:00 2001 From: "mwilck@arcor.de" Date: Fri, 1 Mar 2013 23:28:22 +0100 Subject: [PATCH] DDF: cleanly save the secondary DDF structure So far, mdadm only saved the header of the secondary structure. With this patch, the full secondary DDF structure is saved consistently, too. Some vendor DDF implementations need it. Signed-off-by: Martin Wilck Signed-off-by: NeilBrown --- super-ddf.c | 139 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 59 deletions(-) diff --git a/super-ddf.c b/super-ddf.c index c0fd5fae..38af9132 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2316,17 +2316,87 @@ static int remove_from_super_ddf(struct supertype *st, mdu_disk_info_t *dk) */ #define NULL_CONF_SZ 4096 -static int __write_init_super_ddf(struct supertype *st) +static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type, + char *null_aligned) { + unsigned long long sector; + struct ddf_header *header; + int fd, i, n_config, conf_size; + + fd = d->fd; + + switch (type) { + case DDF_HEADER_PRIMARY: + header = &ddf->primary; + sector = __be64_to_cpu(header->primary_lba); + break; + case DDF_HEADER_SECONDARY: + header = &ddf->secondary; + sector = __be64_to_cpu(header->secondary_lba); + break; + default: + return 0; + } + + header->type = type; + header->openflag = 0; + header->crc = calc_crc(header, 512); + + lseek64(fd, sector<<9, 0); + if (write(fd, header, 512) < 0) + return 0; + + ddf->controller.crc = calc_crc(&ddf->controller, 512); + if (write(fd, &ddf->controller, 512) < 0) + return 0; + ddf->phys->crc = calc_crc(ddf->phys, ddf->pdsize); + if (write(fd, ddf->phys, ddf->pdsize) < 0) + return 0; + ddf->virt->crc = calc_crc(ddf->virt, ddf->vdsize); + if (write(fd, ddf->virt, ddf->vdsize) < 0) + return 0; + + /* Now write lots of config records. */ + n_config = ddf->max_part; + conf_size = ddf->conf_rec_len * 512; + for (i = 0 ; i <= n_config ; i++) { + struct vcl *c = d->vlist[i]; + if (i == n_config) + c = (struct vcl *)d->spare; + + if (c) { + c->conf.crc = calc_crc(&c->conf, conf_size); + if (write(fd, &c->conf, conf_size) < 0) + break; + } else { + unsigned int togo = conf_size; + while (togo > NULL_CONF_SZ) { + if (write(fd, null_aligned, NULL_CONF_SZ) < 0) + break; + togo -= NULL_CONF_SZ; + } + if (write(fd, null_aligned, togo) < 0) + break; + } + } + if (i <= n_config) + return 0; + + d->disk.crc = calc_crc(&d->disk, 512); + if (write(fd, &d->disk, 512) < 0) + return 0; + + return 1; +} + +static int __write_init_super_ddf(struct supertype *st) +{ struct ddf_super *ddf = st->sb; - int i; struct dl *d; - int n_config; - int conf_size; int attempts = 0; int successes = 0; - unsigned long long size, sector; + unsigned long long size; char *null_aligned; if (posix_memalign((void**)&null_aligned, 4096, NULL_CONF_SZ) != 0) { @@ -2354,6 +2424,7 @@ static int __write_init_super_ddf(struct supertype *st) 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); ddf->anchor.seq = __cpu_to_be32(1); memcpy(&ddf->primary, &ddf->anchor, 512); memcpy(&ddf->secondary, &ddf->anchor, 512); @@ -2362,64 +2433,14 @@ static int __write_init_super_ddf(struct supertype *st) ddf->anchor.seq = 0xFFFFFFFF; /* no sequencing in anchor */ ddf->anchor.crc = calc_crc(&ddf->anchor, 512); - ddf->primary.openflag = 0; - ddf->primary.type = DDF_HEADER_PRIMARY; - - ddf->secondary.openflag = 0; - ddf->secondary.type = DDF_HEADER_SECONDARY; - - ddf->primary.crc = calc_crc(&ddf->primary, 512); - ddf->secondary.crc = calc_crc(&ddf->secondary, 512); - - sector = size - 16*1024*2; - lseek64(fd, sector<<9, 0); - if (write(fd, &ddf->primary, 512) < 0) - continue; - - ddf->controller.crc = calc_crc(&ddf->controller, 512); - if (write(fd, &ddf->controller, 512) < 0) + if (!__write_ddf_structure(d, ddf, DDF_HEADER_PRIMARY, + null_aligned)) continue; - ddf->phys->crc = calc_crc(ddf->phys, ddf->pdsize); - - if (write(fd, ddf->phys, ddf->pdsize) < 0) - continue; - - ddf->virt->crc = calc_crc(ddf->virt, ddf->vdsize); - if (write(fd, ddf->virt, ddf->vdsize) < 0) + if (!__write_ddf_structure(d, ddf, DDF_HEADER_SECONDARY, + null_aligned)) continue; - /* Now write lots of config records. */ - n_config = ddf->max_part; - conf_size = ddf->conf_rec_len * 512; - for (i = 0 ; i <= n_config ; i++) { - struct vcl *c = d->vlist[i]; - if (i == n_config) - c = (struct vcl*)d->spare; - - if (c) { - c->conf.crc = calc_crc(&c->conf, conf_size); - if (write(fd, &c->conf, conf_size) < 0) - break; - } else { - unsigned int togo = conf_size; - while (togo > NULL_CONF_SZ) { - if (write(fd, null_aligned, NULL_CONF_SZ) < 0) - break; - togo -= NULL_CONF_SZ; - } - if (write(fd, null_aligned, togo) < 0) - break; - } - } - if (i <= n_config) - continue; - d->disk.crc = calc_crc(&d->disk, 512); - if (write(fd, &d->disk, 512) < 0) - continue; - - /* Maybe do the same for secondary */ - lseek64(fd, (size-1)*512, SEEK_SET); if (write(fd, &ddf->anchor, 512) < 0) continue; -- 2.47.2