X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=super-ddf.c;h=5d38750489193302e6a4bcd0e56809ccdc29957b;hp=a0a9cb0361a25945e667680346bdd814abfb7bf8;hb=103f2410ec581620367d6fde67a3a62f077062a7;hpb=18a2f463fd26076e943b1a0325c1e036f1038369 diff --git a/super-ddf.c b/super-ddf.c index a0a9cb03..5d387504 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -31,11 +31,6 @@ #include "sha1.h" #include -static inline int ROUND_UP(int a, int base) -{ - return ((a+base-1)/base)*base; -} - /* a non-official T10 name for creation GUIDs */ static char T10[] = "Linux-MD"; @@ -395,8 +390,9 @@ struct bad_block_log { * built in Create or Assemble to describe the whole array. */ struct ddf_super { - struct ddf_header anchor, primary, secondary, *active; + struct ddf_header anchor, primary, secondary; struct ddf_controller_data controller; + struct ddf_header *active; struct phys_disk *phys; struct virtual_disk *virt; int pdsize, vdsize; @@ -404,22 +400,32 @@ struct ddf_super { int currentdev; int updates_pending; struct vcl { - struct vcl *next; - __u64 *lba_offset; /* location in 'conf' of - * the lba table */ - int vcnum; /* index into ->virt */ - __u64 *block_sizes; /* NULL if all the same */ + union { + char space[512]; + struct { + struct vcl *next; + __u64 *lba_offset; /* location in 'conf' of + * the lba table */ + int vcnum; /* index into ->virt */ + __u64 *block_sizes; /* NULL if all the same */ + }; + }; struct vd_config conf; } *conflist, *currentconf; struct dl { - struct dl *next; + union { + char space[512]; + struct { + struct dl *next; + int major, minor; + char *devname; + int fd; + unsigned long long size; /* sectors */ + int pdnum; /* index in ->phys */ + struct spare_assign *spare; + }; + }; struct disk_data disk; - int major, minor; - char *devname; - int fd; - unsigned long long size; /* sectors */ - int pdnum; /* index in ->phys */ - struct spare_assign *spare; struct vcl *vlist[0]; /* max_part in size */ } *dlist; }; @@ -497,8 +503,10 @@ static void *load_section(int fd, struct ddf_super *super, void *buf, /* All pre-allocated sections are a single block */ if (len != 1) return NULL; - } else - buf = malloc(len<<9); + } else { + posix_memalign(&buf, 512, len<<9); + } + if (!buf) return NULL; @@ -633,8 +641,9 @@ static int load_ddf_local(int fd, struct ddf_super *super, unsigned long long dsize; /* First the local disk info */ - dl = malloc(sizeof(*dl) + - (super->max_part) * sizeof(dl->vlist[0])); + posix_memalign((void**)&dl, 512, + sizeof(*dl) + + (super->max_part) * sizeof(dl->vlist[0])); load_section(fd, super, &dl->disk, super->active->data_section_offset, @@ -683,7 +692,8 @@ static int load_ddf_local(int fd, struct ddf_super *super, if (vd->magic == DDF_SPARE_ASSIGN_MAGIC) { if (dl->spare) continue; - dl->spare = malloc(super->conf_rec_len*512); + posix_memalign((void**)&dl->spare, 512, + super->conf_rec_len*512); memcpy(dl->spare, vd, super->conf_rec_len*512); continue; } @@ -701,8 +711,9 @@ static int load_ddf_local(int fd, struct ddf_super *super, __be32_to_cpu(vcl->conf.seqnum)) continue; } else { - vcl = malloc(super->conf_rec_len*512 + - offsetof(struct vcl, conf)); + posix_memalign((void**)&vcl, 512, + (super->conf_rec_len*512 + + offsetof(struct vcl, conf))); vcl->next = super->conflist; vcl->block_sizes = NULL; /* FIXME not for CONCAT */ super->conflist = vcl; @@ -766,8 +777,7 @@ static int load_super_ddf(struct supertype *st, int fd, } } - super = malloc(sizeof(*super)); - if (!super) { + if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) { fprintf(stderr, Name ": malloc of %zu failed.\n", sizeof(*super)); return 1; @@ -1276,6 +1286,8 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) // info->disk.raid_disk = find refnum in the table and use index; // info->disk.state = ???; + info->container_member = ddf->currentconf->vcnum; + info->resync_start = 0; if (!(ddf->virt->entries[info->container_member].state & DDF_state_inconsistent) && @@ -1286,9 +1298,10 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) uuid_from_super_ddf(st, info->uuid); - sprintf(info->text_version, "/%s/%d", + info->container_member = atoi(st->subarray); + sprintf(info->text_version, "/%s/%s", devnum2devname(st->container_dev), - info->container_member); + st->subarray); // info->name[] ?? ; } @@ -1442,7 +1455,7 @@ static int init_super_ddf(struct supertype *st, return init_super_ddf_bvd(st, info, size, name, homehost, uuid); - ddf = malloc(sizeof(*ddf)); + posix_memalign((void**)&ddf, 512, sizeof(*ddf)); memset(ddf, 0, sizeof(*ddf)); ddf->dlist = NULL; /* no physical disks yet */ ddf->conflist = NULL; /* No virtual disks yet */ @@ -1569,7 +1582,8 @@ static int init_super_ddf(struct supertype *st, memset(ddf->controller.pad, 0xff, 8); memset(ddf->controller.vendor_data, 0xff, 448); - pd = ddf->phys = malloc(pdsize); + posix_memalign((void**)&pd, 512, pdsize); + ddf->phys = pd; ddf->pdsize = pdsize; memset(pd, 0xff, pdsize); @@ -1579,7 +1593,8 @@ static int init_super_ddf(struct supertype *st, pd->max_pdes = __cpu_to_be16(max_phys_disks); memset(pd->pad, 0xff, 52); - vd = ddf->virt = malloc(vdsize); + posix_memalign((void**)&vd, 512, vdsize); + ddf->virt = vd; ddf->vdsize = vdsize; memset(vd, 0, vdsize); vd->magic = DDF_VIRT_RECORDS_MAGIC; @@ -1804,7 +1819,8 @@ static int init_super_ddf_bvd(struct supertype *st, __cpu_to_be16(__be16_to_cpu(ddf->virt->populated_vdes)+1); /* Now create a new vd_config */ - vcl = malloc(offsetof(struct vcl, conf) + ddf->conf_rec_len * 512); + posix_memalign((void**)&vcl, 512, + (offsetof(struct vcl, conf) + ddf->conf_rec_len * 512)); vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe]; vcl->vcnum = venum; sprintf(st->subarray, "%d", venum); @@ -1973,7 +1989,8 @@ static void add_to_super_ddf(struct supertype *st, * a phys_disk entry and a more detailed disk_data entry. */ fstat(fd, &stb); - dd = malloc(sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part); + posix_memalign((void**)&dd, 512, + sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part); dd->major = major(stb.st_rdev); dd->minor = minor(stb.st_rdev); dd->devname = devname; @@ -2036,7 +2053,7 @@ static void add_to_super_ddf(struct supertype *st, #ifndef MDASSEMBLE -static unsigned char null_conf[4096]; +static unsigned char null_conf[4096+512]; static int __write_init_super_ddf(struct supertype *st, int do_close) { @@ -2108,14 +2125,15 @@ static int __write_init_super_ddf(struct supertype *st, int do_close) c->conf.crc = calc_crc(&c->conf, conf_size); write(fd, &c->conf, conf_size); } else { + char *null_aligned = (char*)((((unsigned long)null_conf)+511)&~511UL); if (null_conf[0] != 0xff) memset(null_conf, 0xff, sizeof(null_conf)); int togo = conf_size; - while (togo > sizeof(null_conf)) { - write(fd, null_conf, sizeof(null_conf)); - togo -= sizeof(null_conf); + while (togo > sizeof(null_conf)-512) { + write(fd, null_aligned, sizeof(null_conf)-512); + togo -= sizeof(null_conf)-512; } - write(fd, null_conf, togo); + write(fd, null_aligned, togo); } } d->disk.crc = calc_crc(&d->disk, 512); @@ -2174,20 +2192,24 @@ static __u64 avail_size_ddf(struct supertype *st, __u64 devsize) } #ifndef MDASSEMBLE -static int validate_geometry_ddf_container(struct supertype *st, - int level, int layout, int raiddisks, - int chunk, unsigned long long size, - char *dev, unsigned long long *freesize); +static int +validate_geometry_ddf_container(struct supertype *st, + int level, int layout, int raiddisks, + int chunk, unsigned long long size, + char *dev, unsigned long long *freesize, + int verbose); static int validate_geometry_ddf_bvd(struct supertype *st, int level, int layout, int raiddisks, int chunk, unsigned long long size, - char *dev, unsigned long long *freesize); + char *dev, unsigned long long *freesize, + int verbose); static int validate_geometry_ddf(struct supertype *st, - int level, int layout, int raiddisks, - int chunk, unsigned long long size, - char *dev, unsigned long long *freesize) + int level, int layout, int raiddisks, + int chunk, unsigned long long size, + char *dev, unsigned long long *freesize, + int verbose) { int fd; struct mdinfo *sra; @@ -2203,8 +2225,9 @@ static int validate_geometry_ddf(struct supertype *st, if (level == LEVEL_CONTAINER) { /* Must be a fresh device to add to a container */ return validate_geometry_ddf_container(st, level, layout, - raiddisks, - chunk, size, dev, freesize); + raiddisks, chunk, + size, dev, freesize, + verbose); } if (st->sb) { @@ -2213,7 +2236,8 @@ static int validate_geometry_ddf(struct supertype *st, * Should make a distinction one day. */ return validate_geometry_ddf_bvd(st, level, layout, raiddisks, - chunk, size, dev, freesize); + chunk, size, dev, freesize, + verbose); } if (!dev) { /* Initial sanity check. Exclude illegal levels. */ @@ -2247,22 +2271,26 @@ static int validate_geometry_ddf(struct supertype *st, /* Somehow return the fact that we have enough */ } - fprintf(stderr, - Name ": Cannot create this array on device %s\n", - dev); + if (verbose) + fprintf(stderr, + Name ": ddf: Cannot create this array " + "on device %s\n", + dev); return 0; } if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) { - fprintf(stderr, Name ": Cannot open %s: %s\n", - dev, strerror(errno)); + if (verbose) + fprintf(stderr, Name ": ddf: Cannot open %s: %s\n", + dev, strerror(errno)); return 0; } /* Well, it is in use by someone, maybe a 'ddf' container. */ cfd = open_container(fd); if (cfd < 0) { close(fd); - fprintf(stderr, Name ": Cannot use %s: It is busy\n", - dev); + if (verbose) + fprintf(stderr, Name ": ddf: Cannot use %s: %s\n", + dev, strerror(EBUSY)); return 0; } sra = sysfs_read(cfd, 0, GET_VERSION); @@ -2279,7 +2307,8 @@ static int validate_geometry_ddf(struct supertype *st, close(cfd); return validate_geometry_ddf_bvd(st, level, layout, raiddisks, chunk, size, - dev, freesize); + dev, freesize, + verbose); } close(cfd); } else /* device may belong to a different container */ @@ -2288,10 +2317,12 @@ static int validate_geometry_ddf(struct supertype *st, return 1; } -static int validate_geometry_ddf_container(struct supertype *st, - int level, int layout, int raiddisks, - int chunk, unsigned long long size, - char *dev, unsigned long long *freesize) +static int +validate_geometry_ddf_container(struct supertype *st, + int level, int layout, int raiddisks, + int chunk, unsigned long long size, + char *dev, unsigned long long *freesize, + int verbose) { int fd; unsigned long long ldsize; @@ -2303,8 +2334,9 @@ static int validate_geometry_ddf_container(struct supertype *st, fd = open(dev, O_RDONLY|O_EXCL, 0); if (fd < 0) { - fprintf(stderr, Name ": Cannot open %s: %s\n", - dev, strerror(errno)); + if (verbose) + fprintf(stderr, Name ": ddf: Cannot open %s: %s\n", + dev, strerror(errno)); return 0; } if (!get_dev_size(fd, dev, &ldsize)) { @@ -2321,7 +2353,8 @@ static int validate_geometry_ddf_container(struct supertype *st, static int validate_geometry_ddf_bvd(struct supertype *st, int level, int layout, int raiddisks, int chunk, unsigned long long size, - char *dev, unsigned long long *freesize) + char *dev, unsigned long long *freesize, + int verbose) { struct stat stb; struct ddf_super *ddf = st->sb; @@ -2366,9 +2399,11 @@ static int validate_geometry_ddf_bvd(struct supertype *st, free(e); } if (dcnt < raiddisks) { - fprintf(stderr, Name ": Not enough devices with space " - "for this array (%d < %d)\n", - dcnt, raiddisks); + if (verbose) + fprintf(stderr, + Name ": ddf: Not enough devices with " + "space for this array (%d < %d)\n", + dcnt, raiddisks); return 0; } return 1; @@ -2384,8 +2419,10 @@ static int validate_geometry_ddf_bvd(struct supertype *st, break; } if (!dl) { - fprintf(stderr, Name ": %s is not in the same DDF set\n", - dev); + if (verbose) + fprintf(stderr, Name ": ddf: %s is not in the " + "same DDF set\n", + dev); return 0; } e = get_extents(ddf, dl); @@ -2424,8 +2461,7 @@ static int load_super_ddf_all(struct supertype *st, int fd, strcmp(sra->text_version, "ddf") != 0) return 1; - super = malloc(sizeof(*super)); - if (!super) + if (posix_memalign((void**)&super, 512, sizeof(*super)) != 0) return 1; memset(super, 0, sizeof(*super)); @@ -2570,8 +2606,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st) dev->disk.raid_disk = i; dev->disk.state = (1<events = __le32_to_cpu(ddf->primary.seq); - dev->data_offset = vc->lba_offset[i]; + dev->events = __be32_to_cpu(ddf->primary.seq); + dev->data_offset = __be64_to_cpu(vc->lba_offset[i]); dev->component_size = __be64_to_cpu(vc->conf.blocks); if (d->devname) strcpy(dev->name, d->devname); @@ -2583,14 +2619,17 @@ static struct mdinfo *container_content_ddf(struct supertype *st) static int store_zero_ddf(struct supertype *st, int fd) { unsigned long long dsize; - char buf[512]; - memset(buf, 0, 512); + void *buf; if (!get_dev_size(fd, NULL, &dsize)) return 1; + posix_memalign(&buf, 512, 512); + memset(buf, 0, 512); + lseek64(fd, dsize-512, 0); write(fd, buf, 512); + free(buf); return 0; } @@ -2627,7 +2666,7 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst) */ static int ddf_open_new(struct supertype *c, struct active_array *a, char *inst) { - fprintf(stderr, "ddf: open_new %s\n", inst); + dprintf("ddf: open_new %s\n", inst); a->info.container_member = atoi(inst); return 0; } @@ -2664,8 +2703,8 @@ static void ddf_set_array_state(struct active_array *a, int consistent) if (old != ddf->virt->entries[inst].init_state) ddf->updates_pending = 1; - printf("ddf mark %d %s %llu\n", inst, consistent?"clean":"dirty", - a->resync_start); + dprintf("ddf mark %d %s %llu\n", inst, consistent?"clean":"dirty", + a->resync_start); } /* @@ -2691,7 +2730,7 @@ static void ddf_set_disk(struct active_array *a, int n, int state) int i, st, working; if (vc == NULL) { - fprintf(stderr, "ddf: cannot find instance %d!!\n", inst); + dprintf("ddf: cannot find instance %d!!\n", inst); return; } if (pd < 0) { @@ -2716,7 +2755,7 @@ static void ddf_set_disk(struct active_array *a, int n, int state) ddf->updates_pending = 1; } - fprintf(stderr, "ddf: set_disk %d to %x\n", n, state); + dprintf("ddf: set_disk %d to %x\n", n, state); /* Now we need to check the state of the array and update * virtual_disk.entries[n].state. @@ -2786,7 +2825,7 @@ static void ddf_sync_metadata(struct supertype *st) return; ddf->updates_pending = 0; __write_init_super_ddf(st, 0); - fprintf(stderr, "ddf: sync_metadata\n"); + dprintf("ddf: sync_metadata\n"); } static void ddf_process_update(struct supertype *st, @@ -2829,7 +2868,7 @@ static void ddf_process_update(struct supertype *st, int mppe; int ent; -// printf("Process update %x\n", *magic); + dprintf("Process update %x\n", *magic); switch (*magic) { case DDF_PHYS_RECORDS_MAGIC: @@ -2869,7 +2908,7 @@ static void ddf_process_update(struct supertype *st, break; case DDF_VD_CONF_MAGIC: -// printf("len %d %d\n", update->len, ddf->conf_rec_len); + dprintf("len %d %d\n", update->len, ddf->conf_rec_len); mppe = __be16_to_cpu(ddf->anchor.max_primary_element_entries); if (update->len != ddf->conf_rec_len * 512) @@ -2878,7 +2917,7 @@ static void ddf_process_update(struct supertype *st, for (vcl = ddf->conflist; vcl ; vcl = vcl->next) if (memcmp(vcl->conf.guid, vc->guid, DDF_GUID_LEN) == 0) break; -// printf("vcl = %p\n", vcl); + dprintf("vcl = %p\n", vcl); if (vcl) { /* An update, just copy the phys_refnum and lba_offset * fields @@ -2903,8 +2942,8 @@ static void ddf_process_update(struct supertype *st, for (dn=0; dn < ddf->mppe ; dn++) if (vcl->conf.phys_refnum[dn] == dl->disk.refnum) { -// printf("dev %d has %p at %d\n", -// dl->pdnum, vcl, vn); + dprintf("dev %d has %p at %d\n", + dl->pdnum, vcl, vn); dl->vlist[vn++] = vcl; break; } @@ -2947,8 +2986,9 @@ static void ddf_prepare_update(struct supertype *st, struct ddf_super *ddf = st->sb; __u32 *magic = (__u32*)update->buf; if (*magic == DDF_VD_CONF_MAGIC) - update->space = malloc(offsetof(struct vcl, conf) - + ddf->conf_rec_len * 512); + posix_memalign(&update->space, 512, + offsetof(struct vcl, conf) + + ddf->conf_rec_len * 512); } /* @@ -2990,8 +3030,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, working ++; } -// printf("ddf_activate: working=%d (%d) level=%d\n", working, a->info.array.raid_disks, -// a->info.array.level); + dprintf("ddf_activate: working=%d (%d) level=%d\n", working, a->info.array.raid_disks, + a->info.array.level); if (working == a->info.array.raid_disks) return NULL; /* array not degraded */ switch (a->info.array.level) { @@ -3018,7 +3058,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, for (d = a->info.devs ; d ; d = d->next) if (d->disk.raid_disk == i) break; - printf("found %d: %p %x\n", i, d, d?d->curr_state:0); + dprintf("found %d: %p %x\n", i, d, d?d->curr_state:0); if (d && (d->state_fd >= 0)) continue; @@ -3036,7 +3076,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, for (d2 = a->info.devs ; d2 ; d2 = d2->next) if (d2->disk.major == dl->major && d2->disk.minor == dl->minor) { - printf("%x:%x already in array\n", dl->major, dl->minor); + dprintf("%x:%x already in array\n", dl->major, dl->minor); break; } if (d2) @@ -3064,7 +3104,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, } if ( ! (is_dedicated || (is_global && global_ok))) { - printf("%x:%x not suitable: %d %d\n", dl->major, dl->minor, + dprintf("%x:%x not suitable: %d %d\n", dl->major, dl->minor, is_dedicated, is_global); continue; } @@ -3073,7 +3113,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, * We need a->info.component_size sectors */ ex = get_extents(ddf, dl); if (!ex) { - printf("cannot get extents\n"); + dprintf("cannot get extents\n"); continue; } j = 0; pos = 0; @@ -3089,8 +3129,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, free(ex); if (esize < a->info.component_size) { - printf("%x:%x has no room: %llu %llu\n", dl->major, dl->minor, - esize, a->info.component_size); + dprintf("%x:%x has no room: %llu %llu\n", dl->major, dl->minor, + esize, a->info.component_size); /* No room */ continue; } @@ -3108,8 +3148,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, di->container_member = dl->pdnum; di->next = rv; rv = di; - printf("%x:%x to be %d at %llu\n", dl->major, dl->minor, - i, pos); + dprintf("%x:%x to be %d at %llu\n", dl->major, dl->minor, + i, pos); break; } @@ -3130,7 +3170,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, */ mu = malloc(sizeof(*mu)); mu->buf = malloc(ddf->conf_rec_len * 512); - mu->space = malloc(sizeof(struct vcl)); + posix_memalign(&mu->space, 512, sizeof(struct vcl)); mu->len = ddf->conf_rec_len; mu->next = *updates; vc = find_vdcr(ddf, a->info.container_member);