Merge git://github.com/djbw/mdadm

This commit is contained in:
NeilBrown 2009-10-19 12:52:58 +11:00
commit 5d504f4278
14 changed files with 784 additions and 293 deletions

View File

@ -565,6 +565,7 @@ int Assemble(struct supertype *st, char *mddev,
#endif
/* Ok, no bad inconsistancy, we can try updating etc */
bitmap_done = 0;
content->update_private = NULL;
for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
char *devname = tmpdev->devname;
struct stat stb;
@ -717,6 +718,8 @@ int Assemble(struct supertype *st, char *mddev,
}
devcnt++;
}
free(content->update_private);
content->update_private = NULL;
if (devcnt == 0) {
fprintf(stderr, Name ": no devices found for %s\n",

View File

@ -194,7 +194,12 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
st->ss->export_detail_super(st);
} else {
struct map_ent *mp, *map = NULL;
char nbuf[64];
mp = map_by_devnum(&map, fd2devnum(fd));
if (mp) {
__fname_from_uuid(mp->uuid, 0, nbuf, ':');
printf("MD_UUID=%s\n", nbuf+5);
}
if (mp && mp->path &&
strncmp(mp->path, "/dev/md/", 8) == 0)
printf("MD_DEVNAME=%s\n", mp->path+8);

View File

@ -680,6 +680,12 @@ void do_manager(struct supertype *container)
read_sock(container);
if (container->sock < 0 || socket_hup_requested) {
/* If this fails, we hope it already exists
* pid file lives in /var/run/mdadm/mdXX.pid
*/
mkdir("/var", 0600);
mkdir("/var/run", 0600);
mkdir("/var/run/mdadm", 0600);
close(container->sock);
container->sock = make_control_sock(container->devname);
make_pidfile(container->devname, 0);

View File

@ -1276,7 +1276,7 @@ int main(int argc, char *argv[])
export, test,
homehost);
else
rv |= WaitClean(name, v);
rv |= WaitClean(name, -1, v);
put_md_name(name);
}
free_mdstat(ms);
@ -1337,7 +1337,7 @@ int main(int argc, char *argv[])
case 'W':
rv |= Wait(dv->devname); continue;
case Waitclean:
rv |= WaitClean(dv->devname, verbose-quiet); continue;
rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
}
mdfd = open_mddev(dv->devname, 1);
if (mdfd>=0) {

View File

@ -153,6 +153,11 @@ struct mdinfo {
int cache_size; /* size of raid456 stripe cache*/
int mismatch_cnt;
char text_version[50];
void *update_private; /* for passing metadata-format
* specific update data
* between successive calls to
* update_super()
*/
int container_member; /* for assembling external-metatdata arrays
* This is to be used internally by metadata
@ -748,7 +753,7 @@ extern int Monitor(mddev_dev_t devlist,
extern int Kill(char *dev, int force, int quiet, int noexcl);
extern int Wait(char *dev);
extern int WaitClean(char *dev, int verbose);
extern int WaitClean(char *dev, int sock, int verbose);
extern int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost,
@ -805,6 +810,7 @@ extern void uuid_from_super(int uuid[4], mdp_super_t *super);
extern const int uuid_match_any[4];
extern int same_uuid(int a[4], int b[4], int swapuuid);
extern void copy_uuid(void *a, int b[4], int swapuuid);
extern char *__fname_from_uuid(int id[4], int swap, char *buf, char sep);
extern char *fname_from_uuid(struct supertype *st,
struct mdinfo *info, char *buf, char sep);
extern unsigned long calc_csum(void *super, int bytes);

115
mdmon.c
View File

@ -113,6 +113,14 @@ static struct superswitch *find_metadata_methods(char *vers)
return NULL;
}
static int test_pidfile(char *devname)
{
char path[100];
struct stat st;
sprintf(path, "/var/run/mdadm/%s.pid", devname);
return stat(path, &st);
}
int make_pidfile(char *devname, int o_excl)
{
@ -149,27 +157,30 @@ int is_container_member(struct mdstat_ent *mdstat, char *container)
return 1;
}
void remove_pidfile(char *devname);
static void try_kill_monitor(char *devname)
pid_t devname2mdmon(char *devname)
{
char buf[100];
pid_t pid = -1;
int fd;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
fd = open(buf, O_RDONLY|O_NOATIME);
if (fd < 0)
return -1;
if (read(fd, buf, sizeof(buf)) > 0)
sscanf(buf, "%d\n", &pid);
close(fd);
return pid;
}
static void try_kill_monitor(pid_t pid, char *devname, int sock)
{
char buf[100];
int fd;
pid_t pid;
struct mdstat_ent *mdstat;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
fd = open(buf, O_RDONLY);
if (fd < 0)
return;
if (read(fd, buf, sizeof(buf)) < 0) {
close(fd);
return;
}
close(fd);
pid = strtoul(buf, NULL, 10);
/* first rule of survival... don't off yourself */
if (pid == getpid())
return;
@ -194,10 +205,9 @@ static void try_kill_monitor(char *devname)
for ( ; mdstat; mdstat = mdstat->next)
if (is_container_member(mdstat, devname)) {
sprintf(buf, "/dev/%s", mdstat->dev);
WaitClean(buf, 0);
WaitClean(buf, sock, 0);
}
free_mdstat(mdstat);
remove_pidfile(devname);
}
void remove_pidfile(char *devname)
@ -355,9 +365,34 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
int pfd[2];
int status;
int ignore;
pid_t victim = -1;
int victim_sock = -1;
dprintf("starting mdmon for %s in %s\n",
devname, switchroot ? : "/");
/* try to spawn mdmon instances from the target file system */
if (switchroot && strcmp(switchroot, "/") != 0) {
char path[1024];
pid_t pid;
sprintf(path, "%s/sbin/mdmon", switchroot);
switch (fork()) {
case 0:
execl(path, "mdmon", devname, NULL);
exit(1);
case -1:
return 1;
default:
pid = wait(&status);
if (pid > -1 && WIFEXITED(status) &&
WEXITSTATUS(status) == 0)
return 0;
else
return 1;
}
}
mdfd = open_dev(devnum);
if (mdfd < 0) {
fprintf(stderr, "mdmon: %s: %s\n", devname,
@ -400,6 +435,7 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
container->devname = devname;
container->arrays = NULL;
container->subarray[0] = 0;
container->sock = -1;
if (!container->devname) {
fprintf(stderr, "mdmon: failed to allocate container name string\n");
@ -464,12 +500,10 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
if (switchroot) {
/* we assume we assume that /sys /proc /dev are available in
* the new root (see nash:setuproot)
*
* kill any monitors in the current namespace and change
* to the new one
* the new root
*/
try_kill_monitor(container->devname);
victim = devname2mdmon(container->devname);
victim_sock = connect_monitor(container->devname);
if (chroot(switchroot) != 0) {
fprintf(stderr, "mdmon: failed to chroot to '%s': %s\n",
switchroot, strerror(errno));
@ -477,40 +511,15 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
}
}
/* If this fails, we hope it already exists
* pid file lives in /var/run/mdadm/mdXX.pid
*/
mkdir("/var", 0600);
mkdir("/var/run", 0600);
mkdir("/var/run/mdadm", 0600);
ignore = chdir("/");
if (make_pidfile(container->devname, O_EXCL) < 0) {
if (victim < 0 && test_pidfile(container->devname) == 0) {
if (ping_monitor(container->devname) == 0) {
fprintf(stderr, "mdmon: %s already managed\n",
container->devname);
exit(3);
} else {
int err;
/* cleanup the old monitor, this one is taking over */
try_kill_monitor(container->devname);
err = make_pidfile(container->devname, 0);
if (err < 0) {
fprintf(stderr, "mdmon: %s Cannot create pidfile\n",
container->devname);
if (err == -EROFS) {
/* FIXME implement a mechanism to
* prevent duplicate monitor instances
*/
fprintf(stderr,
"mdmon: continuing on read-only file system\n");
} else
exit(3);
}
}
} else if (victim < 0)
victim = devname2mdmon(container->devname);
}
container->sock = make_control_sock(container->devname);
if (container->ss->load_super(container, mdfd, devname)) {
fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
devname);
@ -544,6 +553,10 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
exit(2);
}
if (victim > -1) {
try_kill_monitor(victim, container->devname, victim_sock);
close(victim_sock);
}
do_manager(container);
exit(0);

14
msg.c
View File

@ -177,10 +177,8 @@ int connect_monitor(char *devname)
return sfd;
}
/* give the monitor a chance to update the metadata */
int ping_monitor(char *devname)
int fping_monitor(int sfd)
{
int sfd = connect_monitor(devname);
int err = 0;
if (sfd < 0)
@ -194,6 +192,16 @@ int ping_monitor(char *devname)
if (!err && wait_reply(sfd, 20) != 0)
err = -1;
return err;
}
/* give the monitor a chance to update the metadata */
int ping_monitor(char *devname)
{
int sfd = connect_monitor(devname);
int err = fping_monitor(sfd);
close(sfd);
return err;
}

1
msg.h
View File

@ -27,6 +27,7 @@ extern int ack(int fd, int tmo);
extern int wait_reply(int fd, int tmo);
extern int connect_monitor(char *devname);
extern int ping_monitor(char *devname);
extern int fping_monitor(int sock);
extern int ping_manager(char *devname);
#define MSG_MAX_LEN (4*1024*1024)

View File

@ -1589,13 +1589,8 @@ static int init_super_ddf(struct supertype *st,
struct phys_disk *pd;
struct virtual_disk *vd;
if (!info) {
st->sb = NULL;
return 0;
}
if (st->sb)
return init_super_ddf_bvd(st, info, size, name, homehost,
uuid);
return init_super_ddf_bvd(st, info, size, name, homehost, uuid);
if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) {
fprintf(stderr, Name ": %s could not allocate superblock\n", __func__);
@ -1604,6 +1599,12 @@ static int init_super_ddf(struct supertype *st,
memset(ddf, 0, sizeof(*ddf));
ddf->dlist = NULL; /* no physical disks yet */
ddf->conflist = NULL; /* No virtual disks yet */
st->sb = ddf;
if (info == NULL) {
/* zeroing superblock */
return 0;
}
/* At least 32MB *must* be reserved for the ddf. So let's just
* start 32MB from the end, and put the primary header there.
@ -2971,12 +2972,22 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
return rest;
}
static int store_zero_ddf(struct supertype *st, int fd)
static int store_super_ddf(struct supertype *st, int fd)
{
struct ddf_super *ddf = st->sb;
unsigned long long dsize;
void *buf;
int rc;
if (!ddf)
return 1;
/* ->dlist and ->conflist will be set for updates, currently not
* supported
*/
if (ddf->dlist || ddf->conflist)
return 1;
if (!get_dev_size(fd, NULL, &dsize))
return 1;
@ -3627,7 +3638,7 @@ struct superswitch super_ddf = {
.load_super = load_super_ddf,
.init_super = init_super_ddf,
.store_super = store_zero_ddf,
.store_super = store_super_ddf,
.free_super = free_super_ddf,
.match_metadata_desc = match_metadata_desc_ddf,
.container_content = container_content_ddf,

File diff suppressed because it is too large Load Diff

View File

@ -764,7 +764,7 @@ int sysfs_unique_holder(int devnum, long rdev)
static char *clean_states[] = {
"clear", "inactive", "readonly", "read-auto", "clean", NULL };
int WaitClean(char *dev, int verbose)
int WaitClean(char *dev, int sock, int verbose)
{
int fd;
struct mdinfo *mdi;
@ -840,7 +840,8 @@ int WaitClean(char *dev, int verbose)
}
if (rv < 0)
rv = 1;
else if (ping_monitor(mdi->text_version) == 0) {
else if (fping_monitor(sock) == 0 ||
ping_monitor(mdi->text_version) == 0) {
/* we need to ping to close the window between array
* state transitioning to clean and the metadata being
* marked clean

46
tests/09imsm-assemble Normal file
View File

@ -0,0 +1,46 @@
# validate the prodigal member disk scenario i.e. a former container
# member is returned after having been rebuilt on another system
num_disks=4
size=$((10*1024))
mdadm -CR $container -e imsm -n $num_disks $dev0 $dev1 $dev2 $dev3
mdadm -CR $member $dev0 $dev2 -n 2 -l 1 -z $size
mdadm --wait $member
mdadm -Ss
# make dev0 and dev1 a new rebuild family
mdadm -A $container $dev0 $dev1
mdadm -I $container
mdadm --wait ${member}_0
mdadm -Ss
# make dev2 and dev3 a new rebuild family
mdadm -A $container $dev2 $dev3
mdadm -I $container
mdadm --wait ${member}_0
mdadm -Ss
# reassemble and make sure one of the families falls out
mdadm -A $container $dev0 $dev1 $dev2 $dev3
mdadm -I $container
testdev ${member}_0 1 $size 1
if mdadm --remove $container $dev0 ; then
# the dev[23] family won
imsm_check_removal $container $dev1
imsm_check_hold $container $dev2
imsm_check_hold $container $dev3
else
# the dev[01] family won
imsm_check_hold $container $dev1
imsm_check_removal $container $dev2
imsm_check_removal $container $dev3
fi
mdadm -Ss
# reassemble with a new id for the dev[23] family
mdadm -A $container $dev0 $dev1
mdadm -I $container
mdadm -A ${container}2 $dev2 $dev3 --update=uuid
mdadm -I ${container}2
testdev ${member}_0 1 $size 1
testdev ${member}_1 1 $size 1

32
tests/env-09imsm-assemble Normal file
View File

@ -0,0 +1,32 @@
imsm_check_hold() {
if mdadm --remove $1 $2; then
echo "$2 removal from $1 should have been blocked" >&2
cat /proc/mdstat >&2
mdadm -E $2
exit 1
fi
}
imsm_check_removal() {
if ! mdadm --remove $1 $2 ; then
echo "$2 removal from $1 should have succeeded" >&2
cat /proc/mdstat >&2
mdadm -E $2
exit 1
fi
}
setup_env() {
export IMSM_DEVNAME_AS_SERIAL=1
export IMSM_TEST_OROM=1
container=/dev/md/container
member=/dev/md/vol0
}
reset_env() {
unset IMSM_DEVNAME_AS_SERIAL
unset IMSM_TEST_OROM
unset imsm_check
unset container
unset member
}

12
util.c
View File

@ -269,17 +269,15 @@ void copy_uuid(void *a, int b[4], int swapuuid)
memcpy(a, b, 16);
}
char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep)
char *__fname_from_uuid(int id[4], int swap, char *buf, char sep)
{
int i, j;
int id;
char uuid[16];
char *c = buf;
strcpy(c, "UUID-");
c += strlen(c);
copy_uuid(uuid, info->uuid, st->ss->swapuuid);
copy_uuid(uuid, id, swap);
for (i = 0; i < 4; i++) {
id = uuid[i];
if (i)
*c++ = sep;
for (j = 3; j >= 0; j--) {
@ -288,6 +286,12 @@ char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char
}
}
return buf;
}
char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep)
{
return __fname_from_uuid(info->uuid, st->ss->swapuuid, buf, sep);
}
#ifndef MDASSEMBLE