Skip to content

Commit

Permalink
mm/gup: Introduce vaddr_pin_pages()
Browse files Browse the repository at this point in the history
The addition of FOLL_LONGTERM took on additional meaning for CMA pages.
In addition subsystems such as RDMA require new information to be
passed to the GUP interface to track file owning information.  As such a
simple FOLL_LONGTERM flag is no longer sufficient for these users to
pin pages.

Introduce a new GUP like call which takes the newly introduced vaddr_pin
information.  Failure to pass the vaddr_pin object back to a vaddr_put*
call will result in a failure if pins were created on files during the
pin operation.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
  • Loading branch information
weiny2 committed Aug 8, 2019
1 parent fbbcdd0 commit 5d37765
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
7 changes: 7 additions & 0 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,13 @@ int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc);
int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc,
struct task_struct *task, bool bypass_rlim);

long vaddr_pin_pages(unsigned long addr, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages,
struct vaddr_pin *vaddr_pin);
void vaddr_put_pages_dirty_lock(struct page **pages, unsigned long nr_pages,
struct vaddr_pin *vaddr_pin);
void vaddr_put_page(struct page *page, struct vaddr_pin *vaddr_pin);

bool mapping_inode_has_layout(struct vaddr_pin *vaddr_pin, struct page *page);

/* Container for pinned pfns / pages */
Expand Down
53 changes: 53 additions & 0 deletions mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -2538,3 +2538,56 @@ int get_user_pages_fast(unsigned long start, int nr_pages,
return ret;
}
EXPORT_SYMBOL_GPL(get_user_pages_fast);

/**
* vaddr_pin_pages pin pages by virtual address and return the pages to the
* user.
*
* @addr, start address
* @nr_pages, number of pages to pin
* @gup_flags, flags to use for the pin
* @pages, array of pages returned
* @vaddr_pin, initalized meta information this pin is to be associated
* with.
*
* NOTE regarding vaddr_pin:
*
* Some callers can share pins via file descriptors to other processes.
* Callers such as this should use the f_owner field of vaddr_pin to indicate
* the file the fd points to. All other callers should use the mm this pin is
* being made against. Usually "current->mm".
*
* Expects mmap_sem to be read locked.
*/
long vaddr_pin_pages(unsigned long addr, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages,
struct vaddr_pin *vaddr_pin)
{
long ret;

gup_flags |= FOLL_LONGTERM;

if (!vaddr_pin || (!vaddr_pin->mm && !vaddr_pin->f_owner))
return -EINVAL;

ret = __gup_longterm_locked(current,
vaddr_pin->mm,
addr, nr_pages,
pages, NULL, gup_flags,
vaddr_pin);
return ret;
}
EXPORT_SYMBOL(vaddr_pin_pages);

void vaddr_put_pages_dirty_lock(struct page **pages, unsigned long nr_pages,
struct vaddr_pin *vaddr_pin)
{
__put_user_pages_dirty(vaddr_pin, pages, nr_pages, set_page_dirty_lock);
}
EXPORT_SYMBOL(vaddr_put_pages_dirty_lock);

void vaddr_put_page(struct page *page, struct vaddr_pin *vaddr_pin)
{
__put_user_page(vaddr_pin, page);
}
EXPORT_SYMBOL(vaddr_put_page);

0 comments on commit 5d37765

Please sign in to comment.