[CRIU] [PATCH 2/2] lazy-pages: uffd_{copy, zeropage}: rework error handling

Mike Rapoport rppt at linux.vnet.ibm.com
Wed Jun 6 17:30:58 MSK 2018


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 at linux.vnet.ibm.com>
---
 criu/uffd.c | 58 +++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 35 insertions(+), 23 deletions(-)

diff --git a/criu/uffd.c b/criu/uffd.c
index 1141180..5cf8af5 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -814,32 +814,44 @@ static int handle_exit(struct lazy_pages_info *lpi)
 	return 0;
 }
 
+static bool uffd_recoverable_error(int mcopy_rc)
+{
+	if (errno == EAGAIN || errno == ENOENT || errno == EEXIST)
+		return true;
+
+	if (mcopy_rc == -ENOENT || mcopy_rc == -EEXIST)
+		return true;
+
+	return false;
+}
+
 static int uffd_check_op_error(struct lazy_pages_info *lpi, const char *op,
-			       unsigned long len, unsigned long rc_len, int rc)
+			       int *nr_pages, long mcopy_rc)
 {
-	if (rc) {
-		if (errno == ENOSPC || errno == ESRCH) {
-			handle_exit(lpi);
-			return 0;
-		}
-		if (rc_len != -EEXIST) {
-			lp_perror(lpi, "%s: rc:%d copy:%ld, errno:%d",
-				 op, rc, rc_len, errno);
-			return -1;
-		}
-	} else if (rc_len != len) {
-		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;
 	}
 
+	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;
 }
 
-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;
-	unsigned long len = nr_pages * page_size();
-	int rc;
+	unsigned long len = *nr_pages * page_size();
 
 	uffdio_copy.dst = address;
 	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;
 
 	lp_debug(lpi, "uffd_copy: 0x%llx/%ld\n", uffdio_copy.dst, len);
-	rc = ioctl(lpi->lpfd.fd, UFFDIO_COPY, &uffdio_copy);
-	if (uffd_check_op_error(lpi, "copy", len, uffdio_copy.copy, rc))
+	if (ioctl(lpi->lpfd.fd, UFFDIO_COPY, &uffdio_copy) &&
+	    uffd_check_op_error(lpi, "copy", nr_pages, uffdio_copy.copy))
 		return -1;
 
-	lpi->copied_pages += nr_pages;
+	lpi->copied_pages += *nr_pages;
 
 	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;
 	nr = min(nr, req_pages);
 
-	ret = uffd_copy(lpi, addr, nr);
+	ret = uffd_copy(lpi, addr, &nr);
 	if (ret < 0)
 		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;
 	unsigned long len = page_size() * nr_pages;
-	int rc;
 
 	uffdio_zeropage.range.start = address;
 	uffdio_zeropage.range.len = len;
 	uffdio_zeropage.mode = 0;
 
 	lp_debug(lpi, "zero page at 0x%llx\n", address);
-	rc = ioctl(lpi->lpfd.fd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
-	if (uffd_check_op_error(lpi, "zero", len, uffdio_zeropage.zeropage, rc))
+	if (ioctl(lpi->lpfd.fd, UFFDIO_ZEROPAGE, &uffdio_zeropage) &&
+	    uffd_check_op_error(lpi, "zero", &nr_pages,
+				uffdio_zeropage.zeropage))
 		return -1;
 
 	return 0;
-- 
2.7.4



More information about the CRIU mailing list