/*
* mdmon - monitor external metadata arrays
*
- * Copyright (C) 2007-2008 Neil Brown <neilb@suse.de>
- * Copyright (C) 2007-2008 Intel Corporation
+ * Copyright (C) 2007-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2007-2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
void usage(void)
{
- fprintf(stderr, "Usage: mdmon [--switch-root dir] /device/name/for/container\n");
+ fprintf(stderr, "Usage: mdmon /device/name/for/container [target_dir]\n");
exit(2);
}
+int mdmon(char *devname, int devnum, int scan, char *switchroot);
+
int main(int argc, char *argv[])
{
- int mdfd;
- struct mdinfo *mdi, *di;
- struct supertype *container;
- sigset_t set;
- struct sigaction act;
- int pfd[2];
- int status;
- int ignore;
char *container_name = NULL;
char *switchroot = NULL;
int devnum;
char *devname;
+ int scan = 0;
+ int status = 0;
switch (argc) {
+ case 3:
+ switchroot = argv[2];
case 2:
container_name = argv[1];
break;
- case 4:
- if (strcmp(argv[1], "--switch-root") != 0) {
- fprintf(stderr, "mdmon: unknown argument %s\n", argv[1]);
- usage();
- }
- switchroot = argv[2];
- container_name = argv[3];
- break;
default:
usage();
}
- devnum = devname2devnum(container_name);
- devname = devnum2devname(devnum);
- if (strcmp(container_name, devname) != 0) {
+ if (strcmp(container_name, "/proc/mdstat") == 0) {
+ struct mdstat_ent *mdstat, *e;
+
+ /* launch an mdmon instance for each container found */
+ scan = 1;
+ mdstat = mdstat_read(0, 0);
+ for (e = mdstat; e; e = e->next) {
+ if (strncmp(e->metadata_version, "external:", 9) == 0 &&
+ !is_subarray(&e->metadata_version[9])) {
+ devname = devnum2devname(e->devnum);
+ /* update cmdline so this mdmon instance can be
+ * distinguished from others in a call to ps(1)
+ */
+ if (strlen(devname) <= strlen(container_name)) {
+ memset(container_name, 0, strlen(container_name));
+ sprintf(container_name, "%s", devname);
+ }
+ status |= mdmon(devname, e->devnum, scan,
+ switchroot);
+ }
+ }
+ free_mdstat(mdstat);
+
+ return status;
+ } else if (strncmp(container_name, "md", 2) == 0) {
+ devnum = devname2devnum(container_name);
+ devname = devnum2devname(devnum);
+ if (strcmp(container_name, devname) != 0)
+ devname = NULL;
+ } else {
+ struct stat st;
+
+ devnum = NoMdDev;
+ if (stat(container_name, &st) == 0)
+ devnum = stat2devnum(&st);
+ if (devnum == NoMdDev)
+ devname = NULL;
+ else
+ devname = devnum2devname(devnum);
+ }
+
+ if (!devname) {
fprintf(stderr, "mdmon: %s is not a valid md device name\n",
container_name);
exit(1);
}
+ return mdmon(devname, devnum, scan, switchroot);
+}
+
+int mdmon(char *devname, int devnum, int scan, char *switchroot)
+{
+ int mdfd;
+ struct mdinfo *mdi, *di;
+ struct supertype *container;
+ sigset_t set;
+ struct sigaction act;
+ int pfd[2];
+ int status;
+ int ignore;
+
+ dprintf("starting mdmon for %s in %s\n",
+ devname, switchroot ? : "/");
mdfd = open_dev(devnum);
if (mdfd < 0) {
- fprintf(stderr, "mdmon: %s: %s\n", container_name,
+ fprintf(stderr, "mdmon: %s: %s\n", devname,
strerror(errno));
- exit(1);
+ return 1;
}
if (md_get_version(mdfd) < 0) {
fprintf(stderr, "mdmon: %s: Not an md device\n",
- container_name);
- exit(1);
+ devname);
+ return 1;
}
/* Fork, and have the child tell us when they are ready */
- if (do_fork()) {
+ if (do_fork() || scan) {
if (pipe(pfd) != 0) {
fprintf(stderr, "mdmon: failed to create pipe\n");
- exit(1);
+ return 1;
}
switch(fork()) {
case -1:
fprintf(stderr, "mdmon: failed to fork: %s\n",
strerror(errno));
- exit(1);
+ return 1;
case 0: /* child */
close(pfd[0]);
break;
wait(&status);
status = WEXITSTATUS(status);
}
- exit(status);
+ return status;
}
} else
pfd[0] = pfd[1] = -1;
container->devnum = devnum;
container->devname = devname;
container->arrays = NULL;
+ container->subarray[0] = 0;
if (!container->devname) {
fprintf(stderr, "mdmon: failed to allocate container name string\n");
}
mdi = sysfs_read(mdfd, container->devnum,
- GET_VERSION|GET_LEVEL|GET_DEVS);
+ GET_VERSION|GET_LEVEL|GET_DEVS|SKIP_GONE_DEVS);
if (!mdi) {
fprintf(stderr, "mdmon: failed to load sysfs info for %s\n",
}
if (mdi->array.level != UnSet) {
fprintf(stderr, "mdmon: %s is not a container - cannot monitor\n",
- container_name);
+ devname);
exit(3);
}
if (mdi->array.major_version != -1 ||
mdi->array.minor_version != -2) {
fprintf(stderr, "mdmon: %s does not use external metadata - cannot monitor\n",
- container_name);
+ devname);
exit(3);
}
container->ss = find_metadata_methods(mdi->text_version);
if (container->ss == NULL) {
fprintf(stderr, "mdmon: %s uses unknown metadata: %s\n",
- container_name, mdi->text_version);
+ devname, mdi->text_version);
exit(3);
}
}
container->sock = make_control_sock(container->devname);
- if (container->ss->load_super(container, mdfd, container_name)) {
+ if (container->ss->load_super(container, mdfd, devname)) {
fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
- container_name);
+ devname);
exit(3);
}
close(mdfd);