#include <errno.h>
#include <string.h>
#include <fcntl.h>
+#include <signal.h>
#include <sched.h>
#include "mdadm.h"
#include "mdmon.h"
-struct active_array *array_list;
struct active_array *discard_this;
struct active_array *pending_discard;
+struct md_generic_cmd *active_cmd;
int run_child(void *v)
{
struct supertype *c = v;
+ sigset_t set;
+ /* SIGUSR is sent from child to parent, So child must block it */
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
do_monitor(c);
return 0;
}
int clone_monitor(struct supertype *container)
{
- int pfd[2];
static char stack[4096];
int rv;
- pipe(container->pipe);
+ rv = pipe(container->mgr_pipe);
+ if (rv < 0)
+ return rv;
+ rv = pipe(container->mon_pipe);
+ if (rv < 0)
+ goto err_mon_pipe;
rv = clone(run_child, stack+4096-64,
CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
container);
-
if (rv < 0)
+ goto err_clone;
+ else
return rv;
- return pfd[1];
+
+ err_clone:
+ close(container->mon_pipe[0]);
+ close(container->mon_pipe[1]);
+ err_mon_pipe:
+ close(container->mgr_pipe[0]);
+ close(container->mgr_pipe[1]);
+
+ return rv;
}
static struct superswitch *find_metadata_methods(char *vers)
}
-static int make_pidfile(char *devname)
+static int make_pidfile(char *devname, int o_excl)
{
char path[100];
char pid[10];
int fd;
sprintf(path, "/var/run/mdadm/%s.pid", devname);
- fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600);
+ fd = open(path, O_RDWR|O_CREAT|o_excl, 0600);
if (fd < 0)
return -1;
sprintf(pid, "%d\n", getpid());
return 0;
}
+static void try_kill_monitor(char *devname)
+{
+ char buf[100];
+ int fd;
+ pid_t pid;
+
+ 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);
+
+ /* kill this process if it is mdmon */
+ sprintf(buf, "/proc/%lu/cmdline", (unsigned long) pid);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return;
+
+ if (read(fd, buf, sizeof(buf)) < 0) {
+ close(fd);
+ return;
+ }
+
+ if (strstr(buf, "mdmon") != NULL)
+ kill(pid, SIGTERM);
+}
+
+void remove_pidfile(char *devname)
+{
+ char buf[100];
+
+ sprintf(buf, "/var/run/mdadm/%s.pid", devname);
+ unlink(buf);
+}
+
static int make_control_sock(char *devname)
{
char path[100];
int main(int argc, char *argv[])
{
int mdfd;
- int pipefd;
struct mdinfo *mdi, *di;
struct supertype *container;
if (argc != 2) {
/* hopefully it is a container - we'll check later */
container = malloc(sizeof(*container));
- container->devfd = mdfd;
container->devnum = fd2devnum(mdfd);
container->devname = devnum2devname(container->devnum);
+ container->device_name = argv[1];
/* If this fails, we hope it already exists */
mkdir("/var/run/mdadm", 0600);
/* pid file lives in /var/run/mdadm/mdXX.pid */
- if (make_pidfile(container->devname) < 0) {
- fprintf(stderr, "md-manage: %s already managed\n",
- container->devname);
- exit(3);
+ if (make_pidfile(container->devname, O_EXCL) < 0) {
+ if (ping_monitor(container->devname) == 0) {
+ fprintf(stderr, "mdmon: %s already managed\n",
+ container->devname);
+ exit(3);
+ } else {
+ /* cleanup the old monitor, this one is taking over */
+ try_kill_monitor(container->devname);
+ if (make_pidfile(container->devname, 0) < 0) {
+ fprintf(stderr, "mdmon: %s Cannot create pidfile\n",
+ container->devname);
+ exit(3);
+ }
+ }
}
container->sock = make_control_sock(container->devname);
argv[1]);
exit(3);
}
-
+ close(mdfd);
+ close(mdfd);
mlockall(MCL_FUTURE);
- pipefd = clone_monitor(container);
- if (pipefd < 0) {
+ if (clone_monitor(container) < 0) {
fprintf(stderr, "md-manage: failed to start monitor process: %s\n",
strerror(errno));
exit(2);