]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - sysfs.c
platform-intel - cache 'intel_devices' for a few seconds.
[thirdparty/mdadm.git] / sysfs.c
diff --git a/sysfs.c b/sysfs.c
index cddabaee8b6d17dbfab3deb92fe2687edb4cb4b8..b66cebf32a10f72a138b5c2a60e085816bcc216e 100644 (file)
--- a/sysfs.c
+++ b/sysfs.c
@@ -105,10 +105,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
        DIR *dir = NULL;
        struct dirent *de;
 
-       sra = malloc(sizeof(*sra));
-       if (sra == NULL)
-               return sra;
-       memset(sra, 0, sizeof(*sra));
+       sra = xcalloc(1, sizeof(*sra));
        sysfs_init(sra, fd, devnum);
        if (sra->sys_name[0] == 0) {
                free(sra);
@@ -179,8 +176,10 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
        if (options & GET_CACHE) {
                strcpy(base, "stripe_cache_size");
                if (load_sys(fname, buf))
-                       goto abort;
-               sra->cache_size = strtoul(buf, NULL, 0);
+                       /* Probably level doesn't support it */
+                       sra->cache_size = 0;
+               else
+                       sra->cache_size = strtoul(buf, NULL, 0);
        }
        if (options & GET_MISMATCH) {
                strcpy(base, "mismatch_cnt");
@@ -226,7 +225,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                else if (strncmp(buf, "none", 4) == 0)
                        sra->bitmap_offset = 0;
                else if (buf[0] == '+')
-                       sra->bitmap_offset = strtoul(buf+1, NULL, 10);
+                       sra->bitmap_offset = strtol(buf+1, NULL, 10);
                else
                        goto abort;
        }
@@ -250,9 +249,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                dbase = base + strlen(base);
                *dbase++ = '/';
 
-               dev = malloc(sizeof(*dev));
-               if (!dev)
-                       goto abort;
+               dev = xmalloc(sizeof(*dev));
 
                /* Always get slot, major, minor */
                strcpy(dbase, "slot");
@@ -307,6 +304,11 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                        if (load_sys(fname, buf))
                                goto abort;
                        dev->data_offset = strtoull(buf, NULL, 0);
+                       strcpy(dbase, "new_offset");
+                       if (load_sys(fname, buf) == 0)
+                               dev->new_data_offset = strtoull(buf, NULL, 0);
+                       else
+                               dev->new_data_offset = dev->data_offset;
                }
                if (options & GET_SIZE) {
                        strcpy(dbase, "size");
@@ -428,6 +430,14 @@ int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev,
        return sysfs_set_str(sra, dev, name, valstr);
 }
 
+int sysfs_set_num_signed(struct mdinfo *sra, struct mdinfo *dev,
+                        char *name, long long val)
+{
+       char valstr[50];
+       sprintf(valstr, "%lli", val);
+       return sysfs_set_str(sra, dev, name, valstr);
+}
+
 int sysfs_uevent(struct mdinfo *sra, char *event)
 {
        char fname[50];
@@ -572,7 +582,7 @@ int sysfs_set_array(struct mdinfo *info, int vers)
                if ((vers % 100) < 2 ||
                    sysfs_set_str(info, NULL, "metadata_version",
                                  ver) < 0) {
-                       fprintf(stderr, Name ": This kernel does not "
+                       pr_err("This kernel does not "
                                "support external metadata.\n");
                        return 1;
                }
@@ -593,7 +603,7 @@ int sysfs_set_array(struct mdinfo *info, int vers)
                rc = sysfs_set_num(info, NULL, "array_size",
                                   info->custom_array_size/2);
                if (rc && errno == ENOENT) {
-                       fprintf(stderr, Name ": This kernel does not "
+                       pr_err("This kernel does not "
                                "have the md/array_size attribute, "
                                "the array may be larger than expected\n");
                        rc = 0;
@@ -775,18 +785,22 @@ int sysfs_unique_holder(int devnum, long rdev)
         * and is the only holder.
         * we should be locked against races by
         * an O_EXCL on devnum
+        * Return values:
+        *  0 - not unique, not even a holder
+        *  1 - unique, this is the only holder.
+        *  2/3 - not unique, there is another holder
+        * -1 - error, cannot find the holders
         */
        DIR *dir;
        struct dirent *de;
        char dirname[100];
        char l;
-       int found = 0;
+       int ret = 0;
        sprintf(dirname, "/sys/dev/block/%d:%d/holders",
                major(rdev), minor(rdev));
        dir = opendir(dirname);
-       errno = ENOENT;
        if (!dir)
-               return 0;
+               return -1;
        l = strlen(dirname);
        while ((de = readdir(dir)) != NULL) {
                char buf[10];
@@ -804,8 +818,8 @@ int sysfs_unique_holder(int devnum, long rdev)
                strcat(dirname+l, "/dev");
                fd = open(dirname, O_RDONLY);
                if (fd < 0) {
-                       errno = ENOENT;
-                       break;
+                       /* Probably a race, just ignore this */
+                       continue;
                }
                n = read(fd, buf, sizeof(buf)-1);
                close(fd);
@@ -813,24 +827,18 @@ int sysfs_unique_holder(int devnum, long rdev)
                        continue;
                buf[n] = 0;
                if (sscanf(buf, "%d:%d%c", &mj, &mn, &c) != 3 ||
-                   c != '\n') {
-                       errno = ENOENT;
-                       break;
-               }
+                   c != '\n')
+                       continue;
                if (mj != MD_MAJOR)
                        mn = -1-(mn>>6);
 
-               if (devnum != mn) {
-                       errno = EEXIST;
-                       break;
-               }
-               found = 1;
+               if (devnum == mn)
+                       ret |= 1;
+               else
+                       ret |= 2;
        }
        closedir(dir);
-       if (de)
-               return 0;
-       else
-               return found;
+       return ret;
 }
 
 int sysfs_freeze_array(struct mdinfo *sra)