public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Leon Woestenberg <leon.woestenberg@gmail.com>
To: linux-kernel@vger.kernel.org
Subject: get_user_pages() on an mmap()ed file allowed? What to do if 0 <  get_user_pages(..., nr_pages, ...) < nr_pages?
Date: Mon, 3 Aug 2009 17:23:44 +0200	[thread overview]
Message-ID: <c384c5ea0908030823y494ee8bei85aa62c1470fa3ec@mail.gmail.com> (raw)

Hello,


I have a PCI device driver performing DMA to a scattered user-space buffer.
Given a malloc()ed buffer, get_user_pages(..., buffer, nr_pages, ...)
always returns to requested number of pages and everything works as
expected.
So far so good.

Since that I changed userspace to mmap() a file, instead of
malloc()ing a buffer.
The mmap() in userspace works.

However, in the driver get_user_pages() starts to return less pages
than I requested, in an undeterministic fashion (most of the times I
get the expected number,
sometimes I get only a part of the requested pages).

Reading the get_user_pages() implementation dazzles me too much,
still.  I wonder if I am violating the kernel API?

- is it allowed to have a PCI device DMA-read from memory pages, that
belong to a file mmap()'d by userspace?
- what are valid reasons for get_user_pages() to fail?
- what should a driver do when get_user_pages() returns less pages
than requested?


A snippet of the code:


my user space does:

    int fd = open(filename, O_RDONLY);
    assert(fd >= 0);

    /* map the file in memory */
    char *buffer = mmap(0, buffersize, PROT_READ, MAP_SHARED, fd, 0);
    assert(buffer != MAP_FAILED);

    /* advice sequential access */
    int rc = madvise(buffer, buffersize, MADV_SEQUENTIAL);
    assert(rc == 0);

my driver does:

    const unsigned long first = (boe & PAGE_MASK) >> PAGE_SHIFT;
    const unsigned long last  = ((boe + count - 1) & PAGE_MASK) >> PAGE_SHIFT;
    const int nr_pages = last - first + 1;
    ...
    down_read(&current->mm->mmap_sem);
    rc = get_user_pages(current, current->mm, start & PAGE_MASK,
nr_pages, 0 /* do not write*/, 1 /* do force */, pages, NULL);
    up_read(&current->mm->mmap_sem);

    BUG_ON(rc < nr_pages);

Thanks,
-- 
Leon

             reply	other threads:[~2009-08-03 15:23 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-03 15:23 Leon Woestenberg [this message]
2009-08-03 16:30 ` get_user_pages() on an mmap()ed file allowed? What to do if 0 < get_user_pages(..., nr_pages, ...) < nr_pages? Hugh Dickins
2009-08-04  8:57   ` Leon Woestenberg
2009-08-04  9:50     ` KAMEZAWA Hiroyuki
2009-08-04 10:07       ` Leon Woestenberg
2009-08-04  9:18   ` Brice Goglin
2009-08-04  9:59     ` Leon Woestenberg
2009-08-04 10:39       ` [PATCH] mm: get_user_pages() stores ERR_PTR() in pages[i] on failure Brice Goglin
2009-08-04 11:20         ` Leon Woestenberg
2009-08-04 12:00         ` Hugh Dickins
2009-08-04 16:25           ` Leon Woestenberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c384c5ea0908030823y494ee8bei85aa62c1470fa3ec@mail.gmail.com \
    --to=leon.woestenberg@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox