Skip to content

Commit f3c74b3

Browse files
committed
RAS/CEC: Fix binary search function
Switch to using Donald Knuth's binary search algorithm (The Art of Computer Programming, vol. 3, section 6.2.1). This should've been done from the very beginning but the author must've been smoking something very potent at the time. The problem with the current one was that it would return the wrong element index in certain situations: https://lkml.kernel.org/r/CAM_iQpVd02zkVJ846cj-Fg1yUNuz6tY5q1Vpj4LrXmE06dPYYg@mail.gmail.com and the noodling code after the loop was fishy at best. So switch to using Knuth's binary search. The final result is much cleaner and straightforward. Fixes: 011d826 ("RAS: Add a Corrected Errors Collector") Reported-by: Cong Wang <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Cc: Tony Luck <[email protected]> Cc: linux-edac <[email protected]> Cc: <[email protected]>
1 parent f2c7c76 commit f3c74b3

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

drivers/ras/cec.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,32 +183,38 @@ static void cec_timer_fn(struct timer_list *unused)
183183
*/
184184
static int __find_elem(struct ce_array *ca, u64 pfn, unsigned int *to)
185185
{
186+
int min = 0, max = ca->n - 1;
186187
u64 this_pfn;
187-
int min = 0, max = ca->n;
188188

189-
while (min < max) {
190-
int tmp = (max + min) >> 1;
189+
while (min <= max) {
190+
int i = (min + max) >> 1;
191191

192-
this_pfn = PFN(ca->array[tmp]);
192+
this_pfn = PFN(ca->array[i]);
193193

194194
if (this_pfn < pfn)
195-
min = tmp + 1;
195+
min = i + 1;
196196
else if (this_pfn > pfn)
197-
max = tmp;
198-
else {
199-
min = tmp;
200-
break;
197+
max = i - 1;
198+
else if (this_pfn == pfn) {
199+
if (to)
200+
*to = i;
201+
202+
return i;
201203
}
202204
}
203205

206+
/*
207+
* When the loop terminates without finding @pfn, min has the index of
208+
* the element slot where the new @pfn should be inserted. The loop
209+
* terminates when min > max, which means the min index points to the
210+
* bigger element while the max index to the smaller element, in-between
211+
* which the new @pfn belongs to.
212+
*
213+
* For more details, see exercise 1, Section 6.2.1 in TAOCP, vol. 3.
214+
*/
204215
if (to)
205216
*to = min;
206217

207-
this_pfn = PFN(ca->array[min]);
208-
209-
if (this_pfn == pfn)
210-
return min;
211-
212218
return -ENOKEY;
213219
}
214220

0 commit comments

Comments
 (0)