dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/Add-sector-size-as-spare-selection-criterion.patch

2c1b57
commit 4b57ecf6cea134edff75a2f3a87ee48d52715c70
2c1b57
Author: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
2c1b57
Date:   Tue May 9 12:25:47 2017 +0200
2c1b57
2c1b57
    Add sector size as spare selection criterion
2c1b57
    
2c1b57
    Add sector size as new spare selection criterion. Assume that 0 means
2c1b57
    there is no requirement for the sector size in the array. Skip disks
2c1b57
    with unsuitable sector size when looking for a spare to move across
2c1b57
    containers.
2c1b57
    
2c1b57
    Signed-off-by: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
2c1b57
    Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
2c1b57
    Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2c1b57
2c1b57
diff --git a/Incremental.c b/Incremental.c
2c1b57
index fe9d644..30dc7a2 100644
2c1b57
--- a/Incremental.c
2c1b57
+++ b/Incremental.c
2c1b57
@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
2c1b57
 		struct domainlist *dl = NULL;
2c1b57
 		struct mdinfo *sra;
2c1b57
 		unsigned long long devsize;
2c1b57
-		struct spare_criteria sc = {0};
2c1b57
+		struct spare_criteria sc = {0, 0};
2c1b57
 
2c1b57
 		if (is_subarray(mp->metadata))
2c1b57
 			continue;
2c1b57
@@ -1627,7 +1627,7 @@ static int Incremental_container(struct supertype *st, char *devname,
2c1b57
 		struct mdinfo *sinfo;
2c1b57
 
2c1b57
 		if (!sst->ss->load_container(sst, sfd, NULL)) {
2c1b57
-			struct spare_criteria sc = {0};
2c1b57
+			struct spare_criteria sc = {0, 0};
2c1b57
 
2c1b57
 			if (st->ss->get_spare_criteria)
2c1b57
 				st->ss->get_spare_criteria(st, &sc);
2c1b57
diff --git a/Monitor.c b/Monitor.c
2c1b57
index 9a2baad..c96f8e8 100644
2c1b57
--- a/Monitor.c
2c1b57
+++ b/Monitor.c
2c1b57
@@ -731,6 +731,7 @@ static int get_required_spare_criteria(struct state *st,
2c1b57
 	if (!st->metadata ||
2c1b57
 	    !st->metadata->ss->get_spare_criteria) {
2c1b57
 		sc->min_size = 0;
2c1b57
+		sc->sector_size = 0;
2c1b57
 		return 0;
2c1b57
 	}
2c1b57
 
2c1b57
@@ -787,6 +788,7 @@ static dev_t choose_spare(struct state *from, struct state *to,
2c1b57
 		    from->devstate[d] == 0) {
2c1b57
 			struct dev_policy *pol;
2c1b57
 			unsigned long long dev_size;
2c1b57
+			unsigned int dev_sector_size;
2c1b57
 
2c1b57
 			if (to->metadata->ss->external &&
2c1b57
 			    test_partition_from_id(from->devid[d]))
2c1b57
@@ -797,6 +799,12 @@ static dev_t choose_spare(struct state *from, struct state *to,
2c1b57
 			    dev_size < sc->min_size)
2c1b57
 				continue;
2c1b57
 
2c1b57
+			if (sc->sector_size &&
2c1b57
+			    dev_sector_size_from_id(from->devid[d],
2c1b57
+						    &dev_sector_size) &&
2c1b57
+			    sc->sector_size != dev_sector_size)
2c1b57
+				continue;
2c1b57
+
2c1b57
 			pol = devid_policy(from->devid[d]);
2c1b57
 			if (from->spare_group)
2c1b57
 				pol_add(&pol, pol_domain,
2c1b57
diff --git a/mdadm.h b/mdadm.h
2c1b57
index 8da7fd3..ec0a39e 100644
2c1b57
--- a/mdadm.h
2c1b57
+++ b/mdadm.h
2c1b57
@@ -363,6 +363,7 @@ struct createinfo {
2c1b57
 
2c1b57
 struct spare_criteria {
2c1b57
 	unsigned long long min_size;
2c1b57
+	unsigned int sector_size;
2c1b57
 };
2c1b57
 
2c1b57
 enum mode {
2c1b57
@@ -947,6 +948,7 @@ extern struct superswitch {
2c1b57
 	/*
2c1b57
 	 * Return spare criteria for array:
2c1b57
 	 * - minimum disk size can be used in array;
2c1b57
+	 * - sector size can be used in array.
2c1b57
 	 * Return values: 0 - for success and -EINVAL on error.
2c1b57
 	 */
2c1b57
 	int (*get_spare_criteria)(struct supertype *st,
2c1b57
@@ -1189,6 +1191,7 @@ extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
2c1b57
 extern int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep);
2c1b57
 extern int must_be_container(int fd);
2c1b57
 extern int dev_size_from_id(dev_t id, unsigned long long *size);
2c1b57
+extern int dev_sector_size_from_id(dev_t id, unsigned int *size);
2c1b57
 void wait_for(char *dev, int fd);
2c1b57
 
2c1b57
 /*
2c1b57
diff --git a/super-intel.c b/super-intel.c
2c1b57
index be973f8..ba6f810 100644
2c1b57
--- a/super-intel.c
2c1b57
+++ b/super-intel.c
2c1b57
@@ -1396,6 +1396,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
2c1b57
 	unsigned long long size = 0;
2c1b57
 
2c1b57
 	c->min_size = 0;
2c1b57
+	c->sector_size = 0;
2c1b57
 
2c1b57
 	if (!super)
2c1b57
 		return -EINVAL;
2c1b57
@@ -1419,6 +1420,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
2c1b57
 	size += imsm_min_reserved_sectors(super);
2c1b57
 
2c1b57
 	c->min_size = size * 512;
2c1b57
+	c->sector_size = super->sector_size;
2c1b57
 
2c1b57
 	return 0;
2c1b57
 }
2c1b57
diff --git a/util.c b/util.c
2c1b57
index 8b3c67d..fc9cd3f 100644
2c1b57
--- a/util.c
2c1b57
+++ b/util.c
2c1b57
@@ -1265,6 +1265,23 @@ int dev_size_from_id(dev_t id, unsigned long long *size)
2c1b57
 	return 0;
2c1b57
 }
2c1b57
 
2c1b57
+int dev_sector_size_from_id(dev_t id, unsigned int *size)
2c1b57
+{
2c1b57
+	char buf[20];
2c1b57
+	int fd;
2c1b57
+
2c1b57
+	sprintf(buf, "%d:%d", major(id), minor(id));
2c1b57
+	fd = dev_open(buf, O_RDONLY);
2c1b57
+	if (fd < 0)
2c1b57
+		return 0;
2c1b57
+	if (get_dev_sector_size(fd, NULL, size)) {
2c1b57
+		close(fd);
2c1b57
+		return 1;
2c1b57
+	}
2c1b57
+	close(fd);
2c1b57
+	return 0;
2c1b57
+}
2c1b57
+
2c1b57
 struct supertype *dup_super(struct supertype *orig)
2c1b57
 {
2c1b57
 	struct supertype *st;
2c1b57
@@ -2129,12 +2146,24 @@ struct mdinfo *container_choose_spares(struct supertype *st,
2c1b57
 		if (d->disk.state == 0) {
2c1b57
 			/* check if size is acceptable */
2c1b57
 			unsigned long long dev_size;
2c1b57
+			unsigned int dev_sector_size;
2c1b57
+			int size_valid = 0;
2c1b57
+			int sector_size_valid = 0;
2c1b57
+
2c1b57
 			dev_t dev = makedev(d->disk.major,d->disk.minor);
2c1b57
 
2c1b57
 			if (!criteria->min_size ||
2c1b57
 			   (dev_size_from_id(dev,  &dev_size) &&
2c1b57
 			    dev_size >= criteria->min_size))
2c1b57
-				found = 1;
2c1b57
+				size_valid = 1;
2c1b57
+
2c1b57
+			if (!criteria->sector_size ||
2c1b57
+			    (dev_sector_size_from_id(dev, &dev_sector_size) &&
2c1b57
+			     criteria->sector_size == dev_sector_size))
2c1b57
+				sector_size_valid = 1;
2c1b57
+
2c1b57
+			found = size_valid && sector_size_valid;
2c1b57
+
2c1b57
 			/* check if domain matches */
2c1b57
 			if (found && domlist) {
2c1b57
 				struct dev_policy *pol = devid_policy(dev);