]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Monitor.c
util: Introduce md_get_disk_info()
[thirdparty/mdadm.git] / Monitor.c
index 1cd378b7a95697d65bf0a72775ee66ebc8c55316..2c0f717ce505c4572f21b9ca4d709cf9efba14e0 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -33,7 +33,7 @@
 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;
@@ -213,6 +213,8 @@ int Monitor(struct mddev_dev *devlist,
                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,
@@ -495,7 +497,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
                return 0;
        }
        fcntl(fd, F_SETFD, FD_CLOEXEC);
-       if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
+       if (md_get_array_info(fd, &array) < 0) {
                if (!st->err)
                        alert("DeviceDisappeared", dev, NULL, ainfo);
                st->err++;
@@ -597,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;
 
@@ -606,7 +608,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
             i++) {
                mdu_disk_info_t disc;
                disc.number = i;
-               if (ioctl(fd, GET_DISK_INFO, &disc) >= 0) {
+               if (md_get_disk_info(fd, &disc) >= 0) {
                        info[i].state = disc.state;
                        info[i].major = disc.major;
                        info[i].minor = disc.minor;
@@ -687,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] &&
@@ -697,11 +700,19 @@ 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) {
+                           md_get_array_info(fd, &array) < 0) {
                                /* no such array */
-                               if (fd >=0) close(fd);
+                               if (fd >= 0)
+                                       close(fd);
                                put_md_name(st->devname);
                                free(st->devname);
                                if (st->metadata) {
@@ -984,14 +995,21 @@ int Wait(char *dev)
 {
        struct stat stb;
        char devnm[32];
+       char *tmp;
        int rv = 1;
+       int frozen_remaining = 3;
 
        if (stat(dev, &stb) != 0) {
                pr_err("Cannot find %s: %s\n", dev,
                        strerror(errno));
                return 2;
        }
-       strcpy(devnm, stat2devnm(&stb));
+       tmp = stat2devnm(&stb);
+       if (!tmp) {
+               pr_err("%s is not a block device.\n", dev);
+               return 2;
+       }
+       strcpy(devnm, tmp);
 
        while(1) {
                struct mdstat_ent *ms = mdstat_read(1, 0);
@@ -1001,7 +1019,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.
@@ -1011,8 +1029,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 &&