mdmon: allow pid to be stored in different directory.

/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>
This commit is contained in:
NeilBrown 2010-02-04 16:31:49 +11:00
parent 24f6f99b36
commit 5d4d1b26d3
9 changed files with 121 additions and 34 deletions

View File

@ -58,7 +58,13 @@ CONFFILE = $(SYSCONFDIR)/mdadm.conf
CONFFILE2 = $(SYSCONFDIR)/mdadm/mdadm.conf CONFFILE2 = $(SYSCONFDIR)/mdadm/mdadm.conf
MAILCMD =/usr/sbin/sendmail -t MAILCMD =/usr/sbin/sendmail -t
CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE)\" -DCONFFILE2=\"$(CONFFILE2)\" 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 # If you want a static binary, you might uncomment these
# LDFLAGS = -static # LDFLAGS = -static

View File

@ -702,14 +702,29 @@ void do_manager(struct supertype *container)
read_sock(container); read_sock(container);
if (container->sock < 0 || socket_hup_requested) { if (socket_hup_requested) {
/* If this fails, we hope it already exists /* Try to create pid file and socket in
* pid file lives in /var/run/mdadm/mdXX.pid * main or alternate RUN directory.
*/ */
mkdir("/var/run/mdadm", 0600); char *dir = VAR_RUN;
close(container->sock); if (mkdir(dir, 0600) < 0 && errno != EEXIST) {
container->sock = make_control_sock(container->devname); char *dir = ALT_RUN;
make_pidfile(container->devname, 0); 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; socket_hup_requested = 0;
} }
if (container->sock < 0) if (container->sock < 0)
@ -726,12 +741,9 @@ void do_manager(struct supertype *container)
if (sigterm) if (sigterm)
wakeup_monitor(); wakeup_monitor();
if (update_queue == NULL) { if (update_queue == NULL)
if (container->sock < 0) mdstat_wait_fd(container->sock, proc_fd, &set);
mdstat_wait_fd(proc_fd, &set); else
else
mdstat_wait_fd(container->sock, &set);
} else
/* If an update is happening, just wait for signal */ /* If an update is happening, just wait for signal */
pselect(0, NULL, NULL, NULL, NULL, &set); pselect(0, NULL, NULL, NULL, NULL, &set);
} while(1); } while(1);

12
mdadm.h
View File

@ -68,6 +68,15 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
#define DEFAULT_BITMAP_DELAY 5 #define DEFAULT_BITMAP_DELAY 5
#define DEFAULT_MAX_WRITE_BEHIND 256 #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_u.h"
#include "md_p.h" #include "md_p.h"
#include "bitmap.h" #include "bitmap.h"
@ -332,7 +341,7 @@ struct mdstat_ent {
extern struct mdstat_ent *mdstat_read(int hold, int start); extern struct mdstat_ent *mdstat_read(int hold, int start);
extern void free_mdstat(struct mdstat_ent *ms); extern void free_mdstat(struct mdstat_ent *ms);
extern void mdstat_wait(int seconds); 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); extern int mddev_busy(int devnum);
struct map_ent { struct map_ent {
@ -882,6 +891,7 @@ extern int create_mddev(char *dev, char *name, int autof, int trustworthy,
extern int open_mddev(char *dev, int report_errors); extern int open_mddev(char *dev, int report_errors);
extern int open_container(int fd); extern int open_container(int fd);
extern char *pid_dir;
extern int mdmon_running(int devnum); extern int mdmon_running(int devnum);
extern int mdmon_pid(int devnum); extern int mdmon_pid(int devnum);
extern int check_env(char *name); extern int check_env(char *name);

52
mdmon.8
View File

@ -5,7 +5,7 @@ mdmon \- monitor MD external metadata arrays
.SH SYNOPSIS .SH SYNOPSIS
.BI mdmon " CONTAINER [NEWROOT]" .BI mdmon " CONTAINER [NEWROOT | PID]"
.SH OVERVIEW .SH OVERVIEW
The 2.6.27 kernel brings the ability to support external metadata arrays. The 2.6.27 kernel brings the ability to support external metadata arrays.
@ -148,6 +148,45 @@ will terminate any
instances that are running in the current namespace, instances that are running in the current namespace,
.IR chroot (2) .IR chroot (2)
to NEWROOT, and continue monitoring the container. 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 .PP
Note that Note that
.I mdmon .I mdmon
@ -159,6 +198,17 @@ RAID arrays. The only times it is run other that by
is when the boot scripts need to restart it after mounting the new is when the boot scripts need to restart it after mounting the new
root filesystem. 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 .SH SEE ALSO
.IR mdadm (8), .IR mdadm (8),
.IR md (4). .IR md (4).

21
mdmon.c
View File

@ -113,19 +113,16 @@ static struct superswitch *find_metadata_methods(char *vers)
return NULL; return NULL;
} }
int make_pidfile(char *devname, int o_excl) int make_pidfile(char *devname)
{ {
char path[100]; char path[100];
char pid[10]; char pid[10];
int fd; int fd;
int n; int n;
if (sigterm) sprintf(path, "%s/%s.pid", pid_dir, devname);
return -1;
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) if (fd < 0)
return -errno; return -errno;
sprintf(pid, "%d\n", getpid()); sprintf(pid, "%d\n", getpid());
@ -186,13 +183,13 @@ void remove_pidfile(char *devname)
{ {
char buf[100]; char buf[100];
if (sigterm) sprintf(buf, "%s/%s.pid", pid_dir, devname);
return;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
unlink(buf); unlink(buf);
sprintf(buf, "/var/run/mdadm/%s.sock", devname); sprintf(buf, "%s/%s.sock", pid_dir, devname);
unlink(buf); 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) int make_control_sock(char *devname)
@ -205,7 +202,7 @@ int make_control_sock(char *devname)
if (sigterm) if (sigterm)
return -1; return -1;
sprintf(path, "/var/run/mdadm/%s.sock", devname); sprintf(path, "%s/%s.sock", pid_dir, devname);
unlink(path); unlink(path);
sfd = socket(PF_LOCAL, SOCK_STREAM, 0); sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
if (sfd < 0) if (sfd < 0)

View File

@ -66,7 +66,7 @@ void remove_pidfile(char *devname);
void do_monitor(struct supertype *container); void do_monitor(struct supertype *container);
void do_manager(struct supertype *container); void do_manager(struct supertype *container);
int make_control_sock(char *devname); 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 socket_hup_requested;
extern int sigterm; extern int sigterm;

View File

@ -266,16 +266,20 @@ void mdstat_wait(int seconds)
select(maxfd + 1, NULL, NULL, &fds, &tm); 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; fd_set fds, rfds;
int maxfd = fd; int maxfd = 0;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_ZERO(&rfds); FD_ZERO(&rfds);
if (mdstat_fd >= 0) if (mdstat_fd >= 0)
FD_SET(mdstat_fd, &fds); FD_SET(mdstat_fd, &fds);
if (fd >= 0) {
if (fd < 0)
fd = fd2, fd2 = -1;
while (fd >= 0) {
struct stat stb; struct stat stb;
fstat(fd, &stb); fstat(fd, &stb);
if ((stb.st_mode & S_IFMT) == S_IFREG) if ((stb.st_mode & S_IFMT) == S_IFREG)
@ -286,6 +290,12 @@ void mdstat_wait_fd(int fd, const sigset_t *sigmask)
FD_SET(fd, &fds); FD_SET(fd, &fds);
else else
FD_SET(fd, &rfds); FD_SET(fd, &rfds);
if (fd > maxfd)
maxfd = fd;
fd = fd2;
fd2 = -1;
} }
if (mdstat_fd > maxfd) if (mdstat_fd > maxfd)
maxfd = mdstat_fd; maxfd = mdstat_fd;

2
msg.c
View File

@ -147,7 +147,7 @@ int connect_monitor(char *devname)
int pos; int pos;
char *c; char *c;
pos = sprintf(path, "/var/run/mdadm/"); pos = sprintf(path, "%s/", VAR_RUN);
if (is_subarray(devname)) { if (is_subarray(devname)) {
devname++; devname++;
c = strchr(devname, '/'); c = strchr(devname, '/');

4
util.c
View File

@ -1463,13 +1463,15 @@ int fd2devnum(int fd)
return NoMdDev; return NoMdDev;
} }
char *pid_dir = VAR_RUN;
int mdmon_pid(int devnum) int mdmon_pid(int devnum)
{ {
char path[100]; char path[100];
char pid[10]; char pid[10];
int fd; int fd;
int n; 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); fd = open(path, O_RDONLY | O_NOATIME, 0);
if (fd < 0) if (fd < 0)