On 2019-10-12, Michael Ellerman <[email protected]> wrote: > Aleksa Sarai <[email protected]> writes: > > On 2019-10-11, Michael Ellerman <[email protected]> wrote: > >> On a machine with a 64K PAGE_SIZE, the nested for loops in > >> test_check_nonzero_user() can lead to soft lockups, eg: > ... > >> diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c > >> index 950ee88cd6ac..9fb6bc609d4c 100644 > >> --- a/lib/test_user_copy.c > >> +++ b/lib/test_user_copy.c > >> @@ -47,9 +47,26 @@ static bool is_zeroed(void *from, size_t size) > >> static int test_check_nonzero_user(char *kmem, char __user *umem, size_t > >> size) > >> { > >> int ret = 0; > >> - size_t start, end, i; > >> - size_t zero_start = size / 4; > >> - size_t zero_end = size - zero_start; > >> + size_t start, end, i, zero_start, zero_end; > >> + > >> + if (test(size < 1024, "buffer too small")) > >> + return -EINVAL; > >> + > >> + /* > >> + * We want to cross a page boundary to exercise the code more > >> + * effectively. We assume the buffer we're passed has a page boundary at > >> + * size / 2. We also don't want to make the size we scan too large, > >> + * otherwise the test can take a long time and cause soft lockups. So > >> + * scan a 1024 byte region across the page boundary. > >> + */ > >> + start = size / 2 - 512; > >> + size = 1024; > > > > I don't think it's necessary to do "size / 2" here -- you can just use > > PAGE_SIZE directly and check above that "size == 2*PAGE_SIZE" (not that > > this check is exceptionally necessary -- since there's only one caller > > of this function and it's in the same file). > > OK, like this?
Yup -- that looks good. I'll give it a Reviewed-by once you resend it.
> diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c
> index 950ee88cd6ac..48bc669b2549 100644
> --- a/lib/test_user_copy.c
> +++ b/lib/test_user_copy.c
> @@ -47,9 +47,25 @@ static bool is_zeroed(void *from, size_t size)
> static int test_check_nonzero_user(char *kmem, char __user *umem, size_t
> size)
> {
> int ret = 0;
> - size_t start, end, i;
> - size_t zero_start = size / 4;
> - size_t zero_end = size - zero_start;
> + size_t start, end, i, zero_start, zero_end;
> +
> + if (test(size < 2 * PAGE_SIZE, "buffer too small"))
> + return -EINVAL;
> +
> + /*
> + * We want to cross a page boundary to exercise the code more
> + * effectively. We also don't want to make the size we scan too large,
> + * otherwise the test can take a long time and cause soft lockups. So
> + * scan a 1024 byte region across the page boundary.
> + */
> + size = 1024;
> + start = PAGE_SIZE - (size / 2);
> +
> + kmem += start;
> + umem += start;
> +
> + zero_start = size / 4;
> + zero_end = size - zero_start;
>
> /*
> * We conduct a series of check_nonzero_user() tests on a block of
> memory
--
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
<https://www.cyphar.com/>
signature.asc
Description: PGP signature

