From: Neil Brown Date: Sat, 12 Jul 2008 10:27:40 +0000 (+1000) Subject: Create arrays via metadata-update X-Git-Tag: mdadm-3.0-devel1~136 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=edd8d13c0247b8df5876a94c2d61d74d2cf62c7e;hp=bfa44e2e7afb88a9f2d6083f8ff31c2d50cc78dc Create arrays via metadata-update Support creating arrays inside an active ddf container by sending a metadata update over a pipe to mdmon. --- diff --git a/Create.c b/Create.c index fe932387..f4567ca3 100644 --- a/Create.c +++ b/Create.c @@ -573,12 +573,13 @@ int Create(struct supertype *st, char *mddev, int mdfd, return 1; } if (mdmon_running(st->container_dev)) { - fprintf(stderr, Name ": mdmon already running " - "for %s - sorry\n", - devnum2devname(st->container_dev)); - return 1; - } - need_mdmon = 1; + if (verbose) + fprintf(stderr, Name ": reusing mdmon " + "for %s.\n", + devnum2devname(st->container_dev)); + st->update_tail = &st->updates; + } else + need_mdmon = 1; } if ((vers % 100) < 2 || sra == NULL || @@ -707,8 +708,10 @@ int Create(struct supertype *st, char *mddev, int mdfd, } if (dv == moved_disk && dnum != insert_point) break; } - if (pass == 1) + if (pass == 1) { st->ss->write_init_super(st); + flush_metadata_updates(st); + } } free(infos); st->ss->free_super(st); diff --git a/managemon.c b/managemon.c index 19172182..03de9a89 100644 --- a/managemon.c +++ b/managemon.c @@ -428,9 +428,25 @@ void manage(struct mdstat_ent *mdstat, struct supertype *container) } } -static int handle_message(struct supertype *container, struct metadata_update *msg) +static void handle_message(struct supertype *container, struct metadata_update *msg) { - return -1; + /* queue this metadata update through to the monitor */ + + struct metadata_update *mu; + + if (msg->len == 0) { + wait_update_handled(); + } else { + mu = malloc(sizeof(*mu)); + mu->len = msg->len; + mu->buf = msg->buf; + msg->buf = NULL; + mu->space = NULL; + mu->next = NULL; + if (container->ss->prepare_update) + container->ss->prepare_update(container, mu); + queue_metadata_update(mu); + } } void read_sock(struct supertype *container) @@ -460,8 +476,6 @@ void read_sock(struct supertype *container) } else terminate = 1; - if (msg.buf) - free(msg.buf); } while (!terminate); close(fd); diff --git a/mdadm.h b/mdadm.h index 08b78689..5e2cfe41 100644 --- a/mdadm.h +++ b/mdadm.h @@ -542,6 +542,8 @@ extern struct superswitch { void (*sync_metadata)(struct supertype *st); void (*process_update)(struct supertype *st, struct metadata_update *update); + void (*prepare_update)(struct supertype *st, + struct metadata_update *update); /* activate_spare will check if the array is degraded and, if it * is, try to find some spare space in the container. @@ -559,6 +561,13 @@ extern struct superswitch { extern struct superswitch super_imsm; +struct metadata_update { + int len; + char *buf; + void *space; /* allocated space that monitor will use */ + struct metadata_update *next; +}; + /* A supertype holds a particular collection of metadata. * It identifies the metadata type by the superswitch, and the particular * sub-version of that metadata type. @@ -579,6 +588,9 @@ struct supertype { void *sb; void *info; + struct metadata_update *updates; + struct metadata_update **update_tail; + /* extra stuff used by mdmon */ struct active_array *arrays; int sock; /* listen to external programs */ @@ -738,6 +750,8 @@ extern unsigned long long get_component_size(int fd); extern void remove_partitions(int fd); extern unsigned long long calc_array_size(int level, int raid_disks, int layout, int chunksize, unsigned long long devsize); +extern int flush_metadata_updates(struct supertype *st); +extern void append_metadata_update(struct supertype *st, void *buf, int len); extern char *human_size(long long bytes); diff --git a/mdmon.h b/mdmon.h index 40385337..02cdb094 100644 --- a/mdmon.h +++ b/mdmon.h @@ -41,12 +41,6 @@ struct active_array { * superswitch. All common code sees them as opaque * blobs. */ -struct metadata_update { - int len; - char *buf; - void *space; /* allocated space that monitor will use */ - struct metadata_update *next; -}; extern struct metadata_update *update_queue, *update_queue_handled; #define MD_MAJOR 9 diff --git a/super-ddf.c b/super-ddf.c index f3a7904e..aefe25ef 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, }; diff --git a/util.c b/util.c index 4cecd6d0..49c36a06 100644 --- a/util.c +++ b/util.c @@ -29,7 +29,9 @@ #include "mdadm.h" #include "md_p.h" +#include #include +#include #include #include #include @@ -1065,6 +1067,47 @@ int signal_mdmon(int devnum) } +int flush_metadata_updates(struct supertype *st) +{ + int sfd; + if (!st->updates) { + st->update_tail = NULL; + return -1; + } + + sfd = connect_monitor(devnum2devname(st->container_dev)); + if (sfd < 0) + return -1; + + while (st->updates) { + struct metadata_update *mu = st->updates; + st->updates = mu->next; + + send_message(sfd, mu, 0); + wait_reply(sfd, 0); + free(mu->buf); + free(mu); + } + ack(sfd, 0); + wait_reply(sfd, 0); + close(sfd); + st->update_tail = NULL; + return 0; +} + +void append_metadata_update(struct supertype *st, void *buf, int len) +{ + + struct metadata_update *mu = malloc(sizeof(*mu)); + + mu->buf = buf; + mu->len = len; + mu->space = NULL; + mu->next = NULL; + *st->update_tail = mu; + st->update_tail = &mu->next; +} + #ifdef __TINYC__ /* tinyc doesn't optimize this check in ioctl.h out ... */