|
@@ -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)
|