Message ID | 1532010442-4742-1-git-send-email-kewal@zilogic.com |
---|---|
State | Accepted |
Delegated to: | Petr Vorel |
Headers | show |
Series | [v2] Test : madvise('MADV_WIPEONFORK') | expand |
----- Original Message ----- > > madvise10.c :- Present the child process with zero-filled memory in > this range after a fork(2). > Test-Case 1 : madvise with 'MADV_WIPEONFORK' > Test-Case 2 : madvise with 'MADV_WIPEONFORK' as size 'ZERO' > > madvise11.c:- The MADV_WIPEONFORK operation can be applied only to > private anonymous pages. > Test-Case 1 : mmap with 'MAP_SHARED | MAP_ANONYMOUS' > Test-Case 2 : mmap with 'MAP_PRIVATE' > > madvise12.c:- Within the child created by fork(2), the MADV_WIPEONFORK > setting remains in place on the specified address range. > Test-Case 1: 'MADV_WIPEONFORK' on Grand child > > madvise13.c:- MADV_KEEPONFORK Undo the effect of an earlier MADV_WIPEONFORK > Test-Case 1 : Undo 'MADV_WIPEONFORK' by 'MADV_KEEPONFORK' > > * Update from v1 to v2:- > > Added EINVAL error check in madvise02. > Tests having common code are combined together and put into one > single file madvise10.c. > Files were added to .gitignore which was left out in the previous > patch file. > Using -1 as file descriptor for MAP_PRIVATE | MAP_ANONYMOUS page. > Whole mapped-memory area is compared instead of first byte. > Printing test_errno with TFAIL. > > Signed-off-by: Subash Ganesan <subash@zilogic.com> > Signed-off-by: Kewal Ukunde <kewal@zilogic.com> > Acked-by: Jan Stancek <jstancek@redhat.com> Please don't add my ack, when I didn't have a chance to review yet. I'll try to have a look tomorrow. Jan > --- > runtest/syscalls | 1 + > testcases/kernel/syscalls/madvise/.gitignore | 1 + > testcases/kernel/syscalls/madvise/madvise02.c | 12 ++ > testcases/kernel/syscalls/madvise/madvise10.c | 184 > ++++++++++++++++++++++++++ > 4 files changed, 198 insertions(+) > create mode 100644 testcases/kernel/syscalls/madvise/madvise10.c > > diff --git a/runtest/syscalls b/runtest/syscalls > index a9afecf57..9b30635c2 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -773,6 +773,7 @@ madvise06 madvise06 > madvise07 madvise07 > madvise08 madvise08 > madvise09 madvise09 > +madvise10 madvise10 > > newuname01 newuname01 > > diff --git a/testcases/kernel/syscalls/madvise/.gitignore > b/testcases/kernel/syscalls/madvise/.gitignore > index 58bafb1b0..002d8e5d9 100644 > --- a/testcases/kernel/syscalls/madvise/.gitignore > +++ b/testcases/kernel/syscalls/madvise/.gitignore > @@ -5,3 +5,4 @@ > /madvise07 > /madvise08 > /madvise09 > +/madvise10 > diff --git a/testcases/kernel/syscalls/madvise/madvise02.c > b/testcases/kernel/syscalls/madvise/madvise02.c > index 710e46e54..4c357c514 100644 > --- a/testcases/kernel/syscalls/madvise/madvise02.c > +++ b/testcases/kernel/syscalls/madvise/madvise02.c > @@ -25,6 +25,8 @@ > * locked or shared pages (with MADV_DONTNEED) > * 4. MADV_MERGEABLE or MADV_UNMERGEABLE was specified in advice, > * but the kernel was not configured with CONFIG_KSM. > + * 8|9. The MADV_FREE & MADV_WIPEONFORK operation can be applied > + * only to private anonymous pages. > * > * (B) Test Case for ENOMEM > * 5|6. addresses in the specified range are not currently mapped > @@ -51,6 +53,7 @@ > #include "tst_test.h" > #include "lapi/mmap.h" > > +#define MAP_SIZE (4 * 1024) > #define TEST_FILE "testfile" > #define STR "abcdefghijklmnopqrstuvwxyz12345\n" > #define KSM_SYS_DIR "/sys/kernel/mm/ksm" > @@ -59,6 +62,8 @@ static struct stat st; > static long pagesize; > static char *file1; > static char *file2; > +static char *file3; > +static char *shared_anon; > static char *ptr_addr; > static char *tmp_addr; > static char *nonalign; > @@ -81,6 +86,8 @@ static struct tcase { > {MADV_WILLNEED, "MADV_WILLNEED", &tmp_addr, EBADF, 0}, > {MADV_FREE, "MADV_FREE", &file1, EINVAL, 0}, > {MADV_WIPEONFORK, "MADV_WIPEONFORK", &file1, EINVAL, 0}, > + {MADV_WIPEONFORK, "MADV_WIPEONFORK shared_anon", &shared_anon, EINVAL, 0}, > + {MADV_WIPEONFORK, "MADV_WIPEONFORK private file backed", &file3, EINVAL, > 0}, > }; > > static void tcases_filter(void) > @@ -151,6 +158,9 @@ static void setup(void) > file1 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); > file2 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); > SAFE_MUNMAP(file2 + st.st_size - pagesize, pagesize); > + file3 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); > + shared_anon = SAFE_MMAP(0, MAP_SIZE, PROT_READ, MAP_SHARED | > + MAP_ANONYMOUS, -1, 0); > > nonalign = file1 + 100; > > @@ -192,6 +202,8 @@ static void cleanup(void) > free(ptr_addr); > SAFE_MUNMAP(file1, st.st_size); > SAFE_MUNMAP(file2, st.st_size - pagesize); > + SAFE_MUNMAP(file3, st.st_size); > + SAFE_MUNMAP(shared_anon, MAP_SIZE); > } > > static struct tst_test test = { > diff --git a/testcases/kernel/syscalls/madvise/madvise10.c > b/testcases/kernel/syscalls/madvise/madvise10.c > new file mode 100644 > index 000000000..2c3e5902e > --- /dev/null > +++ b/testcases/kernel/syscalls/madvise/madvise10.c > @@ -0,0 +1,184 @@ > +// SPDX-License-Identifier: GPL-2.0 or later > +/* > + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 > + * Email : code@zilogic.com > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + */ > + > +/* > + * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK". > + * > + * DESCRIPTION > + * Present the child process with zero-filled memory in this > + * range after a fork(2). > + * The MADV_WIPEONFORK operation can be applied only to > + * private anonymous pages. > + * Within the child created by fork(2), the MADV_WIPEONFORK > + * setting remains in place on the specified map_address range. > + * The MADV_KEEPONFORK operation undo the effect of MADV_WIPEONFORK. > + * > + * Test-Case 1 : madvise with "MADV_WIPEONFORK" > + * flow : Map memory area as private anonymous page. > + * Mark memory area as wipe-on-fork. > + * On fork, child process memory should be zeroed. > + * > + * Test-Case 2 : madvise with "MADV_WIPEONFORK" as size "ZERO" > + * flow : Map memory area as private anonymous page. > + * Mark memory area as wipe-on-fork, with length zero. > + * On fork, child process memory should be accessible. > + * > + * Test-Case 3 : "MADV_WIPEONFORK" on Grand child > + * flow : Map memory area as private anonymous. > + * Mark memory areas as wipe-on-fork. > + * On fork, child process memory should be zeroed. > + * In child, fork to create grand-child, > + * memory should be zeroed. > + * > + * Test-Case 4 : Undo "MADV_WIPEONFORK" by "MADV_KEEPONFORK" > + * flow : Map memory area as private anonymous page. > + * Mark memory area as wipe-on-fork. > + * Mark memory area as keep-on-fork. > + * On fork, child process memory should be retained. > + **/ > + > +#include <stdio.h> > +#include <signal.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > +#include <sys/mman.h> > +#include <error.h> > +#include <errno.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <stdlib.h> > + > +#include "lapi/mmap.h" > +#include "tst_test.h" > +#include "tst_safe_macros.h" > + > +#define MAP_SIZE (4 * 1024) > + > +static char pattern[MAP_SIZE]; > +static char zero[MAP_SIZE]; > + > +static const struct test_case { > + int size; > + int advise1; > + int advise2; > + char *exp; > + int grand_child; > +} tcases[] = { > + {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 0}, > + {0, MADV_NORMAL, MADV_WIPEONFORK, pattern, 0}, > + {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 1}, > + {MAP_SIZE, MADV_WIPEONFORK, MADV_KEEPONFORK, pattern, 0}, > +}; > + > +static void cmp_area(char *addr, const struct test_case *tc) > +{ > + int i; > + > + for (i = 0; i < tc->size; i++) { > + if (addr[i] != tc->exp[i]) { > + tst_res(TFAIL, "In PID : %d Failed match", getpid()); > + break; > + } > + } > + > + tst_res(TPASS, "In PID : %d Matched expected pattern", getpid()); > +} > + > +static int set_advice(char *addr, int size, int advise) > +{ > + TEST(madvise(addr, size, advise)); > + > + if (TEST_RETURN == -1) { > + tst_res(TFAIL | TTERRNO, "failed :madvise(%p, %d, 0x%x)", > + addr, size, advise); > + > + return 1; > + } > + > + tst_res(TINFO, "success :madvise(%p, %d, 0x%x)", > + addr, size, advise); > + return 0; > +} > + > +static char *mem_map(void) > +{ > + char *ptr; > + > + ptr = SAFE_MMAP(NULL, MAP_SIZE, > + PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, > + -1, 0); > + > + memcpy(ptr, pattern, MAP_SIZE); > + > + return ptr; > +} > + > +static void test_madvise(unsigned int test_nr) > +{ > + const struct test_case *tc = &tcases[test_nr]; > + char *addr; > + pid_t pid; > + > + addr = mem_map(); > + > + if (set_advice(addr, tc->size, tc->advise1)) > + goto un_map; > + > + if (!set_advice(addr, tc->size, tc->advise2)) { > + tst_res(TINFO, "In %s process", > + tc->grand_child ? "grand_child" : "child"); > + > + pid = SAFE_FORK(); > + > + if (!pid) { > + if (tc->grand_child) { > + pid = SAFE_FORK(); > + > + if (!pid) { > + cmp_area(addr, tc); > + exit(0); > + } > + } else { > + cmp_area(addr, tc); > + exit(0); > + } > + } > + tst_reap_children(); > + } > + > +un_map: > + SAFE_MUNMAP(addr, MAP_SIZE); > +} > + > +static void setup(void) > +{ > + unsigned int i; > + > + for (i = 0; i < MAP_SIZE; i++) > + pattern[i] = i % 0x02; > +} > + > +static struct tst_test test = { > + .tcnt = ARRAY_SIZE(tcases), > + .forks_child = 1, > + .test = test_madvise, > + .setup = setup, > + .min_kver = "4.14", > +}; > + > -- > 2.11.0 > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp >
----- Original Message ----- > > madvise10.c :- Present the child process with zero-filled memory in > this range after a fork(2). > Test-Case 1 : madvise with 'MADV_WIPEONFORK' > Test-Case 2 : madvise with 'MADV_WIPEONFORK' as size 'ZERO' > > madvise11.c:- The MADV_WIPEONFORK operation can be applied only to > private anonymous pages. > Test-Case 1 : mmap with 'MAP_SHARED | MAP_ANONYMOUS' > Test-Case 2 : mmap with 'MAP_PRIVATE' > > madvise12.c:- Within the child created by fork(2), the MADV_WIPEONFORK > setting remains in place on the specified address range. > Test-Case 1: 'MADV_WIPEONFORK' on Grand child > > madvise13.c:- MADV_KEEPONFORK Undo the effect of an earlier MADV_WIPEONFORK > Test-Case 1 : Undo 'MADV_WIPEONFORK' by 'MADV_KEEPONFORK' > > * Update from v1 to v2:- > > Added EINVAL error check in madvise02. > Tests having common code are combined together and put into one > single file madvise10.c. > Files were added to .gitignore which was left out in the previous > patch file. > Using -1 as file descriptor for MAP_PRIVATE | MAP_ANONYMOUS page. > Whole mapped-memory area is compared instead of first byte. > Printing test_errno with TFAIL. > > Signed-off-by: Subash Ganesan <subash@zilogic.com> > Signed-off-by: Kewal Ukunde <kewal@zilogic.com> Hi, Pushed with following changes: - split into 2 patches, one for madvise02, and for madvise10 madvise10: - commit message changed to be relevant to latest patch - dropped unnecessary includes - increased MAP_SIZE, so we cover couple pages at least on x86 - added description to struct test_case for each test - cmp_area() changed to print also what failed, index and value - pattern modulo changed to 0x03, so pages are somewhat unique Thanks, Jan @@ -51,23 +51,15 @@ **/ #include <stdio.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <error.h> #include <errno.h> #include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> #include <stdlib.h> #include "lapi/mmap.h" #include "tst_test.h" #include "tst_safe_macros.h" -#define MAP_SIZE (4 * 1024) +#define MAP_SIZE (16 * 1024) static char pattern[MAP_SIZE]; static char zero[MAP_SIZE]; @@ -78,11 +70,16 @@ int advise2; char *exp; int grand_child; + const char *desc; } tcases[] = { - {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 0}, - {0, MADV_NORMAL, MADV_WIPEONFORK, pattern, 0}, - {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 1}, - {MAP_SIZE, MADV_WIPEONFORK, MADV_KEEPONFORK, pattern, 0}, + {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 0, + "MADV_WIPEONFORK zeroes memory in child"}, + {0, MADV_NORMAL, MADV_WIPEONFORK, pattern, 0, + "MADV_WIPEONFORK with zero length does nothing"}, + {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 1, + "MADV_WIPEONFORK zeroes memory in grand-child"}, + {MAP_SIZE, MADV_WIPEONFORK, MADV_KEEPONFORK, pattern, 0, + "MADV_KEEPONFORK will undo MADV_WIPEONFORK"}, }; static void cmp_area(char *addr, const struct test_case *tc) @@ -91,12 +88,14 @@ for (i = 0; i < tc->size; i++) { if (addr[i] != tc->exp[i]) { - tst_res(TFAIL, "In PID : %d Failed match", getpid()); + tst_res(TFAIL, "In PID %d, addr[%d] = 0x%02x, " + "expected[%d] = 0x%02x", getpid(), + i, addr[i], i, tc->exp[i]); break; } } - tst_res(TPASS, "In PID : %d Matched expected pattern", getpid()); + tst_res(TPASS, "In PID %d, Matched expected pattern", getpid()); } static int set_advice(char *addr, int size, int advise) @@ -104,14 +103,13 @@ TEST(madvise(addr, size, advise)); if (TEST_RETURN == -1) { - tst_res(TFAIL | TTERRNO, "failed :madvise(%p, %d, 0x%x)", - addr, size, advise); + tst_res(TFAIL | TTERRNO, "madvise(%p, %d, 0x%x)", + addr, size, advise); return 1; } - tst_res(TINFO, "success :madvise(%p, %d, 0x%x)", - addr, size, advise); + tst_res(TPASS, "madvise(%p, %d, 0x%x)", addr, size, advise); return 0; } @@ -137,13 +135,11 @@ addr = mem_map(); + tst_res(TINFO, "%s", tc->desc); if (set_advice(addr, tc->size, tc->advise1)) goto un_map; if (!set_advice(addr, tc->size, tc->advise2)) { - tst_res(TINFO, "In %s process", - tc->grand_child ? "grand_child" : "child"); - pid = SAFE_FORK(); if (!pid) { @@ -171,7 +167,7 @@ unsigned int i; for (i = 0; i < MAP_SIZE; i++) - pattern[i] = i % 0x02; + pattern[i] = i % 0x03; }
diff --git a/runtest/syscalls b/runtest/syscalls index a9afecf57..9b30635c2 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -773,6 +773,7 @@ madvise06 madvise06 madvise07 madvise07 madvise08 madvise08 madvise09 madvise09 +madvise10 madvise10 newuname01 newuname01 diff --git a/testcases/kernel/syscalls/madvise/.gitignore b/testcases/kernel/syscalls/madvise/.gitignore index 58bafb1b0..002d8e5d9 100644 --- a/testcases/kernel/syscalls/madvise/.gitignore +++ b/testcases/kernel/syscalls/madvise/.gitignore @@ -5,3 +5,4 @@ /madvise07 /madvise08 /madvise09 +/madvise10 diff --git a/testcases/kernel/syscalls/madvise/madvise02.c b/testcases/kernel/syscalls/madvise/madvise02.c index 710e46e54..4c357c514 100644 --- a/testcases/kernel/syscalls/madvise/madvise02.c +++ b/testcases/kernel/syscalls/madvise/madvise02.c @@ -25,6 +25,8 @@ * locked or shared pages (with MADV_DONTNEED) * 4. MADV_MERGEABLE or MADV_UNMERGEABLE was specified in advice, * but the kernel was not configured with CONFIG_KSM. + * 8|9. The MADV_FREE & MADV_WIPEONFORK operation can be applied + * only to private anonymous pages. * * (B) Test Case for ENOMEM * 5|6. addresses in the specified range are not currently mapped @@ -51,6 +53,7 @@ #include "tst_test.h" #include "lapi/mmap.h" +#define MAP_SIZE (4 * 1024) #define TEST_FILE "testfile" #define STR "abcdefghijklmnopqrstuvwxyz12345\n" #define KSM_SYS_DIR "/sys/kernel/mm/ksm" @@ -59,6 +62,8 @@ static struct stat st; static long pagesize; static char *file1; static char *file2; +static char *file3; +static char *shared_anon; static char *ptr_addr; static char *tmp_addr; static char *nonalign; @@ -81,6 +86,8 @@ static struct tcase { {MADV_WILLNEED, "MADV_WILLNEED", &tmp_addr, EBADF, 0}, {MADV_FREE, "MADV_FREE", &file1, EINVAL, 0}, {MADV_WIPEONFORK, "MADV_WIPEONFORK", &file1, EINVAL, 0}, + {MADV_WIPEONFORK, "MADV_WIPEONFORK shared_anon", &shared_anon, EINVAL, 0}, + {MADV_WIPEONFORK, "MADV_WIPEONFORK private file backed", &file3, EINVAL, 0}, }; static void tcases_filter(void) @@ -151,6 +158,9 @@ static void setup(void) file1 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); file2 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); SAFE_MUNMAP(file2 + st.st_size - pagesize, pagesize); + file3 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + shared_anon = SAFE_MMAP(0, MAP_SIZE, PROT_READ, MAP_SHARED | + MAP_ANONYMOUS, -1, 0); nonalign = file1 + 100; @@ -192,6 +202,8 @@ static void cleanup(void) free(ptr_addr); SAFE_MUNMAP(file1, st.st_size); SAFE_MUNMAP(file2, st.st_size - pagesize); + SAFE_MUNMAP(file3, st.st_size); + SAFE_MUNMAP(shared_anon, MAP_SIZE); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/madvise/madvise10.c b/testcases/kernel/syscalls/madvise/madvise10.c new file mode 100644 index 000000000..2c3e5902e --- /dev/null +++ b/testcases/kernel/syscalls/madvise/madvise10.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email : code@zilogic.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + */ + +/* + * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK". + * + * DESCRIPTION + * Present the child process with zero-filled memory in this + * range after a fork(2). + * The MADV_WIPEONFORK operation can be applied only to + * private anonymous pages. + * Within the child created by fork(2), the MADV_WIPEONFORK + * setting remains in place on the specified map_address range. + * The MADV_KEEPONFORK operation undo the effect of MADV_WIPEONFORK. + * + * Test-Case 1 : madvise with "MADV_WIPEONFORK" + * flow : Map memory area as private anonymous page. + * Mark memory area as wipe-on-fork. + * On fork, child process memory should be zeroed. + * + * Test-Case 2 : madvise with "MADV_WIPEONFORK" as size "ZERO" + * flow : Map memory area as private anonymous page. + * Mark memory area as wipe-on-fork, with length zero. + * On fork, child process memory should be accessible. + * + * Test-Case 3 : "MADV_WIPEONFORK" on Grand child + * flow : Map memory area as private anonymous. + * Mark memory areas as wipe-on-fork. + * On fork, child process memory should be zeroed. + * In child, fork to create grand-child, + * memory should be zeroed. + * + * Test-Case 4 : Undo "MADV_WIPEONFORK" by "MADV_KEEPONFORK" + * flow : Map memory area as private anonymous page. + * Mark memory area as wipe-on-fork. + * Mark memory area as keep-on-fork. + * On fork, child process memory should be retained. + **/ + +#include <stdio.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <error.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <stdlib.h> + +#include "lapi/mmap.h" +#include "tst_test.h" +#include "tst_safe_macros.h" + +#define MAP_SIZE (4 * 1024) + +static char pattern[MAP_SIZE]; +static char zero[MAP_SIZE]; + +static const struct test_case { + int size; + int advise1; + int advise2; + char *exp; + int grand_child; +} tcases[] = { + {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 0}, + {0, MADV_NORMAL, MADV_WIPEONFORK, pattern, 0}, + {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 1}, + {MAP_SIZE, MADV_WIPEONFORK, MADV_KEEPONFORK, pattern, 0}, +}; + +static void cmp_area(char *addr, const struct test_case *tc) +{ + int i; + + for (i = 0; i < tc->size; i++) { + if (addr[i] != tc->exp[i]) { + tst_res(TFAIL, "In PID : %d Failed match", getpid()); + break; + } + } + + tst_res(TPASS, "In PID : %d Matched expected pattern", getpid()); +} + +static int set_advice(char *addr, int size, int advise) +{ + TEST(madvise(addr, size, advise)); + + if (TEST_RETURN == -1) { + tst_res(TFAIL | TTERRNO, "failed :madvise(%p, %d, 0x%x)", + addr, size, advise); + + return 1; + } + + tst_res(TINFO, "success :madvise(%p, %d, 0x%x)", + addr, size, advise); + return 0; +} + +static char *mem_map(void) +{ + char *ptr; + + ptr = SAFE_MMAP(NULL, MAP_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + + memcpy(ptr, pattern, MAP_SIZE); + + return ptr; +} + +static void test_madvise(unsigned int test_nr) +{ + const struct test_case *tc = &tcases[test_nr]; + char *addr; + pid_t pid; + + addr = mem_map(); + + if (set_advice(addr, tc->size, tc->advise1)) + goto un_map; + + if (!set_advice(addr, tc->size, tc->advise2)) { + tst_res(TINFO, "In %s process", + tc->grand_child ? "grand_child" : "child"); + + pid = SAFE_FORK(); + + if (!pid) { + if (tc->grand_child) { + pid = SAFE_FORK(); + + if (!pid) { + cmp_area(addr, tc); + exit(0); + } + } else { + cmp_area(addr, tc); + exit(0); + } + } + tst_reap_children(); + } + +un_map: + SAFE_MUNMAP(addr, MAP_SIZE); +} + +static void setup(void) +{ + unsigned int i; + + for (i = 0; i < MAP_SIZE; i++) + pattern[i] = i % 0x02; +} + +static struct tst_test test = { + .tcnt = ARRAY_SIZE(tcases), + .forks_child = 1, + .test = test_madvise, + .setup = setup, + .min_kver = "4.14", +}; +