X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=super-ddf.c;h=a97e05dea0c191b6ac31a1945d1a23789f5df38b;hb=47c74f3f50201e057bac74ed107c9eaba55e5f13;hp=14f83304bde10c8f4ddff2bc17d5f4eb1d08dce5;hpb=d23534e4646313a67296b295666d165a87bb2c92;p=thirdparty%2Fmdadm.git diff --git a/super-ddf.c b/super-ddf.c index 14f83304..a97e05de 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -396,7 +396,7 @@ struct ddf_super { struct phys_disk *phys; struct virtual_disk *virt; int pdsize, vdsize; - int max_part, mppe, conf_rec_len; + unsigned int max_part, mppe, conf_rec_len; int currentdev; int updates_pending; struct vcl { @@ -406,7 +406,7 @@ struct ddf_super { struct vcl *next; __u64 *lba_offset; /* location in 'conf' of * the lba table */ - int vcnum; /* index into ->virt */ + unsigned int vcnum; /* index into ->virt */ __u64 *block_sizes; /* NULL if all the same */ }; }; @@ -440,7 +440,7 @@ struct ddf_super { #endif -static int calc_crc(void *buf, int len) +static unsigned int calc_crc(void *buf, int len) { /* crcs are always at the same place as in the ddf_header */ struct ddf_header *ddf = buf; @@ -522,12 +522,12 @@ static void *load_section(int fd, struct ddf_super *super, void *buf, else offset += __be64_to_cpu(super->active->secondary_lba); - if (lseek64(fd, offset<<9, 0) != (offset<<9)) { + if ((unsigned long long)lseek64(fd, offset<<9, 0) != (offset<<9)) { if (dofree) free(buf); return NULL; } - if (read(fd, buf, len<<9) != (len<<9)) { + if ((unsigned long long)read(fd, buf, len<<9) != (len<<9)) { if (dofree) free(buf); return NULL; @@ -642,10 +642,10 @@ static int load_ddf_local(int fd, struct ddf_super *super, struct dl *dl; struct stat stb; char *conf; - int i; - int confsec; + unsigned int i; + unsigned int confsec; int vnum; - int max_virt_disks = __be16_to_cpu(super->active->max_vd_entries); + unsigned int max_virt_disks = __be16_to_cpu(super->active->max_vd_entries); unsigned long long dsize; /* First the local disk info */ @@ -673,11 +673,11 @@ static int load_ddf_local(int fd, struct ddf_super *super, if (get_dev_size(fd, devname, &dsize)) dl->size = dsize >> 9; dl->spare = NULL; - for (i=0 ; i < super->max_part ; i++) + for (i = 0 ; i < super->max_part ; i++) dl->vlist[i] = NULL; super->dlist = dl; dl->pdnum = -1; - for (i=0; i < __be16_to_cpu(super->active->max_pd_entries); i++) + for (i = 0; i < __be16_to_cpu(super->active->max_pd_entries); i++) if (memcmp(super->phys->entries[i].guid, dl->disk.guid, DDF_GUID_LEN) == 0) dl->pdnum = i; @@ -760,7 +760,7 @@ static int load_ddf_local(int fd, struct ddf_super *super, #ifndef MDASSEMBLE static int load_super_ddf_all(struct supertype *st, int fd, - void **sbp, char *devname, int keep_fd); + void **sbp, char *devname); #endif static void free_super_ddf(struct supertype *st); @@ -774,15 +774,17 @@ static int load_super_ddf(struct supertype *st, int fd, #ifndef MDASSEMBLE /* if 'fd' is a container, load metadata from all the devices */ - if (load_super_ddf_all(st, fd, &st->sb, devname, 1) == 0) + if (load_super_ddf_all(st, fd, &st->sb, devname) == 0) return 0; #endif - if (st->subarray[0]) - return 1; /* FIXME Is this correct */ if (get_dev_size(fd, devname, &dsize) == 0) return 1; + if (test_partition(fd)) + /* DDF is not allowed on partitions */ + return 1; + /* 32M is a lower bound */ if (dsize <= 32*1024*1024) { if (devname) @@ -840,18 +842,6 @@ static int load_super_ddf(struct supertype *st, int fd, return rv; } - if (st->subarray[0]) { - struct vcl *v; - - for (v = super->conflist; v; v = v->next) - if (v->vcnum == atoi(st->subarray)) - super->currentconf = v; - if (!super->currentconf) { - free(super); - return 1; - } - } - /* Should possibly check the sections .... */ st->sb = super; @@ -903,6 +893,7 @@ static struct supertype *match_metadata_desc_ddf(char *arg) st = malloc(sizeof(*st)); memset(st, 0, sizeof(*st)); + st->container_dev = NoMdDev; st->ss = &super_ddf; st->max_devs = 512; st->minor_version = 0; @@ -1042,7 +1033,7 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid) struct vcl *vcl; for (vcl = sb->conflist ; vcl ; vcl = vcl->next) { - int i; + unsigned int i; struct vd_config *vc = &vcl->conf; if (calc_crc(vc, crl*512) != vc->crc) @@ -1053,7 +1044,7 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid) /* Ok, we know about this VD, let's give more details */ printf(" Raid Devices[%d] : %d (", n, __be16_to_cpu(vc->prim_elmnt_count)); - for (i=0; i<__be16_to_cpu(vc->prim_elmnt_count); i++) { + for (i = 0; i < __be16_to_cpu(vc->prim_elmnt_count); i++) { int j; int cnt = __be16_to_cpu(sb->phys->used_pdes); for (j=0; jsb; struct mdinfo info; - int i; + unsigned int i; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); - for (i=0; i<__be16_to_cpu(ddf->virt->max_vdes); i++) { + for (i = 0; i < __be16_to_cpu(ddf->virt->max_vdes); i++) { struct virtual_entry *ve = &ddf->virt->entries[i]; struct vcl vcl; char nbuf1[64]; @@ -1221,7 +1212,7 @@ static void export_examine_super_ddf(struct supertype *st) { struct mdinfo info; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf("MD_METADATA=ddf\n"); printf("MD_LEVEL=container\n"); @@ -1247,7 +1238,7 @@ static void brief_detail_super_ddf(struct supertype *st) // struct ddf_super *ddf = st->sb; struct mdinfo info; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf,':'); printf(" UUID=%s", nbuf + 5); } @@ -1260,7 +1251,11 @@ static int match_home_ddf(struct supertype *st, char *homehost) * the hostname */ struct ddf_super *ddf = st->sb; - int len = strlen(homehost); + unsigned int len; + + if (!homehost) + return 0; + len = strlen(homehost); return (memcmp(ddf->controller.guid, T10, 8) == 0 && len < sizeof(ddf->controller.vendor_data) && @@ -1269,7 +1264,7 @@ static int match_home_ddf(struct supertype *st, char *homehost) } #ifndef MDASSEMBLE -static struct vd_config *find_vdcr(struct ddf_super *ddf, int inst) +static struct vd_config *find_vdcr(struct ddf_super *ddf, unsigned int inst) { struct vcl *v; @@ -1285,8 +1280,8 @@ static int find_phys(struct ddf_super *ddf, __u32 phys_refnum) /* Find the entry in phys_disk which has the given refnum * and return it's index */ - int i; - for (i=0; i < __be16_to_cpu(ddf->phys->max_pdes); i++) + unsigned int i; + for (i = 0; i < __be16_to_cpu(ddf->phys->max_pdes); i++) if (ddf->phys->entries[i].refnum == phys_refnum) return i; return -1; @@ -1330,14 +1325,15 @@ static void uuid_from_super_ddf(struct supertype *st, int uuid[4]) memcpy(uuid, buf, 4*4); } -static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info); +static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map); -static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) +static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *map) { struct ddf_super *ddf = st->sb; + int map_disks = info->array.raid_disks; if (ddf->currentconf) { - getinfo_super_ddf_bvd(st, info); + getinfo_super_ddf_bvd(st, info, map); return; } @@ -1349,6 +1345,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) (ddf->anchor.guid+16)); info->array.utime = 0; info->array.chunk_size = 0; + info->container_enough = 1; info->disk.major = 0; @@ -1369,6 +1366,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) info->disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); + info->recovery_start = MaxSector; info->reshape_active = 0; info->name[0] = 0; @@ -1379,17 +1377,29 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) uuid_from_super_ddf(st, info->uuid); + if (map) { + int i; + for (i = 0 ; i < map_disks; i++) { + if (i < info->array.raid_disks && + (__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Online) && + !(__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Failed)) + map[i] = 1; + else + map[i] = 0; + } + } } static int rlq_to_layout(int rlq, int prl, int raiddisks); -static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) +static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map) { struct ddf_super *ddf = st->sb; struct vcl *vc = ddf->currentconf; int cd = ddf->currentdev; int j; struct dl *dl; + int map_disks = info->array.raid_disks; /* FIXME this returns BVD info - what if we want SVD ?? */ @@ -1404,7 +1414,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) info->array.chunk_size = 512 << vc->conf.chunk_shift; info->custom_array_size = 0; - if (cd >= 0 && cd < ddf->mppe) { + if (cd >= 0 && (unsigned)cd < ddf->mppe) { info->data_offset = __be64_to_cpu(vc->lba_offset[cd]); if (vc->block_sizes) info->component_size = vc->block_sizes[cd]; @@ -1427,7 +1437,9 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) info->container_member = ddf->currentconf->vcnum; + info->recovery_start = MaxSector; info->resync_start = 0; + info->reshape_active = 0; if (!(ddf->virt->entries[info->container_member].state & DDF_state_inconsistent) && (ddf->virt->entries[info->container_member].init_state @@ -1437,12 +1449,11 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) uuid_from_super_ddf(st, info->uuid); - info->container_member = atoi(st->subarray); info->array.major_version = -1; info->array.minor_version = -2; - sprintf(info->text_version, "/%s/%s", + sprintf(info->text_version, "/%s/%d", devnum2devname(st->container_dev), - st->subarray); + info->container_member); info->safe_mode_delay = 200; memcpy(info->name, ddf->virt->entries[info->container_member].name, 16); @@ -1450,6 +1461,18 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) for(j=0; j<16; j++) if (info->name[j] == ' ') info->name[j] = 0; + + if (map) + for (j = 0; j < map_disks; j++) { + map[j] = 0; + if (j < info->array.raid_disks) { + int i = find_phys(ddf, vc->conf.phys_refnum[j]); + if (i >= 0 && + (__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Online) && + !(__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Failed)) + map[i] = 1; + } + } } @@ -1495,28 +1518,24 @@ static int update_super_ddf(struct supertype *st, struct mdinfo *info, if (strcmp(update, "grow") == 0) { /* FIXME */ - } - if (strcmp(update, "resync") == 0) { + } else if (strcmp(update, "resync") == 0) { // info->resync_checkpoint = 0; - } - /* We ignore UUID updates as they make even less sense - * with DDF - */ - if (strcmp(update, "homehost") == 0) { + } else if (strcmp(update, "homehost") == 0) { /* homehost is stored in controller->vendor_data, * or it is when we are the vendor */ // if (info->vendor_is_local) // strcpy(ddf->controller.vendor_data, homehost); - } - if (strcmp(update, "name") == 0) { + rv = -1; + } if (strcmp(update, "name") == 0) { /* name is stored in virtual_entry->name */ // memset(ve->name, ' ', 16); // strncpy(ve->name, info->name, 16); - } - if (strcmp(update, "_reshape_progress") == 0) { + rv = -1; + } if (strcmp(update, "_reshape_progress") == 0) { /* We don't support reshape yet */ - } + } else + rv = -1; // update_all_csum(ddf); @@ -1739,7 +1758,7 @@ static int init_super_ddf(struct supertype *st, memset(pd, 0xff, pdsize); memset(pd, 0, sizeof(*pd)); - pd->magic = DDF_PHYS_DATA_MAGIC; + pd->magic = DDF_PHYS_RECORDS_MAGIC; pd->used_pdes = __cpu_to_be16(0); pd->max_pdes = __cpu_to_be16(max_phys_disks); memset(pd->pad, 0xff, 52); @@ -1889,7 +1908,7 @@ FIXME ignore DDF_Legacy devices? */ struct extent *rv; int n = 0; - int i, j; + unsigned int i, j; rv = malloc(sizeof(struct extent) * (ddf->max_part + 2)); if (!rv) @@ -1899,7 +1918,7 @@ FIXME ignore DDF_Legacy devices? struct vcl *v = dl->vlist[i]; if (v == NULL) continue; - for (j=0; j < v->conf.prim_elmnt_count; j++) + for (j = 0; j < v->conf.prim_elmnt_count; j++) if (v->conf.phys_refnum[j] == dl->disk.refnum) { /* This device plays role 'j' in 'v'. */ rv[n].start = __be64_to_cpu(v->lba_offset[j]); @@ -1927,7 +1946,7 @@ static int init_super_ddf_bvd(struct supertype *st, * We need to create a new vd_config and a new virtual_entry */ struct ddf_super *ddf = st->sb; - int venum; + unsigned int venum; struct virtual_entry *ve; struct vcl *vcl; struct vd_config *vc; @@ -1979,7 +1998,6 @@ static int init_super_ddf_bvd(struct supertype *st, } vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe]; vcl->vcnum = venum; - sprintf(st->subarray, "%d", venum); vcl->block_sizes = NULL; /* FIXME not for CONCAT */ vc = &vcl->conf; @@ -2048,8 +2066,8 @@ static void add_to_super_ddf_bvd(struct supertype *st, struct ddf_super *ddf = st->sb; struct vd_config *vc; __u64 *lba_offset; - int working; - int i; + unsigned int working; + unsigned int i; unsigned long long blocks, pos, esize; struct extent *ex; @@ -2094,7 +2112,7 @@ static void add_to_super_ddf_bvd(struct supertype *st, vc->phys_refnum[dk->raid_disk] = dl->disk.refnum; lba_offset[dk->raid_disk] = __cpu_to_be64(pos); - for (i=0; i < ddf->max_part ; i++) + for (i = 0; i < ddf->max_part ; i++) if (dl->vlist[i] == NULL) break; if (i == ddf->max_part) @@ -2111,7 +2129,7 @@ static void add_to_super_ddf_bvd(struct supertype *st, */ working = 0; - for (i=0; i < __be16_to_cpu(vc->prim_elmnt_count); i++) + for (i = 0; i < __be16_to_cpu(vc->prim_elmnt_count); i++) if (vc->phys_refnum[i] != 0xffffffff) working++; @@ -2145,7 +2163,7 @@ static int add_to_super_ddf(struct supertype *st, struct tm *tm; unsigned long long size; struct phys_disk_entry *pde; - int n, i; + unsigned int n, i; struct stat stb; if (ddf->currentconf) { @@ -2181,11 +2199,11 @@ static int add_to_super_ddf(struct supertype *st, do { /* Cannot be bothered finding a CRC of some irrelevant details*/ dd->disk.refnum = random32(); - for (i = __be16_to_cpu(ddf->active->max_pd_entries) - 1; - i >= 0; i--) - if (ddf->phys->entries[i].refnum == dd->disk.refnum) + for (i = __be16_to_cpu(ddf->active->max_pd_entries); + i > 0; i--) + if (ddf->phys->entries[i-1].refnum == dd->disk.refnum) break; - } while (i >= 0); + } while (i > 0); dd->disk.forced_ref = 1; dd->disk.forced_guid = 1; @@ -2328,7 +2346,7 @@ static int __write_init_super_ddf(struct supertype *st, int do_close) 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; + unsigned int togo = conf_size; while (togo > sizeof(null_conf)-512) { if (write(fd, null_aligned, sizeof(null_conf)-512) < 0) break; @@ -2406,8 +2424,12 @@ static int write_init_super_ddf(struct supertype *st) /* FIXME I need to close the fds! */ return 0; - } else + } else { + struct dl *d; + for (d = ddf->dlist; d; d=d->next) + while (Kill(d->devname, NULL, 0, 1, 1) == 0); return __write_init_super_ddf(st, 1); + } } #endif @@ -2635,7 +2657,7 @@ static int validate_geometry_ddf(struct supertype *st, * and try to create a bvd */ struct ddf_super *ddf; - if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL, 1) == 0) { + if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL) == 0) { st->sb = ddf; st->container_dev = fd2devnum(cfd); close(cfd); @@ -2753,8 +2775,8 @@ static int validate_geometry_ddf_bvd(struct supertype *st, if ((S_IFMT & stb.st_mode) != S_IFBLK) return 0; for (dl = ddf->dlist ; dl ; dl = dl->next) { - if (dl->major == major(stb.st_rdev) && - dl->minor == minor(stb.st_rdev)) + if (dl->major == (int)major(stb.st_rdev) && + dl->minor == (int)minor(stb.st_rdev)) break; } if (!dl) { @@ -2782,7 +2804,7 @@ static int validate_geometry_ddf_bvd(struct supertype *st, } static int load_super_ddf_all(struct supertype *st, int fd, - void **sbp, char *devname, int keep_fd) + void **sbp, char *devname) { struct mdinfo *sra; struct ddf_super *super; @@ -2791,14 +2813,8 @@ static int load_super_ddf_all(struct supertype *st, int fd, int seq; char nm[20]; int dfd; - int devnum = fd2devnum(fd); - enum sysfs_read_flags flags; - - flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE; - if (mdmon_running(devnum)) - flags |= SKIP_GONE_DEVS; - sra = sysfs_read(fd, 0, flags); + sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); if (!sra) return 1; if (sra->array.major_version != -1 || @@ -2844,38 +2860,36 @@ static int load_super_ddf_all(struct supertype *st, int fd, int rv; sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor); - dfd = dev_open(nm, keep_fd? O_RDWR : O_RDONLY); + dfd = dev_open(nm, O_RDWR); if (dfd < 0) return 2; rv = load_ddf_headers(dfd, super, NULL); if (rv == 0) - rv = load_ddf_local(dfd, super, NULL, keep_fd); - if (!keep_fd) close(dfd); + rv = load_ddf_local(dfd, super, NULL, 1); if (rv) return 1; } - if (st->subarray[0]) { - struct vcl *v; - for (v = super->conflist; v; v = v->next) - if (v->vcnum == atoi(st->subarray)) - super->currentconf = v; - if (!super->currentconf) - return 1; - } *sbp = super; if (st->ss == NULL) { st->ss = &super_ddf; st->minor_version = 0; st->max_devs = 512; - st->container_dev = fd2devnum(fd); } + st->container_dev = fd2devnum(fd); st->loaded_container = 1; return 0; } + +static int load_container_ddf(struct supertype *st, int fd, + char *devname) +{ + return load_super_ddf_all(st, fd, &st->sb, devname); +} + #endif /* MDASSEMBLE */ -static struct mdinfo *container_content_ddf(struct supertype *st) +static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray) { /* Given a container loaded by load_super_ddf_all, * extract information about all the arrays into @@ -2891,9 +2905,16 @@ static struct mdinfo *container_content_ddf(struct supertype *st) for (vc = ddf->conflist ; vc ; vc=vc->next) { - int i; - int j; + unsigned int i; + unsigned int j; struct mdinfo *this; + char *ep; + + if (subarray && + (strtoul(subarray, &ep, 10) != vc->vcnum || + *ep != '\0')) + continue; + this = malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->next = rest; @@ -2942,7 +2963,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st) devnum2devname(st->container_dev), this->container_member); - for (i=0 ; i < ddf->mppe ; i++) { + for (i = 0 ; i < ddf->mppe ; i++) { struct mdinfo *dev; struct dl *d; @@ -3110,7 +3131,7 @@ static int ddf_set_array_state(struct active_array *a, int consistent) static void ddf_set_disk(struct active_array *a, int n, int state) { struct ddf_super *ddf = a->container->sb; - int inst = a->info.container_member; + unsigned int inst = a->info.container_member; struct vd_config *vc = find_vdcr(ddf, inst); int pd = find_phys(ddf, vc->phys_refnum[n]); int i, st, working; @@ -3251,8 +3272,8 @@ static void ddf_process_update(struct supertype *st, struct vd_config *vc; struct vcl *vcl; struct dl *dl; - int mppe; - int ent; + unsigned int mppe; + unsigned int ent; dprintf("Process update %x\n", *magic); @@ -3311,7 +3332,7 @@ static void ddf_process_update(struct supertype *st, 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) + if ((unsigned)update->len != ddf->conf_rec_len * 512) return; vc = (struct vd_config*)update->buf; for (vcl = ddf->conflist; vcl ; vcl = vcl->next) @@ -3338,8 +3359,8 @@ static void ddf_process_update(struct supertype *st, } /* Now make sure vlist is correct for each dl. */ for (dl = ddf->dlist; dl; dl = dl->next) { - int dn; - int vn = 0; + unsigned int dn; + unsigned int vn = 0; for (vcl = ddf->conflist; vcl ; vcl = vcl->next) for (dn=0; dn < ddf->mppe ; dn++) if (vcl->conf.phys_refnum[dn] == @@ -3474,7 +3495,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, int is_global = 0; int is_dedicated = 0; struct extent *ex; - int j; + unsigned int j; /* If in this array, skip */ for (d2 = a->info.devs ; d2 ; d2 = d2->next) if (d2->disk.major == dl->major && @@ -3635,6 +3656,7 @@ struct superswitch super_ddf = { .validate_geometry = validate_geometry_ddf, .write_init_super = write_init_super_ddf, .add_to_super = add_to_super_ddf, + .load_container = load_container_ddf, #endif .match_home = match_home_ddf, .uuid_from_super= uuid_from_super_ddf,