From a931db9ed7c40eca0676794f145e3e5308b0bdd7 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 27 May 2008 09:18:42 +1000 Subject: [PATCH] auto-start mdmon on --create FIXME uses sill hardcoded path. Need --assemble too. --- Create.c | 53 +++++++++++++++++++++++++++++++++++++++ mdadm.h | 19 ++++++++++++++ util.c | 75 ++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 132 insertions(+), 15 deletions(-) diff --git a/Create.c b/Create.c index ee73548d..59a41a66 100644 --- a/Create.c +++ b/Create.c @@ -71,6 +71,8 @@ int Create(struct supertype *st, char *mddev, int mdfd, int rv; int bitmap_fd; int have_container = 0; + int container_fd; + int need_mdmon = 0; unsigned long long bitmapsize; struct mdinfo *sra; struct mdinfo info; @@ -545,6 +547,31 @@ int Create(struct supertype *st, char *mddev, int mdfd, sprintf(ver, "external:/%s/%d", devnum2devname(st->container_dev), st->container_member); + /* When creating a member, we need to be careful + * to negotiate with mdmon properly. + * If it is already running, we cannot write to + * the devices and must ask it to do that part. + * If it isn't running, we write to the devices, + * and then start it. + * We hold an exclusive open on the container + * device to make sure mdmon doesn't exit after + * we checked that it is running. + * + * For now, fail if it is already running. + */ + container_fd = open_dev_excl(st->container_dev); + if (container_fd < 0) { + fprintf(stderr, Name ": Cannot get exclusive " + "open on container - weird.\n"); + 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 ((vers % 100) < 2 || sra == NULL || @@ -681,6 +708,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, case 0: sysfs_set_str(sra, NULL, "array_state", "active"); + need_mdmon = 0; break; default: sysfs_set_str(sra, NULL, "array_state", @@ -698,6 +726,31 @@ int Create(struct supertype *st, char *mddev, int mdfd, } if (verbose >= 0) fprintf(stderr, Name ": array %s started.\n", mddev); + if (st->ss->external == 2) { + if (need_mdmon) { + int dn = st->container_dev; + int i; + switch(fork()) { + case 0: + /* FIXME yuk. CLOSE_EXEC?? */ + for (i=3; i < 100; i++) + close(i); + execl("./mdmon", "mdmon", + map_dev(dev2major(dn), + dev2minor(dn), + 1), NULL); + exit(1); + case -1: fprintf(stderr, Name ": cannot fork. " + "Array remains readonly\n"); + return 1; + default: ; /* parent - good */ + } + } else + signal_mdmon(st->container_dev); + /* FIXME wait for mdmon to set array to read-auto */ + sleep(1); + close(container_fd); + } } else { fprintf(stderr, Name ": not starting array - not enough devices.\n"); } diff --git a/mdadm.h b/mdadm.h index 5586dce4..bf7e2967 100644 --- a/mdadm.h +++ b/mdadm.h @@ -584,6 +584,7 @@ extern int check_raid(int fd, char *name); extern int get_mdp_major(void); extern int dev_open(char *dev, int flags); +extern int open_dev_excl(int devnum); extern int is_standard(char *dev, int *nump); extern int parse_auto(char *str, char *msg, int config); @@ -629,9 +630,27 @@ extern int open_mddev_devnum(char *devname, int devnum, char *name, char *chosen_name, int parts); extern int open_container(int fd); +extern int mdmon_running(int devnum); +extern int signal_mdmon(int devnum); + extern char *devnum2devname(int num); extern int fd2devnum(int fd); +static inline int dev2major(int d) +{ + if (d >= 0) + return MD_MAJOR; + else + return get_mdp_major(); +} + +static inline int dev2minor(int d) +{ + if (d >= 0) + return d; + return (-1-d) << MdpMinorShift; +} + #define LEVEL_MULTIPATH (-4) #define LEVEL_LINEAR (-1) #define LEVEL_FAULTY (-5) diff --git a/util.c b/util.c index d026c302..6f1620a6 100644 --- a/util.c +++ b/util.c @@ -32,6 +32,7 @@ #include #include #include +#include /* * following taken from linux/blkpg.h because they aren't @@ -714,21 +715,6 @@ void put_md_name(char *name) unlink(name); } -static int dev2major(int d) -{ - if (d >= 0) - return MD_MAJOR; - else - return get_mdp_major(); -} - -static int dev2minor(int d) -{ - if (d >= 0) - return d; - return (-1-d) << MdpMinorShift; -} - int find_free_devnum(int use_partitions) { int devnum; @@ -781,6 +767,23 @@ int dev_open(char *dev, int flags) return fd; } +int open_dev_excl(int devnum) +{ + char buf[20]; + int i; + + sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum)); + for (i=0 ; i<25 ; i++) { + int fd = dev_open(buf, O_RDWR|O_EXCL); + if (fd >= 0) + return fd; + if (errno != EBUSY) + return fd; + usleep(200000); + } + return -1; +} + struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL }; #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) @@ -1009,6 +1012,48 @@ int fd2devnum(int fd) return -1; } +int mdmon_running(int devnum) +{ + char path[100]; + char pid[10]; + int fd; + int n; + sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum)); + fd = open(path, O_RDONLY, 0); + + if (fd < 0) + return 0; + n = read(fd, pid, 9); + close(fd); + if (n <= 0) + return 0; + if (kill(atoi(pid), 0) == 0) + return 1; + return 0; +} + +int signal_mdmon(int devnum) +{ + char path[100]; + char pid[10]; + int fd; + int n; + sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum)); + fd = open(path, O_RDONLY, 0); + + if (fd < 0) + return 0; + n = read(fd, pid, 9); + close(fd); + if (n <= 0) + return 0; + if (kill(atoi(pid), SIGUSR1) == 0) + return 1; + return 0; +} + + + #ifdef __TINYC__ /* tinyc doesn't optimize this check in ioctl.h out ... */ unsigned int __invalid_size_argument_for_IOC = 0; -- 2.39.2