Create arrays via metadata-update

Support creating arrays inside an active ddf container by
sending a metadata update over a pipe to mdmon.
This commit is contained in:
Neil Brown 2008-07-12 20:27:40 +10:00
parent bfa44e2e7a
commit edd8d13c02
6 changed files with 128 additions and 20 deletions

View File

@ -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);

View File

@ -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);

14
mdadm.h
View File

@ -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);

View File

@ -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

View File

@ -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,
};

43
util.c
View File

@ -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 ... */