Blame SOURCES/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch

fdf7c0
From 756a15f32338fdf0c562678694bc8991ad6afb90 Mon Sep 17 00:00:00 2001
fdf7c0
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
fdf7c0
Date: Mon, 13 Jun 2022 12:00:09 +0200
01ff50
Subject: [PATCH 19/83] imsm: Remove possibility for get_imsm_dev to return
fdf7c0
 NULL
fdf7c0
fdf7c0
Returning NULL from get_imsm_dev or __get_imsm_dev will cause segfault.
fdf7c0
Guarantee that it never happens.
fdf7c0
fdf7c0
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
fdf7c0
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
fdf7c0
---
fdf7c0
 super-intel.c | 153 +++++++++++++++++++++++++-------------------------
fdf7c0
 1 file changed, 78 insertions(+), 75 deletions(-)
fdf7c0
fdf7c0
diff --git a/super-intel.c b/super-intel.c
fdf7c0
index ba3bd41f..3788feb9 100644
fdf7c0
--- a/super-intel.c
fdf7c0
+++ b/super-intel.c
fdf7c0
@@ -851,6 +851,21 @@ static struct disk_info *get_disk_info(struct imsm_update_create_array *update)
fdf7c0
 	return inf;
fdf7c0
 }
fdf7c0
 
fdf7c0
+/**
fdf7c0
+ * __get_imsm_dev() - Get device with index from imsm_super.
fdf7c0
+ * @mpb: &imsm_super pointer, not NULL.
fdf7c0
+ * @index: Device index.
fdf7c0
+ *
fdf7c0
+ * Function works as non-NULL, aborting in such a case,
fdf7c0
+ * when NULL would be returned.
fdf7c0
+ *
fdf7c0
+ * Device index should be in range 0 up to num_raid_devs.
fdf7c0
+ * Function assumes the index was already verified.
fdf7c0
+ * Index must be valid, otherwise abort() is called.
fdf7c0
+ *
fdf7c0
+ * Return: Pointer to corresponding imsm_dev.
fdf7c0
+ *
fdf7c0
+ */
fdf7c0
 static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
fdf7c0
 {
fdf7c0
 	int offset;
fdf7c0
@@ -858,30 +873,47 @@ static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
fdf7c0
 	void *_mpb = mpb;
fdf7c0
 
fdf7c0
 	if (index >= mpb->num_raid_devs)
fdf7c0
-		return NULL;
fdf7c0
+		goto error;
fdf7c0
 
fdf7c0
 	/* devices start after all disks */
fdf7c0
 	offset = ((void *) &mpb->disk[mpb->num_disks]) - _mpb;
fdf7c0
 
fdf7c0
-	for (i = 0; i <= index; i++)
fdf7c0
+	for (i = 0; i <= index; i++, offset += sizeof_imsm_dev(_mpb + offset, 0))
fdf7c0
 		if (i == index)
fdf7c0
 			return _mpb + offset;
fdf7c0
-		else
fdf7c0
-			offset += sizeof_imsm_dev(_mpb + offset, 0);
fdf7c0
-
fdf7c0
-	return NULL;
fdf7c0
+error:
fdf7c0
+	pr_err("cannot find imsm_dev with index %u in imsm_super\n", index);
fdf7c0
+	abort();
fdf7c0
 }
fdf7c0
 
fdf7c0
+/**
fdf7c0
+ * get_imsm_dev() - Get device with index from intel_super.
fdf7c0
+ * @super: &intel_super pointer, not NULL.
fdf7c0
+ * @index: Device index.
fdf7c0
+ *
fdf7c0
+ * Function works as non-NULL, aborting in such a case,
fdf7c0
+ * when NULL would be returned.
fdf7c0
+ *
fdf7c0
+ * Device index should be in range 0 up to num_raid_devs.
fdf7c0
+ * Function assumes the index was already verified.
fdf7c0
+ * Index must be valid, otherwise abort() is called.
fdf7c0
+ *
fdf7c0
+ * Return: Pointer to corresponding imsm_dev.
fdf7c0
+ *
fdf7c0
+ */
fdf7c0
 static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index)
fdf7c0
 {
fdf7c0
 	struct intel_dev *dv;
fdf7c0
 
fdf7c0
 	if (index >= super->anchor->num_raid_devs)
fdf7c0
-		return NULL;
fdf7c0
+		goto error;
fdf7c0
+
fdf7c0
 	for (dv = super->devlist; dv; dv = dv->next)
fdf7c0
 		if (dv->index == index)
fdf7c0
 			return dv->dev;
fdf7c0
-	return NULL;
fdf7c0
+error:
fdf7c0
+	pr_err("cannot find imsm_dev with index %u in intel_super\n", index);
fdf7c0
+	abort();
fdf7c0
 }
fdf7c0
 
fdf7c0
 static inline unsigned long long __le48_to_cpu(const struct bbm_log_block_addr
fdf7c0
@@ -4364,8 +4396,7 @@ int check_mpb_migr_compatibility(struct intel_super *super)
fdf7c0
 	for (i = 0; i < super->anchor->num_raid_devs; i++) {
fdf7c0
 		struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i);
fdf7c0
 
fdf7c0
-		if (dev_iter &&
fdf7c0
-		    dev_iter->vol.migr_state == 1 &&
fdf7c0
+		if (dev_iter->vol.migr_state == 1 &&
fdf7c0
 		    dev_iter->vol.migr_type == MIGR_GEN_MIGR) {
fdf7c0
 			/* This device is migrating */
fdf7c0
 			map0 = get_imsm_map(dev_iter, MAP_0);
fdf7c0
@@ -4514,8 +4545,6 @@ static void clear_hi(struct intel_super *super)
fdf7c0
 	}
fdf7c0
 	for (i = 0; i < mpb->num_raid_devs; ++i) {
fdf7c0
 		struct imsm_dev *dev = get_imsm_dev(super, i);
fdf7c0
-		if (!dev)
fdf7c0
-			return;
fdf7c0
 		for (n = 0; n < 2; ++n) {
fdf7c0
 			struct imsm_map *map = get_imsm_map(dev, n);
fdf7c0
 			if (!map)
fdf7c0
@@ -5836,7 +5865,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
fdf7c0
 		struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
fdf7c0
 
fdf7c0
 		_disk = __get_imsm_disk(mpb, dl->index);
fdf7c0
-		if (!_dev || !_disk) {
fdf7c0
+		if (!_disk) {
fdf7c0
 			pr_err("BUG mpb setup error\n");
fdf7c0
 			return 1;
fdf7c0
 		}
fdf7c0
@@ -6171,10 +6200,10 @@ static int write_super_imsm(struct supertype *st, int doclose)
fdf7c0
 	for (i = 0; i < mpb->num_raid_devs; i++) {
fdf7c0
 		struct imsm_dev *dev = __get_imsm_dev(mpb, i);
fdf7c0
 		struct imsm_dev *dev2 = get_imsm_dev(super, i);
fdf7c0
-		if (dev && dev2) {
fdf7c0
-			imsm_copy_dev(dev, dev2);
fdf7c0
-			mpb_size += sizeof_imsm_dev(dev, 0);
fdf7c0
-		}
fdf7c0
+
fdf7c0
+		imsm_copy_dev(dev, dev2);
fdf7c0
+		mpb_size += sizeof_imsm_dev(dev, 0);
fdf7c0
+
fdf7c0
 		if (is_gen_migration(dev2))
fdf7c0
 			clear_migration_record = 0;
fdf7c0
 	}
fdf7c0
@@ -9033,29 +9062,26 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
fdf7c0
 	__u8 state;
fdf7c0
 
fdf7c0
 	dev2 = get_imsm_dev(cont->sb, dev_idx);
fdf7c0
-	if (dev2) {
fdf7c0
-		state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
fdf7c0
-		if (state == IMSM_T_STATE_FAILED) {
fdf7c0
-			map = get_imsm_map(dev2, MAP_0);
fdf7c0
-			if (!map)
fdf7c0
-				return 1;
fdf7c0
-			for (slot = 0; slot < map->num_members; slot++) {
fdf7c0
-				/*
fdf7c0
-				 * Check if failed disks are deleted from intel
fdf7c0
-				 * disk list or are marked to be deleted
fdf7c0
-				 */
fdf7c0
-				idx = get_imsm_disk_idx(dev2, slot, MAP_X);
fdf7c0
-				idisk = get_imsm_dl_disk(cont->sb, idx);
fdf7c0
-				/*
fdf7c0
-				 * Do not rebuild the array if failed disks
fdf7c0
-				 * from failed sub-array are not removed from
fdf7c0
-				 * container.
fdf7c0
-				 */
fdf7c0
-				if (idisk &&
fdf7c0
-				    is_failed(&idisk->disk) &&
fdf7c0
-				    (idisk->action != DISK_REMOVE))
fdf7c0
-					return 0;
fdf7c0
-			}
fdf7c0
+
fdf7c0
+	state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
fdf7c0
+	if (state == IMSM_T_STATE_FAILED) {
fdf7c0
+		map = get_imsm_map(dev2, MAP_0);
fdf7c0
+		for (slot = 0; slot < map->num_members; slot++) {
fdf7c0
+			/*
fdf7c0
+			 * Check if failed disks are deleted from intel
fdf7c0
+			 * disk list or are marked to be deleted
fdf7c0
+			 */
fdf7c0
+			idx = get_imsm_disk_idx(dev2, slot, MAP_X);
fdf7c0
+			idisk = get_imsm_dl_disk(cont->sb, idx);
fdf7c0
+			/*
fdf7c0
+			 * Do not rebuild the array if failed disks
fdf7c0
+			 * from failed sub-array are not removed from
fdf7c0
+			 * container.
fdf7c0
+			 */
fdf7c0
+			if (idisk &&
fdf7c0
+			    is_failed(&idisk->disk) &&
fdf7c0
+			    (idisk->action != DISK_REMOVE))
fdf7c0
+				return 0;
fdf7c0
 		}
fdf7c0
 	}
fdf7c0
 	return 1;
fdf7c0
@@ -10089,7 +10115,6 @@ static void imsm_process_update(struct supertype *st,
fdf7c0
 		int victim = u->dev_idx;
fdf7c0
 		struct active_array *a;
fdf7c0
 		struct intel_dev **dp;
fdf7c0
-		struct imsm_dev *dev;
fdf7c0
 
fdf7c0
 		/* sanity check that we are not affecting the uuid of
fdf7c0
 		 * active arrays, or deleting an active array
fdf7c0
@@ -10105,8 +10130,7 @@ static void imsm_process_update(struct supertype *st,
fdf7c0
 		 * is active in the container, so checking
fdf7c0
 		 * mpb->num_raid_devs is just extra paranoia
fdf7c0
 		 */
fdf7c0
-		dev = get_imsm_dev(super, victim);
fdf7c0
-		if (a || !dev || mpb->num_raid_devs == 1) {
fdf7c0
+		if (a || mpb->num_raid_devs == 1 || victim >= super->anchor->num_raid_devs) {
fdf7c0
 			dprintf("failed to delete subarray-%d\n", victim);
fdf7c0
 			break;
fdf7c0
 		}
fdf7c0
@@ -10140,7 +10164,7 @@ static void imsm_process_update(struct supertype *st,
fdf7c0
 			if (a->info.container_member == target)
fdf7c0
 				break;
fdf7c0
 		dev = get_imsm_dev(super, u->dev_idx);
fdf7c0
-		if (a || !dev || !check_name(super, name, 1)) {
fdf7c0
+		if (a || !check_name(super, name, 1)) {
fdf7c0
 			dprintf("failed to rename subarray-%d\n", target);
fdf7c0
 			break;
fdf7c0
 		}
fdf7c0
@@ -10169,10 +10193,6 @@ static void imsm_process_update(struct supertype *st,
fdf7c0
 		struct imsm_update_rwh_policy *u = (void *)update->buf;
fdf7c0
 		int target = u->dev_idx;
fdf7c0
 		struct imsm_dev *dev = get_imsm_dev(super, target);
fdf7c0
-		if (!dev) {
fdf7c0
-			dprintf("could not find subarray-%d\n", target);
fdf7c0
-			break;
fdf7c0
-		}
fdf7c0
 
fdf7c0
 		if (dev->rwh_policy != u->new_policy) {
fdf7c0
 			dev->rwh_policy = u->new_policy;
fdf7c0
@@ -11397,8 +11417,10 @@ static int imsm_create_metadata_update_for_migration(
fdf7c0
 {
fdf7c0
 	struct intel_super *super = st->sb;
fdf7c0
 	int update_memory_size;
fdf7c0
+	int current_chunk_size;
fdf7c0
 	struct imsm_update_reshape_migration *u;
fdf7c0
-	struct imsm_dev *dev;
fdf7c0
+	struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
fdf7c0
+	struct imsm_map *map = get_imsm_map(dev, MAP_0);
fdf7c0
 	int previous_level = -1;
fdf7c0
 
fdf7c0
 	dprintf("(enter) New Level = %i\n", geo->level);
fdf7c0
@@ -11415,23 +11437,15 @@ static int imsm_create_metadata_update_for_migration(
fdf7c0
 	u->new_disks[0] = -1;
fdf7c0
 	u->new_chunksize = -1;
fdf7c0
 
fdf7c0
-	dev = get_imsm_dev(super, u->subdev);
fdf7c0
-	if (dev) {
fdf7c0
-		struct imsm_map *map;
fdf7c0
+	current_chunk_size = __le16_to_cpu(map->blocks_per_strip) / 2;
fdf7c0
 
fdf7c0
-		map = get_imsm_map(dev, MAP_0);
fdf7c0
-		if (map) {
fdf7c0
-			int current_chunk_size =
fdf7c0
-				__le16_to_cpu(map->blocks_per_strip) / 2;
fdf7c0
-
fdf7c0
-			if (geo->chunksize != current_chunk_size) {
fdf7c0
-				u->new_chunksize = geo->chunksize / 1024;
fdf7c0
-				dprintf("imsm: chunk size change from %i to %i\n",
fdf7c0
-					current_chunk_size, u->new_chunksize);
fdf7c0
-			}
fdf7c0
-			previous_level = map->raid_level;
fdf7c0
-		}
fdf7c0
+	if (geo->chunksize != current_chunk_size) {
fdf7c0
+		u->new_chunksize = geo->chunksize / 1024;
fdf7c0
+		dprintf("imsm: chunk size change from %i to %i\n",
fdf7c0
+			current_chunk_size, u->new_chunksize);
fdf7c0
 	}
fdf7c0
+	previous_level = map->raid_level;
fdf7c0
+
fdf7c0
 	if (geo->level == 5 && previous_level == 0) {
fdf7c0
 		struct mdinfo *spares = NULL;
fdf7c0
 
fdf7c0
@@ -12519,9 +12533,6 @@ static int validate_internal_bitmap_imsm(struct supertype *st)
fdf7c0
 	unsigned long long offset;
fdf7c0
 	struct dl *d;
fdf7c0
 
fdf7c0
-	if (!dev)
fdf7c0
-		return -1;
fdf7c0
-
fdf7c0
 	if (dev->rwh_policy != RWH_BITMAP)
fdf7c0
 		return 0;
fdf7c0
 
fdf7c0
@@ -12567,16 +12578,8 @@ static int add_internal_bitmap_imsm(struct supertype *st, int *chunkp,
fdf7c0
 		return -1;
fdf7c0
 
fdf7c0
 	dev = get_imsm_dev(super, vol_idx);
fdf7c0
-
fdf7c0
-	if (!dev) {
fdf7c0
-		dprintf("cannot find the device for volume index %d\n",
fdf7c0
-			vol_idx);
fdf7c0
-		return -1;
fdf7c0
-	}
fdf7c0
 	dev->rwh_policy = RWH_BITMAP;
fdf7c0
-
fdf7c0
 	*chunkp = calculate_bitmap_chunksize(st, dev);
fdf7c0
-
fdf7c0
 	return 0;
fdf7c0
 }
fdf7c0
 
fdf7c0
-- 
01ff50
2.38.1
fdf7c0