提交 1d9f98ef 编写于 作者: B Borislav Petkov 提交者: Xie XiuQi

RAS/CEC: Fix binary search function

commit f3c74b38a55aefe1004200d15a83f109b510068c upstream.

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: 011d8261 ("RAS: Add a Corrected Errors Collector")
Reported-by: NCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: NBorislav Petkov <bp@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-edac <linux-edac@vger.kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 6c78034c
...@@ -181,32 +181,38 @@ static void cec_work_fn(struct work_struct *work) ...@@ -181,32 +181,38 @@ static void cec_work_fn(struct work_struct *work)
*/ */
static int __find_elem(struct ce_array *ca, u64 pfn, unsigned int *to) static int __find_elem(struct ce_array *ca, u64 pfn, unsigned int *to)
{ {
int min = 0, max = ca->n - 1;
u64 this_pfn; u64 this_pfn;
int min = 0, max = ca->n;
while (min < max) { while (min <= max) {
int tmp = (max + min) >> 1; int i = (min + max) >> 1;
this_pfn = PFN(ca->array[tmp]); this_pfn = PFN(ca->array[i]);
if (this_pfn < pfn) if (this_pfn < pfn)
min = tmp + 1; min = i + 1;
else if (this_pfn > pfn) else if (this_pfn > pfn)
max = tmp; max = i - 1;
else { else if (this_pfn == pfn) {
min = tmp; if (to)
break; *to = i;
return i;
} }
} }
/*
* When the loop terminates without finding @pfn, min has the index of
* the element slot where the new @pfn should be inserted. The loop
* terminates when min > max, which means the min index points to the
* bigger element while the max index to the smaller element, in-between
* which the new @pfn belongs to.
*
* For more details, see exercise 1, Section 6.2.1 in TAOCP, vol. 3.
*/
if (to) if (to)
*to = min; *to = min;
this_pfn = PFN(ca->array[min]);
if (this_pfn == pfn)
return min;
return -ENOKEY; return -ENOKEY;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册