diff options
author | Neil Brown <neilb@suse.de> | 2008-07-12 20:27:40 +1000 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2008-07-12 20:27:40 +1000 |
commit | edd8d13c0247b8df5876a94c2d61d74d2cf62c7e (patch) | |
tree | 77b53caceb67a989f19811044ce15a61a76bcd28 /super-ddf.c | |
parent | bfa44e2e7afb88a9f2d6083f8ff31c2d50cc78dc (diff) | |
download | mdadm-edd8d13c0247b8df5876a94c2d61d74d2cf62c7e.tar.gz mdadm-edd8d13c0247b8df5876a94c2d61d74d2cf62c7e.tar.xz mdadm-edd8d13c0247b8df5876a94c2d61d74d2cf62c7e.zip |
Create arrays via metadata-update
Support creating arrays inside an active ddf container by
sending a metadata update over a pipe to mdmon.
Diffstat (limited to 'super-ddf.c')
-rw-r--r-- | super-ddf.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/super-ddf.c b/super-ddf.c index f3a7904..aefe25e 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2122,7 +2122,32 @@ static int __write_init_super_ddf(struct supertype *st, int do_close) static int write_init_super_ddf(struct supertype *st) { - return __write_init_super_ddf(st, 1); + + if (st->update_tail) { + /* queue the virtual_disk and vd_config as metadata updates */ + struct virtual_disk *vd; + struct vd_config *vc; + struct ddf_super *ddf = st->sb; + int len; + + /* First the virtual disk. We have a slightly fake header */ + len = sizeof(struct virtual_disk) + sizeof(struct virtual_entry); + vd = malloc(len); + *vd = *ddf->virt; + vd->entries[0] = ddf->virt->entries[ddf->currentconf->vcnum]; + vd->populated_vdes = __cpu_to_be16(ddf->currentconf->vcnum); + append_metadata_update(st, vd, len); + + /* Then the vd_config */ + len = ddf->conf_rec_len * 512; + vc = malloc(len); + memcpy(vc, &ddf->currentconf->conf, len); + append_metadata_update(st, vc, len); + + /* FIXME I need to close the fds! */ + return 0; + } else + return __write_init_super_ddf(st, 1); } #endif @@ -2812,7 +2837,7 @@ static void ddf_process_update(struct supertype *st, printf("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) + if (update->len != ddf->conf_rec_len * 512) return; vc = (struct vd_config*)update->buf; for (vcl = ddf->conflist; vcl ; vcl = vcl->next) @@ -2830,7 +2855,7 @@ static void ddf_process_update(struct supertype *st, vcl = update->space; update->space = NULL; vcl->next = ddf->conflist; - vcl->conf = *vc; + memcpy(&vcl->conf, vc, update->len); vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[mppe]; ddf->conflist = vcl; @@ -2876,6 +2901,20 @@ static void ddf_process_update(struct supertype *st, } } +static void ddf_prepare_update(struct supertype *st, + struct metadata_update *update) +{ + /* This update arrived at managemon. + * We are about to pass it to monitor. + * If a malloc is needed, do it here. + */ + 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); +} + /* * Check if the array 'a' is degraded but not failed. * If it is, find as many spares as are available and needed and @@ -3106,6 +3145,7 @@ struct superswitch super_ddf = { .set_disk = ddf_set_disk, .sync_metadata = ddf_sync_metadata, .process_update = ddf_process_update, + .prepare_update = ddf_prepare_update, .activate_spare = ddf_activate_spare, }; |