summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-07-12 20:27:40 +1000
committerNeil Brown <neilb@suse.de>2008-07-12 20:27:40 +1000
commitedd8d13c0247b8df5876a94c2d61d74d2cf62c7e (patch)
tree77b53caceb67a989f19811044ce15a61a76bcd28
parentbfa44e2e7afb88a9f2d6083f8ff31c2d50cc78dc (diff)
downloadmdadm-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.
-rw-r--r--Create.c17
-rw-r--r--managemon.c22
-rw-r--r--mdadm.h14
-rw-r--r--mdmon.h6
-rw-r--r--super-ddf.c46
-rw-r--r--util.c43
6 files changed, 128 insertions, 20 deletions
diff --git a/Create.c b/Create.c
index fe93238..f4567ca 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 1917218..03de9a8 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 08b7868..5e2cfe4 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 4038533..02cdb09 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 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,
};
diff --git a/util.c b/util.c
index 4cecd6d..49c36a0 100644
--- a/util.c
+++ b/util.c
@@ -29,7 +29,9 @@
#include "mdadm.h"
#include "md_p.h"
+#include <sys/socket.h>
#include <sys/utsname.h>
+#include <sys/un.h>
#include <ctype.h>
#include <dirent.h>
#include <signal.h>
@@ -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 ... */