[CRIU] [PATCH 06/11] lazy-pages: introduce handle_user_fault
Mike Rapoport
rppt at linux.vnet.ibm.com
Sun Apr 10 23:19:49 PDT 2016
It will handle page fault notifications from userfaultfd
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/uffd.c | 95 ++++++++++++++++++++++++++++++-------------------------------
1 file changed, 47 insertions(+), 48 deletions(-)
diff --git a/criu/uffd.c b/criu/uffd.c
index 14de015..87c2602 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -500,6 +500,51 @@ out:
return ret;
}
+static int handle_user_fault(int fd, struct list_head *uffd_list, void *dest)
+{
+ struct uffd_msg msg;
+ __u64 flags;
+ __u64 address;
+ struct uffd_pages_struct *uffd_pages;
+ int ret;
+
+ ret = read(fd, &msg, sizeof(msg));
+ pr_debug("read() ret: 0x%x\n", ret);
+ if (!ret)
+ return 1;
+
+ if (ret != sizeof(msg)) {
+ pr_perror("Can't read userfaultfd message");
+ return -1;
+ }
+
+ /* Align requested address to the next page boundary */
+ address = msg.arg.pagefault.address & ~(page_size() - 1);
+ pr_debug("msg.arg.pagefault.address 0x%llx\n", address);
+
+ /* Make sure to not transfer a page twice */
+ list_for_each_entry(uffd_pages, uffd_list, list)
+ if ((uffd_pages->addr == address) && (uffd_pages->flags & UFFD_FLAG_SENT))
+ return 0;
+
+ /* Now handle the pages actually requested. */
+ flags = msg.arg.pagefault.flags;
+ pr_debug("msg.arg.pagefault.flags 0x%llx\n", flags);
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT) {
+ pr_err("unexpected msg event %u\n", msg.event);
+ return -1;
+ }
+
+ ret = handle_regular_pages(fd, uffd_list, dest, address);
+ if (ret < 0) {
+ pr_err("Error during regular page copy\n");
+ return -1;
+ }
+
+ return 0;
+}
+
#define POLL_TIMEOUT 5000
static int handle_requests(int fd)
@@ -507,11 +552,7 @@ static int handle_requests(int fd)
struct pollfd *pollfd;
int nr_pollfd;
int ret = -1;
- struct uffd_msg msg;
- __u64 flags;
- __u64 address;
unsigned long ps;
- struct uffd_pages_struct *uffd_pages;
void *dest;
LIST_HEAD(uffd_list);
@@ -546,7 +587,6 @@ static int handle_requests(int fd)
pollfd[0].events = POLLIN;
while (1) {
- bool page_sent = false;
/*
* Setting the timeout to 5 seconds. If after this time
* no uffd pages are requested the code switches to
@@ -563,50 +603,9 @@ static int handle_requests(int fd)
break;
}
- ret = read(fd, &msg, sizeof(msg));
- pr_debug("read() ret: 0x%x\n", ret);
- if (!ret)
- break;
-
- if (ret != sizeof(msg)) {
- pr_perror("Can't read userfaultfd message from socket");
- ret = -1;
- break;
- }
-
- ret = 0;
- /* Align requested address to the next page boundary */
- address = msg.arg.pagefault.address & ~(ps - 1);
- pr_debug("msg.arg.pagefault.address 0x%llx\n", address);
-
- /* Make sure to not transfer a page twice */
- list_for_each_entry(uffd_pages, &uffd_list, list) {
- if ((uffd_pages->addr == address) && (uffd_pages->flags & UFFD_FLAG_SENT)) {
- page_sent = true;
- break;
- }
- }
-
- if (page_sent)
- continue;
-
- /* Now handle the pages actually requested. */
-
- flags = msg.arg.pagefault.flags;
- pr_debug("msg.arg.pagefault.flags 0x%llx\n", flags);
-
- if (msg.event != UFFD_EVENT_PAGEFAULT) {
- pr_err("unexpected msg event %u\n", msg.event);
- ret = -1;
+ ret = handle_user_fault(fd, &uffd_list, dest);
+ if (ret < 0)
goto out;
- }
-
- ret = handle_regular_pages(fd, &uffd_list, dest, address);
- if (ret < 0) {
- pr_err("Error during regular page copy\n");
- ret = -1;
- goto out;
- }
}
pr_debug("Handle remaining pages\n");
ret = handle_remaining_pages(fd, &uffd_list, dest);
--
1.9.1
More information about the CRIU
mailing list