]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - sysfs.c
Remove race for starting container devices.
[thirdparty/mdadm.git] / sysfs.c
diff --git a/sysfs.c b/sysfs.c
index 56813b7d6ae0811dd5289fdbd5da7a8337932667..a5fcdd0388ced1f7b9898a9409c8a0246df4013d 100644 (file)
--- a/sysfs.c
+++ b/sysfs.c
@@ -541,8 +541,21 @@ int sysfs_set_array(struct mdinfo *info, int vers)
        ver[0] = 0;
        if (info->array.major_version == -1 &&
            info->array.minor_version == -2) {
+               char buf[1024];
+
                strcat(strcpy(ver, "external:"), info->text_version);
 
+               /* meta version might already be set if we are setting
+                * new geometry for a reshape.  In that case we don't
+                * want to over-write the 'readonly' flag that is
+                * stored in the metadata version.  So read the current
+                * version first, and preserve the flag
+                */
+               if (sysfs_get_str(info, NULL, "metadata_version",
+                                 buf, 1024) > 0)
+                       if (strlen(buf) >= 9 && buf[9] == '-')
+                               ver[9] = '-';
+
                if ((vers % 100) < 2 ||
                    sysfs_set_str(info, NULL, "metadata_version",
                                  ver) < 0) {
@@ -606,7 +619,7 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume)
 
        memset(nm, 0, sizeof(nm));
        sprintf(dv, "/sys/dev/block/%d:%d", sd->disk.major, sd->disk.minor);
-       rv = readlink(dv, nm, sizeof(nm));
+       rv = readlink(dv, nm, sizeof(nm)-1);
        if (rv <= 0)
                return -1;
        nm[rv] = '\0';
@@ -709,9 +722,9 @@ int sysfs_disk_to_scsi_id(int fd, __u32 *id)
        /* from an open block device, try to retrieve it scsi_id */
        struct stat st;
        char path[256];
-       char *c1, *c2;
        DIR *dir;
        struct dirent *de;
+       int host, bus, target, lun;
 
        if (fstat(fd, &st))
                return 1;
@@ -723,32 +736,22 @@ int sysfs_disk_to_scsi_id(int fd, __u32 *id)
        if (!dir)
                return 1;
 
-       de = readdir(dir);
-       while (de) {
-               if (strchr(de->d_name, ':'))
+       for (de = readdir(dir); de; de = readdir(dir)) {
+               int count;
+
+               if (de->d_type != DT_DIR)
+                       continue;
+
+               count = sscanf(de->d_name, "%d:%d:%d:%d", &host, &bus, &target, &lun);
+               if (count == 4)
                        break;
-               de = readdir(dir);
        }
        closedir(dir);
 
        if (!de)
                return 1;
 
-       c1 = de->d_name;
-       c2 = strchr(c1, ':');
-       *c2 = '\0';
-       *id = strtol(c1, NULL, 10) << 24; /* host */
-       c1 = c2 + 1;
-       c2 = strchr(c1, ':');
-       *c2 = '\0';
-       *id |= strtol(c1, NULL, 10) << 16; /* bus */
-       c1 = c2 + 1;
-       c2 = strchr(c1, ':');
-       *c2 = '\0';
-       *id |= strtol(c1, NULL, 10) << 8; /* target */
-       c1 = c2 + 1;
-       *id |= strtol(c1, NULL, 10); /* lun */
-
+       *id = (host << 24) | (bus << 16) | (target << 8) | (lun << 0);
        return 0;
 }