/var/run probably doesn't persist from early boot.
So if necessary, store in in /lib/init/rw or somewhere else
that does persist.
Signed-off-by: NeilBrown <neilb@suse.de>
CONFFILE2 = $(SYSCONFDIR)/mdadm/mdadm.conf
MAILCMD =/usr/sbin/sendmail -t
CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE)\" -DCONFFILE2=\"$(CONFFILE2)\"
-CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS)
+# ALT_RUN should be somewhere that persists across the pivotroot
+# from early boot to late boot.
+# If you don't have /lib/init/rw you might want to use /dev/.something
+# e.g. make ALT_RUN=/dev/.mdadm
+ALT_RUN = /lib/init/rw
+ALTFLAGS = -DALT_RUN=\"$(ALT_RUN)\"
+CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(ALTFLAGS)
# If you want a static binary, you might uncomment these
# LDFLAGS = -static
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
+ if (socket_hup_requested) {
+ /* Try to create pid file and socket in
+ * main or alternate RUN directory.
*/
- mkdir("/var/run/mdadm", 0600);
- close(container->sock);
- container->sock = make_control_sock(container->devname);
- make_pidfile(container->devname, 0);
+ char *dir = VAR_RUN;
+ if (mkdir(dir, 0600) < 0 && errno != EEXIST) {
+ char *dir = ALT_RUN;
+ if (mkdir(dir, 0600) < 0 && errno != EEXIST)
+ dir = NULL;
+ } else {
+ if (proc_fd >= 0)
+ close(proc_fd);
+ proc_fd = -1;
+ }
+ if (dir && !sigterm &&
+ (container->sock < 0 ||
+ strcmp(dir, pid_dir) != 0)) {
+ close(container->sock);
+ remove_pidfile(container->devname);
+ pid_dir = dir;
+ container->sock = make_control_sock(container->devname);
+ make_pidfile(container->devname);
+ }
socket_hup_requested = 0;
}
if (container->sock < 0)
if (sigterm)
wakeup_monitor();
- if (update_queue == NULL) {
- if (container->sock < 0)
- mdstat_wait_fd(proc_fd, &set);
- else
- mdstat_wait_fd(container->sock, &set);
- } else
+ if (update_queue == NULL)
+ mdstat_wait_fd(container->sock, proc_fd, &set);
+ else
/* If an update is happening, just wait for signal */
pselect(0, NULL, NULL, NULL, NULL, &set);
} while(1);
#define DEFAULT_BITMAP_DELAY 5
#define DEFAULT_MAX_WRITE_BEHIND 256
+#define VAR_RUN "/var/run/mdadm"
+/* ALT_RUN should be somewhere that persists across the pivotroot
+ * from early boot to late boot.
+ * If you don't have /lib/init/rw you might want to use /dev/.something
+ */
+#ifndef ALT_RUN
+#define ALT_RUN "/lib/init/rw/mdadm"
+#endif /* ALT_RUN */
+
#include "md_u.h"
#include "md_p.h"
#include "bitmap.h"
extern struct mdstat_ent *mdstat_read(int hold, int start);
extern void free_mdstat(struct mdstat_ent *ms);
extern void mdstat_wait(int seconds);
-extern void mdstat_wait_fd(int fd, const sigset_t *sigmask);
+extern void mdstat_wait_fd(int fd, int fd2, const sigset_t *sigmask);
extern int mddev_busy(int devnum);
struct map_ent {
extern int open_mddev(char *dev, int report_errors);
extern int open_container(int fd);
+extern char *pid_dir;
extern int mdmon_running(int devnum);
extern int mdmon_pid(int devnum);
extern int check_env(char *name);
.SH SYNOPSIS
-.BI mdmon " CONTAINER [NEWROOT]"
+.BI mdmon " CONTAINER [NEWROOT | PID]"
.SH OVERVIEW
The 2.6.27 kernel brings the ability to support external metadata arrays.
instances that are running in the current namespace,
.IR chroot (2)
to NEWROOT, and continue monitoring the container.
+
+Alternately the new
+.I mdmon
+can be started after the new root has been installed with
+.I pivotroot
+by passing
+.B /
+as the NEWROOT. For
+.I mdmon
+to be able to find and kill the old
+.I mdmon
+there must be some part of the filesystem that persists from before
+the
+.I pivotroot
+to afterwards. This can be
+.B /var/run/mdadm
+or some other directory. The default other directory is
+.B /lib/init/rw/mdadm
+but this can easily be changed when
+.I mdmon
+is compiled.
+If
+.I mdmon
+cannot store the pid file in
+.B /var/run/mdadm
+it will store it in the other directory until
+.B /var/run/mdadm
+becomes available, or until it is killed.
+.TP
+[PID]
+If the second argument to
+.I mdmon
+does not start with a slash it is assumed to be the pid of a previous
+instance of
+.I mdmon
+to kill. This is used internally by
+.I mdmon
+to pass the pid across a chroot/exec and should not be used otherwise.
+
.PP
Note that
.I mdmon
is when the boot scripts need to restart it after mounting the new
root filesystem.
+.SH EXMAPLES
+
+.B " mdmon /proc/mdstat /"
+.br
+Any
+.I mdmon
+which is currently running is killed and a new instance is started.
+This should be run early in the boot sequence after a
+.I pivotroot
+to the final root filesystem, but before that filesystem is remounted
+read-write.
.SH SEE ALSO
.IR mdadm (8),
.IR md (4).
return NULL;
}
-int make_pidfile(char *devname, int o_excl)
+int make_pidfile(char *devname)
{
char path[100];
char pid[10];
int fd;
int n;
- if (sigterm)
- return -1;
-
- sprintf(path, "/var/run/mdadm/%s.pid", devname);
+ sprintf(path, "%s/%s.pid", pid_dir, 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 -errno;
sprintf(pid, "%d\n", getpid());
{
char buf[100];
- if (sigterm)
- return;
-
- sprintf(buf, "/var/run/mdadm/%s.pid", devname);
+ sprintf(buf, "%s/%s.pid", pid_dir, devname);
unlink(buf);
- sprintf(buf, "/var/run/mdadm/%s.sock", devname);
+ sprintf(buf, "%s/%s.sock", pid_dir, devname);
unlink(buf);
+ if (strcmp(pid_dir, ALT_RUN) == 0)
+ /* try to clean up when we are finished with this dir */
+ rmdir(pid_dir);
}
int make_control_sock(char *devname)
if (sigterm)
return -1;
- sprintf(path, "/var/run/mdadm/%s.sock", devname);
+ sprintf(path, "%s/%s.sock", pid_dir, devname);
unlink(path);
sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
if (sfd < 0)
void do_monitor(struct supertype *container);
void do_manager(struct supertype *container);
int make_control_sock(char *devname);
-int make_pidfile(char *devname, int o_excl);
+int make_pidfile(char *devname);
extern int socket_hup_requested;
extern int sigterm;
select(maxfd + 1, NULL, NULL, &fds, &tm);
}
-void mdstat_wait_fd(int fd, const sigset_t *sigmask)
+void mdstat_wait_fd(int fd, int fd2, const sigset_t *sigmask)
{
fd_set fds, rfds;
- int maxfd = fd;
+ int maxfd = 0;
FD_ZERO(&fds);
FD_ZERO(&rfds);
if (mdstat_fd >= 0)
FD_SET(mdstat_fd, &fds);
- if (fd >= 0) {
+
+ if (fd < 0)
+ fd = fd2, fd2 = -1;
+
+ while (fd >= 0) {
struct stat stb;
fstat(fd, &stb);
if ((stb.st_mode & S_IFMT) == S_IFREG)
FD_SET(fd, &fds);
else
FD_SET(fd, &rfds);
+
+ if (fd > maxfd)
+ maxfd = fd;
+
+ fd = fd2;
+ fd2 = -1;
}
if (mdstat_fd > maxfd)
maxfd = mdstat_fd;
int pos;
char *c;
- pos = sprintf(path, "/var/run/mdadm/");
+ pos = sprintf(path, "%s/", VAR_RUN);
if (is_subarray(devname)) {
devname++;
c = strchr(devname, '/');
return NoMdDev;
}
+char *pid_dir = VAR_RUN;
+
int mdmon_pid(int devnum)
{
char path[100];
char pid[10];
int fd;
int n;
- sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum));
+ sprintf(path, "%s/%s.pid", pid_dir, devnum2devname(devnum));
fd = open(path, O_RDONLY | O_NOATIME, 0);
if (fd < 0)