mlx4_core: INIT/CLOSE port logic for IB ports in SR-IOV mode
[cascardo/linux.git] / mm / swap.c
index 4e7e2ec..7782588 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -236,6 +236,58 @@ 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;
+
+               pages[seg] = kmap_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)