#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);
struct ddf_super *super;
int rv;
-#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)
- return 0;
-#endif
- if (st->subarray[0])
- return 1; /* FIXME Is this correct */
-
if (get_dev_size(fd, devname, &dsize) == 0)
return 1;
return rv;
}
- if (st->subarray[0]) {
- unsigned long val;
- struct vcl *v;
- char *ep;
-
- val = strtoul(st->subarray, &ep, 10);
- if (*ep != '\0') {
- free(super);
- return 1;
- }
-
- for (v = super->conflist; v; v = v->next)
- if (v->vcnum == val)
- super->currentconf = v;
- if (!super->currentconf) {
- free(super);
- return 1;
- }
- }
-
/* Should possibly check the sections .... */
st->sb = super;
st->minor_version = 0;
st->max_devs = 512;
}
- st->loaded_container = 0;
return 0;
}
free(d->spare);
free(d);
}
+ while (ddf->add_list) {
+ struct dl *d = ddf->add_list;
+ ddf->add_list = d->next;
+ if (d->fd >= 0)
+ close(d->fd);
+ if (d->spare)
+ free(d->spare);
+ free(d);
+ }
free(ddf);
st->sb = NULL;
}
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;
(type&8) ? "spare" : "",
(type&16)? ", foreign" : "",
(type&32)? "pass-through" : "");
+ if (state & DDF_Failed)
+ /* This over-rides these three */
+ state &= ~(DDF_Online|DDF_Rebuilding|DDF_Transition);
printf("/%s%s%s%s%s%s%s",
(state&1)? "Online": "Offline",
(state&2)? ", Failed": "",
examine_pds(sb);
}
-static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info);
+static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *map);
static void uuid_from_super_ddf(struct supertype *st, int uuid[4]);
*/
struct mdinfo info;
char nbuf[64];
- getinfo_super_ddf(st, &info);
+ getinfo_super_ddf(st, &info, NULL);
fname_from_uuid(st, &info, nbuf, ':');
printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
struct mdinfo info;
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++) {
{
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");
// 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);
}
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;
}
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 ?? */
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);
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;
+ }
+ }
}
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;
+ } else 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;
+ } else if (strcmp(update, "_reshape_progress") == 0) {
/* We don't support reshape yet */
- }
+ } else if (strcmp(update, "assemble") == 0 ) {
+ /* Do nothing, just succeed */
+ rv = 0;
+ } else
+ rv = -1;
// update_all_csum(ddf);
}
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;
static unsigned char null_conf[4096+512];
-static int __write_init_super_ddf(struct supertype *st, int do_close)
+static int __write_init_super_ddf(struct supertype *st)
{
struct ddf_super *ddf = st->sb;
successes++;
}
- if (do_close)
- for (d = ddf->dlist; d; d=d->next) {
- close(d->fd);
- d->fd = -1;
- }
-
return attempts != successes;
}
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);
+ return __write_init_super_ddf(st);
}
}
static int validate_geometry_ddf_bvd(struct supertype *st,
int level, int layout, int raiddisks,
- int chunk, unsigned long long size,
+ int *chunk, unsigned long long size,
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,
+ int *chunk, unsigned long long size,
char *dev, unsigned long long *freesize,
int verbose)
{
* If given BVDs, we make an SVD, changing all the GUIDs in the process.
*/
+ if (chunk && *chunk == UnSet)
+ *chunk = DEFAULT_CHUNK;
+
+
if (level == LEVEL_CONTAINER) {
/* Must be a fresh device to add to a container */
return validate_geometry_ddf_container(st, level, layout,
- raiddisks, chunk,
+ raiddisks, chunk?*chunk:0,
size, dev, freesize,
verbose);
}
* chosen so that add_to_super/getinfo_super
* can return them.
*/
- return reserve_space(st, raiddisks, size, chunk, freesize);
+ return reserve_space(st, raiddisks, size, chunk?*chunk:0, freesize);
}
return 1;
}
* 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);
static int validate_geometry_ddf_bvd(struct supertype *st,
int level, int layout, int raiddisks,
- int chunk, unsigned long long size,
+ int *chunk, unsigned long long size,
char *dev, unsigned long long *freesize,
int verbose)
{
}
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;
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]) {
- unsigned long val;
- struct vcl *v;
- char *ep;
-
- val = strtoul(st->subarray, &ep, 10);
- if (*ep != '\0') {
- free(super);
- return 1;
- }
-
- for (v = super->conflist; v; v = v->next)
- if (v->vcnum == val)
- super->currentconf = v;
- if (!super->currentconf) {
- free(super);
- 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->loaded_container = 1;
+ st->container_dev = fd2devnum(fd);
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
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;
return consistent;
}
+ #define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
/*
* The state of each disk is stored in the global phys_disk structure
* in phys_disk.entries[n].state.
struct vd_config *vc = find_vdcr(ddf, inst);
int pd = find_phys(ddf, vc->phys_refnum[n]);
int i, st, working;
+ struct mdinfo *mdi;
+ struct dl *dl;
if (vc == NULL) {
dprintf("ddf: cannot find instance %d!!\n", inst);
return;
}
- if (pd < 0) {
- /* disk doesn't currently exist. If it is now in_sync,
- * insert it. */
+ /* Find the matching slot in 'info'. */
+ for (mdi = a->info.devs; mdi; mdi = mdi->next)
+ if (mdi->disk.raid_disk == n)
+ break;
+ if (!mdi)
+ return;
+
+ /* and find the 'dl' entry corresponding to that. */
+ for (dl = ddf->dlist; dl; dl = dl->next)
+ if (mdi->disk.major == dl->major &&
+ mdi->disk.minor == dl->minor)
+ break;
+ if (!dl)
+ return;
+
+ if (pd < 0 || pd != dl->pdnum) {
+ /* disk doesn't currently exist or has changed.
+ * If it is now in_sync, insert it. */
if ((state & DS_INSYNC) && ! (state & DS_FAULTY)) {
- /* Find dev 'n' in a->info->devs, determine the
- * ddf refnum, and set vc->phys_refnum and update
- * phys->entries[]
- */
- /* FIXME */
+ struct vcl *vcl;
+ pd = dl->pdnum;
+ vc->phys_refnum[n] = dl->disk.refnum;
+ vcl = container_of(vc, struct vcl, conf);
+ vcl->lba_offset[n] = mdi->data_offset;
+ ddf->phys->entries[pd].type &=
+ ~__cpu_to_be16(DDF_Global_Spare);
+ ddf->phys->entries[pd].type |=
+ __cpu_to_be16(DDF_Active_in_VD);
+ ddf->updates_pending = 1;
}
} else {
int old = ddf->phys->entries[pd].state;
if (!ddf->updates_pending)
return;
ddf->updates_pending = 0;
- __write_init_super_ddf(st, 0);
+ __write_init_super_ddf(st);
dprintf("ddf: sync_metadata\n");
}
memcpy(&vcl->conf, vc, update->len);
vcl->lba_offset = (__u64*)
&vcl->conf.phys_refnum[mppe];
+ for (ent = 0;
+ ent < __be16_to_cpu(ddf->virt->populated_vdes);
+ ent++)
+ if (memcmp(vc->guid, ddf->virt->entries[ent].guid,
+ DDF_GUID_LEN) == 0) {
+ vcl->vcnum = ent;
+ break;
+ }
ddf->conflist = vcl;
}
/* Now make sure vlist is correct for each dl. */
unsigned int j;
/* If in this array, skip */
for (d2 = a->info.devs ; d2 ; d2 = d2->next)
- if (d2->disk.major == dl->major &&
+ if (d2->state_fd >= 0 &&
+ d2->disk.major == dl->major &&
d2->disk.minor == dl->minor) {
dprintf("%x:%x already in array\n", dl->major, dl->minor);
break;
}
mu->buf = malloc(ddf->conf_rec_len * 512);
- mu->len = ddf->conf_rec_len;
+ mu->len = ddf->conf_rec_len * 512;
+ mu->space = NULL;
mu->next = *updates;
vc = find_vdcr(ddf, a->info.container_member);
memcpy(mu->buf, vc, ddf->conf_rec_len * 512);
}
}
+static void default_geometry_ddf(struct supertype *st, int *level, int *layout, int *chunk)
+{
+ if (level && *level == UnSet)
+ *level = LEVEL_CONTAINER;
+
+ if (level && layout && *layout == UnSet)
+ *layout = ddf_level_to_layout(*level);
+}
+
struct superswitch super_ddf = {
#ifndef MDASSEMBLE
.examine_super = examine_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,
.free_super = free_super_ddf,
.match_metadata_desc = match_metadata_desc_ddf,
.container_content = container_content_ddf,
- .default_layout = ddf_level_to_layout,
+ .default_geometry = default_geometry_ddf,
.external = 1,