]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - sysfs.c
Factor out add-disk code
[thirdparty/mdadm.git] / sysfs.c
diff --git a/sysfs.c b/sysfs.c
index 8979ec4e23c80fd1812fe6b4f277cc4ad325d923..fdad790f06e2d1294e5ace28ca62462949a6767e 100644 (file)
--- a/sysfs.c
+++ b/sysfs.c
@@ -25,6 +25,7 @@
 
 #include       "mdadm.h"
 #include       <dirent.h>
+#include       <ctype.h>
 
 int load_sys(char *path, char *buf)
 {
@@ -153,6 +154,12 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                        goto abort;
                sra->array.raid_disks = strtoul(buf, NULL, 0);
        }
+       if (options & GET_DEGRADED) {
+               strcpy(base, "degraded");
+               if (load_sys(fname, buf))
+                       goto abort;
+               sra->array.failed_disks = strtoul(buf, NULL, 0);
+       }
        if (options & GET_COMPONENT) {
                strcpy(base, "component_size");
                if (load_sys(fname, buf))
@@ -179,6 +186,35 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                        goto abort;
                sra->mismatch_cnt = strtoul(buf, NULL, 0);
        }
+       if (options & GET_SAFEMODE) {
+               int scale = 1;
+               int dot = 0;
+               int i;
+               unsigned long msec;
+               size_t len;
+
+               strcpy(base, "safe_mode_delay");
+               if (load_sys(fname, buf))
+                       goto abort;
+
+               /* remove a period, and count digits after it */
+               len = strlen(buf);
+               for (i = 0; i < len; i++) {
+                       if (dot) {
+                               if (isdigit(buf[i])) {
+                                       buf[i-1] = buf[i];
+                                       scale *= 10;
+                               }
+                               buf[i] = 0;
+                       } else if (buf[i] == '.') {
+                               dot=1;
+                               buf[i] = 0;
+                       }
+               }
+               msec = strtoul(buf, NULL, 10);
+               msec = (msec * 1000) / scale;
+               sra->safe_mode_delay = msec;
+       }
 
        if (! (options & GET_DEVS))
                return sra;
@@ -202,14 +238,33 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                dev = malloc(sizeof(*dev));
                if (!dev)
                        goto abort;
-               dev->next = sra->devs;
-               sra->devs = dev;
-               strcpy(dev->sys_name, de->d_name);
 
                /* Always get slot, major, minor */
                strcpy(dbase, "slot");
-               if (load_sys(fname, buf))
-                       goto abort;
+               if (load_sys(fname, buf)) {
+                       /* hmm... unable to read 'slot' maybe the device
+                        * is going away?
+                        */
+                       strcpy(dbase, "block");
+                       if (readlink(fname, buf, sizeof(buf)) < 0 &&
+                           errno != ENAMETOOLONG) {
+                               /* ...yup device is gone */
+                               free(dev);
+                               continue;
+                       } else {
+                               /* slot is unreadable but 'block' link
+                                * still intact... something bad is happening
+                                * so abort
+                                */
+                               free(dev);
+                               goto abort;
+                       }
+                       
+               }
+               dev->next = sra->devs;
+               sra->devs = dev;
+
+               strcpy(dev->sys_name, de->d_name);
                dev->disk.raid_disk = strtoul(buf, &ep, 10);
                if (*ep) dev->disk.raid_disk = -1;
 
@@ -259,6 +314,31 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
        return NULL;
 }
 
+int sysfs_attr_match(const char *attr, const char *str)
+{
+       /* See if attr, read from a sysfs file, matches
+        * str.  They must either be the same, or attr can
+        * have a trailing newline or comma
+        */
+       while (*attr && *str && *attr == *str) {
+               attr++;
+               str++;
+       }
+
+       if (*str || (*attr && *attr != ',' && *attr != '\n'))
+               return 0;
+       return 1;
+}
+
+int sysfs_match_word(const char *word, char **list)
+{
+       int n;
+       for (n=0; list[n]; n++)
+               if (sysfs_attr_match(word, list[n]))
+                       break;
+       return n;
+}
+
 unsigned long long get_component_size(int fd)
 {
        /* Find out the component size of the array.
@@ -340,6 +420,19 @@ int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev,
        return 0;
 }
 
+int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms)
+{
+       unsigned long sec;
+       unsigned long msec;
+       char delay[30];
+
+       sec = ms / 1000;
+       msec = ms - (sec * 1000);
+
+       sprintf(delay, "%ld.%ld", sec, msec);
+       return sysfs_set_str(sra, NULL, "safe_mode_delay", delay);
+}
+
 int sysfs_set_array(struct mdinfo *sra,
                    struct mdinfo *info)
 {
@@ -363,7 +456,6 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd)
 {
        char dv[100];
        char nm[100];
-       struct mdinfo *sd2;
        char *dname;
        int rv;
 
@@ -389,15 +481,10 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd)
                rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk);
 //             rv |= sysfs_set_str(sra, sd, "state", "in_sync");
        }
-       if (! rv) {
-               sd2 = malloc(sizeof(*sd2));
-               *sd2 = *sd;
-               sd2->next = sra->devs;
-               sra->devs = sd2;
-       }
        return rv;
 }
 
+#if 0
 int sysfs_disk_to_sg(int fd)
 {
        /* from an open block device, try find and open its corresponding
@@ -461,6 +548,7 @@ int sysfs_disk_to_sg(int fd)
 
        return -1;
 }
+#endif
 
 int sysfs_disk_to_scsi_id(int fd, __u32 *id)
 {