mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
criu: lazy-pages: move find_vmas and related code around
Moving the find_vmas and collect_uffd_pages functions before they are actually used. This allows to drop forward declaration of find_vmas and will make subsequent refactoring cleaner. Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com> Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This commit is contained in:
committed by
Andrei Vagin
parent
6d405370da
commit
c00dd3459f
400
criu/uffd.c
400
criu/uffd.c
@@ -287,85 +287,6 @@ out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_vmas(struct lazy_pages_info *lpi);
|
||||
|
||||
static int ud_open(int client, struct lazy_pages_info **_lpi)
|
||||
{
|
||||
struct lazy_pages_info *lpi;
|
||||
int ret = -1;
|
||||
int uffd_flags;
|
||||
|
||||
lpi = lpi_init();
|
||||
if (!lpi)
|
||||
goto out;
|
||||
|
||||
/* The "transfer protocol" is first the pid as int and then
|
||||
* the FD for UFFD */
|
||||
ret = recv(client, &lpi->pid, sizeof(lpi->pid), 0);
|
||||
if (ret != sizeof(lpi->pid)) {
|
||||
if (ret < 0)
|
||||
pr_perror("PID recv error");
|
||||
else
|
||||
pr_err("PID recv: short read\n");
|
||||
goto out;
|
||||
}
|
||||
pr_debug("received PID: %d\n", lpi->pid);
|
||||
|
||||
if (lpi->pid == -1) {
|
||||
lpi_fini(lpi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lpi->uffd = recv_fd(client);
|
||||
if (lpi->uffd < 0) {
|
||||
pr_err("recv_fd error\n");
|
||||
goto out;
|
||||
}
|
||||
pr_debug("lpi->uffd %d\n", lpi->uffd);
|
||||
|
||||
pr_debug("uffd is 0x%d\n", lpi->uffd);
|
||||
uffd_flags = fcntl(lpi->uffd, F_GETFD, NULL);
|
||||
pr_debug("uffd_flags are 0x%x\n", uffd_flags);
|
||||
|
||||
/*
|
||||
* Find the memory pages belonging to the restored process
|
||||
* so that it is trackable when all pages have been transferred.
|
||||
*/
|
||||
if ((lpi->total_pages = find_vmas(lpi)) == -1)
|
||||
goto out;
|
||||
|
||||
list_add_tail(&lpi->l, &lpis);
|
||||
*_lpi = lpi;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
lpi_fini(lpi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_page(struct lazy_pages_info *lpi, unsigned long addr, void *dest)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lpi->pr.reset(&lpi->pr);
|
||||
|
||||
ret = lpi->pr.seek_page(&lpi->pr, addr);
|
||||
pr_debug("seek_pagemap_page ret 0x%x\n", ret);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (pagemap_zero(lpi->pr.pe))
|
||||
return 0;
|
||||
|
||||
ret = lpi->pr.read_pages(&lpi->pr, addr, 1, dest, 0);
|
||||
pr_debug("read_pages ret %d\n", ret);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define UFFD_FLAG_SENT 0x1
|
||||
|
||||
struct uffd_pages_struct {
|
||||
@@ -374,80 +295,6 @@ struct uffd_pages_struct {
|
||||
int flags;
|
||||
};
|
||||
|
||||
static int uffd_copy_page(struct lazy_pages_info *lpi, __u64 address,
|
||||
void *dest)
|
||||
{
|
||||
struct uffdio_copy uffdio_copy;
|
||||
int rc;
|
||||
|
||||
if (opts.use_page_server)
|
||||
rc = get_remote_pages(lpi->pid, address, 1, dest);
|
||||
else
|
||||
rc = get_page(lpi, address, dest);
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
|
||||
uffdio_copy.dst = address;
|
||||
uffdio_copy.src = (unsigned long) dest;
|
||||
uffdio_copy.len = page_size();
|
||||
uffdio_copy.mode = 0;
|
||||
uffdio_copy.copy = 0;
|
||||
|
||||
pr_debug("uffdio_copy.dst 0x%llx\n", uffdio_copy.dst);
|
||||
rc = ioctl(lpi->uffd, 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) {
|
||||
/* real retval in ufdio_copy.copy */
|
||||
if (uffdio_copy.copy != -EEXIST) {
|
||||
pr_err("UFFDIO_COPY error %Ld\n", uffdio_copy.copy);
|
||||
return -1;
|
||||
}
|
||||
} else if (uffdio_copy.copy != page_size()) {
|
||||
pr_err("UFFDIO_COPY unexpected size %Ld\n", uffdio_copy.copy);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lpi->copied_pages++;
|
||||
|
||||
return uffdio_copy.copy;
|
||||
|
||||
}
|
||||
|
||||
static int uffd_zero_page(struct lazy_pages_info *lpi, __u64 address)
|
||||
{
|
||||
struct uffdio_zeropage uffdio_zeropage;
|
||||
unsigned long ps = page_size();
|
||||
int rc;
|
||||
|
||||
uffdio_zeropage.range.start = address;
|
||||
uffdio_zeropage.range.len = ps;
|
||||
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);
|
||||
pr_debug("ioctl UFFDIO_ZEROPAGE rc 0x%x\n", rc);
|
||||
pr_debug("uffdio_zeropage.zeropage 0x%llx\n", uffdio_zeropage.zeropage);
|
||||
if (rc) {
|
||||
pr_err("UFFDIO_ZEROPAGE error %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
static int uffd_handle_page(struct lazy_pages_info *lpi, __u64 address,
|
||||
void *dest)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = uffd_copy_page(lpi, address, dest);
|
||||
if (rc == 0)
|
||||
rc = uffd_zero_page(lpi, address);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int collect_uffd_pages(struct page_read *pr, struct lazy_pages_info *lpi)
|
||||
{
|
||||
unsigned long base;
|
||||
@@ -512,54 +359,6 @@ static int collect_uffd_pages(struct page_read *pr, struct lazy_pages_info *lpi)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_remaining_pages(struct lazy_pages_info *lpi, void *dest)
|
||||
{
|
||||
struct uffd_pages_struct *uffd_pages;
|
||||
int rc;
|
||||
|
||||
list_for_each_entry(uffd_pages, &lpi->pages, list) {
|
||||
pr_debug("Checking remaining pages 0x%lx (flags 0x%x)\n",
|
||||
uffd_pages->addr, uffd_pages->flags);
|
||||
if (uffd_pages->flags & UFFD_FLAG_SENT)
|
||||
continue;
|
||||
|
||||
rc = uffd_handle_page(lpi, uffd_pages->addr, dest);
|
||||
if (rc < 0) {
|
||||
pr_err("Error during UFFD copy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uffd_pages->flags |= UFFD_FLAG_SENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int handle_regular_pages(struct lazy_pages_info *lpi, void *dest,
|
||||
__u64 address)
|
||||
{
|
||||
int rc;
|
||||
struct uffd_pages_struct *uffd_pages;
|
||||
|
||||
rc = uffd_handle_page(lpi, address, dest);
|
||||
if (rc < 0) {
|
||||
pr_err("Error during UFFD copy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark this page as having been already transferred, so
|
||||
* that it has not to be copied again later.
|
||||
*/
|
||||
list_for_each_entry(uffd_pages, &lpi->pages, list) {
|
||||
if (uffd_pages->addr == address)
|
||||
uffd_pages->flags |= UFFD_FLAG_SENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting up criu infrastructure and scan for VMAs.
|
||||
*/
|
||||
@@ -643,6 +442,205 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ud_open(int client, struct lazy_pages_info **_lpi)
|
||||
{
|
||||
struct lazy_pages_info *lpi;
|
||||
int ret = -1;
|
||||
int uffd_flags;
|
||||
|
||||
lpi = lpi_init();
|
||||
if (!lpi)
|
||||
goto out;
|
||||
|
||||
/* The "transfer protocol" is first the pid as int and then
|
||||
* the FD for UFFD */
|
||||
ret = recv(client, &lpi->pid, sizeof(lpi->pid), 0);
|
||||
if (ret != sizeof(lpi->pid)) {
|
||||
if (ret < 0)
|
||||
pr_perror("PID recv error");
|
||||
else
|
||||
pr_err("PID recv: short read\n");
|
||||
goto out;
|
||||
}
|
||||
pr_debug("received PID: %d\n", lpi->pid);
|
||||
|
||||
if (lpi->pid == -1) {
|
||||
lpi_fini(lpi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lpi->uffd = recv_fd(client);
|
||||
if (lpi->uffd < 0) {
|
||||
pr_err("recv_fd error\n");
|
||||
goto out;
|
||||
}
|
||||
pr_debug("lpi->uffd %d\n", lpi->uffd);
|
||||
|
||||
pr_debug("uffd is 0x%d\n", lpi->uffd);
|
||||
uffd_flags = fcntl(lpi->uffd, F_GETFD, NULL);
|
||||
pr_debug("uffd_flags are 0x%x\n", uffd_flags);
|
||||
|
||||
/*
|
||||
* Find the memory pages belonging to the restored process
|
||||
* so that it is trackable when all pages have been transferred.
|
||||
*/
|
||||
if ((lpi->total_pages = find_vmas(lpi)) == -1)
|
||||
goto out;
|
||||
|
||||
list_add_tail(&lpi->l, &lpis);
|
||||
*_lpi = lpi;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
lpi_fini(lpi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_page(struct lazy_pages_info *lpi, unsigned long addr, void *dest)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lpi->pr.reset(&lpi->pr);
|
||||
|
||||
ret = lpi->pr.seek_page(&lpi->pr, addr);
|
||||
pr_debug("seek_pagemap_page ret 0x%x\n", ret);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (pagemap_zero(lpi->pr.pe))
|
||||
return 0;
|
||||
|
||||
ret = lpi->pr.read_pages(&lpi->pr, addr, 1, dest, 0);
|
||||
pr_debug("read_pages ret %d\n", ret);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uffd_copy_page(struct lazy_pages_info *lpi, __u64 address,
|
||||
void *dest)
|
||||
{
|
||||
struct uffdio_copy uffdio_copy;
|
||||
int rc;
|
||||
|
||||
if (opts.use_page_server)
|
||||
rc = get_remote_pages(lpi->pid, address, 1, dest);
|
||||
else
|
||||
rc = get_page(lpi, address, dest);
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
|
||||
uffdio_copy.dst = address;
|
||||
uffdio_copy.src = (unsigned long) dest;
|
||||
uffdio_copy.len = page_size();
|
||||
uffdio_copy.mode = 0;
|
||||
uffdio_copy.copy = 0;
|
||||
|
||||
pr_debug("uffdio_copy.dst 0x%llx\n", uffdio_copy.dst);
|
||||
rc = ioctl(lpi->uffd, 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) {
|
||||
/* real retval in ufdio_copy.copy */
|
||||
if (uffdio_copy.copy != -EEXIST) {
|
||||
pr_err("UFFDIO_COPY error %Ld\n", uffdio_copy.copy);
|
||||
return -1;
|
||||
}
|
||||
} else if (uffdio_copy.copy != page_size()) {
|
||||
pr_err("UFFDIO_COPY unexpected size %Ld\n", uffdio_copy.copy);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lpi->copied_pages++;
|
||||
|
||||
return uffdio_copy.copy;
|
||||
|
||||
}
|
||||
|
||||
static int uffd_zero_page(struct lazy_pages_info *lpi, __u64 address)
|
||||
{
|
||||
struct uffdio_zeropage uffdio_zeropage;
|
||||
unsigned long ps = page_size();
|
||||
int rc;
|
||||
|
||||
uffdio_zeropage.range.start = address;
|
||||
uffdio_zeropage.range.len = ps;
|
||||
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);
|
||||
pr_debug("ioctl UFFDIO_ZEROPAGE rc 0x%x\n", rc);
|
||||
pr_debug("uffdio_zeropage.zeropage 0x%llx\n", uffdio_zeropage.zeropage);
|
||||
if (rc) {
|
||||
pr_err("UFFDIO_ZEROPAGE error %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
static int uffd_handle_page(struct lazy_pages_info *lpi, __u64 address,
|
||||
void *dest)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = uffd_copy_page(lpi, address, dest);
|
||||
if (rc == 0)
|
||||
rc = uffd_zero_page(lpi, address);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_remaining_pages(struct lazy_pages_info *lpi, void *dest)
|
||||
{
|
||||
struct uffd_pages_struct *uffd_pages;
|
||||
int rc;
|
||||
|
||||
list_for_each_entry(uffd_pages, &lpi->pages, list) {
|
||||
pr_debug("Checking remaining pages 0x%lx (flags 0x%x)\n",
|
||||
uffd_pages->addr, uffd_pages->flags);
|
||||
if (uffd_pages->flags & UFFD_FLAG_SENT)
|
||||
continue;
|
||||
|
||||
rc = uffd_handle_page(lpi, uffd_pages->addr, dest);
|
||||
if (rc < 0) {
|
||||
pr_err("Error during UFFD copy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uffd_pages->flags |= UFFD_FLAG_SENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int handle_regular_pages(struct lazy_pages_info *lpi, void *dest,
|
||||
__u64 address)
|
||||
{
|
||||
int rc;
|
||||
struct uffd_pages_struct *uffd_pages;
|
||||
|
||||
rc = uffd_handle_page(lpi, address, dest);
|
||||
if (rc < 0) {
|
||||
pr_err("Error during UFFD copy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark this page as having been already transferred, so
|
||||
* that it has not to be copied again later.
|
||||
*/
|
||||
list_for_each_entry(uffd_pages, &lpi->pages, list) {
|
||||
if (uffd_pages->addr == address)
|
||||
uffd_pages->flags |= UFFD_FLAG_SENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_user_fault(struct lazy_pages_info *lpi, void *dest)
|
||||
{
|
||||
struct uffd_msg msg;
|
||||
|
Reference in New Issue
Block a user