lkml.org 
[lkml]   [2019]   [Nov]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 16/18] mm/gup_benchmark: support pin_user_pages() and related calls
    Date
    Up until now, gup_benchmark supported testing of the
    following kernel functions:

    * get_user_pages(): via the '-U' command line option
    * get_user_pages_longterm(): via the '-L' command line option
    * get_user_pages_fast(): as the default (no options required)

    Add test coverage for the new corresponding pin_*() functions:

    * pin_user_pages(): via the '-c' command line option
    * pin_longterm_pages(): via the '-b' command line option
    * pin_user_pages_fast(): via the '-a' command line option

    Also, add an option for clarity: '-u' for what is now (still) the
    default choice: get_user_pages_fast().

    Also, for the three commands that set FOLL_PIN, verify that the pages
    really are dma-pinned, via the new is_dma_pinned() routine.
    Those commands are:

    PIN_FAST_BENCHMARK : calls pin_user_pages_fast()
    PIN_LONGTERM_BENCHMARK : calls pin_longterm_pages()
    PIN_BENCHMARK : calls pin_user_pages()

    In between the calls to pin_*() and put_user_pages(),
    check each page: if page_dma_pinned() returns false, then
    WARN and return.

    Do this outside of the benchmark timestamps, so that it doesn't
    affect reported times.

    Signed-off-by: John Hubbard <jhubbard@nvidia.com>
    ---
    mm/gup_benchmark.c | 74 ++++++++++++++++++++--
    tools/testing/selftests/vm/gup_benchmark.c | 23 ++++++-
    2 files changed, 91 insertions(+), 6 deletions(-)

    diff --git a/mm/gup_benchmark.c b/mm/gup_benchmark.c
    index 7dd602d7f8db..2bb0f5df4803 100644
    --- a/mm/gup_benchmark.c
    +++ b/mm/gup_benchmark.c
    @@ -8,6 +8,9 @@
    #define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark)
    #define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark)
    #define GUP_BENCHMARK _IOWR('g', 3, struct gup_benchmark)
    +#define PIN_FAST_BENCHMARK _IOWR('g', 4, struct gup_benchmark)
    +#define PIN_LONGTERM_BENCHMARK _IOWR('g', 5, struct gup_benchmark)
    +#define PIN_BENCHMARK _IOWR('g', 6, struct gup_benchmark)

    struct gup_benchmark {
    __u64 get_delta_usec;
    @@ -19,6 +22,44 @@ struct gup_benchmark {
    __u64 expansion[10]; /* For future use */
    };

    +static void put_back_pages(int cmd, struct page **pages, unsigned long nr_pages)
    +{
    + int i;
    +
    + switch (cmd) {
    + case GUP_FAST_BENCHMARK:
    + case GUP_LONGTERM_BENCHMARK:
    + case GUP_BENCHMARK:
    + for (i = 0; i < nr_pages; i++)
    + put_page(pages[i]);
    + break;
    +
    + case PIN_FAST_BENCHMARK:
    + case PIN_LONGTERM_BENCHMARK:
    + case PIN_BENCHMARK:
    + put_user_pages(pages, nr_pages);
    + break;
    + }
    +}
    +
    +static void verify_dma_pinned(int cmd, struct page **pages,
    + unsigned long nr_pages)
    +{
    + int i;
    +
    + switch (cmd) {
    + case PIN_FAST_BENCHMARK:
    + case PIN_LONGTERM_BENCHMARK:
    + case PIN_BENCHMARK:
    + for (i = 0; i < nr_pages; i++) {
    + if (WARN(!page_dma_pinned(pages[i]),
    + "pages[%d] is NOT dma-pinned\n", i))
    + break;
    + }
    + break;
    + }
    +}
    +
    static int __gup_benchmark_ioctl(unsigned int cmd,
    struct gup_benchmark *gup)
    {
    @@ -62,6 +103,19 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
    nr = get_user_pages(addr, nr, gup->flags & 1, pages + i,
    NULL);
    break;
    + case PIN_FAST_BENCHMARK:
    + nr = pin_user_pages_fast(addr, nr, gup->flags & 1,
    + pages + i);
    + break;
    + case PIN_LONGTERM_BENCHMARK:
    + nr = pin_longterm_pages(addr, nr,
    + (gup->flags & 1),
    + pages + i, NULL);
    + break;
    + case PIN_BENCHMARK:
    + nr = pin_user_pages(addr, nr, gup->flags & 1, pages + i,
    + NULL);
    + break;
    default:
    return -1;
    }
    @@ -72,15 +126,22 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
    }
    end_time = ktime_get();

    + /* Shifting the meaning of nr_pages: now it is actual number pinned: */
    + nr_pages = i;
    +
    gup->get_delta_usec = ktime_us_delta(end_time, start_time);
    gup->size = addr - gup->addr;

    + /*
    + * Take an un-benchmark-timed moment to verify DMA pinned
    + * state: print a warning if any non-dma-pinned pages are found:
    + */
    + verify_dma_pinned(cmd, pages, nr_pages);
    +
    start_time = ktime_get();
    - for (i = 0; i < nr_pages; i++) {
    - if (!pages[i])
    - break;
    - put_page(pages[i]);
    - }
    +
    + put_back_pages(cmd, pages, nr_pages);
    +
    end_time = ktime_get();
    gup->put_delta_usec = ktime_us_delta(end_time, start_time);

    @@ -98,6 +159,9 @@ static long gup_benchmark_ioctl(struct file *filep, unsigned int cmd,
    case GUP_FAST_BENCHMARK:
    case GUP_LONGTERM_BENCHMARK:
    case GUP_BENCHMARK:
    + case PIN_FAST_BENCHMARK:
    + case PIN_LONGTERM_BENCHMARK:
    + case PIN_BENCHMARK:
    break;
    default:
    return -EINVAL;
    diff --git a/tools/testing/selftests/vm/gup_benchmark.c b/tools/testing/selftests/vm/gup_benchmark.c
    index 485cf06ef013..c5c934c0f402 100644
    --- a/tools/testing/selftests/vm/gup_benchmark.c
    +++ b/tools/testing/selftests/vm/gup_benchmark.c
    @@ -18,6 +18,15 @@
    #define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark)
    #define GUP_BENCHMARK _IOWR('g', 3, struct gup_benchmark)

    +/*
    + * Similar to above, but use FOLL_PIN instead of FOLL_GET. This is done
    + * by calling pin_user_pages_fast(), pin_longterm_pages(), and pin_user_pages(),
    + * respectively.
    + */
    +#define PIN_FAST_BENCHMARK _IOWR('g', 4, struct gup_benchmark)
    +#define PIN_LONGTERM_BENCHMARK _IOWR('g', 5, struct gup_benchmark)
    +#define PIN_BENCHMARK _IOWR('g', 6, struct gup_benchmark)
    +
    struct gup_benchmark {
    __u64 get_delta_usec;
    __u64 put_delta_usec;
    @@ -37,8 +46,17 @@ int main(int argc, char **argv)
    char *file = "/dev/zero";
    char *p;

    - while ((opt = getopt(argc, argv, "m:r:n:f:tTLUwSH")) != -1) {
    + while ((opt = getopt(argc, argv, "m:r:n:f:abctTLUuwSH")) != -1) {
    switch (opt) {
    + case 'a':
    + cmd = PIN_FAST_BENCHMARK;
    + break;
    + case 'b':
    + cmd = PIN_LONGTERM_BENCHMARK;
    + break;
    + case 'c':
    + cmd = PIN_BENCHMARK;
    + break;
    case 'm':
    size = atoi(optarg) * MB;
    break;
    @@ -60,6 +78,9 @@ int main(int argc, char **argv)
    case 'U':
    cmd = GUP_BENCHMARK;
    break;
    + case 'u':
    + cmd = GUP_FAST_BENCHMARK;
    + break;
    case 'w':
    write = 1;
    break;
    --
    2.23.0
    \
     
     \ /
      Last update: 2019-11-03 22:20    [W:4.255 / U:0.312 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site