]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
super1: only set clustered flag when bitmap is present
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 21a63c9a638ca9e6bbb6d5a1b2ea4b5e6d3efaa5..c1c850956b12654024e92dcfe73ed3eb3bee3948 100644 (file)
--- a/util.c
+++ b/util.c
@@ -200,21 +200,41 @@ out:
        return ret;
 }
 
-int md_array_active(int fd)
+int md_array_valid(int fd)
 {
        struct mdinfo *sra;
-       struct mdu_array_info_s array;
        int ret;
 
        sra = sysfs_read(fd, NULL, GET_ARRAY_STATE);
        if (sra) {
-               if (sra->array_state != ARRAY_CLEAR &&
-                   sra->array_state != ARRAY_INACTIVE &&
-                   sra->array_state != ARRAY_UNKNOWN_STATE)
+               if (sra->array_state != ARRAY_UNKNOWN_STATE)
                        ret = 0;
                else
                        ret = -ENODEV;
 
+               free(sra);
+       } else {
+               /*
+                * GET_ARRAY_INFO doesn't provide access to the proper state
+                * information, so fallback to a basic check for raid_disks != 0
+                */
+               ret = ioctl(fd, RAID_VERSION);
+       }
+
+       return !ret;
+}
+
+int md_array_active(int fd)
+{
+       struct mdinfo *sra;
+       struct mdu_array_info_s array;
+       int ret = 0;
+
+       sra = sysfs_read(fd, NULL, GET_ARRAY_STATE);
+       if (sra) {
+               if (!md_array_is_active(sra))
+                       ret = -ENODEV;
+
                free(sra);
        } else {
                /*
@@ -227,6 +247,13 @@ int md_array_active(int fd)
        return !ret;
 }
 
+int md_array_is_active(struct mdinfo *info)
+{
+       return (info->array_state != ARRAY_CLEAR &&
+               info->array_state != ARRAY_INACTIVE &&
+               info->array_state != ARRAY_UNKNOWN_STATE);
+}
+
 /*
  * Get array info from the kernel. Longer term we want to deprecate the
  * ioctl and get it from sysfs.
@@ -706,6 +733,40 @@ int check_raid(int fd, char *name)
        return 1;
 }
 
+int fstat_is_blkdev(int fd, char *devname, dev_t *rdev)
+{
+       struct stat stb;
+
+       if (fstat(fd, &stb) != 0) {
+               pr_err("fstat failed for %s: %s\n", devname, strerror(errno));
+               return 0;
+       }
+       if ((S_IFMT & stb.st_mode) != S_IFBLK) {
+               pr_err("%s is not a block device.\n", devname);
+               return 0;
+       }
+       if (rdev)
+               *rdev = stb.st_rdev;
+       return 1;
+}
+
+int stat_is_blkdev(char *devname, dev_t *rdev)
+{
+       struct stat stb;
+
+       if (stat(devname, &stb) != 0) {
+               pr_err("stat failed for %s: %s\n", devname, strerror(errno));
+               return 0;
+       }
+       if ((S_IFMT & stb.st_mode) != S_IFBLK) {
+               pr_err("%s is not a block device.\n", devname);
+               return 0;
+       }
+       if (rdev)
+               *rdev = stb.st_rdev;
+       return 1;
+}
+
 int ask(char *mesg)
 {
        char *add = "";
@@ -956,21 +1017,18 @@ char *get_md_name(char *devnm)
        if (strncmp(devnm, "md_", 3) == 0) {
                snprintf(devname, sizeof(devname), "/dev/md/%s",
                        devnm + 3);
-               if (stat(devname, &stb) == 0
-                   && (S_IFMT&stb.st_mode) == S_IFBLK
-                   && (stb.st_rdev == rdev))
+               if (stat(devname, &stb) == 0 &&
+                   (S_IFMT&stb.st_mode) == S_IFBLK && (stb.st_rdev == rdev))
                        return devname;
        }
        snprintf(devname, sizeof(devname), "/dev/%s", devnm);
-       if (stat(devname, &stb) == 0
-           && (S_IFMT&stb.st_mode) == S_IFBLK
-           && (stb.st_rdev == rdev))
+       if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
+           (stb.st_rdev == rdev))
                return devname;
 
        snprintf(devname, sizeof(devname), "/dev/md/%s", devnm+2);
-       if (stat(devname, &stb) == 0
-           && (S_IFMT&stb.st_mode) == S_IFBLK
-           && (stb.st_rdev == rdev))
+       if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
+           (stb.st_rdev == rdev))
                return devname;
 
        dn = map_dev(major(rdev), minor(rdev), 0);
@@ -981,9 +1039,8 @@ char *get_md_name(char *devnm)
                if (errno != EEXIST)
                        return NULL;
 
-       if (stat(devname, &stb) == 0
-           && (S_IFMT&stb.st_mode) == S_IFBLK
-           && (stb.st_rdev == rdev))
+       if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
+           (stb.st_rdev == rdev))
                return devname;
        unlink(devname);
        return NULL;
@@ -1115,7 +1172,7 @@ void wait_for(char *dev, int fd)
                        delay *= 2;
        }
        if (i == 25)
-               dprintf("timeout waiting for %s\n", dev);
+               pr_err("timeout waiting for %s\n", dev);
 }
 
 struct superswitch *superlist[] =
@@ -1207,6 +1264,23 @@ int dev_size_from_id(dev_t id, unsigned long long *size)
        return 0;
 }
 
+int dev_sector_size_from_id(dev_t id, unsigned int *size)
+{
+       char buf[20];
+       int fd;
+
+       sprintf(buf, "%d:%d", major(id), minor(id));
+       fd = dev_open(buf, O_RDONLY);
+       if (fd < 0)
+               return 0;
+       if (get_dev_sector_size(fd, NULL, size)) {
+               close(fd);
+               return 1;
+       }
+       close(fd);
+       return 0;
+}
+
 struct supertype *dup_super(struct supertype *orig)
 {
        struct supertype *st;
@@ -2049,7 +2123,7 @@ int experimental(void)
  * if spare_group given add it to domains of each spare
  * metadata allows to test domains using metadata of destination array */
 struct mdinfo *container_choose_spares(struct supertype *st,
-                                      unsigned long long min_size,
+                                      struct spare_criteria *criteria,
                                       struct domainlist *domlist,
                                       char *spare_group,
                                       const char *metadata, int get_one)
@@ -2071,12 +2145,24 @@ struct mdinfo *container_choose_spares(struct supertype *st,
                if (d->disk.state == 0) {
                        /* check if size is acceptable */
                        unsigned long long dev_size;
+                       unsigned int dev_sector_size;
+                       int size_valid = 0;
+                       int sector_size_valid = 0;
+
                        dev_t dev = makedev(d->disk.major,d->disk.minor);
 
-                       if (!min_size ||
+                       if (!criteria->min_size ||
                           (dev_size_from_id(dev,  &dev_size) &&
-                           dev_size >= min_size))
-                               found = 1;
+                           dev_size >= criteria->min_size))
+                               size_valid = 1;
+
+                       if (!criteria->sector_size ||
+                           (dev_sector_size_from_id(dev, &dev_sector_size) &&
+                            criteria->sector_size == dev_sector_size))
+                               sector_size_valid = 1;
+
+                       found = size_valid && sector_size_valid;
+
                        /* check if domain matches */
                        if (found && domlist) {
                                struct dev_policy *pol = devid_policy(dev);
@@ -2130,8 +2216,7 @@ void enable_fds(int devices)
 {
        unsigned int fds = 20 + devices;
        struct rlimit lim;
-       if (getrlimit(RLIMIT_NOFILE, &lim) != 0
-           || lim.rlim_cur >= fds)
+       if (getrlimit(RLIMIT_NOFILE, &lim) != 0 || lim.rlim_cur >= fds)
                return;
        if (lim.rlim_max < fds)
                lim.rlim_max = fds;