From: Souptick Joarder <jrdr.linux@gmail.com>
To: jgross@suse.com, boris.ostrovsky@oracle.com, sstabellini@kernel.org
Cc: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org,
John Hubbard <jhubbard@nvidia.com>,
Souptick Joarder <jrdr.linux@gmail.com>
Subject: [RFC PATCH v2] xen/privcmd: Convert get_user_pages*() to pin_user_pages*()
Date: Tue, 23 Jun 2020 17:25:28 +0530 [thread overview]
Message-ID: <1592913328-15486-1-git-send-email-jrdr.linux@gmail.com> (raw)
In 2019, we introduced pin_user_pages*() and now we are converting
get_user_pages*() to the new API as appropriate. [1] & [2] could
be referred for more information. This is case 5 as per document [1].
As discussed, pages need to be marked as dirty before unpinned it.
Previously, if lock_pages() end up partially mapping pages, it used
to return -ERRNO due to which unlock_pages() have to go through
each pages[i] till *nr_pages* to validate them. This can be avoided
by passing correct number partially mapped pages & -ERRNO separately
while returning from lock_pages() due to error.
With this fix unlock_pages() doesn't need to validate pages[i] till
*nr_pages* for error scenario.
[1] Documentation/core-api/pin_user_pages.rst
[2] "Explicit pinning of user-space pages":
https://lwn.net/Articles/807108/
Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
drivers/xen/privcmd.c | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index a250d11..eea90cd 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -580,25 +580,30 @@ 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, int *errno)
{
unsigned int i;
+ int pinned = 0, rc = 0;
for (i = 0; i < num; i++) {
unsigned int requested;
- int pinned;
+ rc += pinned;
requested = DIV_ROUND_UP(
offset_in_page(kbufs[i].uptr) + kbufs[i].size,
PAGE_SIZE);
- if (requested > nr_pages)
- return -ENOSPC;
+ if (requested > nr_pages) {
+ *errno = -ENOSPC;
+ return rc;
+ }
- pinned = get_user_pages_fast(
+ pinned = pin_user_pages_fast(
(unsigned long) kbufs[i].uptr,
requested, FOLL_WRITE, pages);
- if (pinned < 0)
- return pinned;
+ if (pinned < 0) {
+ *errno = pinned;
+ return rc;
+ }
nr_pages -= pinned;
pages += pinned;
@@ -613,11 +618,7 @@ static void unlock_pages(struct page *pages[], unsigned int nr_pages)
if (!pages)
return;
-
- for (i = 0; i < nr_pages; i++) {
- if (pages[i])
- put_page(pages[i]);
- }
+ unpin_user_pages_dirty_lock(pages, nr_pages, 1);
}
static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
@@ -630,6 +631,7 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
struct xen_dm_op_buf *xbufs = NULL;
unsigned int i;
long rc;
+ int errno = 0;
if (copy_from_user(&kdata, udata, sizeof(kdata)))
return -EFAULT;
@@ -683,9 +685,12 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
goto out;
}
- rc = lock_pages(kbufs, kdata.num, pages, nr_pages);
- if (rc)
+ rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &errno);
+ if (errno < 0) {
+ nr_pages = rc;
+ rc = errno;
goto out;
+ }
for (i = 0; i < kdata.num; i++) {
set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);
--
1.9.1
WARNING: multiple messages have this Message-ID (diff)
From: Souptick Joarder <jrdr.linux@gmail.com>
To: jgross@suse.com, boris.ostrovsky@oracle.com, sstabellini@kernel.org
Cc: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org,
Souptick Joarder <jrdr.linux@gmail.com>,
John Hubbard <jhubbard@nvidia.com>
Subject: [RFC PATCH v2] xen/privcmd: Convert get_user_pages*() to pin_user_pages*()
Date: Tue, 23 Jun 2020 17:25:28 +0530 [thread overview]
Message-ID: <1592913328-15486-1-git-send-email-jrdr.linux@gmail.com> (raw)
In 2019, we introduced pin_user_pages*() and now we are converting
get_user_pages*() to the new API as appropriate. [1] & [2] could
be referred for more information. This is case 5 as per document [1].
As discussed, pages need to be marked as dirty before unpinned it.
Previously, if lock_pages() end up partially mapping pages, it used
to return -ERRNO due to which unlock_pages() have to go through
each pages[i] till *nr_pages* to validate them. This can be avoided
by passing correct number partially mapped pages & -ERRNO separately
while returning from lock_pages() due to error.
With this fix unlock_pages() doesn't need to validate pages[i] till
*nr_pages* for error scenario.
[1] Documentation/core-api/pin_user_pages.rst
[2] "Explicit pinning of user-space pages":
https://lwn.net/Articles/807108/
Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
drivers/xen/privcmd.c | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index a250d11..eea90cd 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -580,25 +580,30 @@ 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, int *errno)
{
unsigned int i;
+ int pinned = 0, rc = 0;
for (i = 0; i < num; i++) {
unsigned int requested;
- int pinned;
+ rc += pinned;
requested = DIV_ROUND_UP(
offset_in_page(kbufs[i].uptr) + kbufs[i].size,
PAGE_SIZE);
- if (requested > nr_pages)
- return -ENOSPC;
+ if (requested > nr_pages) {
+ *errno = -ENOSPC;
+ return rc;
+ }
- pinned = get_user_pages_fast(
+ pinned = pin_user_pages_fast(
(unsigned long) kbufs[i].uptr,
requested, FOLL_WRITE, pages);
- if (pinned < 0)
- return pinned;
+ if (pinned < 0) {
+ *errno = pinned;
+ return rc;
+ }
nr_pages -= pinned;
pages += pinned;
@@ -613,11 +618,7 @@ static void unlock_pages(struct page *pages[], unsigned int nr_pages)
if (!pages)
return;
-
- for (i = 0; i < nr_pages; i++) {
- if (pages[i])
- put_page(pages[i]);
- }
+ unpin_user_pages_dirty_lock(pages, nr_pages, 1);
}
static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
@@ -630,6 +631,7 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
struct xen_dm_op_buf *xbufs = NULL;
unsigned int i;
long rc;
+ int errno = 0;
if (copy_from_user(&kdata, udata, sizeof(kdata)))
return -EFAULT;
@@ -683,9 +685,12 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
goto out;
}
- rc = lock_pages(kbufs, kdata.num, pages, nr_pages);
- if (rc)
+ rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &errno);
+ if (errno < 0) {
+ nr_pages = rc;
+ rc = errno;
goto out;
+ }
for (i = 0; i < kdata.num; i++) {
set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);
--
1.9.1
next reply other threads:[~2020-06-23 11:47 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-23 11:55 Souptick Joarder [this message]
2020-06-23 11:55 ` [RFC PATCH v2] xen/privcmd: Convert get_user_pages*() to pin_user_pages*() Souptick Joarder
-- strict thread matches above, loose matches on Subject: below --
2020-06-23 11:58 Souptick Joarder
2020-06-23 11:58 ` Souptick Joarder
2020-06-23 17:41 ` Boris Ostrovsky
2020-06-24 1:36 ` Souptick Joarder
2020-06-24 1:36 ` Souptick Joarder
2020-06-24 15:37 ` Boris Ostrovsky
2020-06-24 15:37 ` Boris Ostrovsky
2020-06-24 16:41 ` Souptick Joarder
2020-06-24 16:41 ` Souptick Joarder
2020-06-24 22:31 ` Boris Ostrovsky
2020-06-24 22:31 ` Boris Ostrovsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1592913328-15486-1-git-send-email-jrdr.linux@gmail.com \
--to=jrdr.linux@gmail.com \
--cc=boris.ostrovsky@oracle.com \
--cc=jgross@suse.com \
--cc=jhubbard@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=sstabellini@kernel.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.