Re: [PATCH] selftest/vm: add mremap expand merge offset test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jan 02, 2023 at 02:32:55PM +0100, David Hildenbrand wrote:
> On 16.12.22 22:44, Lorenzo Stoakes wrote:
> > Add a test to assert that we can mremap() and expand a mapping starting
> > from an offset within an existing mapping. We unmap the last page in a 3
> > page mapping to ensure that the remap should always succeed, before
> > remapping from the 2nd page.
> >
> > This is additionally a regression test for the issue solved in "mm, mremap:
> > fix mremap() expanding vma with addr inside vma" and confirmed to fail
> > prior to the change and pass after it.
> >
> > Finally, this patch updates the existing mremap expand merge test to check
> > error conditions and reduce code duplication between the two tests.
> >
> > Signed-off-by: Lorenzo Stoakes <lstoakes@xxxxxxxxx>
> > ---
> >   tools/testing/selftests/vm/mremap_test.c | 111 +++++++++++++++++++----
> >   1 file changed, 93 insertions(+), 18 deletions(-)
> >
> > diff --git a/tools/testing/selftests/vm/mremap_test.c b/tools/testing/selftests/vm/mremap_test.c
> > index 9496346973d4..28a17d4e8afd 100644
> > --- a/tools/testing/selftests/vm/mremap_test.c
> > +++ b/tools/testing/selftests/vm/mremap_test.c
> > @@ -119,30 +119,19 @@ static unsigned long long get_mmap_min_addr(void)
> >   }
> >
> >   /*
> > - * This test validates that merge is called when expanding a mapping.
> > - * Mapping containing three pages is created, middle page is unmapped
> > - * and then the mapping containing the first page is expanded so that
> > - * it fills the created hole. The two parts should merge creating
> > - * single mapping with three pages.
> > + * Using /proc/self/maps, assert that the specified address range is contained
> > + * within a single mapping.
> >    */
> > -static void mremap_expand_merge(unsigned long page_size)
> > +static bool is_range_mapped(void *start, void *end)
> >   {
> > -	char *test_name = "mremap expand merge";
> >   	FILE *fp;
> >   	char *line = NULL;
> >   	size_t len = 0;
> >   	bool success = false;
> > -	char *start = mmap(NULL, 3 * page_size, PROT_READ | PROT_WRITE,
> > -			   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> > -
> > -	munmap(start + page_size, page_size);
> > -	mremap(start, page_size, 2 * page_size, 0);
> >
> >   	fp = fopen("/proc/self/maps", "r");
> > -	if (fp == NULL) {
> > -		ksft_test_result_fail("%s\n", test_name);
> > -		return;
> > -	}
> > +	if (fp == NULL)
> > +		return false;
>
> This is unexpected. It would be valuable to ksft_print_msg("[INFO] .."
> something, indicating that we don't know because we cannot access that info.
>
> ksft_print_msg("[INFO] Opening /proc/self/maps failed"
>
>
> But I'd even suggest opening "/proc/self/maps" once in main() and failing
> directly there. Then we don't have to worry about it here.
>
> >
> >   	while (getline(&line, &len, fp) != -1) {
> >   		char *first = strtok(line, "- ");
> > @@ -150,16 +139,101 @@ static void mremap_expand_merge(unsigned long page_size)
> >   		char *second = strtok(NULL, "- ");
> >   		void *second_val = (void *) strtol(second, NULL, 16);
> >
> > -		if (first_val == start && second_val == start + 3 * page_size) {
> > +		if (first_val <= start && second_val >= end) {
> >   			success = true;
> >   			break;
> >   		}
> >   	}
> > +
> > +	fclose(fp);
> > +	return success;
> > +}
> > +
> > +/*
> > + * This test validates that merge is called when expanding a mapping.
> > + * Mapping containing three pages is created, middle page is unmapped
> > + * and then the mapping containing the first page is expanded so that
> > + * it fills the created hole. The two parts should merge creating
> > + * single mapping with three pages.
> > + */
> > +static void mremap_expand_merge(unsigned long page_size)
> > +{
> > +	char *test_name = "mremap expand merge";
> > +	bool success = false;
> > +	int errsv = 0;
> > +	char *remap;
> > +	char *start = mmap(NULL, 3 * page_size, PROT_READ | PROT_WRITE,
> > +			   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
> I'd suggest
>
>
> 	char *remap, *start;
>
> 	start = mmap()
> 	if (start == MAP_FAILED) { ...
>
> to make this easier to read.
>
> > +
> > +	if (start == MAP_FAILED) {
> > +		errsv = errno;
> > +		goto error;
> > +	}
> > +
> > +	munmap(start + page_size, page_size);
> > +	remap = mremap(start, page_size, 2 * page_size, 0);
> > +	if (remap == MAP_FAILED) {
> > +		errsv = errno;
> > +		munmap(start, page_size);
> > +		munmap(start + 2 * page_size, page_size);
> > +		goto error;
> > +	}
> > +
> > +	success = is_range_mapped(start, start + 3 * page_size);
> > +
> > +	munmap(start, 3 * page_size);
> > +	goto out;
> > +
> > +error:
> > +	ksft_print_msg("Unexpected mapping/remapping error: %s\n",
> > +		       strerror(errsv));
>
> Please avoid the "error" label and just print proper errors directly at the
> two callsites. Then, remove the "goto out".
>
> > +out:
> > +	if (success)
> > +		ksft_test_result_pass("%s\n", test_name);
> > +	else
> > +		ksft_test_result_fail("%s\n", test_name);
> > +}
> > +
> > +/*
> > + * Similar to mremap_expand_merge() except instead of removing the middle page,
> > + * we remove the last then attempt to remap offset from the second page. This
> > + * should result in the mapping being restored to its former state.
> > + */
> > +static void mremap_expand_merge_offset(unsigned long page_size)
> > +{
> > +
> > +	char *test_name = "mremap expand merge offset";
> > +	bool success = false;
> > +	int errsv = 0;
> > +	char *remap;
> > +	char *start = mmap(NULL, 3 * page_size, PROT_READ | PROT_WRITE,
> > +			   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
> Dito.
>
> > +
> > +	if (start == MAP_FAILED) {
> > +		errsv = errno;
> > +		goto error;
> > +	}
> > +
> > +	/* Unmap final page to ensure we have space to expand. */
> > +	munmap(start + 2 * page_size, page_size);
> > +	remap = mremap(start + page_size, page_size, 2 * page_size, 0);
> > +	if (remap == MAP_FAILED) {
> > +		errsv = errno;
> > +		munmap(start, 2 * page_size);
> > +		goto error;
> > +	}
> > +
> > +	success = is_range_mapped(start, start + 3 * page_size);
> > +	goto out;
> > +
> > +error:
> > +	ksft_print_msg("Unexpected mapping/remapping error: %s\n",
> > +		       strerror(errsv));
>
> Dito.
>
> > +out:
>
>
> --
> Thanks,
>
> David / dhildenb
>

Ack on all, will spin a v2. Thanks for review!



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux