int mon_tid, mgr_tid;
+int sigterm;
+
int run_child(void *v)
{
struct supertype *c = v;
}
-static int make_pidfile(char *devname, int o_excl)
+int make_pidfile(char *devname, int o_excl)
{
char path[100];
char pid[10];
int fd;
+ int n;
+
+ if (sigterm)
+ return -1;
+
sprintf(path, "/var/run/mdadm/%s.pid", devname);
fd = open(path, O_RDWR|O_CREAT|o_excl, 0600);
if (fd < 0)
- return -1;
+ return -errno;
sprintf(pid, "%d\n", getpid());
- write(fd, pid, strlen(pid));
+ n = write(fd, pid, strlen(pid));
close(fd);
+ if (n < 0)
+ return -errno;
return 0;
}
{
char buf[100];
+ if (sigterm)
+ return;
+
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
unlink(buf);
+ sprintf(buf, "/var/run/mdadm/%s.sock", devname);
+ unlink(buf);
}
-static int make_control_sock(char *devname)
+int make_control_sock(char *devname)
{
char path[100];
int sfd;
long fl;
struct sockaddr_un addr;
+ if (sigterm)
+ return -1;
+
sprintf(path, "/var/run/mdadm/%s.sock", devname);
unlink(path);
sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
return sfd;
}
+int socket_hup_requested;
+static void hup(int sig)
+{
+ socket_hup_requested = 1;
+}
+
+static void term(int sig)
+{
+ sigterm = 1;
+}
+
static void wake_me(int sig)
{
struct sigaction act;
int pfd[2];
int status;
+ int ignore;
if (argc != 2) {
fprintf(stderr, "Usage: md-manage /device/name/for/container\n");
/* Fork, and have the child tell us when they are ready */
if (do_fork()) {
- pipe(pfd);
+ if (pipe(pfd) != 0) {
+ fprintf(stderr, "mdmon: failed to create pipe\n");
+ exit(1);
+ }
switch(fork()) {
case -1:
fprintf(stderr, "mdmon: failed to fork: %s\n",
container->devname);
exit(3);
} else {
+ int err;
+
/* cleanup the old monitor, this one is taking over */
try_kill_monitor(container->devname);
- if (make_pidfile(container->devname, 0) < 0) {
+ err = make_pidfile(container->devname, 0);
+ if (err < 0) {
fprintf(stderr, "mdmon: %s Cannot create pidfile\n",
container->devname);
- exit(3);
+ 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);
}
}
}
container->sock = make_control_sock(container->devname);
- if (container->sock < 0) {
- fprintf(stderr, "mdmon: Cannot create socket in /var/run/mdadm\n");
- exit(3);
- }
container->arrays = NULL;
mdi = sysfs_read(mdfd, container->devnum,
container->devs = NULL;
for (di = mdi->devs; di; di = di->next) {
struct mdinfo *cd = malloc(sizeof(*cd));
- cd = di;
+ *cd = *di;
cd->next = container->devs;
container->devs = cd;
}
/* Ok, this is close enough. We can say goodbye to our parent now.
*/
status = 0;
- write(pfd[1], &status, sizeof(status));
+ if (write(pfd[1], &status, sizeof(status)) < 0)
+ fprintf(stderr, "mdmon: failed to notify our parent: %d\n",
+ getppid());
close(pfd[1]);
- chdir("/");
+ ignore = chdir("/");
setsid();
close(0);
open("/dev/null", O_RDWR);
close(1);
- dup(0);
+ ignore = dup(0);
#ifndef DEBUG
close(2);
- dup(0);
+ ignore = dup(0);
#endif
mlockall(MCL_FUTURE);
*/
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
+ sigaddset(&set, SIGHUP);
+ sigaddset(&set, SIGALRM);
+ sigaddset(&set, SIGTERM);
sigprocmask(SIG_BLOCK, &set, NULL);
act.sa_handler = wake_me;
act.sa_flags = 0;
sigaction(SIGUSR1, &act, NULL);
+ sigaction(SIGALRM, &act, NULL);
+ act.sa_handler = hup;
+ sigaction(SIGHUP, &act, NULL);
+ act.sa_handler = term;
+ sigaction(SIGTERM, &act, NULL);
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
if (clone_monitor(container) < 0) {
- fprintf(stderr, "md-manage: failed to start monitor process: %s\n",
+ fprintf(stderr, "mdmon: failed to start monitor process: %s\n",
strerror(errno));
exit(2);
}