From: Li Nan <linan122@xxxxxxxxxx> Add a helper badblocks_merge() to merge badblocks, it makes code more readable. No functional change. Signed-off-by: Li Nan <linan122@xxxxxxxxxx> --- block/badblocks.c | 143 +++++++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 64 deletions(-) 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' */ -- 2.31.1