[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 20/34] xen: convert put_page() to put_user_page*()



From: John Hubbard <jhubbard@xxxxxxxxxx>

For pages that were retained via get_user_pages*(), release those pages
via the new put_user_page*() routines, instead of via put_page() or
release_pages().

This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").

This also handles pages[i] == NULL cases, thanks to an approach
that is actually written by Juergen Gross.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>

Cc: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
Cc: xen-devel@xxxxxxxxxxxxxxxxxxxx
---

Hi Juergen,

Say, this is *exactly* what you proposed in your gup.patch, so
I've speculatively added your Signed-off-by above, but need your
approval before that's final. Let me know please...

thanks,
John Hubbard


 drivers/xen/privcmd.c | 32 +++++++++++---------------------
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index c6070e70dd73..c7d0763ca8c2 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -582,10 +582,11 @@ static long privcmd_ioctl_mmap_batch(
 
 static int lock_pages(
        struct privcmd_dm_op_buf kbufs[], unsigned int num,
-       struct page *pages[], unsigned int nr_pages)
+       struct page *pages[], unsigned int *nr_pages)
 {
-       unsigned int i;
+       unsigned int i, free = *nr_pages;
 
+       *nr_pages = 0;
        for (i = 0; i < num; i++) {
                unsigned int requested;
                int pinned;
@@ -593,35 +594,22 @@ static int lock_pages(
                requested = DIV_ROUND_UP(
                        offset_in_page(kbufs[i].uptr) + kbufs[i].size,
                        PAGE_SIZE);
-               if (requested > nr_pages)
+               if (requested > free)
                        return -ENOSPC;
 
                pinned = get_user_pages_fast(
                        (unsigned long) kbufs[i].uptr,
-                       requested, FOLL_WRITE, pages);
+                       requested, FOLL_WRITE, pages + *nr_pages);
                if (pinned < 0)
                        return pinned;
 
-               nr_pages -= pinned;
-               pages += pinned;
+               free -= pinned;
+               *nr_pages += pinned;
        }
 
        return 0;
 }
 
-static void unlock_pages(struct page *pages[], unsigned int nr_pages)
-{
-       unsigned int i;
-
-       if (!pages)
-               return;
-
-       for (i = 0; i < nr_pages; i++) {
-               if (pages[i])
-                       put_page(pages[i]);
-       }
-}
-
 static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
 {
        struct privcmd_data *data = file->private_data;
@@ -681,11 +669,12 @@ static long privcmd_ioctl_dm_op(struct file *file, void 
__user *udata)
 
        xbufs = kcalloc(kdata.num, sizeof(*xbufs), GFP_KERNEL);
        if (!xbufs) {
+               nr_pages = 0;
                rc = -ENOMEM;
                goto out;
        }
 
-       rc = lock_pages(kbufs, kdata.num, pages, nr_pages);
+       rc = lock_pages(kbufs, kdata.num, pages, &nr_pages);
        if (rc)
                goto out;
 
@@ -699,7 +688,8 @@ static long privcmd_ioctl_dm_op(struct file *file, void 
__user *udata)
        xen_preemptible_hcall_end();
 
 out:
-       unlock_pages(pages, nr_pages);
+       if (pages)
+               put_user_pages(pages, nr_pages);
        kfree(xbufs);
        kfree(pages);
        kfree(kbufs);
-- 
2.22.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.