Add sector size as spare selection criterion
authorAlexey Obitotskiy <aleksey.obitotskiy@intel.com>
Tue, 9 May 2017 10:25:47 +0000 (12:25 +0200)
committerJes Sorensen <jsorensen@fb.com>
Tue, 9 May 2017 18:18:38 +0000 (14:18 -0400)
Add sector size as new spare selection criterion. Assume that 0 means
there is no requirement for the sector size in the array. Skip disks
with unsuitable sector size when looking for a spare to move across
containers.

Signed-off-by: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
Incremental.c
Monitor.c
mdadm.h
super-intel.c
util.c

index fe9d644..30dc7a2 100644 (file)
@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                struct domainlist *dl = NULL;
                struct mdinfo *sra;
                unsigned long long devsize;
-               struct spare_criteria sc = {0};
+               struct spare_criteria sc = {0, 0};
 
                if (is_subarray(mp->metadata))
                        continue;
@@ -1627,7 +1627,7 @@ static int Incremental_container(struct supertype *st, char *devname,
                struct mdinfo *sinfo;
 
                if (!sst->ss->load_container(sst, sfd, NULL)) {
-                       struct spare_criteria sc = {0};
+                       struct spare_criteria sc = {0, 0};
 
                        if (st->ss->get_spare_criteria)
                                st->ss->get_spare_criteria(st, &sc);
index 9a2baad..c96f8e8 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -731,6 +731,7 @@ static int get_required_spare_criteria(struct state *st,
        if (!st->metadata ||
            !st->metadata->ss->get_spare_criteria) {
                sc->min_size = 0;
+               sc->sector_size = 0;
                return 0;
        }
 
@@ -787,6 +788,7 @@ static dev_t choose_spare(struct state *from, struct state *to,
                    from->devstate[d] == 0) {
                        struct dev_policy *pol;
                        unsigned long long dev_size;
+                       unsigned int dev_sector_size;
 
                        if (to->metadata->ss->external &&
                            test_partition_from_id(from->devid[d]))
@@ -797,6 +799,12 @@ static dev_t choose_spare(struct state *from, struct state *to,
                            dev_size < sc->min_size)
                                continue;
 
+                       if (sc->sector_size &&
+                           dev_sector_size_from_id(from->devid[d],
+                                                   &dev_sector_size) &&
+                           sc->sector_size != dev_sector_size)
+                               continue;
+
                        pol = devid_policy(from->devid[d]);
                        if (from->spare_group)
                                pol_add(&pol, pol_domain,
diff --git a/mdadm.h b/mdadm.h
index 8da7fd3..ec0a39e 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -363,6 +363,7 @@ struct createinfo {
 
 struct spare_criteria {
        unsigned long long min_size;
+       unsigned int sector_size;
 };
 
 enum mode {
@@ -947,6 +948,7 @@ extern struct superswitch {
        /*
         * Return spare criteria for array:
         * - minimum disk size can be used in array;
+        * - sector size can be used in array.
         * Return values: 0 - for success and -EINVAL on error.
         */
        int (*get_spare_criteria)(struct supertype *st,
@@ -1189,6 +1191,7 @@ extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
 extern int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep);
 extern int must_be_container(int fd);
 extern int dev_size_from_id(dev_t id, unsigned long long *size);
+extern int dev_sector_size_from_id(dev_t id, unsigned int *size);
 void wait_for(char *dev, int fd);
 
 /*
index be973f8..ba6f810 100644 (file)
@@ -1396,6 +1396,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
        unsigned long long size = 0;
 
        c->min_size = 0;
+       c->sector_size = 0;
 
        if (!super)
                return -EINVAL;
@@ -1419,6 +1420,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
        size += imsm_min_reserved_sectors(super);
 
        c->min_size = size * 512;
+       c->sector_size = super->sector_size;
 
        return 0;
 }
diff --git a/util.c b/util.c
index 8b3c67d..fc9cd3f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1265,6 +1265,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;
@@ -2129,12 +2146,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 (!criteria->min_size ||
                           (dev_size_from_id(dev,  &dev_size) &&
                            dev_size >= criteria->min_size))
-                               found = 1;
+                               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);