lib/string_helpers.c: fix infinite loop in string_get_size()
Some string_get_size() calls (e.g.: string_get_size(1, 512, STRING_UNITS_10, ..., ...) string_get_size(15, 64, STRING_UNITS_10, ..., ...) ) result in an infinite loop. The problem is that if size is equal to divisor[units]/blk_size and is smaller than divisor[units] we'll end up with size == 0 when we start doing sf_cap calculations: For string_get_size(1, 512, STRING_UNITS_10, ..., ...) case: ... remainder = do_div(size, divisor[units]); -> size is 0, remainder is 1 remainder *= blk_size; -> remainder is 512 ... size *= blk_size; -> size is still 0 size += remainder / divisor[units]; -> size is still 0 The caller causing the issue is sd_read_capacity(), the problem was noticed on Hyper-V, such weird size was reported by host when scanning collides with device removal. This is probably a separate issue worth fixing, this patch is intended to prevent the library routine from infinite looping. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Acked-by: James Bottomley <JBottomley@Odin.com> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: "K. Y. Srinivasan" <kys@microsoft.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
14b97deddf
commit
62bef58a55
|
@ -59,7 +59,11 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
|
|||
}
|
||||
|
||||
exp = divisor[units] / (u32)blk_size;
|
||||
if (size >= exp) {
|
||||
/*
|
||||
* size must be strictly greater than exp here to ensure that remainder
|
||||
* is greater than divisor[units] coming out of the if below.
|
||||
*/
|
||||
if (size > exp) {
|
||||
remainder = do_div(size, divisor[units]);
|
||||
remainder *= blk_size;
|
||||
i++;
|
||||
|
|
Loading…
Reference in New Issue