[CRIU] [PATCH 10/10] uffd: Introduce lazy_pages_fd as preparation for socket polling
Pavel Emelyanov
xemul at virtuozzo.com
Fri Nov 11 21:26:27 PST 2016
We will want to poll not only a bunch of uffd-s, but also the lazy
socket, so here's "an fd and a callback" object to be pushed into
epoll.
Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
criu/uffd.c | 49 +++++++++++++++++++++++++++++++------------------
1 file changed, 31 insertions(+), 18 deletions(-)
diff --git a/criu/uffd.c b/criu/uffd.c
index 1393a70..a5c2f8e 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -48,9 +48,13 @@
static mutex_t *lazy_sock_mutex;
static void *aux_page;
+struct lazy_pages_fd {
+ int fd;
+ int (*event)(struct lazy_pages_fd *);
+};
+
struct lazy_pages_info {
int pid;
- int uffd;
struct list_head pages;
@@ -59,10 +63,13 @@ struct lazy_pages_info {
unsigned long total_pages;
unsigned long copied_pages;
+ struct lazy_pages_fd lpfd;
+
struct list_head l;
};
static LIST_HEAD(lpis);
+static int handle_user_fault(struct lazy_pages_fd *lpfd);
static struct lazy_pages_info *lpi_init(void)
{
@@ -75,6 +82,7 @@ static struct lazy_pages_info *lpi_init(void)
memset(lpi, 0, sizeof(*lpi));
INIT_LIST_HEAD(&lpi->pages);
INIT_LIST_HEAD(&lpi->l);
+ lpi->lpfd.event = handle_user_fault;
return lpi;
}
@@ -83,8 +91,8 @@ static void lpi_fini(struct lazy_pages_info *lpi)
{
if (!lpi)
return;
- if (lpi->uffd > 0)
- close(lpi->uffd);
+ if (lpi->lpfd.fd > 0)
+ close(lpi->lpfd.fd);
if (lpi->pr.close)
lpi->pr.close(&lpi->pr);
free(lpi);
@@ -318,15 +326,15 @@ static int ud_open(int client, struct lazy_pages_info **_lpi)
return 0;
}
- lpi->uffd = recv_fd(client);
- if (lpi->uffd < 0) {
+ lpi->lpfd.fd = recv_fd(client);
+ if (lpi->lpfd.fd < 0) {
pr_err("recv_fd error");
goto out;
}
- pr_debug("lpi->uffd %d\n", lpi->uffd);
+ pr_debug("lpi->uffd %d\n", lpi->lpfd.fd);
- pr_debug("uffd is 0x%d\n", lpi->uffd);
- uffd_flags = fcntl(lpi->uffd, F_GETFD, NULL);
+ pr_debug("uffd is 0x%d\n", lpi->lpfd.fd);
+ uffd_flags = fcntl(lpi->lpfd.fd, F_GETFD, NULL);
pr_debug("uffd_flags are 0x%x\n", uffd_flags);
/*
@@ -395,7 +403,7 @@ static int uffd_copy_page(struct lazy_pages_info *lpi, __u64 address)
uffdio_copy.copy = 0;
pr_debug("uffdio_copy.dst 0x%llx\n", uffdio_copy.dst);
- rc = ioctl(lpi->uffd, UFFDIO_COPY, &uffdio_copy);
+ rc = ioctl(lpi->lpfd.fd, UFFDIO_COPY, &uffdio_copy);
pr_debug("ioctl UFFDIO_COPY rc 0x%x\n", rc);
pr_debug("uffdio_copy.copy 0x%llx\n", uffdio_copy.copy);
if (rc) {
@@ -426,7 +434,7 @@ static int uffd_zero_page(struct lazy_pages_info *lpi, __u64 address)
uffdio_zeropage.mode = 0;
pr_debug("uffdio_zeropage.range.start 0x%llx\n", uffdio_zeropage.range.start);
- rc = ioctl(lpi->uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
+ rc = ioctl(lpi->lpfd.fd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
pr_debug("ioctl UFFDIO_ZEROPAGE rc 0x%x\n", rc);
pr_debug("uffdio_zeropage.zeropage 0x%llx\n", uffdio_zeropage.zeropage);
if (rc) {
@@ -643,15 +651,18 @@ out:
return ret;
}
-static int handle_user_fault(struct lazy_pages_info *lpi)
+static int handle_user_fault(struct lazy_pages_fd *lpfd)
{
+ struct lazy_pages_info *lpi;
struct uffd_msg msg;
__u64 flags;
__u64 address;
struct uffd_pages_struct *uffd_pages;
int ret;
- ret = read(lpi->uffd, &msg, sizeof(msg));
+ lpi = container_of(lpfd, struct lazy_pages_info, lpfd);
+
+ ret = read(lpfd->fd, &msg, sizeof(msg));
pr_debug("read() ret: 0x%x\n", ret);
if (!ret)
return 1;
@@ -723,6 +734,8 @@ static int handle_requests(int epollfd, struct epoll_event *events)
return ret;
while (1) {
+ struct lazy_pages_fd *lpfd;
+
/*
* Setting the timeout to 5 seconds. If after this time
* no uffd pages are requested the code switches to
@@ -742,8 +755,8 @@ static int handle_requests(int epollfd, struct epoll_event *events)
for (i = 0; i < ret; i++) {
int err;
- lpi = (struct lazy_pages_info *)events[i].data.ptr;
- err = handle_user_fault(lpi);
+ lpfd = (struct lazy_pages_fd *)events[i].data.ptr;
+ err = lpfd->event(lpfd);
if (err < 0)
goto out;
}
@@ -803,13 +816,13 @@ free_events:
return -1;
}
-static int epoll_add_lpi(int epollfd, struct lazy_pages_info *lpi)
+static int epoll_add_lpfd(int epollfd, struct lazy_pages_fd *lpfd)
{
struct epoll_event ev;
ev.events = EPOLLIN;
- ev.data.ptr = lpi;
- if (epoll_ctl(epollfd, EPOLL_CTL_ADD, lpi->uffd, &ev) == -1) {
+ ev.data.ptr = lpfd;
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, lpfd->fd, &ev) == -1) {
pr_perror("epoll_ctl failed");
return -1;
}
@@ -856,7 +869,7 @@ static int prepare_uffds(int listen, int epollfd)
goto close_uffd;
if (lpi == NULL)
continue;
- if (epoll_add_lpi(epollfd, lpi))
+ if (epoll_add_lpfd(epollfd, &lpi->lpfd))
goto close_uffd;
}
--
2.5.0
More information about the CRIU
mailing list