On Sun, Jan 24, 2021 at 6:03 PM John Hubbard <jhubbard@xxxxxxxxxx> wrote: > > On 1/21/21 7:37 PM, Pavel Tatashin wrote: > > In gup_test both gup_flags and test_flags use the same flags field. > > This is broken. > > > > Farther, in the actual gup_test.c all the passed gup_flags are erased and > > unconditionally replaced with FOLL_WRITE. > > > > Which means that test_flags are ignored, and code like this always > > performs pin dump test: > > > > 155 if (gup->flags & GUP_TEST_FLAG_DUMP_PAGES_USE_PIN) > > 156 nr = pin_user_pages(addr, nr, gup->flags, > > 157 pages + i, NULL); > > 158 else > > 159 nr = get_user_pages(addr, nr, gup->flags, > > 160 pages + i, NULL); > > 161 break; > > > > Add a new test_flags field, to allow raw gup_flags to work. > > Add a new subcommand for DUMP_USER_PAGES_TEST to specify that pin test > > should be performed. > > Remove unconditional overwriting of gup_flags via FOLL_WRITE. But, > > preserve the previous behaviour where FOLL_WRITE was the default flag, > > and add a new option "-W" to unset FOLL_WRITE. > > > > Rename flags with gup_flags. > > Hi Pavel, > > Thanks again for fixing this up! Looks good, with a tiny point about the > subject line: > > 1) To follow convention, the subject line should say what you're doing, > not what the previous condition was. Also, there are several tests in that > directory, so we should say which one. So more like this: > > "selftests/vm: gup_test: fix test flag" > > That is just a minor documentation point, so either way, feel free to add: > > > Reviewed-by: John Hubbard <jhubbard@xxxxxxxxxx> Thank you for your review , I will change the subject line in the next update. Pasha > > > thanks, > -- > John Hubbard > NVIDIA > > > > > With the fix, dump works like this: > > > > root@virtme:/# gup_test -c > > ---- page #0, starting from user virt addr: 0x7f8acb9e4000 > > page:00000000d3d2ee27 refcount:2 mapcount:1 mapping:0000000000000000 > > index:0x0 pfn:0x100bcf > > anon flags: 0x300000000080016(referenced|uptodate|lru|swapbacked) > > raw: 0300000000080016 ffffd0e204021608 ffffd0e208df2e88 ffff8ea04243ec61 > > raw: 0000000000000000 0000000000000000 0000000200000000 0000000000000000 > > page dumped because: gup_test: dump_pages() test > > DUMP_USER_PAGES_TEST: done > > > > root@virtme:/# gup_test -c -p > > ---- page #0, starting from user virt addr: 0x7fd19701b000 > > page:00000000baed3c7d refcount:1025 mapcount:1 mapping:0000000000000000 > > index:0x0 pfn:0x108008 > > anon flags: 0x300000000080014(uptodate|lru|swapbacked) > > raw: 0300000000080014 ffffd0e204200188 ffffd0e205e09088 ffff8ea04243ee71 > > raw: 0000000000000000 0000000000000000 0000040100000000 0000000000000000 > > page dumped because: gup_test: dump_pages() test > > DUMP_USER_PAGES_TEST: done > > > > Refcount shows the difference between pin vs no-pin case. > > Also change type of nr from int to long, as it counts number of pages. > > > > Signed-off-by: Pavel Tatashin <pasha.tatashin@xxxxxxxxxx> > > --- > > mm/gup_test.c | 23 ++++++++++------------- > > mm/gup_test.h | 3 ++- > > tools/testing/selftests/vm/gup_test.c | 15 +++++++++++---- > > 3 files changed, 23 insertions(+), 18 deletions(-) > > > > diff --git a/mm/gup_test.c b/mm/gup_test.c > > index e3cf78e5873e..a6ed1c877679 100644 > > --- a/mm/gup_test.c > > +++ b/mm/gup_test.c > > @@ -94,7 +94,7 @@ static int __gup_test_ioctl(unsigned int cmd, > > { > > ktime_t start_time, end_time; > > unsigned long i, nr_pages, addr, next; > > - int nr; > > + long nr; > > struct page **pages; > > int ret = 0; > > bool needs_mmap_lock = > > @@ -126,37 +126,34 @@ static int __gup_test_ioctl(unsigned int cmd, > > nr = (next - addr) / PAGE_SIZE; > > } > > > > - /* Filter out most gup flags: only allow a tiny subset here: */ > > - gup->flags &= FOLL_WRITE; > > - > > switch (cmd) { > > case GUP_FAST_BENCHMARK: > > - nr = get_user_pages_fast(addr, nr, gup->flags, > > + nr = get_user_pages_fast(addr, nr, gup->gup_flags, > > pages + i); > > break; > > case GUP_BASIC_TEST: > > - nr = get_user_pages(addr, nr, gup->flags, pages + i, > > + nr = get_user_pages(addr, nr, gup->gup_flags, pages + i, > > NULL); > > break; > > case PIN_FAST_BENCHMARK: > > - nr = pin_user_pages_fast(addr, nr, gup->flags, > > + nr = pin_user_pages_fast(addr, nr, gup->gup_flags, > > pages + i); > > break; > > case PIN_BASIC_TEST: > > - nr = pin_user_pages(addr, nr, gup->flags, pages + i, > > + nr = pin_user_pages(addr, nr, gup->gup_flags, pages + i, > > NULL); > > break; > > case PIN_LONGTERM_BENCHMARK: > > nr = pin_user_pages(addr, nr, > > - gup->flags | FOLL_LONGTERM, > > + gup->gup_flags | FOLL_LONGTERM, > > pages + i, NULL); > > break; > > case DUMP_USER_PAGES_TEST: > > - if (gup->flags & GUP_TEST_FLAG_DUMP_PAGES_USE_PIN) > > - nr = pin_user_pages(addr, nr, gup->flags, > > + if (gup->test_flags & GUP_TEST_FLAG_DUMP_PAGES_USE_PIN) > > + nr = pin_user_pages(addr, nr, gup->gup_flags, > > pages + i, NULL); > > else > > - nr = get_user_pages(addr, nr, gup->flags, > > + nr = get_user_pages(addr, nr, gup->gup_flags, > > pages + i, NULL); > > break; > > default: > > @@ -187,7 +184,7 @@ static int __gup_test_ioctl(unsigned int cmd, > > > > start_time = ktime_get(); > > > > - put_back_pages(cmd, pages, nr_pages, gup->flags); > > + put_back_pages(cmd, pages, nr_pages, gup->test_flags); > > > > end_time = ktime_get(); > > gup->put_delta_usec = ktime_us_delta(end_time, start_time); > > diff --git a/mm/gup_test.h b/mm/gup_test.h > > index 90a6713d50eb..887ac1d5f5bc 100644 > > --- a/mm/gup_test.h > > +++ b/mm/gup_test.h > > @@ -21,7 +21,8 @@ struct gup_test { > > __u64 addr; > > __u64 size; > > __u32 nr_pages_per_call; > > - __u32 flags; > > + __u32 gup_flags; > > + __u32 test_flags; > > /* > > * Each non-zero entry is the number of the page (1-based: first page is > > * page 1, so that zero entries mean "do nothing") from the .addr base. > > diff --git a/tools/testing/selftests/vm/gup_test.c b/tools/testing/selftests/vm/gup_test.c > > index 6c6336dd3b7f..943cc2608dc2 100644 > > --- a/tools/testing/selftests/vm/gup_test.c > > +++ b/tools/testing/selftests/vm/gup_test.c > > @@ -37,13 +37,13 @@ int main(int argc, char **argv) > > { > > struct gup_test gup = { 0 }; > > unsigned long size = 128 * MB; > > - int i, fd, filed, opt, nr_pages = 1, thp = -1, repeats = 1, write = 0; > > + int i, fd, filed, opt, nr_pages = 1, thp = -1, repeats = 1, write = 1; > > unsigned long cmd = GUP_FAST_BENCHMARK; > > int flags = MAP_PRIVATE; > > char *file = "/dev/zero"; > > char *p; > > > > - while ((opt = getopt(argc, argv, "m:r:n:F:f:abctTLUuwSH")) != -1) { > > + while ((opt = getopt(argc, argv, "m:r:n:F:f:abctTLUuwWSHp")) != -1) { > > switch (opt) { > > case 'a': > > cmd = PIN_FAST_BENCHMARK; > > @@ -65,9 +65,13 @@ int main(int argc, char **argv) > > */ > > gup.which_pages[0] = 1; > > break; > > + case 'p': > > + /* works only with DUMP_USER_PAGES_TEST */ > > + gup.test_flags |= GUP_TEST_FLAG_DUMP_PAGES_USE_PIN; > > + break; > > case 'F': > > /* strtol, so you can pass flags in hex form */ > > - gup.flags = strtol(optarg, 0, 0); > > + gup.gup_flags = strtol(optarg, 0, 0); > > break; > > case 'm': > > size = atoi(optarg) * MB; > > @@ -93,6 +97,9 @@ int main(int argc, char **argv) > > case 'w': > > write = 1; > > break; > > + case 'W': > > + write = 0; > > + break; > > case 'f': > > file = optarg; > > break; > > @@ -140,7 +147,7 @@ int main(int argc, char **argv) > > > > gup.nr_pages_per_call = nr_pages; > > if (write) > > - gup.flags |= FOLL_WRITE; > > + gup.gup_flags |= FOLL_WRITE; > > > > fd = open("/sys/kernel/debug/gup_test", O_RDWR); > > if (fd == -1) { > > >