mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
mm: add get_kernel_page[s] for pinning of kernel addresses for I/O
This patch adds two new APIs get_kernel_pages() and get_kernel_page() that may be used to pin a vector of kernel addresses for IO. The initial user is expected to be NFS for allowing pages to be written to swap using aops->direct_IO(). Strictly speaking, swap-over-NFS only needs to pin one page for IO but it makes sense to express the API in terms of a vector and add a helper for pinning single pages. Signed-off-by: Mel Gorman <[email protected]> Reviewed-by: Rik van Riel <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: David S. Miller <[email protected]> Cc: Eric B Munson <[email protected]> Cc: Eric Paris <[email protected]> Cc: James Morris <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Mike Christie <[email protected]> Cc: Neil Brown <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Sebastian Andrzej Siewior <[email protected]> Cc: Trond Myklebust <[email protected]> Cc: Xiaotian Feng <[email protected]> Cc: Mark Salter <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
f981c5950f
commit
18022c5d86
4 changed files with 61 additions and 0 deletions
53
mm/swap.c
53
mm/swap.c
|
|
@ -236,6 +236,59 @@ void put_pages_list(struct list_head *pages)
|
|||
}
|
||||
EXPORT_SYMBOL(put_pages_list);
|
||||
|
||||
/*
|
||||
* get_kernel_pages() - pin kernel pages in memory
|
||||
* @kiov: An array of struct kvec structures
|
||||
* @nr_segs: number of segments to pin
|
||||
* @write: pinning for read/write, currently ignored
|
||||
* @pages: array that receives pointers to the pages pinned.
|
||||
* Should be at least nr_segs long.
|
||||
*
|
||||
* Returns number of pages pinned. This may be fewer than the number
|
||||
* requested. If nr_pages is 0 or negative, returns 0. If no pages
|
||||
* were pinned, returns -errno. Each page returned must be released
|
||||
* with a put_page() call when it is finished with.
|
||||
*/
|
||||
int get_kernel_pages(const struct kvec *kiov, int nr_segs, int write,
|
||||
struct page **pages)
|
||||
{
|
||||
int seg;
|
||||
|
||||
for (seg = 0; seg < nr_segs; seg++) {
|
||||
if (WARN_ON(kiov[seg].iov_len != PAGE_SIZE))
|
||||
return seg;
|
||||
|
||||
/* virt_to_page sanity checks the PFN */
|
||||
pages[seg] = virt_to_page(kiov[seg].iov_base);
|
||||
page_cache_get(pages[seg]);
|
||||
}
|
||||
|
||||
return seg;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_kernel_pages);
|
||||
|
||||
/*
|
||||
* get_kernel_page() - pin a kernel page in memory
|
||||
* @start: starting kernel address
|
||||
* @write: pinning for read/write, currently ignored
|
||||
* @pages: array that receives pointer to the page pinned.
|
||||
* Must be at least nr_segs long.
|
||||
*
|
||||
* Returns 1 if page is pinned. If the page was not pinned, returns
|
||||
* -errno. The page returned must be released with a put_page() call
|
||||
* when it is finished with.
|
||||
*/
|
||||
int get_kernel_page(unsigned long start, int write, struct page **pages)
|
||||
{
|
||||
const struct kvec kiov = {
|
||||
.iov_base = (void *)start,
|
||||
.iov_len = PAGE_SIZE
|
||||
};
|
||||
|
||||
return get_kernel_pages(&kiov, 1, write, pages);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_kernel_page);
|
||||
|
||||
static void pagevec_lru_move_fn(struct pagevec *pvec,
|
||||
void (*move_fn)(struct page *page, struct lruvec *lruvec, void *arg),
|
||||
void *arg)
|
||||
|
|
|
|||
Loading…
Reference in a new issue