mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
lazy-pages: uffd_{copy, zeropage}: rework error handling
Improve code readability and take into account that even if uffdio_{copy,zeropage} has failed, some pages had been updated. Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
committed by
Andrei Vagin
parent
a72719d365
commit
48fcb8934c
60
criu/uffd.c
60
criu/uffd.c
@@ -814,32 +814,44 @@ static int handle_exit(struct lazy_pages_info *lpi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uffd_check_op_error(struct lazy_pages_info *lpi, const char *op,
|
static bool uffd_recoverable_error(int mcopy_rc)
|
||||||
unsigned long len, unsigned long rc_len, int rc)
|
|
||||||
{
|
{
|
||||||
if (rc) {
|
if (errno == EAGAIN || errno == ENOENT || errno == EEXIST)
|
||||||
if (errno == ENOSPC || errno == ESRCH) {
|
return true;
|
||||||
handle_exit(lpi);
|
|
||||||
return 0;
|
if (mcopy_rc == -ENOENT || mcopy_rc == -EEXIST)
|
||||||
}
|
return true;
|
||||||
if (rc_len != -EEXIST) {
|
|
||||||
lp_perror(lpi, "%s: rc:%d copy:%ld, errno:%d",
|
return false;
|
||||||
op, rc, rc_len, errno);
|
}
|
||||||
return -1;
|
|
||||||
}
|
static int uffd_check_op_error(struct lazy_pages_info *lpi, const char *op,
|
||||||
} else if (rc_len != len) {
|
int *nr_pages, long mcopy_rc)
|
||||||
lp_err(lpi, "%s unexpected size %ld\n", op, rc_len);
|
{
|
||||||
|
if (errno == ENOSPC || errno == ESRCH) {
|
||||||
|
handle_exit(lpi);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uffd_recoverable_error(mcopy_rc)) {
|
||||||
|
lp_perror(lpi, "%s: mcopy_rc:%ld", op, mcopy_rc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lp_debug(lpi, "%s: mcopy_rc:%ld, errno:%d\n", op, mcopy_rc, errno);
|
||||||
|
|
||||||
|
if (mcopy_rc <= 0)
|
||||||
|
*nr_pages = 0;
|
||||||
|
else
|
||||||
|
*nr_pages = mcopy_rc / PAGE_SIZE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uffd_copy(struct lazy_pages_info *lpi, __u64 address, int nr_pages)
|
static int uffd_copy(struct lazy_pages_info *lpi, __u64 address, int *nr_pages)
|
||||||
{
|
{
|
||||||
struct uffdio_copy uffdio_copy;
|
struct uffdio_copy uffdio_copy;
|
||||||
unsigned long len = nr_pages * page_size();
|
unsigned long len = *nr_pages * page_size();
|
||||||
int rc;
|
|
||||||
|
|
||||||
uffdio_copy.dst = address;
|
uffdio_copy.dst = address;
|
||||||
uffdio_copy.src = (unsigned long)lpi->buf;
|
uffdio_copy.src = (unsigned long)lpi->buf;
|
||||||
@@ -848,11 +860,11 @@ static int uffd_copy(struct lazy_pages_info *lpi, __u64 address, int nr_pages)
|
|||||||
uffdio_copy.copy = 0;
|
uffdio_copy.copy = 0;
|
||||||
|
|
||||||
lp_debug(lpi, "uffd_copy: 0x%llx/%ld\n", uffdio_copy.dst, len);
|
lp_debug(lpi, "uffd_copy: 0x%llx/%ld\n", uffdio_copy.dst, len);
|
||||||
rc = ioctl(lpi->lpfd.fd, UFFDIO_COPY, &uffdio_copy);
|
if (ioctl(lpi->lpfd.fd, UFFDIO_COPY, &uffdio_copy) &&
|
||||||
if (uffd_check_op_error(lpi, "copy", len, uffdio_copy.copy, rc))
|
uffd_check_op_error(lpi, "copy", nr_pages, uffdio_copy.copy))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
lpi->copied_pages += nr_pages;
|
lpi->copied_pages += *nr_pages;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -895,7 +907,7 @@ static int uffd_io_complete(struct page_read *pr, unsigned long img_addr, int nr
|
|||||||
req_pages = (req->end - req->start) / PAGE_SIZE;
|
req_pages = (req->end - req->start) / PAGE_SIZE;
|
||||||
nr = min(nr, req_pages);
|
nr = min(nr, req_pages);
|
||||||
|
|
||||||
ret = uffd_copy(lpi, addr, nr);
|
ret = uffd_copy(lpi, addr, &nr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -916,15 +928,15 @@ static int uffd_zero(struct lazy_pages_info *lpi, __u64 address, int nr_pages)
|
|||||||
{
|
{
|
||||||
struct uffdio_zeropage uffdio_zeropage;
|
struct uffdio_zeropage uffdio_zeropage;
|
||||||
unsigned long len = page_size() * nr_pages;
|
unsigned long len = page_size() * nr_pages;
|
||||||
int rc;
|
|
||||||
|
|
||||||
uffdio_zeropage.range.start = address;
|
uffdio_zeropage.range.start = address;
|
||||||
uffdio_zeropage.range.len = len;
|
uffdio_zeropage.range.len = len;
|
||||||
uffdio_zeropage.mode = 0;
|
uffdio_zeropage.mode = 0;
|
||||||
|
|
||||||
lp_debug(lpi, "zero page at 0x%llx\n", address);
|
lp_debug(lpi, "zero page at 0x%llx\n", address);
|
||||||
rc = ioctl(lpi->lpfd.fd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
|
if (ioctl(lpi->lpfd.fd, UFFDIO_ZEROPAGE, &uffdio_zeropage) &&
|
||||||
if (uffd_check_op_error(lpi, "zero", len, uffdio_zeropage.zeropage, rc))
|
uffd_check_op_error(lpi, "zero", &nr_pages,
|
||||||
|
uffdio_zeropage.zeropage))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user