[CRIU] [PATCH 3/3] img: Introduce empty images

Pavel Emelyanov xemul at parallels.com
Fri Mar 6 07:02:43 PST 2015


When an image of a certian type is not found, CRIU sometimes
fails, sometimes ignores this fact. I propose to ignore this
fact always and treat absent images and those containing no
objects inside (i.e. -- empty). If the latter code flow will
_need_ objects, then criu will fail later.

Why object will be explicitly required? For example, due to
restoring code reading the image with pb_read_one, w/o the
_eof suffix thus required the object to be in the image.

Another example is objects dependencies. E.g. fdinfo objects
require various files objects. So missing image files will
result in non-resolved searches later.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cgroup.c        |  8 ++------
 cr-restore.c    | 24 +++++-------------------
 file-lock.c     |  8 ++------
 files.c         | 31 +++++++++----------------------
 image.c         | 12 ++++++++----
 include/image.h |  7 +++++++
 irmap.c         | 28 ++++++++++++++++------------
 mem.c           | 12 ++++--------
 mount.c         |  6 ++++--
 page-read.c     | 22 ++++++++++++----------
 protobuf.c      | 13 ++++++-------
 pstree.c        | 13 ++++++-------
 12 files changed, 81 insertions(+), 103 deletions(-)

diff --git a/cgroup.c b/cgroup.c
index f20d6c3..b1a2f92 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -1292,12 +1292,8 @@ int prepare_cgroup(void)
 	CgroupEntry *ce;
 
 	img = open_image(CR_FD_CGROUP, O_RSTR);
-	if (!img) {
-		if (errno == ENOENT) /* backward compatibility */
-			return 0;
-		else
-			return -1;
-	}
+	if (!img)
+		return -1;
 
 	ret = pb_read_one_eof(img, &ce, PB_CGROUP);
 	close_image(img);
diff --git a/cr-restore.c b/cr-restore.c
index 15b9b7f..154b617 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -2157,12 +2157,8 @@ static int prepare_posix_timers_from_fd(int pid)
 	struct restore_posix_timer *t;
 
 	img = open_image(CR_FD_POSIX_TIMERS, O_RSTR, pid);
-	if (!img) {
-		if (errno == ENOENT) /* backward compatibility */
-			return 0;
-		else
-			return -1;
-	}
+	if (!img)
+		return -1;
 
 	while (1) {
 		PosixTimerEntry *pte;
@@ -2407,14 +2403,8 @@ static int prepare_rlimits_from_fd(int pid)
 	 * Old image -- read from the file.
 	 */
 	img = open_image(CR_FD_RLIMIT, O_RSTR, pid);
-	if (!img) {
-		if (errno == ENOENT) {
-			pr_info("Skip rlimits for %d\n", pid);
-			return 0;
-		}
-
+	if (!img)
 		return -1;
-	}
 
 	while (1) {
 		RlimitEntry *re;
@@ -2499,12 +2489,8 @@ static int open_signal_image(int type, pid_t pid, unsigned int *nr)
 	struct cr_img *img;
 
 	img = open_image(type, O_RSTR, pid);
-	if (!img) {
-		if (errno == ENOENT) /* backward compatibility */
-			return 0;
-		else
-			return -1;
-	}
+	if (!img)
+		return -1;
 
 	*nr = 0;
 	while (1) {
diff --git a/file-lock.c b/file-lock.c
index 03189b2..377c7eb 100644
--- a/file-lock.c
+++ b/file-lock.c
@@ -342,12 +342,8 @@ static int restore_file_locks_legacy(int pid)
 	FileLockEntry *fle;
 
 	img = open_image(CR_FD_FILE_LOCKS_PID, O_RSTR, pid);
-	if (!img) {
-		if (errno == ENOENT)
-			return 0;
-		else
-			return -1;
-	}
+	if (!img)
+		return -1;
 
 	while (1) {
 		ret = pb_read_one_eof(img, &fle, PB_FILE_LOCK);
diff --git a/files.c b/files.c
index 7c94951..acd5735 100644
--- a/files.c
+++ b/files.c
@@ -610,11 +610,8 @@ int prepare_fd_pid(struct pstree_item *item)
 
 	if (!fdinfo_per_id) {
 		img = open_image(CR_FD_FDINFO, O_RSTR, pid);
-		if (!img) {
-			if (errno == ENOENT)
-				return 0;
+		if (!img)
 			return -1;
-		}
 	} else {
 		if (item->ids == NULL) /* zombie */
 			return 0;
@@ -1115,19 +1112,16 @@ int prepare_fs_pid(struct pstree_item *item)
 	struct rst_info *ri = rsti(item);
 	struct cr_img *img;
 	FsEntry *fe;
+	int ret = -1;
 
 	img = open_image(CR_FD_FS, O_RSTR, pid);
-	if (!img) {
-		if (errno == ENOENT)
-			goto ok;
-		else
-			goto out;
-	}
-
-	if (pb_read_one(img, &fe, PB_FS) < 0)
-		goto out_i;
+	if (!img)
+		goto out;
 
+	ret = pb_read_one_eof(img, &fe, PB_FS);
 	close_image(img);
+	if (ret <= 0)
+		goto out;
 
 	ri->cwd = collect_special_file(fe->cwd_id);
 	if (!ri->cwd) {
@@ -1144,18 +1138,11 @@ int prepare_fs_pid(struct pstree_item *item)
 	ri->has_umask = fe->has_umask;
 	ri->umask = fe->umask;
 
-	fs_entry__free_unpacked(fe, NULL);
-ok:
-	return 0;
-
+	ret = 0;
 out_f:
 	fs_entry__free_unpacked(fe, NULL);
-	return -1;
-
-out_i:
-	close_image(img);
 out:
-	return -1;
+	return ret;
 }
 
 int shared_fdt_prepare(struct pstree_item *item)
diff --git a/image.c b/image.c
index 5e13bd3..a734e88 100644
--- a/image.c
+++ b/image.c
@@ -223,10 +223,13 @@ struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...)
 
 	ret = openat(dfd, path, flags, CR_FD_PERM);
 	if (ret < 0) {
-		if (errno == ENOENT)
+		if (!(flags & O_CREAT) && (errno == ENOENT)) {
 			pr_info("No %s image\n", path);
-		else
-			pr_perror("Unable to open %s", path);
+			img->_x.fd = EMPTY_IMG_FD;
+			goto skip_magic;
+		}
+
+		pr_perror("Unable to open %s", path);
 		goto err;
 	}
 
@@ -267,7 +270,8 @@ err_close:
 
 void close_image(struct cr_img *img)
 {
-	bclose(&img->_x);
+	if (!empty_image(img))
+		bclose(&img->_x);
 	xfree(img);
 }
 
diff --git a/include/image.h b/include/image.h
index 43cd691..e146b75 100644
--- a/include/image.h
+++ b/include/image.h
@@ -127,6 +127,13 @@ struct cr_img {
 	struct bfd _x;
 };
 
+#define EMPTY_IMG_FD	(-404)
+
+static inline bool empty_image(struct cr_img *img)
+{
+	return img && img->_x.fd == EMPTY_IMG_FD;
+}
+
 static inline int img_raw_fd(struct cr_img *img)
 {
 	BUG_ON(bfd_buffered(&img->_x));
diff --git a/irmap.c b/irmap.c
index e671bb5..fd9374f 100644
--- a/irmap.c
+++ b/irmap.c
@@ -403,23 +403,27 @@ in:
 	if (dir != AT_FDCWD)
 		close(dir);
 
-	if (*img) {
-		pr_info("... done\n");
-		return 1;
-	}
+	if (empty_image(*img)) {
+		close_image(*img);
+		if (dir == AT_FDCWD) {
+			pr_info("Searching irmap cache in parent\n");
+			dir = openat(get_service_fd(IMG_FD_OFF),
+					CR_PARENT_LINK, O_RDONLY);
+			if (dir >= 0)
+				goto in;
+			if (errno != ENOENT)
+				return -1;
+		}
 
-	if (errno == ENOENT && dir == AT_FDCWD) {
-		pr_info("Searching irmap cache in parent\n");
-		dir = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY);
-		if (dir >= 0)
-			goto in;
+		pr_info("No irmap cache\n");
+		return 0;
 	}
 
-	if (errno != ENOENT)
+	if (!*img)
 		return -1;
 
-	pr_info("No irmap cache\n");
-	return 0;
+	pr_info("... done\n");
+	return 1;
 }
 
 int irmap_load_cache(void)
diff --git a/mem.c b/mem.c
index f049cc3..9164f97 100644
--- a/mem.c
+++ b/mem.c
@@ -396,17 +396,13 @@ int prepare_mm_pid(struct pstree_item *i)
 	struct rst_info *ri = rsti(i);
 
 	img = open_image(CR_FD_MM, O_RSTR, pid);
-	if (!img) {
-		if (errno == ENOENT)
-			return 0;
+	if (!img)
 		return -1;
-	}
 
-	ret = pb_read_one(img, &ri->mm, PB_MM);
+	ret = pb_read_one_eof(img, &ri->mm, PB_MM);
 	close_image(img);
-
-	if (ret < 0)
-		return -1;
+	if (ret <= 0)
+		return ret;
 
 	if (collect_special_file(ri->mm->exe_file_id) == NULL)
 		return -1;
diff --git a/mount.c b/mount.c
index 11651e4..e59cb0d 100644
--- a/mount.c
+++ b/mount.c
@@ -937,9 +937,11 @@ static int tmpfs_restore(struct mount_info *pm)
 	struct cr_img *img;
 
 	img = open_image(CR_FD_TMPFS_DEV, O_RSTR, pm->s_dev);
-	if (!img && errno == ENOENT)
+	if (empty_image(img)) {
+		close_image(img);
 		img = open_image(CR_FD_TMPFS_IMG, O_RSTR, pm->mnt_id);
-	if (!img)
+	}
+	if (!img || empty_image(img))
 		return -1;
 
 	ret = cr_system(img_raw_fd(img), -1, -1, "tar",
diff --git a/page-read.c b/page-read.c
index c3d8a8f..832c057 100644
--- a/page-read.c
+++ b/page-read.c
@@ -256,11 +256,12 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
 	pr->bunch.iov_base = NULL;
 
 	pr->pmi = open_image_at(dfd, i_typ, O_RSTR, (long)pid);
-	if (!pr->pmi) {
-		if (errno == ENOENT)
-			goto open_old;
-		else
-			return -1;
+	if (!pr->pmi)
+		return -1;
+
+	if (empty_image(pr->pmi)) {
+		close_image(pr->pmi);
+		goto open_old;
 	}
 
 	if ((i_typ != CR_FD_SHMEM_PAGEMAP) && try_open_parent(dfd, pid, pr, pr_flags)) {
@@ -287,11 +288,12 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
 
 open_old:
 	pr->pmi = open_image_at(dfd, i_typ_o, flags, pid);
-	if (!pr->pmi) {
-		if (errno == ENOENT)
-			return 0;
-		else
-			return -1;
+	if (!pr->pmi)
+		return -1;
+
+	if (empty_image(pr->pmi)) {
+		close_image(pr->pmi);
+		return 0;
 	}
 
 	pr->get_pagemap = get_page_vaddr;
diff --git a/protobuf.c b/protobuf.c
index be80f27..4a65579 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -528,7 +528,10 @@ int do_pb_read_one(struct cr_img *img, void **pobj, int type, bool eof)
 
 	*pobj = NULL;
 
-	ret = bread(&img->_x, &size, sizeof(size));
+	if (unlikely(empty_image(img)))
+		ret = 0;
+	else
+		ret = bread(&img->_x, &size, sizeof(size));
 	if (ret == 0) {
 		if (eof) {
 			return 0;
@@ -642,12 +645,8 @@ int collect_image(struct collect_image_info *cinfo)
 			cinfo->fd_type, cinfo->pb_type, cinfo->flags);
 
 	img = open_image(cinfo->fd_type, O_RSTR);
-	if (!img) {
-		if (errno == ENOENT)
-			return 0;
-		else
-			return -1;
-	}
+	if (!img)
+		return -1;
 
 	cinfo->flags |= COLLECT_HAPPENED;
 	if (cinfo->flags & COLLECT_SHARED) {
diff --git a/pstree.c b/pstree.c
index 659be0c..6f0f138 100644
--- a/pstree.c
+++ b/pstree.c
@@ -427,16 +427,15 @@ static int read_pstree_image(void)
 			struct cr_img *img;
 
 			img = open_image(CR_FD_IDS, O_RSTR, pi->pid.virt);
-			if (!img) {
-				if (errno == ENOENT)
-					continue;
+			if (!img)
 				goto err;
-			}
-			ret = pb_read_one(img, &pi->ids, PB_IDS);
+			ret = pb_read_one_eof(img, &pi->ids, PB_IDS);
 			close_image(img);
-			}
+		}
 
-		if (ret != 1)
+		if (ret == 0)
+			continue;
+		if (ret < 0)
 			goto err;
 
 		if (pi->ids->has_mnt_ns_id) {
-- 
1.8.4.2




More information about the CRIU mailing list