dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/Allow-more-spare-selection-criteria.patch

dd3a91
commit fbfdcb06dc5b1dcb227b0394f174faa2df734700
dd3a91
Author: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
dd3a91
Date:   Tue May 9 12:25:46 2017 +0200
dd3a91
dd3a91
    Allow more spare selection criteria
dd3a91
    
dd3a91
    Disks can be moved across containers in order to be used as a spare
dd3a91
    drive for reubild. At the moment the only requirement checked for such
dd3a91
    disk is its size (if it matches donor expectations). In order to
dd3a91
    introduce more criteria rename corresponding superswitch method to more
dd3a91
    generic name and move function parameter to a structure. This change is
dd3a91
    a big edit but it doesn't introduce any changes in code logic, it just
dd3a91
    updates function naming and parameters.
dd3a91
    
dd3a91
    Signed-off-by: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
dd3a91
    Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
dd3a91
    Signed-off-by: Jes Sorensen <jsorensen@fb.com>
dd3a91
dd3a91
diff --git a/Incremental.c b/Incremental.c
dd3a91
index 680d318..fe9d644 100644
dd3a91
--- a/Incremental.c
dd3a91
+++ b/Incremental.c
dd3a91
@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
dd3a91
 		struct domainlist *dl = NULL;
dd3a91
 		struct mdinfo *sra;
dd3a91
 		unsigned long long devsize;
dd3a91
-		unsigned long long component_size = 0;
dd3a91
+		struct spare_criteria sc = {0};
dd3a91
 
dd3a91
 		if (is_subarray(mp->metadata))
dd3a91
 			continue;
dd3a91
@@ -936,7 +936,8 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
dd3a91
 			}
dd3a91
 			if (st3->ss->load_container &&
dd3a91
 			    !st3->ss->load_container(st3, mdfd, mp->path)) {
dd3a91
-				component_size = st3->ss->min_acceptable_spare_size(st3);
dd3a91
+				if (st3->ss->get_spare_criteria)
dd3a91
+					st3->ss->get_spare_criteria(st3, &sc);
dd3a91
 				st3->ss->free_super(st3);
dd3a91
 			}
dd3a91
 			free(st3);
dd3a91
@@ -947,7 +948,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
dd3a91
					 : INVALID_SECTORS)
dd3a91
		     < sra->component_size)
dd3a91
		    ||
dd3a91
-		    (sra->component_size == 0 && devsize < component_size)) {
dd3a91
+		    (sra->component_size == 0 && devsize < sc.min_size)) {
dd3a91
 			if (verbose > 1)
dd3a91
 				pr_err("not adding %s to %s as it is too small\n",
dd3a91
 					devname, mp->path);
dd3a91
@@ -1624,12 +1625,15 @@ static int Incremental_container(struct supertype *st, char *devname,
dd3a91
 		struct supertype *sst =
dd3a91
 			super_imsm.match_metadata_desc("imsm");
dd3a91
 		struct mdinfo *sinfo;
dd3a91
-		unsigned long long min_size = 0;
dd3a91
-		if (st->ss->min_acceptable_spare_size)
dd3a91
-			min_size = st->ss->min_acceptable_spare_size(st);
dd3a91
+
dd3a91
 		if (!sst->ss->load_container(sst, sfd, NULL)) {
dd3a91
+			struct spare_criteria sc = {0};
dd3a91
+
dd3a91
+			if (st->ss->get_spare_criteria)
dd3a91
+				st->ss->get_spare_criteria(st, &sc);
dd3a91
+
dd3a91
 			close(sfd);
dd3a91
-			sinfo = container_choose_spares(sst, min_size,
dd3a91
+			sinfo = container_choose_spares(sst, &sc,
dd3a91
 							domains, NULL,
dd3a91
 							st->ss->name, 0);
dd3a91
 			sst->ss->free_super(sst);
dd3a91
diff --git a/Monitor.c b/Monitor.c
dd3a91
index ec643d4..9a2baad 100644
dd3a91
--- a/Monitor.c
dd3a91
+++ b/Monitor.c
dd3a91
@@ -723,13 +723,14 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
dd3a91
 	return new_found;
dd3a91
 }
dd3a91
 
dd3a91
-static int get_min_spare_size_required(struct state *st, unsigned long long *sizep)
dd3a91
+static int get_required_spare_criteria(struct state *st,
dd3a91
+				       struct spare_criteria *sc)
dd3a91
 {
dd3a91
 	int fd;
dd3a91
 
dd3a91
 	if (!st->metadata ||
dd3a91
-	    !st->metadata->ss->min_acceptable_spare_size) {
dd3a91
-		*sizep = 0;
dd3a91
+	    !st->metadata->ss->get_spare_criteria) {
dd3a91
+		sc->min_size = 0;
dd3a91
 		return 0;
dd3a91
 	}
dd3a91
 
dd3a91
@@ -743,7 +744,8 @@ static int get_min_spare_size_required(struct state *st, unsigned long long *siz
dd3a91
 	close(fd);
dd3a91
 	if (!st->metadata->sb)
dd3a91
 		return 1;
dd3a91
-	*sizep = st->metadata->ss->min_acceptable_spare_size(st->metadata);
dd3a91
+
dd3a91
+	st->metadata->ss->get_spare_criteria(st->metadata, sc);
dd3a91
 	st->metadata->ss->free_super(st->metadata);
dd3a91
 
dd3a91
 	return 0;
dd3a91
@@ -775,7 +777,7 @@ static int check_donor(struct state *from, struct state *to)
dd3a91
 }
dd3a91
 
dd3a91
 static dev_t choose_spare(struct state *from, struct state *to,
dd3a91
-			struct domainlist *domlist, unsigned long long min_size)
dd3a91
+			struct domainlist *domlist, struct spare_criteria *sc)
dd3a91
 {
dd3a91
 	int d;
dd3a91
 	dev_t dev = 0;
dd3a91
@@ -790,9 +792,9 @@ static dev_t choose_spare(struct state *from, struct state *to,
dd3a91
 			    test_partition_from_id(from->devid[d]))
dd3a91
 				continue;
dd3a91
 
dd3a91
-			if (min_size &&
dd3a91
+			if (sc->min_size &&
dd3a91
 			    dev_size_from_id(from->devid[d], &dev_size) &&
dd3a91
-			    dev_size < min_size)
dd3a91
+			    dev_size < sc->min_size)
dd3a91
 				continue;
dd3a91
 
dd3a91
 			pol = devid_policy(from->devid[d]);
dd3a91
@@ -809,7 +811,7 @@ static dev_t choose_spare(struct state *from, struct state *to,
dd3a91
 
dd3a91
 static dev_t container_choose_spare(struct state *from, struct state *to,
dd3a91
 				    struct domainlist *domlist,
dd3a91
-				    unsigned long long min_size, int active)
dd3a91
+				    struct spare_criteria *sc, int active)
dd3a91
 {
dd3a91
 	/* This is similar to choose_spare, but we cannot trust devstate,
dd3a91
 	 * so we need to read the metadata instead
dd3a91
@@ -860,7 +862,7 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
dd3a91
 	}
dd3a91
 
dd3a91
 	/* We only need one spare so full list not needed */
dd3a91
-	list = container_choose_spares(st, min_size, domlist, from->spare_group,
dd3a91
+	list = container_choose_spares(st, sc, domlist, from->spare_group,
dd3a91
 				       to->metadata->ss->name, 1);
dd3a91
 	if (list) {
dd3a91
 		struct mdinfo *disks = list->devs;
dd3a91
@@ -876,6 +878,7 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
dd3a91
 {
dd3a91
 	struct state *from;
dd3a91
 	struct state *st;
dd3a91
+	struct spare_criteria sc;
dd3a91
 
dd3a91
 	link_containers_with_subarrays(statelist);
dd3a91
 	for (st = statelist; st; st = st->next)
dd3a91
@@ -884,7 +887,6 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
dd3a91
 			struct domainlist *domlist = NULL;
dd3a91
 			int d;
dd3a91
 			struct state *to = st;
dd3a91
-			unsigned long long min_size;
dd3a91
 
dd3a91
 			if (to->parent_devnm[0] && !to->parent)
dd3a91
 				/* subarray monitored without parent container
dd3a91
@@ -895,14 +897,14 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
dd3a91
 				/* member of a container */
dd3a91
 				to = to->parent;
dd3a91
 
dd3a91
-			if (get_min_spare_size_required(to, &min_size))
dd3a91
+			if (get_required_spare_criteria(to, &sc))
dd3a91
 				continue;
dd3a91
 			if (to->metadata->ss->external) {
dd3a91
 				/* We must make sure there is
dd3a91
 				 * no suitable spare in container already.
dd3a91
 				 * If there is we don't add more */
dd3a91
 				dev_t devid = container_choose_spare(
dd3a91
-					to, to, NULL, min_size, st->active);
dd3a91
+					to, to, NULL, &sc, st->active);
dd3a91
 				if (devid > 0)
dd3a91
 					continue;
dd3a91
 			}
dd3a91
@@ -925,10 +927,10 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
dd3a91
 					continue;
dd3a91
 				if (from->metadata->ss->external)
dd3a91
 					devid = container_choose_spare(
dd3a91
-						from, to, domlist, min_size, 0);
dd3a91
+						from, to, domlist, &sc, 0);
dd3a91
 				else
dd3a91
 					devid = choose_spare(from, to, domlist,
dd3a91
-							     min_size);
dd3a91
+							     &sc);
dd3a91
 				if (devid > 0
dd3a91
 				    && move_spare(from->devname, to->devname, devid)) {
dd3a91
 					alert("MoveSpare", to->devname, from->devname, info);
dd3a91
diff --git a/mdadm.h b/mdadm.h
dd3a91
index a92feb2..8da7fd3 100644
dd3a91
--- a/mdadm.h
dd3a91
+++ b/mdadm.h
dd3a91
@@ -361,6 +361,10 @@ struct createinfo {
dd3a91
 	struct supertype *supertype;
dd3a91
 };
dd3a91
 
dd3a91
+struct spare_criteria {
dd3a91
+	unsigned long long min_size;
dd3a91
+};
dd3a91
+
dd3a91
 enum mode {
dd3a91
 	ASSEMBLE=1,
dd3a91
 	BUILD,
dd3a91
@@ -940,11 +944,13 @@ extern struct superswitch {
dd3a91
 	 */
dd3a91
 	__u64 (*avail_size)(struct supertype *st, __u64 size,
dd3a91
 			    unsigned long long data_offset);
dd3a91
-	/* This is similar to 'avail_size' in purpose, but is used for
dd3a91
-	 * containers for which there is no 'component size' to compare.
dd3a91
-	 * This reports that whole-device size which is a minimum
dd3a91
+	/*
dd3a91
+	 * Return spare criteria for array:
dd3a91
+	 * - minimum disk size can be used in array;
dd3a91
+	 * Return values: 0 - for success and -EINVAL on error.
dd3a91
 	 */
dd3a91
-	unsigned long long (*min_acceptable_spare_size)(struct supertype *st);
dd3a91
+	int (*get_spare_criteria)(struct supertype *st,
dd3a91
+				  struct spare_criteria *sc);
dd3a91
 	/* Find somewhere to put a bitmap - possibly auto-size it - and
dd3a91
 	 * update the metadata to record this.  The array may be newly
dd3a91
 	 * created, in which case data_size may be updated, or it might
dd3a91
@@ -1507,7 +1513,7 @@ extern int assemble_container_content(struct supertype *st, int mdfd,
dd3a91
 #define	INCR_ALREADY	4
dd3a91
 #define	INCR_YES	8
dd3a91
 extern struct mdinfo *container_choose_spares(struct supertype *st,
dd3a91
-					      unsigned long long min_size,
dd3a91
+					      struct spare_criteria *criteria,
dd3a91
 					      struct domainlist *domlist,
dd3a91
 					      char *spare_group,
dd3a91
 					      const char *metadata, int get_one);
dd3a91
diff --git a/super-intel.c b/super-intel.c
dd3a91
index e88fe82..be973f8 100644
dd3a91
--- a/super-intel.c
dd3a91
+++ b/super-intel.c
dd3a91
@@ -1383,37 +1383,44 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
dd3a91
 	return  (remainder < rv) ? remainder : rv;
dd3a91
 }
dd3a91
 
dd3a91
-/* Return minimum size of a spare that can be used in this array*/
dd3a91
-static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
dd3a91
+/*
dd3a91
+ * Return minimum size of a spare and sector size
dd3a91
+ * that can be used in this array
dd3a91
+ */
dd3a91
+int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
dd3a91
 {
dd3a91
 	struct intel_super *super = st->sb;
dd3a91
 	struct dl *dl;
dd3a91
 	struct extent *e;
dd3a91
 	int i;
dd3a91
-	unsigned long long rv = 0;
dd3a91
+	unsigned long long size = 0;
dd3a91
+
dd3a91
+	c->min_size = 0;
dd3a91
 
dd3a91
 	if (!super)
dd3a91
-		return rv;
dd3a91
+		return -EINVAL;
dd3a91
 	/* find first active disk in array */
dd3a91
 	dl = super->disks;
dd3a91
 	while (dl && (is_failed(&dl->disk) || dl->index == -1))
dd3a91
 		dl = dl->next;
dd3a91
 	if (!dl)
dd3a91
-		return rv;
dd3a91
+		return -EINVAL;
dd3a91
 	/* find last lba used by subarrays */
dd3a91
 	e = get_extents(super, dl);
dd3a91
 	if (!e)
dd3a91
-		return rv;
dd3a91
+		return -EINVAL;
dd3a91
 	for (i = 0; e[i].size; i++)
dd3a91
 		continue;
dd3a91
 	if (i > 0)
dd3a91
-		rv = e[i-1].start + e[i-1].size;
dd3a91
+		size = e[i-1].start + e[i-1].size;
dd3a91
 	free(e);
dd3a91
 
dd3a91
 	/* add the amount of space needed for metadata */
dd3a91
-	rv = rv + imsm_min_reserved_sectors(super);
dd3a91
+	size += imsm_min_reserved_sectors(super);
dd3a91
+
dd3a91
+	c->min_size = size * 512;
dd3a91
 
dd3a91
-	return rv * 512;
dd3a91
+	return 0;
dd3a91
 }
dd3a91
 
dd3a91
 static int is_gen_migration(struct imsm_dev *dev);
dd3a91
@@ -10817,8 +10824,10 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
dd3a91
  */
dd3a91
 static struct mdinfo *get_spares_for_grow(struct supertype *st)
dd3a91
 {
dd3a91
-	unsigned long long min_size = min_acceptable_spare_size_imsm(st);
dd3a91
-	return container_choose_spares(st, min_size, NULL, NULL, NULL, 0);
dd3a91
+	struct spare_criteria sc;
dd3a91
+
dd3a91
+	get_spare_criteria_imsm(st, &sc);
dd3a91
+	return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
dd3a91
 }
dd3a91
 
dd3a91
 /******************************************************************************
dd3a91
@@ -11853,7 +11862,7 @@ struct superswitch super_imsm = {
dd3a91
 	.update_super	= update_super_imsm,
dd3a91
 
dd3a91
 	.avail_size	= avail_size_imsm,
dd3a91
-	.min_acceptable_spare_size = min_acceptable_spare_size_imsm,
dd3a91
+	.get_spare_criteria = get_spare_criteria_imsm,
dd3a91
 
dd3a91
 	.compare_super	= compare_super_imsm,
dd3a91
 
dd3a91
diff --git a/util.c b/util.c
dd3a91
index 11ff2cc..8b3c67d 100644
dd3a91
--- a/util.c
dd3a91
+++ b/util.c
dd3a91
@@ -2107,7 +2107,7 @@ int experimental(void)
dd3a91
  * if spare_group given add it to domains of each spare
dd3a91
  * metadata allows to test domains using metadata of destination array */
dd3a91
 struct mdinfo *container_choose_spares(struct supertype *st,
dd3a91
-				       unsigned long long min_size,
dd3a91
+				       struct spare_criteria *criteria,
dd3a91
 				       struct domainlist *domlist,
dd3a91
 				       char *spare_group,
dd3a91
 				       const char *metadata, int get_one)
dd3a91
@@ -2131,9 +2131,9 @@ struct mdinfo *container_choose_spares(struct supertype *st,
dd3a91
 			unsigned long long dev_size;
dd3a91
 			dev_t dev = makedev(d->disk.major,d->disk.minor);
dd3a91
 
dd3a91
-			if (!min_size ||
dd3a91
+			if (!criteria->min_size ||
dd3a91
 			   (dev_size_from_id(dev,  &dev_size) &&
dd3a91
-			    dev_size >= min_size))
dd3a91
+			    dev_size >= criteria->min_size))
dd3a91
 				found = 1;
dd3a91
 			/* check if domain matches */
dd3a91
 			if (found && domlist) {