[v2,08/11] block/badblocks: factor out a helper to merge badblocks

Message ID 20230504124828.679770-9-linan666@huaweicloud.com
State New
Headers
Series block/badblocks: fix badblocks setting error |

Commit Message

Li Nan May 4, 2023, 12:48 p.m. UTC
  From: Li Nan <linan122@huawei.com>

Add a helper badblocks_merge() to merge badblocks, it makes code more
readable. No functional change.

Signed-off-by: Li Nan <linan122@huawei.com>
---
 block/badblocks.c | 143 +++++++++++++++++++++++++---------------------
 1 file changed, 79 insertions(+), 64 deletions(-)
  

Patch

diff --git a/block/badblocks.c b/block/badblocks.c
index 3cb8513cbd7f..f498fae201a1 100644
--- a/block/badblocks.c
+++ b/block/badblocks.c
@@ -144,6 +144,80 @@  static void badblocks_update_acked(struct badblocks *bb)
 		bb->unacked_exist = false;
 }
 
+/*
+ * try to merge new range with lo and hi.
+ * if s is within lo, merge with lo.
+ * if s + sectors > start of hi, merge with hi.
+ *
+ * Return:
+ *  Number of merged sectors
+ */
+static int badblocks_merge(struct badblocks *bb, sector_t s, int sectors,
+			int acknowledged, int *lo, int *hi, bool *changed)
+{
+	u64 *p = bb->page;
+	sector_t a = BB_OFFSET(p[*lo]);
+	sector_t e = a + BB_LEN(p[*lo]);
+	int merged_sectors = 0, ack = acknowledged;
+
+	if (a > s) {
+		*hi = *lo;
+	} else if (e >= s) {
+		/* we can merge with a previous range */
+		if (s > a || s + sectors < e)
+			ack = ack && BB_ACK(p[*lo]);
+
+		if (e < s + sectors)
+			e = s + sectors;
+		if (e - a <= BB_MAX_LEN) {
+			s = e;
+		} else {
+			/*
+			 * does not all fit in one range,
+			 * make p[lo] maximal
+			 */
+			s = a + BB_MAX_LEN;
+		}
+		if (s - a != BB_LEN(p[*lo]) || ack != BB_ACK(p[*lo])) {
+			p[*lo] = BB_MAKE(a, s - a, ack);
+			*changed = true;
+		}
+		merged_sectors += sectors - e + s;
+		sectors = e - s;
+	}
+	if (sectors && *hi < bb->count) {
+		/*
+		 * 'hi' points to the first range that starts after 's'.
+		 * Maybe we can merge with the start of that range
+		 */
+		a = BB_OFFSET(p[*hi]);
+		e = a + BB_LEN(p[*hi]);
+		ack = acknowledged;
+
+		if (a <= s + sectors) {
+			/* merging is possible */
+			if (e <= s + sectors) {
+				/* full overlap */
+				e = s + sectors;
+			} else
+				ack = ack && BB_ACK(p[*hi]);
+
+			a = s;
+			if (e - a <= BB_MAX_LEN)
+				s = e;
+			else
+				s = a + BB_MAX_LEN;
+			p[*hi] = BB_MAKE(a, s-a, ack);
+
+			merged_sectors += sectors - e + s;
+			*changed = true;
+			*lo = *hi;
+			*hi += 1;
+		}
+	}
+	return merged_sectors;
+}
+
 /**
  * badblocks_set() - Add a range of bad blocks to the table.
  * @bb:		the badblocks structure that holds all badblock information
@@ -191,6 +265,7 @@  int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
 		sector_t a;
 		sector_t e;
 		int ack;
+		int merged_sectors;
 
 		/* Find the last range that starts at-or-before 's' */
 		while (hi - lo > 1) {
@@ -203,70 +278,10 @@  int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
 				hi = mid;
 		}
 
-		/* we found a range that might merge with the start
-		 * of our new range
-		 */
-		a = BB_OFFSET(p[lo]);
-		e = a + BB_LEN(p[lo]);
-		ack = BB_ACK(p[lo]);
-
-		if (a > s) {
-			hi = lo;
-		} else if (e >= s) {
-			/* Yes, we can merge with a previous range */
-			if (s == a && s + sectors >= e)
-				/* new range covers old */
-				ack = acknowledged;
-			else
-				ack = ack && acknowledged;
-
-			if (e < s + sectors)
-				e = s + sectors;
-			if (e - a <= BB_MAX_LEN) {
-				s = e;
-			} else {
-				/* does not all fit in one range,
-				 * make p[lo] maximal
-				 */
-				s = a + BB_MAX_LEN;
-			}
-			if (s - a != BB_LEN(p[lo]) || ack != BB_ACK(p[lo])) {
-				p[lo] = BB_MAKE(a, s - a, ack);
-				changed = true;
-			}
-			sectors = e - s;
-		}
-		if (sectors && hi < bb->count) {
-			/* 'hi' points to the first range that starts after 's'.
-			 * Maybe we can merge with the start of that range
-			 */
-			a = BB_OFFSET(p[hi]);
-			e = a + BB_LEN(p[hi]);
-			ack = BB_ACK(p[hi]);
-
-			if (a <= s + sectors) {
-				/* merging is possible */
-				if (e <= s + sectors) {
-					/* full overlap */
-					e = s + sectors;
-					ack = acknowledged;
-				} else
-					ack = ack && acknowledged;
-
-				a = s;
-				if (e - a <= BB_MAX_LEN) {
-					p[hi] = BB_MAKE(a, e-a, ack);
-					s = e;
-				} else {
-					p[hi] = BB_MAKE(a, BB_MAX_LEN, ack);
-					s = a + BB_MAX_LEN;
-				}
-				sectors = e - s;
-				lo = hi;
-				hi++;
-				changed = true;
-			}
-		}
+		merged_sectors = badblocks_merge(bb, s, sectors, acknowledged,
+						 &lo, &hi, &changed);
+		s += merged_sectors;
+		sectors -= merged_sectors;
 		if (sectors == 0 && hi < bb->count) {
 			/* we might be able to combine lo and hi */
 			/* Note: 's' is at the end of 'lo' */