]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Monitor.c
sysfs: Avoid if and return on the same line
[thirdparty/mdadm.git] / Monitor.c
index b82e7b6a5ba0c228e3eabd653264227036eca83c..802a9d9864b9cbec68ec8d2214642970070160a7 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
 struct state {
        char *devname;
        char devnm[32]; /* to sync with mdstat info */
-       long utime;
+       unsigned int utime;
        int err;
        char *spare_group;
        int active, working, failed, spare, raid;
        int from_config;
+       int from_auto;
        int expected_spares;
        int devstate[MAX_DISKS];
        dev_t devid[MAX_DISKS];
@@ -156,7 +157,7 @@ int Monitor(struct mddev_dev *devlist,
                        return rv;
        }
 
-       if (share) 
+       if (share)
                if (check_one_sharer(c->scan))
                        return 1;
 
@@ -204,21 +205,22 @@ int Monitor(struct mddev_dev *devlist,
                }
        }
 
-
        while (! finished) {
                int new_found = 0;
-               struct state *st;
+               struct state *st, **stp;
                int anydegraded = 0;
 
                if (mdstat)
                        free_mdstat(mdstat);
                mdstat = mdstat_read(oneshot?0:1, 0);
+               if (!mdstat)
+                       mdstat_close();
 
                for (st=statelist; st; st=st->next)
                        if (check_array(st, mdstat, c->test, &info,
                                        increments, c->prefer))
                                anydegraded = 1;
-               
+
                /* now check if there are any new devices found in mdstat */
                if (c->scan)
                        new_found = add_new_arrays(mdstat, &statelist, c->test,
@@ -237,6 +239,16 @@ int Monitor(struct mddev_dev *devlist,
                                mdstat_wait(c->delay);
                }
                c->test = 0;
+
+               for (stp = &statelist; (st = *stp) != NULL; ) {
+                       if (st->from_auto && st->err > 5) {
+                               *stp = st->next;
+                               free(st->devname);
+                               free(st->spare_group);
+                               free(st);
+                       } else
+                               stp = &st->next;
+               }
        }
        for (st2 = statelist; st2; st2 = statelist) {
                statelist = st2->next;
@@ -300,15 +312,11 @@ static int check_one_sharer(int scan)
                rv = stat(dir, &buf);
                if (rv != -1) {
                        if (scan) {
-                               pr_err("Only one "
-                                       "autorebuild process allowed"
-                                       " in scan mode, aborting\n");
+                               pr_err("Only one autorebuild process allowed in scan mode, aborting\n");
                                fclose(fp);
                                return 1;
                        } else {
-                               pr_err("Warning: One"
-                                       " autorebuild process already"
-                                       " running.\n");
+                               pr_err("Warning: One autorebuild process already running.\n");
                        }
                }
                fclose(fp);
@@ -316,14 +324,11 @@ static int check_one_sharer(int scan)
        if (scan) {
                if (mkdir(MDMON_DIR, S_IRWXU) < 0 &&
                    errno != EEXIST) {
-                       pr_err("Can't create "
-                               "autorebuild.pid file\n");
+                       pr_err("Can't create autorebuild.pid file\n");
                } else {
                        fp = fopen(path, "w");
                        if (!fp)
-                               pr_err("Cannot create"
-                                       " autorebuild.pid"
-                                       "file\n");
+                               pr_err("Cannot create autorebuild.pidfile\n");
                        else {
                                pid = getpid();
                                fprintf(fp, "%d\n", pid);
@@ -371,24 +376,21 @@ static void alert(char *event, char *dev, char *disc, struct alert_info *info)
                        if (info->mailfrom)
                                fprintf(mp, "From: %s\n", info->mailfrom);
                        else
-                               fprintf(mp, "From: " Name " monitoring <root>\n");
+                               fprintf(mp, "From: %s monitoring <root>\n", Name);
                        fprintf(mp, "To: %s\n", info->mailaddr);
                        fprintf(mp, "Subject: %s event on %s:%s\n\n",
                                event, dev, hname);
 
                        fprintf(mp,
-                               "This is an automatically generated"
-                               " mail message from " Name "\n");
+                               "This is an automatically generated mail message from %s\n", Name);
                        fprintf(mp, "running on %s\n\n", hname);
 
                        fprintf(mp,
-                               "A %s event had been detected on"
-                               " md device %s.\n\n", event, dev);
+                               "A %s event had been detected on md device %s.\n\n", event, dev);
 
                        if (disc && disc[0] != ' ')
                                fprintf(mp,
-                                       "It could be related to"
-                                       " component device %s.\n\n", disc);
+                                       "It could be related to component device %s.\n\n", disc);
                        if (disc && disc[0] == ' ')
                                fprintf(mp, "Extra information:%s.\n\n", disc);
 
@@ -399,8 +401,7 @@ static void alert(char *event, char *dev, char *disc, struct alert_info *info)
                                char buf[8192];
                                int n;
                                fprintf(mp,
-                                       "\nP.S. The /proc/mdstat file"
-                                       " currently contains the following:\n\n");
+                                       "\nP.S. The /proc/mdstat file currently contains the following:\n\n");
                                while ( (n=fread(buf, 1, sizeof(buf), mdstat)) > 0)
                                        n=fwrite(buf, 1, n, mp);
                                fclose(mdstat);
@@ -427,10 +428,13 @@ static void alert(char *event, char *dev, char *disc, struct alert_info *info)
                else
                        priority = LOG_INFO;
 
-               if (disc)
+               if (disc && disc[0] != ' ')
                        syslog(priority,
-                              "%s event detected on md device %s,"
-                              " component device %s", event, dev, disc);
+                              "%s event detected on md device %s, component device %s", event, dev, disc);
+               else if (disc)
+                       syslog(priority,
+                              "%s event detected on md device %s: %s",
+                              event, dev, disc);
                else
                        syslog(priority,
                               "%s event detected on md device %s",
@@ -450,7 +454,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
        mdu_array_info_t array;
        struct mdstat_ent *mse = NULL, *mse2;
        char *dev = st->devname;
-       int fd;
+       int fd = -1;
        int i;
        int remaining_disks;
        int last_disk;
@@ -458,18 +462,45 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
 
        if (test)
                alert("TestMessage", dev, NULL, ainfo);
+       if (st->devnm[0])
+               fd = open("/sys/block", O_RDONLY|O_DIRECTORY);
+       if (fd >= 0) {
+               /* Don't open the device unless it is present and
+                * active in sysfs.
+                */
+               char buf[10];
+               close(fd);
+               fd = sysfs_open(st->devnm, NULL, "array_state");
+               if (fd < 0 ||
+                   read(fd, buf, 10) < 5 ||
+                   strncmp(buf,"clear",5) == 0 ||
+                   strncmp(buf,"inact",5) == 0) {
+                       if (fd >= 0)
+                               close(fd);
+                       fd = sysfs_open(st->devnm, NULL, "level");
+                       if (fd < 0 || read(fd, buf, 10) != 0) {
+                               if (fd >= 0)
+                                       close(fd);
+                               if (!st->err)
+                                       alert("DeviceDisappeared", dev, NULL, ainfo);
+                               st->err++;
+                               return 0;
+                       }
+               }
+               close(fd);
+       }
        fd = open(dev, O_RDONLY);
        if (fd < 0) {
                if (!st->err)
                        alert("DeviceDisappeared", dev, NULL, ainfo);
-               st->err=1;
+               st->err++;
                return 0;
        }
        fcntl(fd, F_SETFD, FD_CLOEXEC);
        if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
                if (!st->err)
                        alert("DeviceDisappeared", dev, NULL, ainfo);
-               st->err=1;
+               st->err++;
                close(fd);
                return 0;
        }
@@ -478,8 +509,8 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
         */
        if (array.level == 0 || array.level == -1) {
                if (!st->err && !st->from_config)
-                       alert("DeviceDisappeared", dev, "Wrong-Level", ainfo);
-               st->err = 1;
+                       alert("DeviceDisappeared", dev, " Wrong-Level", ainfo);
+               st->err++;
                close(fd);
                return 0;
        }
@@ -495,7 +526,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
        if (!mse) {
                /* duplicated array in statelist
                 * or re-created after reading mdstat*/
-               st->err = 1;
+               st->err++;
                close(fd);
                return 0;
        }
@@ -506,7 +537,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
                array.utime = st->utime + 1;;
 
        if (st->err) {
-               /* New array appeared where previously had and error */
+               /* New array appeared where previously had an error */
                st->err = 0;
                st->percent = RESYNC_NONE;
                new_array = 1;
@@ -568,7 +599,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
                } else
                        alert("RebuildFinished", dev, NULL, ainfo);
                if (sra)
-                       free(sra);
+                       sysfs_free(sra);
        }
        st->percent = mse->percent;
 
@@ -658,6 +689,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
 {
        struct mdstat_ent *mse;
        int new_found = 0;
+       char *name;
 
        for (mse=mdstat; mse; mse=mse->next)
                if (mse->devnm[0] &&
@@ -668,7 +700,14 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
                        struct state *st = xcalloc(1, sizeof *st);
                        mdu_array_info_t array;
                        int fd;
-                       st->devname = xstrdup(get_md_name(mse->devnm));
+
+                       name = get_md_name(mse->devnm);
+                       if (!name) {
+                               free(st);
+                               continue;
+                       }
+
+                       st->devname = xstrdup(name);
                        if ((fd = open(st->devname, O_RDONLY)) < 0 ||
                            ioctl(fd, GET_ARRAY_INFO, &array)< 0) {
                                /* no such array */
@@ -685,6 +724,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
                        close(fd);
                        st->next = *statelist;
                        st->err = 1;
+                       st->from_auto = 1;
                        strcpy(st->devnm, mse->devnm);
                        st->percent = RESYNC_UNKNOWN;
                        st->expected_spares = -1;
@@ -809,12 +849,12 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
                close(fd);
                return 0;
        }
-       
+
        err = st->ss->load_container(st, fd, NULL);
        close(fd);
        if (err)
                return 0;
-       
+
        if (from == to) {
                /* We must check if number of active disks has not increased
                 * since ioctl in main loop. mdmon may have added spare
@@ -855,7 +895,6 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
        return dev;
 }
 
-
 static void try_spare_migration(struct state *statelist, struct alert_info *info)
 {
        struct state *from;
@@ -874,7 +913,7 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
                                /* subarray monitored without parent container
                                 * we can't move spares here */
                                continue;
-                       
+
                        if (to->parent)
                                /* member of a container */
                                to = to->parent;
@@ -956,6 +995,7 @@ int Wait(char *dev)
        struct stat stb;
        char devnm[32];
        int rv = 1;
+       int frozen_remaining = 3;
 
        if (stat(dev, &stb) != 0) {
                pr_err("Cannot find %s: %s\n", dev,
@@ -972,7 +1012,7 @@ int Wait(char *dev)
                        if (strcmp(e->devnm, devnm) == 0)
                                break;
 
-               if (e->percent == RESYNC_NONE) {
+               if (e && e->percent == RESYNC_NONE) {
                        /* We could be in the brief pause before something
                         * starts. /proc/mdstat doesn't show that, but
                         * sync_action does.
@@ -982,8 +1022,15 @@ int Wait(char *dev)
                        sysfs_init(&mdi, -1, devnm);
                        if (sysfs_get_str(&mdi, NULL, "sync_action",
                                          buf, 20) > 0 &&
-                           strcmp(buf,"idle\n") != 0)
+                           strcmp(buf,"idle\n") != 0) {
                                e->percent = RESYNC_UNKNOWN;
+                               if (strcmp(buf, "frozen\n") == 0) {
+                                       if (frozen_remaining == 0)
+                                               e->percent = RESYNC_NONE;
+                                       else
+                                               frozen_remaining -= 1;
+                               }
+                       }
                }
                if (!e || e->percent == RESYNC_NONE) {
                        if (e && e->metadata_version &&
@@ -1025,8 +1072,7 @@ int WaitClean(char *dev, int sock, int verbose)
        mdi = sysfs_read(fd, devnm, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
        if (!mdi) {
                if (verbose)
-                       pr_err("Failed to read sysfs attributes for "
-                              "%s\n", dev);
+                       pr_err("Failed to read sysfs attributes for %s\n", dev);
                close(fd);
                return 0;
        }
@@ -1052,17 +1098,12 @@ int WaitClean(char *dev, int sock, int verbose)
        if (rv) {
                int state_fd = sysfs_open(fd2devnm(fd), NULL, "array_state");
                char buf[20];
-               fd_set fds;
-               struct timeval tm;
+               int delay = 5000;
 
                /* 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;
-
-               FD_ZERO(&fds);
 
                /* wait for array_state to be clean */
                while (1) {
@@ -1071,8 +1112,7 @@ int WaitClean(char *dev, int sock, int verbose)
                                break;
                        if (sysfs_match_word(buf, clean_states) <= 4)
                                break;
-                       FD_SET(state_fd, &fds);
-                       rv = select(state_fd + 1, NULL, NULL, &fds, &tm);
+                       rv = sysfs_wait(state_fd, &delay);
                        if (rv < 0 && errno != EINTR)
                                break;
                        lseek(state_fd, 0, SEEK_SET);