]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Monitor.c
Merge branch 'master' in devel-3.0
[thirdparty/mdadm.git] / Monitor.c
index 3197b42a37b86daeb6856747ea253b38a3fec058..af531294cc53c908ea7a1b88f7a1e0870c5c62bf 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -165,7 +165,10 @@ int Monitor(mddev_dev_t devlist,
        if (devlist == NULL) {
                mddev_ident_t mdlist = conf_get_ident(NULL);
                for (; mdlist; mdlist=mdlist->next) {
-                       struct state *st = malloc(sizeof *st);
+                       struct state *st;
+                       if (mdlist->devname == NULL)
+                               continue;
+                       st = malloc(sizeof *st);
                        if (st == NULL)
                                continue;
                        st->devname = strdup(mdlist->devname);
@@ -431,6 +434,8 @@ int Monitor(mddev_dev_t devlist,
                                        st->spare_group = NULL;
                                        st->expected_spares = -1;
                                        statelist = st;
+                                       if (test)
+                                               alert("TestMessage", st->devname, NULL, mailaddr, mailfrom, alert_cmd, dosyslog);
                                        alert("NewArray", st->devname, NULL, mailaddr, mailfrom, alert_cmd, dosyslog);
                                        new_found = 1;
                                }
@@ -613,7 +618,7 @@ int Wait(char *dev)
                                break;
 
                if (!e || e->percent < 0) {
-                       if (e &&
+                       if (e && e->metadata_version &&
                            strncmp(e->metadata_version, "external:", 9) == 0) {
                                if (is_subarray(&e->metadata_version[9]))
                                        ping_monitor(&e->metadata_version[9]);
@@ -623,7 +628,7 @@ int Wait(char *dev)
                        free_mdstat(ms);
                        return rv;
                }
-               free(ms);
+               free_mdstat(ms);
                rv = 0;
                mdstat_wait(5);
        }
@@ -632,7 +637,7 @@ int Wait(char *dev)
 static char *clean_states[] = {
        "clear", "inactive", "readonly", "read-auto", "clean", NULL };
 
-int WaitClean(char *dev)
+int WaitClean(char *dev, int verbose)
 {
        int fd;
        struct mdinfo *mdi;
@@ -641,15 +646,17 @@ int WaitClean(char *dev)
 
        fd = open(dev, O_RDONLY); 
        if (fd < 0) {
-               fprintf(stderr, Name ": Couldn't open %s: %s\n", dev, strerror(errno));
+               if (verbose)
+                       fprintf(stderr, Name ": Couldn't open %s: %s\n", dev, strerror(errno));
                return 1;
        }
 
        devnum = fd2devnum(fd);
        mdi = sysfs_read(fd, devnum, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
        if (!mdi) {
-               fprintf(stderr, Name ": Failed to read sysfs attributes for "
-                       "%s\n", dev);
+               if (verbose)
+                       fprintf(stderr, Name ": Failed to read sysfs attributes for "
+                               "%s\n", dev);
                close(fd);
                return 0;
        }
@@ -675,41 +682,55 @@ int WaitClean(char *dev)
 
        if (rv) {
                int state_fd = sysfs_open(fd2devnum(fd), NULL, "array_state");
-               unsigned long secs;
                char buf[20];
+               fd_set fds;
+               struct timeval tm;
+
+               /* minimize the safe_mode_delay and prepare to wait up to 5s
+                * for writes to quiesce
+                */
+               sysfs_set_safemode(mdi, 1);
+               tm.tv_sec = 5;
+               tm.tv_usec = 0;
 
-               secs = mdi->safe_mode_delay / 1000;
-               if (mdi->safe_mode_delay - secs * 1000)
-                       secs++;
-               secs *= 2;
+               /* give mdmon a chance to checkpoint resync */
+               sysfs_set_str(mdi, NULL, "sync_action", "idle");
 
-               for (; secs; secs--) {
+               FD_ZERO(&fds);
+
+               /* wait for array_state to be clean */
+               while (1) {
                        rv = read(state_fd, buf, sizeof(buf));
                        if (rv < 0)
                                break;
                        if (sysfs_match_word(buf, clean_states) <= 4)
                                break;
-                       sleep(1);
+                       FD_SET(state_fd, &fds);
+                       rv = select(state_fd + 1, &fds, NULL, NULL, &tm);
+                       if (rv < 0 && errno != EINTR)
+                               break;
                        lseek(state_fd, 0, SEEK_SET);
                }
                if (rv < 0)
                        rv = 1;
-               else if (secs) {
+               else if (ping_monitor(mdi->text_version) == 0) {
                        /* we need to ping to close the window between array
                         * state transitioning to clean and the metadata being
                         * marked clean
                         */
-                       if (ping_monitor(mdi->text_version) == 0)
-                               rv = 0;
-               }
-               if (rv)
+                       rv = 0;
+               } else
+                       rv = 1;
+               if (rv && verbose)
                        fprintf(stderr, Name ": Error waiting for %s to be clean\n",
                                dev);
 
+               /* restore the original safe_mode_delay */
+               sysfs_set_safemode(mdi, mdi->safe_mode_delay);
                close(state_fd);
        }
 
-       sysfs_free(mdi);                
+       sysfs_free(mdi);
        close(fd);
 
        return rv;