Blame SOURCES/0024-imsm-use-same-slot-across-container.patch

fdf7c0
From 6d4d9ab295de165e57b5c30e044028dbffb8f297 Mon Sep 17 00:00:00 2001
fdf7c0
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
fdf7c0
Date: Tue, 21 Jun 2022 00:10:42 +0800
01ff50
Subject: [PATCH 24/83] imsm: use same slot across container
fdf7c0
fdf7c0
Autolayout relies on drives order on super->disks list, but
fdf7c0
it is not quaranted by readdir() in sysfs_read(). As a result
fdf7c0
drive could be put in different slot in second volume.
fdf7c0
fdf7c0
Make it consistent by reffering to first volume, if exists.
fdf7c0
fdf7c0
Use enum imsm_status to unify error handling.
fdf7c0
fdf7c0
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
fdf7c0
Acked-by: Coly Li <colyli@suse.de>
fdf7c0
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
fdf7c0
---
fdf7c0
 super-intel.c | 169 ++++++++++++++++++++++++++++++++------------------
fdf7c0
 1 file changed, 108 insertions(+), 61 deletions(-)
fdf7c0
fdf7c0
diff --git a/super-intel.c b/super-intel.c
fdf7c0
index cd1f1e3d..deef7c87 100644
fdf7c0
--- a/super-intel.c
fdf7c0
+++ b/super-intel.c
fdf7c0
@@ -7522,11 +7522,27 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
fdf7c0
 	return 1;
fdf7c0
 }
fdf7c0
 
fdf7c0
-static int imsm_get_free_size(struct supertype *st, int raiddisks,
fdf7c0
-			 unsigned long long size, int chunk,
fdf7c0
-			 unsigned long long *freesize)
fdf7c0
+/**
fdf7c0
+ * imsm_get_free_size() - get the biggest, common free space from members.
fdf7c0
+ * @super: &intel_super pointer, not NULL.
fdf7c0
+ * @raiddisks: number of raid disks.
fdf7c0
+ * @size: requested size, could be 0 (means max size).
fdf7c0
+ * @chunk: requested chunk.
fdf7c0
+ * @freesize: pointer for returned size value.
fdf7c0
+ *
fdf7c0
+ * Return: &IMSM_STATUS_OK or &IMSM_STATUS_ERROR.
fdf7c0
+ *
fdf7c0
+ * @freesize is set to meaningful value, this can be @size, or calculated
fdf7c0
+ * max free size.
fdf7c0
+ * super->create_offset value is modified and set appropriately in
fdf7c0
+ * merge_extends() for further creation.
fdf7c0
+ */
fdf7c0
+static imsm_status_t imsm_get_free_size(struct intel_super *super,
fdf7c0
+					const int raiddisks,
fdf7c0
+					unsigned long long size,
fdf7c0
+					const int chunk,
fdf7c0
+					unsigned long long *freesize)
fdf7c0
 {
fdf7c0
-	struct intel_super *super = st->sb;
fdf7c0
 	struct imsm_super *mpb = super->anchor;
fdf7c0
 	struct dl *dl;
fdf7c0
 	int i;
fdf7c0
@@ -7570,12 +7586,10 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
fdf7c0
 		/* chunk is in K */
fdf7c0
 		minsize = chunk * 2;
fdf7c0
 
fdf7c0
-	if (cnt < raiddisks ||
fdf7c0
-	    (super->orom && used && used != raiddisks) ||
fdf7c0
-	    maxsize < minsize ||
fdf7c0
-	    maxsize == 0) {
fdf7c0
+	if (cnt < raiddisks || (super->orom && used && used != raiddisks) ||
fdf7c0
+	    maxsize < minsize || maxsize == 0) {
fdf7c0
 		pr_err("not enough devices with space to create array.\n");
fdf7c0
-		return 0; /* No enough free spaces large enough */
fdf7c0
+		return IMSM_STATUS_ERROR;
fdf7c0
 	}
fdf7c0
 
fdf7c0
 	if (size == 0) {
fdf7c0
@@ -7588,37 +7602,69 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
fdf7c0
 	}
fdf7c0
 	if (mpb->num_raid_devs > 0 && size && size != maxsize)
fdf7c0
 		pr_err("attempting to create a second volume with size less then remaining space.\n");
fdf7c0
-	cnt = 0;
fdf7c0
-	for (dl = super->disks; dl; dl = dl->next)
fdf7c0
-		if (dl->e)
fdf7c0
-			dl->raiddisk = cnt++;
fdf7c0
-
fdf7c0
 	*freesize = size;
fdf7c0
 
fdf7c0
 	dprintf("imsm: imsm_get_free_size() returns : %llu\n", size);
fdf7c0
 
fdf7c0
-	return 1;
fdf7c0
+	return IMSM_STATUS_OK;
fdf7c0
 }
fdf7c0
 
fdf7c0
-static int reserve_space(struct supertype *st, int raiddisks,
fdf7c0
-			 unsigned long long size, int chunk,
fdf7c0
-			 unsigned long long *freesize)
fdf7c0
+/**
fdf7c0
+ * autolayout_imsm() - automatically layout a new volume.
fdf7c0
+ * @super: &intel_super pointer, not NULL.
fdf7c0
+ * @raiddisks: number of raid disks.
fdf7c0
+ * @size: requested size, could be 0 (means max size).
fdf7c0
+ * @chunk: requested chunk.
fdf7c0
+ * @freesize: pointer for returned size value.
fdf7c0
+ *
fdf7c0
+ * We are being asked to automatically layout a new volume based on the current
fdf7c0
+ * contents of the container. If the parameters can be satisfied autolayout_imsm
fdf7c0
+ * will record the disks, start offset, and will return size of the volume to
fdf7c0
+ * be created. See imsm_get_free_size() for details.
fdf7c0
+ * add_to_super() and getinfo_super() detect when autolayout is in progress.
fdf7c0
+ * If first volume exists, slots are set consistently to it.
fdf7c0
+ *
fdf7c0
+ * Return: &IMSM_STATUS_OK on success, &IMSM_STATUS_ERROR otherwise.
fdf7c0
+ *
fdf7c0
+ * Disks are marked for creation via dl->raiddisk.
fdf7c0
+ */
fdf7c0
+static imsm_status_t autolayout_imsm(struct intel_super *super,
fdf7c0
+				     const int raiddisks,
fdf7c0
+				     unsigned long long size, const int chunk,
fdf7c0
+				     unsigned long long *freesize)
fdf7c0
 {
fdf7c0
-	struct intel_super *super = st->sb;
fdf7c0
-	struct dl *dl;
fdf7c0
-	int cnt;
fdf7c0
-	int rv = 0;
fdf7c0
+	int curr_slot = 0;
fdf7c0
+	struct dl *disk;
fdf7c0
+	int vol_cnt = super->anchor->num_raid_devs;
fdf7c0
+	imsm_status_t rv;
fdf7c0
 
fdf7c0
-	rv = imsm_get_free_size(st, raiddisks, size, chunk, freesize);
fdf7c0
-	if (rv) {
fdf7c0
-		cnt = 0;
fdf7c0
-		for (dl = super->disks; dl; dl = dl->next)
fdf7c0
-			if (dl->e)
fdf7c0
-				dl->raiddisk = cnt++;
fdf7c0
-		rv = 1;
fdf7c0
+	rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize);
fdf7c0
+	if (rv != IMSM_STATUS_OK)
fdf7c0
+		return IMSM_STATUS_ERROR;
fdf7c0
+
fdf7c0
+	for (disk = super->disks; disk; disk = disk->next) {
fdf7c0
+		if (!disk->e)
fdf7c0
+			continue;
fdf7c0
+
fdf7c0
+		if (curr_slot == raiddisks)
fdf7c0
+			break;
fdf7c0
+
fdf7c0
+		if (vol_cnt == 0) {
fdf7c0
+			disk->raiddisk = curr_slot;
fdf7c0
+		} else {
fdf7c0
+			int _slot = get_disk_slot_in_dev(super, 0, disk->index);
fdf7c0
+
fdf7c0
+			if (_slot == -1) {
fdf7c0
+				pr_err("Disk %s is not used in first volume, aborting\n",
fdf7c0
+				       disk->devname);
fdf7c0
+				return IMSM_STATUS_ERROR;
fdf7c0
+			}
fdf7c0
+			disk->raiddisk = _slot;
fdf7c0
+		}
fdf7c0
+		curr_slot++;
fdf7c0
 	}
fdf7c0
 
fdf7c0
-	return rv;
fdf7c0
+	return IMSM_STATUS_OK;
fdf7c0
 }
fdf7c0
 
fdf7c0
 static int validate_geometry_imsm(struct supertype *st, int level, int layout,
fdf7c0
@@ -7654,35 +7700,35 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
fdf7c0
 	}
fdf7c0
 
fdf7c0
 	if (!dev) {
fdf7c0
-		if (st->sb) {
fdf7c0
-			struct intel_super *super = st->sb;
fdf7c0
-			if (!validate_geometry_imsm_orom(st->sb, level, layout,
fdf7c0
-							 raiddisks, chunk, size,
fdf7c0
-							 verbose))
fdf7c0
+		struct intel_super *super = st->sb;
fdf7c0
+
fdf7c0
+		/*
fdf7c0
+		 * Autolayout mode, st->sb and freesize must be set.
fdf7c0
+		 */
fdf7c0
+		if (!super || !freesize) {
fdf7c0
+			pr_vrb("freesize and superblock must be set for autolayout, aborting\n");
fdf7c0
+			return 1;
fdf7c0
+		}
fdf7c0
+
fdf7c0
+		if (!validate_geometry_imsm_orom(st->sb, level, layout,
fdf7c0
+						 raiddisks, chunk, size,
fdf7c0
+						 verbose))
fdf7c0
+			return 0;
fdf7c0
+
fdf7c0
+		if (super->orom) {
fdf7c0
+			imsm_status_t rv;
fdf7c0
+			int count = count_volumes(super->hba, super->orom->dpa,
fdf7c0
+					      verbose);
fdf7c0
+			if (super->orom->vphba <= count) {
fdf7c0
+				pr_vrb("platform does not support more than %d raid volumes.\n",
fdf7c0
+				       super->orom->vphba);
fdf7c0
 				return 0;
fdf7c0
-			/* we are being asked to automatically layout a
fdf7c0
-			 * new volume based on the current contents of
fdf7c0
-			 * the container.  If the the parameters can be
fdf7c0
-			 * satisfied reserve_space will record the disks,
fdf7c0
-			 * start offset, and size of the volume to be
fdf7c0
-			 * created.  add_to_super and getinfo_super
fdf7c0
-			 * detect when autolayout is in progress.
fdf7c0
-			 */
fdf7c0
-			/* assuming that freesize is always given when array is
fdf7c0
-			   created */
fdf7c0
-			if (super->orom && freesize) {
fdf7c0
-				int count;
fdf7c0
-				count = count_volumes(super->hba,
fdf7c0
-						      super->orom->dpa, verbose);
fdf7c0
-				if (super->orom->vphba <= count) {
fdf7c0
-					pr_vrb("platform does not support more than %d raid volumes.\n",
fdf7c0
-					       super->orom->vphba);
fdf7c0
-					return 0;
fdf7c0
-				}
fdf7c0
 			}
fdf7c0
-			if (freesize)
fdf7c0
-				return reserve_space(st, raiddisks, size,
fdf7c0
-						     *chunk, freesize);
fdf7c0
+
fdf7c0
+			rv = autolayout_imsm(super, raiddisks, size, *chunk,
fdf7c0
+					     freesize);
fdf7c0
+			if (rv != IMSM_STATUS_OK)
fdf7c0
+				return 0;
fdf7c0
 		}
fdf7c0
 		return 1;
fdf7c0
 	}
fdf7c0
@@ -11538,7 +11584,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
fdf7c0
 	unsigned long long current_size;
fdf7c0
 	unsigned long long free_size;
fdf7c0
 	unsigned long long max_size;
fdf7c0
-	int rv;
fdf7c0
+	imsm_status_t rv;
fdf7c0
 
fdf7c0
 	getinfo_super_imsm_volume(st, &info, NULL);
fdf7c0
 	if (geo->level != info.array.level && geo->level >= 0 &&
fdf7c0
@@ -11657,9 +11703,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
fdf7c0
 		}
fdf7c0
 		/* check the maximum available size
fdf7c0
 		 */
fdf7c0
-		rv =  imsm_get_free_size(st, dev->vol.map->num_members,
fdf7c0
-					 0, chunk, &free_size);
fdf7c0
-		if (rv == 0)
fdf7c0
+		rv = imsm_get_free_size(super, dev->vol.map->num_members,
fdf7c0
+					0, chunk, &free_size);
fdf7c0
+
fdf7c0
+		if (rv != IMSM_STATUS_OK)
fdf7c0
 			/* Cannot find maximum available space
fdf7c0
 			 */
fdf7c0
 			max_size = 0;
fdf7c0
-- 
01ff50
2.38.1
fdf7c0