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)
{
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;
- pid_t pid;
- struct mdstat_ent *mdstat;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
- fd = open(buf, O_RDONLY);
+ fd = open(buf, O_RDONLY|O_NOATIME);
if (fd < 0)
- return;
-
- if (read(fd, buf, sizeof(buf)) < 0) {
- close(fd);
- return;
- }
+ return -1;
+ if (read(fd, buf, sizeof(buf)) > 0)
+ sscanf(buf, "%d\n", &pid);
close(fd);
- pid = strtoul(buf, NULL, 10);
+
+ return pid;
+}
+
+static void try_kill_monitor(pid_t pid, char *devname, int sock)
+{
+ char buf[100];
+ int fd;
+ struct mdstat_ent *mdstat;
/* first rule of survival... don't off yourself */
if (pid == getpid())
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)
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,
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");
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));
}
}
- /* 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);
ignore = dup(0);
#endif
- mlockall(MCL_FUTURE);
+ mlockall(MCL_CURRENT | MCL_FUTURE);
if (clone_monitor(container) < 0) {
fprintf(stderr, "mdmon: failed to start monitor process: %s\n",
exit(2);
}
+ if (victim > -1) {
+ try_kill_monitor(victim, container->devname, victim_sock);
+ close(victim_sock);
+ }
do_manager(container);
exit(0);