[CRIU] [PATCH 08/15] img: Introduce the struct cr_img

Pavel Emelyanov xemul at parallels.com
Mon Sep 29 01:48:53 PDT 2014


We want to have buffered images to speed up dump and,
slightly, restore. Right now we use plan file descriptors
to write and read images to/from. Making them buffered
cannot be gracefully done on plain fds, so introduce
a new class.

This will also help if (when?) we will want to do more
complex changes with images, e.g. store them all in one
file or send them directly to the network.

For now the cr_img just contains one int _fd variable.

This patch chages the prototype of open_image() to
return struct cr_img *, pb_(read|write)* to accept one
and fixes the compilation of the rest of the code :)

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cgroup.c            |  11 ++--
 cr-dedup.c          |   4 +-
 cr-dump.c           |  27 +++++-----
 cr-restore.c        |  95 +++++++++++++++++---------------
 cr-show.c           | 103 ++++++++++++++++++-----------------
 fifo.c              |   2 +-
 file-lock.c         |  11 ++--
 files-ext.c         |  12 ++---
 files-reg.c         |  31 ++++++-----
 files.c             |  68 +++++++++++------------
 image.c             | 114 +++++++++++++++++++++++++--------------
 include/cr-show.h   |  18 ++++---
 include/files.h     |   6 ++-
 include/image.h     |  33 ++++++++----
 include/imgset.h    |   5 +-
 include/log.h       |   4 +-
 include/page-read.h |   4 +-
 include/page-xfer.h |  13 +++--
 include/protobuf.h  |  10 ++--
 include/sockets.h   |   3 +-
 ipc_ns.c            | 152 ++++++++++++++++++++++++++++------------------------
 irmap.c             |  28 +++++-----
 mem.c               |  26 ++++-----
 mount.c             |  47 ++++++++--------
 namespaces.c        |  45 ++++++++--------
 net.c               |  44 ++++++++-------
 page-read.c         |  33 ++++++------
 page-xfer.c         |  33 ++++++------
 parasite-syscall.c  |   7 +--
 pipes.c             |  21 ++++----
 protobuf.c          |  29 +++++-----
 pstree.c            |  33 ++++++------
 shmem.c             |   7 +--
 sk-queue.c          |  34 ++++++------
 sk-tcp.c            |  52 +++++++++---------
 sockets.c           |   4 +-
 stats.c             |  10 ++--
 tun.c               |   4 +-
 uts_ns.c            |  22 ++++----
 39 files changed, 664 insertions(+), 541 deletions(-)

diff --git a/cgroup.c b/cgroup.c
index a4967ef..3b14773 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -1300,19 +1300,20 @@ static int rewrite_cgroup_roots(CgroupEntry *cge)
 
 int prepare_cgroup(void)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	CgroupEntry *ce;
 
-	fd = open_image(CR_FD_CGROUP, O_RSTR | O_OPT);
-	if (fd < 0) {
+	img = open_image(CR_FD_CGROUP, O_RSTR | O_OPT);
+	if (!img) {
 		if (errno == ENOENT) /* backward compatibility */
 			return 0;
 		else
 			return -1;
 	}
 
-	ret = pb_read_one_eof(fd, &ce, PB_CGROUP);
-	close(fd);
+	ret = pb_read_one_eof(img, &ce, PB_CGROUP);
+	close_image(img);
 	if (ret <= 0) /* Zero is OK -- no sets there. */
 		return ret;
 
diff --git a/cr-dedup.c b/cr-dedup.c
index 7758674..b619137 100644
--- a/cr-dedup.c
+++ b/cr-dedup.c
@@ -125,7 +125,7 @@ int punch_hole(struct page_read *pr, unsigned long off, unsigned long len,
 	} else {
 		if (bunch->iov_len > 0) {
 			pr_debug("Punch!/%p/%zu/\n", bunch->iov_base, bunch->iov_len);
-			ret = fallocate(pr->fd_pg, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+			ret = fallocate(img_raw_fd(pr->pi), FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
 					(unsigned long)bunch->iov_base, bunch->iov_len);
 			if (ret != 0) {
 				pr_perror("Error punching hole");
@@ -169,7 +169,7 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
 			return -1;
 		pagemap2iovec(pr->pe, &piov);
 		piov_end = (unsigned long)piov.iov_base + piov.iov_len;
-		off_real = lseek(pr->fd_pg, 0, SEEK_CUR);
+		off_real = lseek(img_raw_fd(pr->pi), 0, SEEK_CUR);
 		if (!pr->pe->in_parent) {
 			ret = punch_hole(pr, off_real, min(piov_end, iov_end) - off, false);
 			if (ret == -1)
diff --git a/cr-dump.c b/cr-dump.c
index c620aac..b4a38f7 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -706,7 +706,7 @@ static int dump_task_core_all(struct pstree_item *item,
 		const struct parasite_dump_misc *misc,
 		const struct cr_imgset *cr_imgset)
 {
-	int fd_core = img_from_set(cr_imgset, CR_FD_CORE);
+	struct cr_img *img;
 	CoreEntry *core = item->core[0];
 	pid_t pid = item->pid.real;
 	int ret = -1;
@@ -737,7 +737,8 @@ static int dump_task_core_all(struct pstree_item *item,
 	if (ret)
 		goto err;
 
-	ret = pb_write_one(fd_core, core, PB_CORE);
+	img = img_from_set(cr_imgset, CR_FD_CORE);
+	ret = pb_write_one(img, core, PB_CORE);
 	if (ret < 0)
 		goto err;
 
@@ -1103,7 +1104,8 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
 	struct pid *tid = &item->threads[id];
 	CoreEntry *core = item->core[id];
 	pid_t pid = tid->real;
-	int ret = -1, fd_core;
+	int ret = -1;
+	struct cr_img *img;
 
 	pr_info("\n");
 	pr_info("Dumping core for thread (pid: %d)\n", pid);
@@ -1115,13 +1117,13 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
 		goto err;
 	}
 
-	fd_core = open_image(CR_FD_CORE, O_DUMP, tid->virt);
-	if (fd_core < 0)
+	img = open_image(CR_FD_CORE, O_DUMP, tid->virt);
+	if (!img)
 		goto err;
 
-	ret = pb_write_one(fd_core, core, PB_CORE);
+	ret = pb_write_one(img, core, PB_CORE);
 
-	close(fd_core);
+	close_image(img);
 err:
 	pr_info("----------------------------------------\n");
 	return ret;
@@ -1131,7 +1133,8 @@ static int dump_one_zombie(const struct pstree_item *item,
 			   const struct proc_pid_stat *pps)
 {
 	CoreEntry *core;
-	int ret = -1, fd_core;
+	int ret = -1;
+	struct cr_img *img;
 
 	core = core_entry_alloc(0, 1);
 	if (!core)
@@ -1141,12 +1144,12 @@ static int dump_one_zombie(const struct pstree_item *item,
 	core->tc->task_state = TASK_DEAD;
 	core->tc->exit_code = pps->exit_code;
 
-	fd_core = open_image(CR_FD_CORE, O_DUMP, item->pid.virt);
-	if (fd_core < 0)
+	img = open_image(CR_FD_CORE, O_DUMP, item->pid.virt);
+	if (!img)
 		goto err;
 
-	ret = pb_write_one(fd_core, core, PB_CORE);
-	close(fd_core);
+	ret = pb_write_one(img, core, PB_CORE);
+	close_image(img);
 err:
 	core_entry_free(core);
 	return ret;
diff --git a/cr-restore.c b/cr-restore.c
index 0999116..4c9308c 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -633,7 +633,7 @@ static int prepare_sigactions(void)
 {
 	int pid = current->pid.virt;
 	rt_sigaction_t act;
-	int fd_sigact;
+	struct cr_img *img;
 	SaEntry *e;
 	int sig, rst = 0;
 	int ret = 0;
@@ -643,15 +643,15 @@ static int prepare_sigactions(void)
 
 	pr_info("Restore sigacts for %d\n", pid);
 
-	fd_sigact = open_image(CR_FD_SIGACT, O_RSTR, pid);
-	if (fd_sigact < 0)
+	img = open_image(CR_FD_SIGACT, O_RSTR, pid);
+	if (!img)
 		return -1;
 
 	for (sig = 1; sig <= SIGMAX; sig++) {
 		if (sig == SIGKILL || sig == SIGSTOP)
 			continue;
 
-		ret = pb_read_one_eof(fd_sigact, &e, PB_SIGACT);
+		ret = pb_read_one_eof(img, &e, PB_SIGACT);
 		if (ret == 0) {
 			if (sig != SIGMAX_OLD + 1) { /* backward compatibility */
 				pr_err("Unexpected EOF %d\n", sig);
@@ -697,7 +697,7 @@ static int prepare_sigactions(void)
 			SIGMAX - 3 /* KILL, STOP and CHLD */);
 
 err:
-	close_safe(&fd_sigact);
+	close_image(img);
 	return ret;
 }
 
@@ -731,7 +731,7 @@ static int collect_helper_pids()
 
 static int open_cores(int pid, CoreEntry *leader_core)
 {
-	int fd = -1, i, tpid;
+	int i, tpid;
 	CoreEntry **cores = NULL;
 
 	cores = xmalloc(sizeof(*cores)*current->nr_threads);
@@ -744,16 +744,20 @@ static int open_cores(int pid, CoreEntry *leader_core)
 		if (tpid == pid)
 			cores[i] = leader_core;
 		else {
-			fd = open_image(CR_FD_CORE, O_RSTR, tpid);
-			if (fd < 0) {
+			struct cr_img *img;
+
+			img = open_image(CR_FD_CORE, O_RSTR, tpid);
+			if (!img) {
 				pr_err("Can't open core data for thread %d\n", tpid);
 				goto err;
 			}
 
-			if (pb_read_one(fd, &cores[i], PB_CORE) <= 0)
+			if (pb_read_one(img, &cores[i], PB_CORE) <= 0) {
+				close_image(img);
 				goto err;
+			}
 
-			close(fd);
+			close_image(img);
 		}
 	}
 
@@ -762,7 +766,6 @@ static int open_cores(int pid, CoreEntry *leader_core)
 	return 0;
 err:
 	xfree(cores);
-	close_safe(&fd);
 	return -1;
 }
 
@@ -1001,16 +1004,18 @@ static void maybe_clone_parent(struct pstree_item *item,
 static inline int fork_with_pid(struct pstree_item *item)
 {
 	struct cr_clone_arg ca;
-	int ret = -1, fd;
+	int ret = -1;
 	pid_t pid = item->pid.virt;
 
 	if (item->state != TASK_HELPER) {
-		fd = open_image(CR_FD_CORE, O_RSTR, pid);
-		if (fd < 0)
+		struct cr_img *img;
+
+		img = open_image(CR_FD_CORE, O_RSTR, pid);
+		if (!img)
 			return -1;
 
-		ret = pb_read_one(fd, &ca.core, PB_CORE);
-		close(fd);
+		ret = pb_read_one(img, &ca.core, PB_CORE);
+		close_image(img);
 
 		if (ret < 0)
 			return -1;
@@ -1979,14 +1984,15 @@ static inline int decode_itimer(char *n, ItimerEntry *ie, struct itimerval *val)
 
 static int prepare_itimers_from_fd(int pid, struct task_restore_args *args)
 {
-	int fd, ret = -1;
+	int ret = -1;
+	struct cr_img *img;
 	ItimerEntry *ie;
 
-	fd = open_image(CR_FD_ITIMERS, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_ITIMERS, O_RSTR, pid);
+	if (!img)
 		return -1;
 
-	ret = pb_read_one(fd, &ie, PB_ITIMER);
+	ret = pb_read_one(img, &ie, PB_ITIMER);
 	if (ret < 0)
 		goto out;
 	ret = decode_itimer("real", ie, &args->itimers[0]);
@@ -1994,7 +2000,7 @@ static int prepare_itimers_from_fd(int pid, struct task_restore_args *args)
 	if (ret < 0)
 		goto out;
 
-	ret = pb_read_one(fd, &ie, PB_ITIMER);
+	ret = pb_read_one(img, &ie, PB_ITIMER);
 	if (ret < 0)
 		goto out;
 	ret = decode_itimer("virt", ie, &args->itimers[1]);
@@ -2002,7 +2008,7 @@ static int prepare_itimers_from_fd(int pid, struct task_restore_args *args)
 	if (ret < 0)
 		goto out;
 
-	ret = pb_read_one(fd, &ie, PB_ITIMER);
+	ret = pb_read_one(img, &ie, PB_ITIMER);
 	if (ret < 0)
 		goto out;
 	ret = decode_itimer("prof", ie, &args->itimers[2]);
@@ -2010,7 +2016,7 @@ static int prepare_itimers_from_fd(int pid, struct task_restore_args *args)
 	if (ret < 0)
 		goto out;
 out:
-	close_safe(&fd);
+	close_image(img);
 	return ret;
 }
 
@@ -2100,12 +2106,12 @@ static void sort_posix_timers(void)
 
 static int prepare_posix_timers_from_fd(int pid)
 {
-	int fd = -1;
+	struct cr_img *img;
 	int ret = -1;
 	struct restore_posix_timer *t;
 
-	fd = open_image(CR_FD_POSIX_TIMERS, O_RSTR, pid);
-	if (fd < 0) {
+	img = open_image(CR_FD_POSIX_TIMERS, O_RSTR, pid);
+	if (!img) {
 		if (errno == ENOENT) /* backward compatibility */
 			return 0;
 		else
@@ -2115,7 +2121,7 @@ static int prepare_posix_timers_from_fd(int pid)
 	while (1) {
 		PosixTimerEntry *pte;
 
-		ret = pb_read_one_eof(fd, &pte, PB_POSIX_TIMER);
+		ret = pb_read_one_eof(img, &pte, PB_POSIX_TIMER);
 		if (ret <= 0)
 			break;
 
@@ -2131,7 +2137,7 @@ static int prepare_posix_timers_from_fd(int pid)
 		posix_timers_nr++;
 	}
 
-	close_safe(&fd);
+	close_image(img);
 	if (!ret)
 		sort_posix_timers();
 
@@ -2173,15 +2179,16 @@ static inline int verify_cap_size(CredsEntry *ce)
 
 static int prepare_creds(int pid, struct task_restore_args *args)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	CredsEntry *ce;
 
-	fd = open_image(CR_FD_CREDS, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_CREDS, O_RSTR, pid);
+	if (!img)
 		return -1;
 
-	ret = pb_read_one(fd, &ce, PB_CREDS);
-	close_safe(&fd);
+	ret = pb_read_one(img, &ce, PB_CREDS);
+	close_image(img);
 
 	if (ret < 0)
 		return ret;
@@ -2347,13 +2354,14 @@ static unsigned int rlims_nr;
 static int prepare_rlimits_from_fd(int pid)
 {
 	struct rlimit *r;
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 
 	/*
 	 * Old image -- read from the file.
 	 */
-	fd = open_image(CR_FD_RLIMIT, O_RSTR | O_OPT, pid);
-	if (fd < 0) {
+	img = open_image(CR_FD_RLIMIT, O_RSTR | O_OPT, pid);
+	if (!img) {
 		if (errno == ENOENT) {
 			pr_info("Skip rlimits for %d\n", pid);
 			return 0;
@@ -2365,7 +2373,7 @@ static int prepare_rlimits_from_fd(int pid)
 	while (1) {
 		RlimitEntry *re;
 
-		ret = pb_read_one_eof(fd, &re, PB_RLIMIT);
+		ret = pb_read_one_eof(img, &re, PB_RLIMIT);
 		if (ret <= 0)
 			break;
 
@@ -2389,7 +2397,7 @@ static int prepare_rlimits_from_fd(int pid)
 		rlims_nr++;
 	}
 
-	close(fd);
+	close_image(img);
 
 	return 0;
 }
@@ -2441,10 +2449,11 @@ static int signal_to_mem(SiginfoEntry *sie)
 
 static int open_signal_image(int type, pid_t pid, unsigned int *nr)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 
-	fd = open_image(type, O_RSTR | O_OPT, pid);
-	if (fd < 0) {
+	img = open_image(type, O_RSTR | O_OPT, pid);
+	if (!img) {
 		if (errno == ENOENT) /* backward compatibility */
 			return 0;
 		else
@@ -2455,7 +2464,7 @@ static int open_signal_image(int type, pid_t pid, unsigned int *nr)
 	while (1) {
 		SiginfoEntry *sie;
 
-		ret = pb_read_one_eof(fd, &sie, PB_SIGINFO);
+		ret = pb_read_one_eof(img, &sie, PB_SIGINFO);
 		if (ret <= 0)
 			break;
 		if (sie->siginfo.len != sizeof(siginfo_t)) {
@@ -2473,7 +2482,7 @@ static int open_signal_image(int type, pid_t pid, unsigned int *nr)
 		siginfo_entry__free_unpacked(sie, NULL);
 	}
 
-	close(fd);
+	close_image(img);
 
 	return ret ? : 0;
 }
diff --git a/cr-show.c b/cr-show.c
index 0de92ba..dc85502 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -37,10 +37,10 @@
 
 static LIST_HEAD(pstree_list);
 
-static void pipe_data_handler(int fd, void *obj)
+static void pipe_data_handler(struct cr_img *img, void *obj)
 {
 	PipeDataEntry *e = obj;
-	print_image_data(fd, e->bytes, opts.show_pages_content);
+	print_image_data(img, e->bytes, opts.show_pages_content);
 }
 
 static int nice_width_for(unsigned long addr)
@@ -115,13 +115,13 @@ void print_data(unsigned long addr, unsigned char *data, size_t size)
 	}
 }
 
-void print_image_data(int fd, unsigned int length, int show)
+void print_image_data(struct cr_img *img, unsigned int length, int show)
 {
 	void *data;
 	int ret;
 
 	if (!show) {
-		lseek(fd, length, SEEK_CUR);
+		lseek(img_raw_fd(img), length, SEEK_CUR);
 		return;
 	}
 
@@ -130,7 +130,7 @@ void print_image_data(int fd, unsigned int length, int show)
 	data = xmalloc(length);
 	if (!data)
 		return;
-	ret = read_img_buf(fd, (unsigned char *)data, length);
+	ret = read_img_buf(img, (unsigned char *)data, length);
 	if (ret < 0) {
 		xfree(data);
 		return;
@@ -139,12 +139,12 @@ void print_image_data(int fd, unsigned int length, int show)
 	xfree(data);
 }
 
-static void show_pagemaps(int fd, void *obj)
+static void show_pagemaps(struct cr_img *img, void *obj)
 {
-	pb_show_plain_pretty(fd, PB_PAGEMAP, "nr_pages:%u");
+	pb_show_plain_pretty(img, PB_PAGEMAP, "nr_pages:%u");
 }
 
-void show_siginfo(int fd)
+void show_siginfo(struct cr_img *img)
 {
 	int ret;
 
@@ -153,7 +153,7 @@ void show_siginfo(int fd)
 		SiginfoEntry *sie;
 		siginfo_t *info;
 
-		ret = pb_read_one_eof(fd, &sie, PB_SIGINFO);
+		ret = pb_read_one_eof(img, &sie, PB_SIGINFO);
 		if (ret <= 0)
 			break;
 
@@ -182,7 +182,7 @@ static int pstree_item_from_pb(PstreeEntry *e, struct pstree_item *item)
 	return 0;
 }
 
-static void pstree_handler(int fd, void *obj)
+static void pstree_handler(struct cr_img *img, void *obj)
 {
 	PstreeEntry *e = obj;
 	struct pstree_item *item = NULL;
@@ -199,9 +199,9 @@ static void pstree_handler(int fd, void *obj)
 	list_add_tail(&item->sibling, &pstree_list);
 }
 
-void show_collect_pstree(int fd, int collect)
+static void show_collect_pstree(struct cr_img *img, int collect)
 {
-	pb_show_plain_payload_pretty(fd, PB_PSTREE,
+	pb_show_plain_payload_pretty(img, PB_PSTREE,
 			collect ? pstree_handler : NULL, "*:%d");
 }
 
@@ -349,6 +349,7 @@ static int cr_parse_file(void)
 {
 	u32 magic;
 	int ret = -1, fd;
+	struct cr_img *img = NULL;
 
 	fd = open(opts.show_dump_file, O_RDONLY);
 	if (fd < 0) {
@@ -356,26 +357,33 @@ static int cr_parse_file(void)
 		goto out;
 	}
 
-	if (read_img(fd, &magic) < 0)
+	img = img_from_fd(fd);
+	if (!img)
 		goto out;
 
-	ret = cr_parse_fd(fd, magic);
+	if (read_img(img, &magic) < 0)
+		goto out;
+
+	ret = cr_parse_fd(img, magic);
 out:
-	close_safe(&fd);
+	if (img)
+		close_image(img);
+	else
+		close_safe(&fd);
 	return ret;
 }
 
-int cr_parse_fd(int fd, u32 magic)
+int cr_parse_fd(struct cr_img *img, u32 magic)
 {
 	int ret = 0, i;
 
 	if (magic == PSTREE_MAGIC) {
-		show_collect_pstree(fd, 0);
+		show_collect_pstree(img, 0);
 		goto out;
 	}
 
 	if (magic == SIGNAL_MAGIC || magic == PSIGNAL_MAGIC) {
-		show_siginfo(fd);
+		show_siginfo(img);
 		goto out;
 	}
 
@@ -386,7 +394,7 @@ int cr_parse_fd(int fd, u32 magic)
 		if (si->magic != magic)
 			continue;
 
-		do_pb_show_plain(fd, si->pb_type, si->single,
+		do_pb_show_plain(img, si->pb_type, si->single,
 				si->payload, si->fmt);
 		goto out;
 	}
@@ -403,6 +411,7 @@ out:
 static int cr_show_pstree_item(struct pstree_item *item)
 {
 	int ret = -1, i;
+	struct cr_img *img;
 	struct cr_imgset *cr_imgset = NULL;
 	TaskKobjIdsEntry *ids;
 
@@ -416,22 +425,20 @@ static int cr_show_pstree_item(struct pstree_item *item)
 	cr_parse_fd(img_from_set(cr_imgset, CR_FD_CORE), CORE_MAGIC);
 
 	if (item->nr_threads > 1) {
-		int fd_th;
-
 		for (i = 0; i < item->nr_threads; i++) {
 
 			if (item->threads[i].virt == item->pid.virt)
 				continue;
 
-			fd_th = open_image(CR_FD_CORE, O_SHOW, item->threads[i].virt);
-			if (fd_th < 0)
+			img = open_image(CR_FD_CORE, O_SHOW, item->threads[i].virt);
+			if (!img)
 				goto outc;
 
 			pr_msg("Thread %d.%d:\n", item->pid.virt, item->threads[i].virt);
 			pr_msg("----------------------------------------\n");
 
-			cr_parse_fd(fd_th, CORE_MAGIC);
-			close_safe(&fd_th);
+			cr_parse_fd(img, CORE_MAGIC);
+			close_image(img);
 		}
 	}
 
@@ -445,25 +452,25 @@ static int cr_show_pstree_item(struct pstree_item *item)
 			cr_parse_fd(img_from_set(cr_imgset, i), imgset_template[i].magic);
 		}
 
-	i = open_image(CR_FD_RLIMIT, O_SHOW | O_OPT, item->pid.virt);
-	if (i >= 0) {
+	img = open_image(CR_FD_RLIMIT, O_SHOW | O_OPT, item->pid.virt);
+	if (img) {
 		pr_msg("* ");
 		pr_msg(imgset_template[CR_FD_RLIMIT].fmt, item->pid.virt);
 		pr_msg(":\n");
 
-		cr_parse_fd(i, RLIMIT_MAGIC);
-		close(i);
+		cr_parse_fd(img, RLIMIT_MAGIC);
+		close_image(img);
 	}
 
 	if (pb_read_one(img_from_set(cr_imgset, CR_FD_IDS), &ids, PB_IDS) > 0) {
-		i = open_image(CR_FD_FDINFO, O_SHOW, ids->files_id);
-		if (i >= 0) {
+		img = open_image(CR_FD_FDINFO, O_SHOW, ids->files_id);
+		if (img) {
 			pr_msg("* ");
 			pr_msg(imgset_template[CR_FD_FDINFO].fmt, ids->files_id);
 			pr_msg(":\n");
 
-			cr_parse_fd(i, FDINFO_MAGIC);
-			close(i);
+			cr_parse_fd(img, FDINFO_MAGIC);
+			close_image(img);
 		}
 
 		task_kobj_ids_entry__free_unpacked(ids, NULL);
@@ -480,19 +487,20 @@ out:
 
 static int cr_show_pid(int pid)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	struct pstree_item item;
 
-	fd = open_image(CR_FD_PSTREE, O_SHOW);
-	if (fd < 0)
+	img = open_image(CR_FD_PSTREE, O_SHOW);
+	if (!img)
 		return -1;
 
 	while (1) {
 		PstreeEntry *pe;
 
-		ret = pb_read_one_eof(fd, &pe, PB_PSTREE);
+		ret = pb_read_one_eof(img, &pe, PB_PSTREE);
 		if (ret <= 0) {
-			close(fd);
+			close_image(img);
 			return ret;
 		}
 
@@ -505,7 +513,7 @@ static int cr_show_pid(int pid)
 		pstree_entry__free_unpacked(pe, NULL);
 	}
 
-	close(fd);
+	close_image(img);
 
 	return cr_show_pstree_item(&item);
 }
@@ -513,19 +521,14 @@ static int cr_show_pid(int pid)
 static int cr_show_all(void)
 {
 	struct pstree_item *item = NULL, *tmp;
-	int ret = -1, fd, pid;
-
-	fd = open_image(CR_FD_PSTREE, O_SHOW);
-	if (fd < 0)
-		goto out;
-	show_collect_pstree(fd, 1);
-	close(fd);
+	int ret = -1, pid;
+	struct cr_img *img;
 
-	fd = open_image(CR_FD_SK_QUEUES, O_SHOW);
-	if (fd < 0)
+	img = open_image(CR_FD_PSTREE, O_SHOW);
+	if (!img)
 		goto out;
-
-	close(fd);
+	show_collect_pstree(img, 1);
+	close_image(img);
 
 	pid = list_first_entry(&pstree_list, struct pstree_item, sibling)->pid.virt;
 	ret = try_show_namespaces(pid);
diff --git a/fifo.c b/fifo.c
index af85088..bd06da9 100644
--- a/fifo.c
+++ b/fifo.c
@@ -41,7 +41,7 @@ static struct pipe_data_dump pd_fifo = { .img_type = CR_FD_FIFO_DATA, };
 
 static int dump_one_fifo(int lfd, u32 id, const struct fd_parms *p)
 {
-	int img = img_from_set(glob_imgset, CR_FD_FIFO);
+	struct cr_img *img = img_from_set(glob_imgset, CR_FD_FIFO);
 	FifoEntry e = FIFO_ENTRY__INIT;
 
 	/*
diff --git a/file-lock.c b/file-lock.c
index f97beae..210e67c 100644
--- a/file-lock.c
+++ b/file-lock.c
@@ -338,11 +338,12 @@ static int restore_file_locks(int pid)
 
 static int restore_file_locks_legacy(int pid)
 {
-	int fd, ret = -1;
+	int ret = -1;
+	struct cr_img *img;
 	FileLockEntry *fle;
 
-	fd = open_image(CR_FD_FILE_LOCKS_PID, O_RSTR | O_OPT, pid);
-	if (fd < 0) {
+	img = open_image(CR_FD_FILE_LOCKS_PID, O_RSTR | O_OPT, pid);
+	if (!img) {
 		if (errno == ENOENT)
 			return 0;
 		else
@@ -350,7 +351,7 @@ static int restore_file_locks_legacy(int pid)
 	}
 
 	while (1) {
-		ret = pb_read_one_eof(fd, &fle, PB_FILE_LOCK);
+		ret = pb_read_one_eof(img, &fle, PB_FILE_LOCK);
 		if (ret <= 0)
 			break;
 
@@ -360,7 +361,7 @@ static int restore_file_locks_legacy(int pid)
 			break;
 	}
 
-	close_safe(&fd);
+	close_image(img);
 	return ret;
 }
 
diff --git a/files-ext.c b/files-ext.c
index e0b30e4..b196b25 100644
--- a/files-ext.c
+++ b/files-ext.c
@@ -11,7 +11,8 @@
 
 static int dump_one_ext_file(int lfd, u32 id, const struct fd_parms *p)
 {
-	int rfd, ret;
+	int ret;
+	struct cr_img *rimg;
 
 	ExtFileEntry xfe = EXT_FILE_ENTRY__INIT;
 
@@ -22,9 +23,8 @@ static int dump_one_ext_file(int lfd, u32 id, const struct fd_parms *p)
 	xfe.id		= id;
 	xfe.fown	= (FownEntry *)&p->fown;
 
-	rfd = img_from_set(glob_imgset, CR_FD_EXT_FILES);
-
-	return pb_write_one(rfd, &xfe, PB_EXT_FILE);
+	rimg = img_from_set(glob_imgset, CR_FD_EXT_FILES);
+	return pb_write_one(rimg, &xfe, PB_EXT_FILE);
 }
 
 const struct fdtype_ops ext_dump_ops = {
@@ -79,11 +79,11 @@ struct collect_image_info ext_file_cinfo = {
 };
 
 int dump_unsupp_fd(struct fd_parms *p, int lfd,
-			  const int fdinfo, char *more, char *info)
+			  struct cr_img *img, char *more, char *info)
 {
 	int ret;
 
-	ret = do_dump_gen_file(p, lfd, &ext_dump_ops, fdinfo);
+	ret = do_dump_gen_file(p, lfd, &ext_dump_ops, img);
 	if (ret == 0)
 		return 0;
 	if (ret == -ENOTSUP)
diff --git a/files-reg.c b/files-reg.c
index 0d9d76e..627cee6 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -69,7 +69,7 @@ static LIST_HEAD(link_remaps);
  */
 #define MAX_GHOST_FILE_SIZE	(1 * 1024 * 1024)
 
-static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, char *root, int ifd)
+static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, char *root, struct cr_img *img)
 {
 	int gfd, ghost_flags, ret = -1;
 	char path[PATH_MAX];
@@ -113,7 +113,7 @@ static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, char *root,
 	}
 
 	if (S_ISREG(gfe->mode)) {
-		if (copy_file(ifd, gfd, 0) < 0)
+		if (copy_file(img_raw_fd(img), gfd, 0) < 0)
 			goto err_c;
 	}
 
@@ -129,7 +129,7 @@ static int open_remap_ghost(struct reg_file_info *rfi,
 {
 	struct ghost_file *gf;
 	GhostFileEntry *gfe = NULL;
-	int ifd;
+	struct cr_img *img;
 	char *root;
 
 	list_for_each_entry(gf, &ghost_files, list)
@@ -158,11 +158,11 @@ static int open_remap_ghost(struct reg_file_info *rfi,
 	if (!gf->remap.path)
 		goto err;
 
-	ifd = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id);
-	if (ifd < 0)
+	img = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id);
+	if (!img)
 		goto err;
 
-	if (pb_read_one(ifd, &gfe, PB_GHOST_FILE) < 0)
+	if (pb_read_one(img, &gfe, PB_GHOST_FILE) < 0)
 		goto close_ifd;
 
 	/*
@@ -175,11 +175,11 @@ static int open_remap_ghost(struct reg_file_info *rfi,
 
 	snprintf(gf->remap.path, PATH_MAX, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
 
-	if (create_ghost(gf, gfe, root, ifd))
+	if (create_ghost(gf, gfe, root, img))
 		goto close_ifd;
 
 	ghost_file_entry__free_unpacked(gfe, NULL);
-	close(ifd);
+	close_image(img);
 
 	gf->id = rfe->remap_id;
 	gf->remap.users = 0;
@@ -190,7 +190,7 @@ gf_found:
 	return 0;
 
 close_ifd:
-	close_safe(&ifd);
+	close_image(img);
 err:
 	if (gfe)
 		ghost_file_entry__free_unpacked(gfe, NULL);
@@ -314,7 +314,7 @@ struct collect_image_info remap_cinfo = {
 
 static int dump_ghost_file(int _fd, u32 id, const struct stat *st, dev_t phys_dev)
 {
-	int img;
+	struct cr_img *img;
 	GhostFileEntry gfe = GHOST_FILE_ENTRY__INIT;
 
 	pr_info("Dumping ghost file contents (id %#x)\n", id);
@@ -353,13 +353,13 @@ static int dump_ghost_file(int _fd, u32 id, const struct stat *st, dev_t phys_de
 			pr_perror("Can't open ghost original file");
 			return -1;
 		}
-		ret = copy_file(fd, img, st->st_size);
+		ret = copy_file(fd, img_raw_fd(img), st->st_size);
 		close(fd);
 		if (ret)
 			return -1;
 	}
 
-	close(img);
+	close_image(img);
 	return 0;
 }
 
@@ -752,7 +752,7 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 {
 	struct fd_link _link, *link;
 	struct ns_id *nsid;
-	int rfd;
+	struct cr_img *rimg;
 
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
 
@@ -799,9 +799,8 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 		rfe.size = p->stat.st_size;
 	}
 
-	rfd = img_from_set(glob_imgset, CR_FD_REG_FILES);
-
-	return pb_write_one(rfd, &rfe, PB_REG_FILE);
+	rimg = img_from_set(glob_imgset, CR_FD_REG_FILES);
+	return pb_write_one(rimg, &rfe, PB_REG_FILE);
 }
 
 const struct fdtype_ops regfile_dump_ops = {
diff --git a/files.c b/files.c
index 1b09244..8d13651 100644
--- a/files.c
+++ b/files.c
@@ -163,7 +163,7 @@ static u32 make_gen_id(const struct fd_parms *p)
 }
 
 int do_dump_gen_file(struct fd_parms *p, int lfd,
-		const struct fdtype_ops *ops, const int fdinfo)
+		const struct fdtype_ops *ops, struct cr_img *img)
 {
 	FdinfoEntry e = FDINFO_ENTRY__INIT;
 	int ret = -1;
@@ -183,7 +183,7 @@ int do_dump_gen_file(struct fd_parms *p, int lfd,
 	pr_info("fdinfo: type: 0x%2x flags: %#o/%#o pos: 0x%8"PRIx64" fd: %d\n",
 		ops->type, p->flags, (int)p->fd_flags, p->pos, p->fd);
 
-	return pb_write_one(fdinfo, &e, PB_FDINFO);
+	return pb_write_one(img, &e, PB_FDINFO);
 }
 
 int fill_fdlink(int lfd, const struct fd_parms *p, struct fd_link *link)
@@ -264,7 +264,7 @@ static const struct fdtype_ops *get_misc_dev_ops(int minor)
 	return NULL;
 }
 
-static int dump_chrdev(struct fd_parms *p, int lfd, const int fdinfo)
+static int dump_chrdev(struct fd_parms *p, int lfd, struct cr_img *img)
 {
 	int maj = major(p->stat.st_rdev);
 	const struct fdtype_ops *ops;
@@ -287,15 +287,15 @@ static int dump_chrdev(struct fd_parms *p, int lfd, const int fdinfo)
 		char more[32];
 
 		sprintf(more, "%d:%d", maj, minor(p->stat.st_rdev));
-		return dump_unsupp_fd(p, lfd, fdinfo, "chr", more);
+		return dump_unsupp_fd(p, lfd, img, "chr", more);
 	}
 	}
 
-	return do_dump_gen_file(p, lfd, ops, fdinfo);
+	return do_dump_gen_file(p, lfd, ops, img);
 }
 
 static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_opts *opts,
-		       const int fdinfo)
+		       struct cr_img *img)
 {
 	struct fd_parms p = FD_PARMS_INIT;
 	const struct fdtype_ops *ops;
@@ -309,10 +309,10 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 		return -1;
 
 	if (S_ISSOCK(p.stat.st_mode))
-		return dump_socket(&p, lfd, fdinfo);
+		return dump_socket(&p, lfd, img);
 
 	if (S_ISCHR(p.stat.st_mode))
-		return dump_chrdev(&p, lfd, fdinfo);
+		return dump_chrdev(&p, lfd, img);
 
 	if (p.fs_type == ANON_INODE_FS_MAGIC) {
 		char link[32];
@@ -333,9 +333,9 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 		else if (is_timerfd_link(link))
 			ops = &timerfd_dump_ops;
 		else
-			return dump_unsupp_fd(&p, lfd, fdinfo, "anon", link);
+			return dump_unsupp_fd(&p, lfd, img, "anon", link);
 
-		return do_dump_gen_file(&p, lfd, ops, fdinfo);
+		return do_dump_gen_file(&p, lfd, ops, img);
 	}
 
 	if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode)) {
@@ -346,12 +346,12 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 
 		p.link = &link;
 		if (link.name[1] == '/')
-			return do_dump_gen_file(&p, lfd, &regfile_dump_ops, fdinfo);
+			return do_dump_gen_file(&p, lfd, &regfile_dump_ops, img);
 
 		if (check_ns_proc(&link))
-			return do_dump_gen_file(&p, lfd, &nsfile_dump_ops, fdinfo);
+			return do_dump_gen_file(&p, lfd, &nsfile_dump_ops, img);
 
-		return dump_unsupp_fd(&p, lfd, fdinfo, "reg", link.name + 1);
+		return dump_unsupp_fd(&p, lfd, img, "reg", link.name + 1);
 	}
 
 	if (S_ISFIFO(p.stat.st_mode)) {
@@ -360,16 +360,17 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 		else
 			ops = &fifo_dump_ops;
 
-		return do_dump_gen_file(&p, lfd, ops, fdinfo);
+		return do_dump_gen_file(&p, lfd, ops, img);
 	}
 
-	return dump_unsupp_fd(&p, lfd, fdinfo, "unknown", NULL);
+	return dump_unsupp_fd(&p, lfd, img, "unknown", NULL);
 }
 
 int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 		struct parasite_drain_fd *dfds)
 {
-	int *lfds, fdinfo;
+	int *lfds;
+	struct cr_img *img;
 	struct fd_opts *opts;
 	int i, ret = -1;
 
@@ -389,18 +390,18 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 	if (ret)
 		goto err2;
 
-	fdinfo = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
-	if (fdinfo < 0)
+	img = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
+	if (!img)
 		goto err2;
 
 	for (i = 0; i < dfds->nr_fds; i++) {
-		ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, fdinfo);
+		ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, img);
 		close(lfds[i]);
 		if (ret)
 			break;
 	}
 
-	close(fdinfo);
+	close_image(img);
 
 	pr_info("----------------------------------------\n");
 err2:
@@ -587,7 +588,8 @@ int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
 
 int prepare_fd_pid(struct pstree_item *item)
 {
-	int fdinfo_fd, ret = 0;
+	int ret = 0;
+	struct cr_img *img;
 	pid_t pid = item->pid.virt;
 	struct rst_info *rst_info = item->rst;
 
@@ -596,8 +598,8 @@ int prepare_fd_pid(struct pstree_item *item)
 	INIT_LIST_HEAD(&rst_info->tty_slaves);
 
 	if (!fdinfo_per_id) {
-		fdinfo_fd = open_image(CR_FD_FDINFO, O_RSTR | O_OPT, pid);
-		if (fdinfo_fd < 0) {
+		img = open_image(CR_FD_FDINFO, O_RSTR | O_OPT, pid);
+		if (!img) {
 			if (errno == ENOENT)
 				return 0;
 			return -1;
@@ -609,15 +611,15 @@ int prepare_fd_pid(struct pstree_item *item)
 		if (item->rst->fdt && item->rst->fdt->pid != item->pid.virt)
 			return 0;
 
-		fdinfo_fd = open_image(CR_FD_FDINFO, O_RSTR, item->ids->files_id);
-		if (fdinfo_fd < 0)
+		img = open_image(CR_FD_FDINFO, O_RSTR, item->ids->files_id);
+		if (!img)
 			return -1;
 	}
 
 	while (1) {
 		FdinfoEntry *e;
 
-		ret = pb_read_one_eof(fdinfo_fd, &e, PB_FDINFO);
+		ret = pb_read_one_eof(img, &e, PB_FDINFO);
 		if (ret <= 0)
 			break;
 
@@ -628,7 +630,7 @@ int prepare_fd_pid(struct pstree_item *item)
 		}
 	}
 
-	close(fdinfo_fd);
+	close_image(img);
 	return ret;
 }
 
@@ -1081,21 +1083,21 @@ int prepare_fs_pid(struct pstree_item *item)
 {
 	pid_t pid = item->pid.virt;
 	struct rst_info *ri = item->rst;
-	int ifd;
+	struct cr_img *img;
 	FsEntry *fe;
 
-	ifd = open_image(CR_FD_FS, O_RSTR | O_OPT, pid);
-	if (ifd < 0) {
+	img = open_image(CR_FD_FS, O_RSTR | O_OPT, pid);
+	if (!img) {
 		if (errno == ENOENT)
 			goto ok;
 		else
 			goto out;
 	}
 
-	if (pb_read_one(ifd, &fe, PB_FS) < 0)
+	if (pb_read_one(img, &fe, PB_FS) < 0)
 		goto out_i;
 
-	close(ifd);
+	close_image(img);
 
 	ri->cwd = collect_special_file(fe->cwd_id);
 	if (!ri->cwd) {
@@ -1121,7 +1123,7 @@ out_f:
 	return -1;
 
 out_i:
-	close(ifd);
+	close_image(img);
 out:
 	return -1;
 }
diff --git a/image.c b/image.c
index b9a8e4a..e7f8b86 100644
--- a/image.c
+++ b/image.c
@@ -19,14 +19,15 @@ u32 root_cg_set;
 
 int check_img_inventory(void)
 {
-	int fd, ret = -1;
+	int ret = -1;
+	struct cr_img *img;
 	InventoryEntry *he;
 
-	fd = open_image(CR_FD_INVENTORY, O_RSTR);
-	if (fd < 0)
+	img = open_image(CR_FD_INVENTORY, O_RSTR);
+	if (!img)
 		return -1;
 
-	if (pb_read_one(fd, &he, PB_INVENTORY) < 0)
+	if (pb_read_one(img, &he, PB_INVENTORY) < 0)
 		goto out_close;
 
 	fdinfo_per_id = he->has_fdinfo_per_id ?  he->fdinfo_per_id : false;
@@ -58,20 +59,20 @@ int check_img_inventory(void)
 out_err:
 	inventory_entry__free_unpacked(he, NULL);
 out_close:
-	close(fd);
+	close_image(img);
 	return ret;
 }
 
 int write_img_inventory(void)
 {
-	int fd;
+	struct cr_img *img;
 	InventoryEntry he = INVENTORY_ENTRY__INIT;
 	struct pstree_item crt = { };
 
 	pr_info("Writing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
 
-	fd = open_image(CR_FD_INVENTORY, O_DUMP);
-	if (fd < 0)
+	img = open_image(CR_FD_INVENTORY, O_DUMP);
+	if (!img)
 		return -1;
 
 	he.img_version = CRTOOLS_IMAGES_V1;
@@ -83,7 +84,7 @@ int write_img_inventory(void)
 	crt.state = TASK_ALIVE;
 	crt.pid.real = getpid();
 	if (get_task_ids(&crt)) {
-		close(fd);
+		close_image(img);
 		return -1;
 	}
 
@@ -93,11 +94,11 @@ int write_img_inventory(void)
 
 	he.root_ids = crt.ids;
 
-	if (pb_write_one(fd, &he, PB_INVENTORY) < 0)
+	if (pb_write_one(img, &he, PB_INVENTORY) < 0)
 		return -1;
 
 	xfree(crt.ids);
-	close(fd);
+	close_image(img);
 	return 0;
 }
 
@@ -116,14 +117,14 @@ static struct cr_imgset *alloc_cr_imgset(int nr)
 	if (cr_imgset == NULL)
 		return NULL;
 
-	cr_imgset->_imgs = xmalloc(nr * sizeof(int));
+	cr_imgset->_imgs = xmalloc(nr * sizeof(struct cr_img *));
 	if (cr_imgset->_imgs == NULL) {
 		xfree(cr_imgset);
 		return NULL;
 	}
 
 	for (i = 0; i < nr; i++)
-		cr_imgset->_imgs[i] = -1;
+		cr_imgset->_imgs[i] = NULL;
 	cr_imgset->fd_nr = nr;
 	return cr_imgset;
 }
@@ -136,10 +137,10 @@ static void __close_cr_imgset(struct cr_imgset *cr_imgset)
 		return;
 
 	for (i = 0; i < cr_imgset->fd_nr; i++) {
-		if (cr_imgset->_imgs[i] == -1)
+		if (!cr_imgset->_imgs[i])
 			continue;
-		close_safe(&cr_imgset->_imgs[i]);
-		cr_imgset->_imgs[i] = -1;
+		close_image(cr_imgset->_imgs[i]);
+		cr_imgset->_imgs[i] = NULL;
 	}
 }
 
@@ -160,7 +161,6 @@ struct cr_imgset *cr_imgset_open_range(int pid, int from, int to,
 {
 	struct cr_imgset *imgset;
 	unsigned int i;
-	int ret = -1;
 
 	imgset = alloc_cr_imgset(to - from);
 	if (!imgset)
@@ -169,15 +169,17 @@ struct cr_imgset *cr_imgset_open_range(int pid, int from, int to,
 	from++;
 	imgset->fd_off = from;
 	for (i = from; i < to; i++) {
-		ret = open_image(i, flags, pid);
-		if (ret < 0) {
+		struct cr_img *img;
+
+		img = open_image(i, flags, pid);
+		if (!img) {
 			if (!(flags & O_CREAT))
 				/* caller should check himself */
 				continue;
 			goto err;
 		}
 
-		imgset->_imgs[i - from] = ret;
+		imgset->_imgs[i - from] = img;
 	}
 
 	return imgset;
@@ -197,13 +199,18 @@ struct cr_imgset *cr_glob_imgset_open(int mode)
 	return cr_imgset_open(-1 /* ignored */, GLOB, mode);
 }
 
-int open_image_at(int dfd, int type, unsigned long flags, ...)
+struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...)
 {
+	struct cr_img *img;
 	unsigned long oflags = flags;
 	char path[PATH_MAX];
 	va_list args;
 	int ret;
 
+	img = xmalloc(sizeof(*img));
+	if (!img)
+		goto errn;
+
 	flags &= ~O_OPT;
 
 	va_start(args, flags);
@@ -212,33 +219,56 @@ int open_image_at(int dfd, int type, unsigned long flags, ...)
 
 	ret = openat(dfd, path, flags, CR_FD_PERM);
 	if (ret < 0) {
-		if ((oflags & O_OPT) && errno == ENOENT)
-			return -ENOENT;
+		if ((oflags & O_OPT) && errno == ENOENT) {
+			xfree(img);
+			return NULL;
+		}
+
 		pr_perror("Unable to open %s", path);
 		goto err;
 	}
 
+	img->_fd = ret;
 	if (imgset_template[type].magic == RAW_IMAGE_MAGIC)
 		goto skip_magic;
 
 	if (flags == O_RDONLY) {
 		u32 magic;
 
-		if (read_img(ret, &magic) < 0)
+		if (read_img(img, &magic) < 0)
 			goto err;
 		if (magic != imgset_template[type].magic) {
 			pr_err("Magic doesn't match for %s\n", path);
 			goto err;
 		}
 	} else {
-		if (write_img(ret, &imgset_template[type].magic))
+		if (write_img(img, &imgset_template[type].magic))
 			goto err;
 	}
 
 skip_magic:
-	return ret;
+	return img;
+
 err:
-	return -1;
+	xfree(img);
+errn:
+	return NULL;
+}
+
+void close_image(struct cr_img *img)
+{
+	close(img->_fd);
+	xfree(img);
+}
+
+struct cr_img *img_from_fd(int fd)
+{
+	struct cr_img *img;
+
+	img = xmalloc(sizeof(*img));
+	if (img)
+		img->_fd = fd;
+	return img;
 }
 
 int open_image_dir(char *dir)
@@ -291,29 +321,29 @@ void up_page_ids_base(void)
 	page_ids += 0x10000;
 }
 
-int open_pages_image_at(int dfd, unsigned long flags, int pm_fd)
+struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *pmi)
 {
 	unsigned id;
 
 	if (flags == O_RDONLY || flags == O_RDWR) {
 		PagemapHead *h;
-		if (pb_read_one(pm_fd, &h, PB_PAGEMAP_HEAD) < 0)
-			return -1;
+		if (pb_read_one(pmi, &h, PB_PAGEMAP_HEAD) < 0)
+			return NULL;
 		id = h->pages_id;
 		pagemap_head__free_unpacked(h, NULL);
 	} else {
 		PagemapHead h = PAGEMAP_HEAD__INIT;
 		id = h.pages_id = page_ids++;
-		if (pb_write_one(pm_fd, &h, PB_PAGEMAP_HEAD) < 0)
-			return -1;
+		if (pb_write_one(pmi, &h, PB_PAGEMAP_HEAD) < 0)
+			return NULL;
 	}
 
 	return open_image_at(dfd, CR_FD_PAGES, flags, id);
 }
 
-int open_pages_image(unsigned long flags, int pm_fd)
+struct cr_img *open_pages_image(unsigned long flags, struct cr_img *pmi)
 {
-	return open_pages_image_at(get_service_fd(IMG_FD_OFF), flags, pm_fd);
+	return open_pages_image_at(get_service_fd(IMG_FD_OFF), flags, pmi);
 }
 
 /*
@@ -322,9 +352,11 @@ int open_pages_image(unsigned long flags, int pm_fd)
  *	0  on success
  *	-1 on error (error message is printed)
  */
-int write_img_buf(int fd, const void *ptr, int size)
+int write_img_buf(struct cr_img *img, const void *ptr, int size)
 {
+	int fd = img->_fd;
 	int ret;
+
 	ret = write(fd, ptr, size);
 	if (ret == size)
 		return 0;
@@ -343,9 +375,11 @@ int write_img_buf(int fd, const void *ptr, int size)
  *	0  on EOF (silently)
  *	-1 on error (error message is printed)
  */
-int read_img_buf_eof(int fd, void *ptr, int size)
+int read_img_buf_eof(struct cr_img *img, void *ptr, int size)
 {
+	int fd = img->_fd;
 	int ret;
+
 	ret = read(fd, ptr, size);
 	if (ret == size)
 		return 1;
@@ -365,11 +399,11 @@ int read_img_buf_eof(int fd, void *ptr, int size)
  *	1  on success
  *	-1 on error or EOF (error message is printed)
  */
-int read_img_buf(int fd, void *ptr, int size)
+int read_img_buf(struct cr_img *img, void *ptr, int size)
 {
 	int ret;
 
-	ret = read_img_buf_eof(fd, ptr, size);
+	ret = read_img_buf_eof(img, ptr, size);
 	if (ret == 0) {
 		pr_err("Unexpected EOF\n");
 		ret = -1;
@@ -383,7 +417,7 @@ int read_img_buf(int fd, void *ptr, int size)
  * the buffer and puts the '\0' at the end
  */
 
-int read_img_str(int fd, char **pstr, int size)
+int read_img_str(struct cr_img *img, char **pstr, int size)
 {
 	int ret;
 	char *str;
@@ -392,7 +426,7 @@ int read_img_str(int fd, char **pstr, int size)
 	if (!str)
 		return -1;
 
-	ret = read_img_buf(fd, str, size);
+	ret = read_img_buf(img, str, size);
 	if (ret < 0) {
 		xfree(str);
 		return -1;
diff --git a/include/cr-show.h b/include/cr-show.h
index 165f87a..6ebdb4c 100644
--- a/include/cr-show.h
+++ b/include/cr-show.h
@@ -4,20 +4,22 @@
 #include <stdbool.h>
 #include "asm/types.h"
 
+struct cr_img;
+
 struct show_image_info {
 	u32	magic;
 	int	pb_type;
 	bool	single;
-	void	(*payload)(int, void *);
+	void	(*payload)(struct cr_img *, void *);
 	char	*fmt;
 };
 
-extern void show_siginfo(int fd);
-extern void sk_queue_data_handler(int fd, void *obj);
-extern void ipc_shm_handler(int fd, void *obj);
-extern void ipc_msg_handler(int fd, void *obj);
-extern void ipc_sem_handler(int fd, void *obj);
-extern int cr_parse_fd(int fd, u32 magic);
-extern void show_tcp_stream(int fd, void *obj);
+extern void show_siginfo(struct cr_img *);
+extern void sk_queue_data_handler(struct cr_img *, void *obj);
+extern void ipc_shm_handler(struct cr_img *, void *obj);
+extern void ipc_msg_handler(struct cr_img *, void *obj);
+extern void ipc_sem_handler(struct cr_img *, void *obj);
+extern int cr_parse_fd(struct cr_img *, u32 magic);
+extern void show_tcp_stream(struct cr_img *, void *obj);
 
 #endif /* __CR_SHOW_H__ */
diff --git a/include/files.h b/include/files.h
index 012a0ec..07167cb 100644
--- a/include/files.h
+++ b/include/files.h
@@ -125,9 +125,11 @@ struct fdtype_ops {
 	int			(*pre_dump)(int pid, int lfd);
 };
 
+struct cr_img;
+
 extern int do_dump_gen_file(struct fd_parms *p, int lfd,
 			    const struct fdtype_ops *ops,
-			    const int fdinfo);
+			    struct cr_img *);
 struct parasite_drain_fd;
 int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 		struct parasite_drain_fd *dfds);
@@ -163,6 +165,6 @@ extern int shared_fdt_prepare(struct pstree_item *item);
 
 extern struct collect_image_info ext_file_cinfo;
 extern int dump_unsupp_fd(struct fd_parms *p, int lfd,
-			  const int fdinfo, char *more, char *info);
+			  struct cr_img *, char *more, char *info);
 
 #endif /* __CR_FILES_H__ */
diff --git a/include/image.h b/include/image.h
index e6bdebd..ee6ca7e 100644
--- a/include/image.h
+++ b/include/image.h
@@ -74,21 +74,34 @@ extern bool ns_per_id;
 #define O_RSTR	(O_RDONLY)
 #define O_OPT	(O_PATH)
 
+struct cr_img {
+	int _fd;
+};
+
+static inline int img_raw_fd(struct cr_img *img)
+{
+	return img->_fd;
+}
+
 extern int open_image_dir(char *dir);
 extern void close_image_dir(void);
 
-extern int open_image_at(int dfd, int type, unsigned long flags, ...);
+extern struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...);
 #define open_image(typ, flags, ...) open_image_at(get_service_fd(IMG_FD_OFF), typ, flags, ##__VA_ARGS__)
-extern int open_pages_image(unsigned long flags, int pm_fd);
-extern int open_pages_image_at(int dfd, unsigned long flags, int pm_fd);
+extern struct cr_img *open_pages_image(unsigned long flags, struct cr_img *pmi);
+extern struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *pmi);
 extern void up_page_ids_base(void);
 
-extern int write_img_buf(int fd, const void *ptr, int size);
-#define write_img(fd, ptr)	write_img_buf((fd), (ptr), sizeof(*(ptr)))
-extern int read_img_buf_eof(int fd, void *ptr, int size);
-#define read_img_eof(fd, ptr)	read_img_buf_eof((fd), (ptr), sizeof(*(ptr)))
-extern int read_img_buf(int fd, void *ptr, int size);
-#define read_img(fd, ptr)	read_img_buf((fd), (ptr), sizeof(*(ptr)))
-extern int read_img_str(int fd, char **pstr, int size);
+extern struct cr_img *img_from_fd(int fd); /* for cr-show mostly */
+
+extern int write_img_buf(struct cr_img *, const void *ptr, int size);
+#define write_img(img, ptr)	write_img_buf((img), (ptr), sizeof(*(ptr)))
+extern int read_img_buf_eof(struct cr_img *, void *ptr, int size);
+#define read_img_eof(img, ptr)	read_img_buf_eof((img), (ptr), sizeof(*(ptr)))
+extern int read_img_buf(struct cr_img *, void *ptr, int size);
+#define read_img(img, ptr)	read_img_buf((img), (ptr), sizeof(*(ptr)))
+extern int read_img_str(struct cr_img *, char **pstr, int size);
+
+extern void close_image(struct cr_img *);
 
 #endif /* __CR_IMAGE_H__ */
diff --git a/include/imgset.h b/include/imgset.h
index 13c6168..04be917 100644
--- a/include/imgset.h
+++ b/include/imgset.h
@@ -3,14 +3,15 @@
 
 #include "image-desc.h"
 #include "bug.h"
+#include "image.h"
 
 struct cr_imgset {
 	int fd_off;
 	int fd_nr;
-	int *_imgs;
+	struct cr_img **_imgs;
 };
 
-static inline int img_from_set(const struct cr_imgset *imgset, int type)
+static inline struct cr_img *img_from_set(const struct cr_imgset *imgset, int type)
 {
 	int idx;
 
diff --git a/include/log.h b/include/log.h
index 45303de..cc59870 100644
--- a/include/log.h
+++ b/include/log.h
@@ -24,8 +24,10 @@ extern int write_pidfile(int pid);
 
 #define DEFAULT_LOG_FILENAME "criu.log"
 
+struct cr_img;
+
 extern void print_data(unsigned long addr, unsigned char *data, size_t size);
-extern void print_image_data(int fd, unsigned int length, int show);
+extern void print_image_data(struct cr_img *, unsigned int length, int show);
 
 static inline int pr_quelled(unsigned int loglevel)
 {
diff --git a/include/page-read.h b/include/page-read.h
index 64a8579..df967bd 100644
--- a/include/page-read.h
+++ b/include/page-read.h
@@ -53,8 +53,8 @@ struct page_read {
 	void (*close)(struct page_read *);
 
 	/* Private data of reader */
-	int fd;
-	int fd_pg;
+	struct cr_img *pmi;
+	struct cr_img *pi;
 
 	PagemapEntry *pe;		/* current pagemap we are on */
 	struct page_read *parent;	/* parent pagemap (if ->in_parent
diff --git a/include/page-xfer.h b/include/page-xfer.h
index d900932..b50065d 100644
--- a/include/page-xfer.h
+++ b/include/page-xfer.h
@@ -20,11 +20,18 @@ struct page_xfer {
 	void (*close)(struct page_xfer *self);
 
 	/* private data for every page-xfer engine */
-	int fd;
 	union {
-		int fd_pg;
-		u64 dst_id;
+		struct /* local */ {
+			struct cr_img *pmi; /* pagemaps */
+			struct cr_img *pi;  /* pages */
+		};
+
+		struct /* page-server */ {
+			int sk;
+			u64 dst_id;
+		};
 	};
+
 	struct page_read *parent;
 };
 
diff --git a/include/protobuf.h b/include/protobuf.h
index 025cb6d..83b24c6 100644
--- a/include/protobuf.h
+++ b/include/protobuf.h
@@ -7,12 +7,14 @@
 #include "compiler.h"
 #include "util.h"
 
-extern int do_pb_read_one(int fd, void **objp, int type, bool eof);
+struct cr_img;
+
+extern int do_pb_read_one(struct cr_img *, void **objp, int type, bool eof);
 
 #define pb_read_one(fd, objp, type) do_pb_read_one(fd, (void **)objp, type, false)
 #define pb_read_one_eof(fd, objp, type) do_pb_read_one(fd, (void **)objp, type, true)
 
-extern int pb_write_one(int fd, void *obj, int type);
+extern int pb_write_one(struct cr_img *, void *obj, int type);
 
 #define pb_pksize(__obj, __proto_message_name)						\
 	(__proto_message_name ##__get_packed_size(__obj) + sizeof(u32))
@@ -25,8 +27,8 @@ extern int pb_write_one(int fd, void *obj, int type);
 
 #include <google/protobuf-c/protobuf-c.h>
 
-extern void do_pb_show_plain(int fd, int type, int single_entry,
-		void (*payload_hadler)(int fd, void *obj),
+extern void do_pb_show_plain(struct cr_img *, int type, int single_entry,
+		void (*payload_hadler)(struct cr_img *, void *obj),
 		const char *pretty_fmt);
 
 /* Don't have objects at hands to also do typechecking here */
diff --git a/include/sockets.h b/include/sockets.h
index 34fb167..3a2fe81 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -14,6 +14,7 @@ struct file_desc;
 struct fd_parms;
 struct cr_imgset;
 struct nlmsghdr;
+struct cr_img;
 
 struct socket_desc {
 	unsigned int		family;
@@ -22,7 +23,7 @@ struct socket_desc {
 	int			already_dumped;
 };
 
-extern int dump_socket(struct fd_parms *p, int lfd, const int fdinfo);
+extern int dump_socket(struct fd_parms *p, int lfd, struct cr_img *);
 extern int dump_socket_opts(int sk, SkOptsEntry *soe);
 extern int restore_socket_opts(int sk, SkOptsEntry *soe);
 extern void release_skopts(SkOptsEntry *);
diff --git a/ipc_ns.c b/ipc_ns.c
index 7ad04a4..8ac4298 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -70,7 +70,7 @@ static void pr_info_ipc_sem_entry(const IpcSemEntry *sem)
 	print_on_level(LOG_INFO, "nsems: %-10d\n", sem->nsems);
 }
 
-static int dump_ipc_sem_set(int fd, const IpcSemEntry *sem)
+static int dump_ipc_sem_set(struct cr_img *img, const IpcSemEntry *sem)
 {
 	size_t rounded;
 	int ret, size;
@@ -93,7 +93,7 @@ static int dump_ipc_sem_set(int fd, const IpcSemEntry *sem)
 	pr_info_ipc_sem_array(sem->nsems, values);
 
 	memzero((void *)values + size, rounded - size);
-	ret = write_img_buf(fd, values, rounded);
+	ret = write_img_buf(img, values, rounded);
 	if (ret < 0) {
 		pr_err("Failed to write IPC message data\n");
 		goto out;
@@ -103,7 +103,7 @@ out:
 	return ret;
 }
 
-static int dump_ipc_sem_desc(int fd, int id, const struct semid_ds *ds)
+static int dump_ipc_sem_desc(struct cr_img *img, int id, const struct semid_ds *ds)
 {
 	IpcSemEntry sem = IPC_SEM_ENTRY__INIT;
 	IpcDescEntry desc = IPC_DESC_ENTRY__INIT;
@@ -115,15 +115,15 @@ static int dump_ipc_sem_desc(int fd, int id, const struct semid_ds *ds)
 	fill_ipc_desc(id, sem.desc, &ds->sem_perm);
 	pr_info_ipc_sem_entry(&sem);
 
-	ret = pb_write_one(fd, &sem, PB_IPC_SEM);
+	ret = pb_write_one(img, &sem, PB_IPC_SEM);
 	if (ret < 0) {
 		pr_err("Failed to write IPC semaphores set\n");
 		return ret;
 	}
-	return dump_ipc_sem_set(fd, &sem);
+	return dump_ipc_sem_set(img, &sem);
 }
 
-static int dump_ipc_sem(int fd)
+static int dump_ipc_sem(struct cr_img *img)
 {
 	int i, maxid;
 	struct seminfo info;
@@ -147,7 +147,7 @@ static int dump_ipc_sem(int fd)
 			pr_perror("Failed to get stats for IPC semaphore set");
 			break;
 		}
-		ret = dump_ipc_sem_desc(fd, id, &ds);
+		ret = dump_ipc_sem_desc(img, id, &ds);
 		if (!ret)
 			slot++;
 	}
@@ -171,7 +171,7 @@ static void pr_info_ipc_msg_entry(const IpcMsgEntry *msg)
 		       msg->qbytes, msg->qnum);
 }
 
-static int dump_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq,
+static int dump_ipc_msg_queue_messages(struct cr_img *img, const IpcMsgEntry *msq,
 				       unsigned int msg_nr)
 {
 	struct msgbuf *message = NULL;
@@ -210,7 +210,7 @@ static int dump_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq,
 
 		pr_info_ipc_msg(msg_cnt, &msg);
 
-		ret = pb_write_one(fd, &msg, PB_IPCNS_MSG);
+		ret = pb_write_one(img, &msg, PB_IPCNS_MSG);
 		if (ret < 0) {
 			pr_err("Failed to write IPC message header\n");
 			break;
@@ -218,7 +218,7 @@ static int dump_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq,
 
 		rounded = round_up(msg.msize, sizeof(u64));
 		memzero(((void *)message->mtext + msg.msize), rounded - msg.msize);
-		ret = write_img_buf(fd, message->mtext, rounded);
+		ret = write_img_buf(img, message->mtext, rounded);
 		if (ret < 0) {
 			pr_err("Failed to write IPC message data\n");
 			break;
@@ -230,7 +230,7 @@ err:
 	return ret;
 }
 
-static int dump_ipc_msg_queue(int fd, int id, const struct msqid_ds *ds)
+static int dump_ipc_msg_queue(struct cr_img *img, int id, const struct msqid_ds *ds)
 {
 	IpcMsgEntry msg = IPC_MSG_ENTRY__INIT;
 	IpcDescEntry desc = IPC_DESC_ENTRY__INIT;
@@ -243,15 +243,15 @@ static int dump_ipc_msg_queue(int fd, int id, const struct msqid_ds *ds)
 
 	pr_info_ipc_msg_entry(&msg);
 
-	ret = pb_write_one(fd, &msg, PB_IPCNS_MSG_ENT);
+	ret = pb_write_one(img, &msg, PB_IPCNS_MSG_ENT);
 	if (ret < 0) {
 		pr_err("Failed to write IPC message queue\n");
 		return ret;
 	}
-	return dump_ipc_msg_queue_messages(fd, &msg, ds->msg_qnum);
+	return dump_ipc_msg_queue_messages(img, &msg, ds->msg_qnum);
 }
 
-static int dump_ipc_msg(int fd)
+static int dump_ipc_msg(struct cr_img *img)
 {
 	int i, maxid;
 	struct msginfo info;
@@ -275,7 +275,7 @@ static int dump_ipc_msg(int fd)
 			pr_perror("Failed to get stats for IPC message queue");
 			break;
 		}
-		ret = dump_ipc_msg_queue(fd, id, &ds);
+		ret = dump_ipc_msg_queue(img, id, &ds);
 		if (!ret)
 			slot++;
 	}
@@ -332,7 +332,7 @@ static int ipc_sysctl_req(IpcVarEntry *e, int op)
  * TODO: Function below should be later improved to locate and dump only dirty
  * pages via updated sys_mincore().
  */
-static int dump_ipc_shm_pages(int fd, const IpcShmEntry *shm)
+static int dump_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
 {
 	void *data;
 	int ret;
@@ -342,7 +342,7 @@ static int dump_ipc_shm_pages(int fd, const IpcShmEntry *shm)
 		pr_perror("Failed to attach IPC shared memory");
 		return -errno;
 	}
-	ret = write_img_buf(fd, data, round_up(shm->size, sizeof(u32)));
+	ret = write_img_buf(img, data, round_up(shm->size, sizeof(u32)));
 	if (ret < 0) {
 		pr_err("Failed to write IPC shared memory data\n");
 		return ret;
@@ -354,7 +354,7 @@ static int dump_ipc_shm_pages(int fd, const IpcShmEntry *shm)
 	return 0;
 }
 
-static int dump_ipc_shm_seg(int fd, int id, const struct shmid_ds *ds)
+static int dump_ipc_shm_seg(struct cr_img *img, int id, const struct shmid_ds *ds)
 {
 	IpcShmEntry shm = IPC_SHM_ENTRY__INIT;
 	IpcDescEntry desc = IPC_DESC_ENTRY__INIT;
@@ -365,15 +365,15 @@ static int dump_ipc_shm_seg(int fd, int id, const struct shmid_ds *ds)
 	fill_ipc_desc(id, shm.desc, &ds->shm_perm);
 	pr_info_ipc_shm(&shm);
 
-	ret = pb_write_one(fd, &shm, PB_IPC_SHM);
+	ret = pb_write_one(img, &shm, PB_IPC_SHM);
 	if (ret < 0) {
 		pr_err("Failed to write IPC shared memory segment\n");
 		return ret;
 	}
-	return dump_ipc_shm_pages(fd, &shm);
+	return dump_ipc_shm_pages(img, &shm);
 }
 
-static int dump_ipc_shm(int fd)
+static int dump_ipc_shm(struct cr_img *img)
 {
 	int i, maxid, slot;
 	struct shm_info info;
@@ -397,7 +397,7 @@ static int dump_ipc_shm(int fd)
 			break;
 		}
 
-		ret = dump_ipc_shm_seg(fd, id, &ds);
+		ret = dump_ipc_shm_seg(img, id, &ds);
 		if (ret < 0)
 			return ret;
 		slot++;
@@ -410,7 +410,7 @@ static int dump_ipc_shm(int fd)
 	return 0;
 }
 
-static int dump_ipc_var(int fd)
+static int dump_ipc_var(struct cr_img *img)
 {
 	IpcVarEntry var = IPC_VAR_ENTRY__INIT;
 	int ret = -1;
@@ -426,7 +426,7 @@ static int dump_ipc_var(int fd)
 		goto err;
 	}
 
-	ret = pb_write_one(fd, &var, PB_IPC_VAR);
+	ret = pb_write_one(img, &var, PB_IPC_VAR);
 	if (ret < 0) {
 		pr_err("Failed to write IPC variables\n");
 		goto err;
@@ -480,7 +480,7 @@ err:
 	return ret < 0 ? -1 : 0;
 }
 
-void ipc_sem_handler(int fd, void *obj)
+void ipc_sem_handler(struct cr_img *img, void *obj)
 {
 	IpcSemEntry *e = obj;
 	u16 *values;
@@ -491,37 +491,37 @@ void ipc_sem_handler(int fd, void *obj)
 	values = xmalloc(size);
 	if (values == NULL)
 		return;
-	if (read_img_buf(fd, values, size) <= 0) {
+	if (read_img_buf(img, values, size) <= 0) {
 		xfree(values);
 		return;
 	}
 	pr_msg_ipc_sem_array(e->nsems, values);
 }
 
-static void ipc_msg_data_handler(int fd, void *obj)
+static void ipc_msg_data_handler(struct cr_img *img, void *obj)
 {
 	IpcMsg *e = obj;
-	print_image_data(fd, round_up(e->msize, sizeof(u64)), opts.show_pages_content);
+	print_image_data(img, round_up(e->msize, sizeof(u64)), opts.show_pages_content);
 }
 
-void ipc_msg_handler(int fd, void *obj)
+void ipc_msg_handler(struct cr_img *img, void *obj)
 {
 	IpcMsgEntry *e = obj;
 	int msg_nr = 0;
 
 	pr_msg("\n");
 	while (msg_nr++ < e->qnum)
-		pb_show_plain_payload(fd, PB_IPCNS_MSG, ipc_msg_data_handler);
+		pb_show_plain_payload(img, PB_IPCNS_MSG, ipc_msg_data_handler);
 
 }
 
-void ipc_shm_handler(int fd, void *obj)
+void ipc_shm_handler(struct cr_img *img, void *obj)
 {
 	IpcShmEntry *e = obj;
-	print_image_data(fd, round_up(e->size, sizeof(u32)), opts.show_pages_content);
+	print_image_data(img, round_up(e->size, sizeof(u32)), opts.show_pages_content);
 }
 
-static int prepare_ipc_sem_values(int fd, const IpcSemEntry *sem)
+static int prepare_ipc_sem_values(struct cr_img *img, const IpcSemEntry *sem)
 {
 	int ret, size;
 	u16 *values;
@@ -534,7 +534,7 @@ static int prepare_ipc_sem_values(int fd, const IpcSemEntry *sem)
 		goto out;
 	}
 
-	ret = read_img_buf(fd, values, size);
+	ret = read_img_buf(img, values, size);
 	if (ret < 0) {
 		pr_err("Failed to allocate memory for semaphores set values\n");
 		ret = -ENOMEM;
@@ -553,7 +553,7 @@ out:
 	return ret;
 }
 
-static int prepare_ipc_sem_desc(int fd, const IpcSemEntry *sem)
+static int prepare_ipc_sem_desc(struct cr_img *img, const IpcSemEntry *sem)
 {
 	int ret, id;
 	struct sysctl_req req[] = {
@@ -596,7 +596,7 @@ static int prepare_ipc_sem_desc(int fd, const IpcSemEntry *sem)
 		return -EFAULT;
 	}
 
-	ret = prepare_ipc_sem_values(fd, sem);
+	ret = prepare_ipc_sem_values(img, sem);
 	if (ret < 0) {
 		pr_err("Failed to update sem pages\n");
 		return ret;
@@ -606,17 +606,18 @@ static int prepare_ipc_sem_desc(int fd, const IpcSemEntry *sem)
 
 static int prepare_ipc_sem(int pid)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 
 	pr_info("Restoring IPC semaphores sets\n");
-	fd = open_image(CR_FD_IPCNS_SEM, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_IPCNS_SEM, O_RSTR, pid);
+	if (!img)
 		return -1;
 
 	while (1) {
 		IpcSemEntry *sem;
 
-		ret = pb_read_one_eof(fd, &sem, PB_IPC_SEM);
+		ret = pb_read_one_eof(img, &sem, PB_IPC_SEM);
 		if (ret < 0) {
 			ret = -EIO;
 			goto err;
@@ -626,7 +627,7 @@ static int prepare_ipc_sem(int pid)
 
 		pr_info_ipc_sem_entry(sem);
 
-		ret = prepare_ipc_sem_desc(fd, sem);
+		ret = prepare_ipc_sem_desc(img, sem);
 		ipc_sem_entry__free_unpacked(sem, NULL);
 
 		if (ret < 0) {
@@ -635,13 +636,15 @@ static int prepare_ipc_sem(int pid)
 		}
 	}
 
-	return close_safe(&fd);
+	close_image(img);
+	return 0;
+
 err:
-	close_safe(&fd);
+	close_image(img);
 	return ret;
 }
 
-static int prepare_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq)
+static int prepare_ipc_msg_queue_messages(struct cr_img *img, const IpcMsgEntry *msq)
 {
 	IpcMsg *msg = NULL;
 	int msg_nr = 0;
@@ -653,7 +656,7 @@ static int prepare_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq)
 			char mtext[MSGMAX];
 		} data;
 
-		ret = pb_read_one(fd, &msg, PB_IPCNS_MSG);
+		ret = pb_read_one(img, &msg, PB_IPCNS_MSG);
 		if (ret <= 0)
 			return -EIO;
 
@@ -666,7 +669,7 @@ static int prepare_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq)
 			break;
 		}
 
-		ret = read_img_buf(fd, data.mtext, round_up(msg->msize, sizeof(u64)));
+		ret = read_img_buf(img, data.mtext, round_up(msg->msize, sizeof(u64)));
 		if (ret < 0) {
 			pr_err("Failed to read IPC message data\n");
 			break;
@@ -687,7 +690,7 @@ static int prepare_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq)
 	return ret;
 }
 
-static int prepare_ipc_msg_queue(int fd, const IpcMsgEntry *msq)
+static int prepare_ipc_msg_queue(struct cr_img *img, const IpcMsgEntry *msq)
 {
 	int ret, id;
 	struct sysctl_req req[] = {
@@ -729,7 +732,7 @@ static int prepare_ipc_msg_queue(int fd, const IpcMsgEntry *msq)
 		return -EFAULT;
 	}
 
-	ret = prepare_ipc_msg_queue_messages(fd, msq);
+	ret = prepare_ipc_msg_queue_messages(img, msq);
 	if (ret < 0) {
 		pr_err("Failed to update message queue messages\n");
 		return ret;
@@ -739,17 +742,18 @@ static int prepare_ipc_msg_queue(int fd, const IpcMsgEntry *msq)
 
 static int prepare_ipc_msg(int pid)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 
 	pr_info("Restoring IPC message queues\n");
-	fd = open_image(CR_FD_IPCNS_MSG, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_IPCNS_MSG, O_RSTR, pid);
+	if (!img)
 		return -1;
 
 	while (1) {
 		IpcMsgEntry *msq;
 
-		ret = pb_read_one_eof(fd, &msq, PB_IPCNS_MSG_ENT);
+		ret = pb_read_one_eof(img, &msq, PB_IPCNS_MSG_ENT);
 		if (ret < 0) {
 			pr_err("Failed to read IPC messages queue\n");
 			ret = -EIO;
@@ -760,7 +764,7 @@ static int prepare_ipc_msg(int pid)
 
 		pr_info_ipc_msg_entry(msq);
 
-		ret = prepare_ipc_msg_queue(fd, msq);
+		ret = prepare_ipc_msg_queue(img, msq);
 		ipc_msg_entry__free_unpacked(msq, NULL);
 
 		if (ret < 0) {
@@ -768,13 +772,15 @@ static int prepare_ipc_msg(int pid)
 			goto err;
 		}
 	}
-	return close_safe(&fd);
+
+	close_image(img);
+	return 0;
 err:
-	close_safe(&fd);
+	close_image(img);
 	return ret;
 }
 
-static int prepare_ipc_shm_pages(int fd, const IpcShmEntry *shm)
+static int prepare_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
 {
 	int ret;
 	void *data;
@@ -784,7 +790,7 @@ static int prepare_ipc_shm_pages(int fd, const IpcShmEntry *shm)
 		pr_perror("Failed to attach IPC shared memory");
 		return -errno;
 	}
-	ret = read_img_buf(fd, data, round_up(shm->size, sizeof(u32)));
+	ret = read_img_buf(img, data, round_up(shm->size, sizeof(u32)));
 	if (ret < 0) {
 		pr_err("Failed to read IPC shared memory data\n");
 		return ret;
@@ -796,7 +802,7 @@ static int prepare_ipc_shm_pages(int fd, const IpcShmEntry *shm)
 	return 0;
 }
 
-static int prepare_ipc_shm_seg(int fd, const IpcShmEntry *shm)
+static int prepare_ipc_shm_seg(struct cr_img *img, const IpcShmEntry *shm)
 {
 	int ret, id;
 	struct sysctl_req req[] = {
@@ -839,7 +845,7 @@ static int prepare_ipc_shm_seg(int fd, const IpcShmEntry *shm)
 		return -EFAULT;
 	}
 
-	ret = prepare_ipc_shm_pages(fd, shm);
+	ret = prepare_ipc_shm_pages(img, shm);
 	if (ret < 0) {
 		pr_err("Failed to update shm pages\n");
 		return ret;
@@ -849,17 +855,18 @@ static int prepare_ipc_shm_seg(int fd, const IpcShmEntry *shm)
 
 static int prepare_ipc_shm(int pid)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 
 	pr_info("Restoring IPC shared memory\n");
-	fd = open_image(CR_FD_IPCNS_SHM, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_IPCNS_SHM, O_RSTR, pid);
+	if (!img)
 		return -1;
 
 	while (1) {
 		IpcShmEntry *shm;
 
-		ret = pb_read_one_eof(fd, &shm, PB_IPC_SHM);
+		ret = pb_read_one_eof(img, &shm, PB_IPC_SHM);
 		if (ret < 0) {
 			pr_err("Failed to read IPC shared memory segment\n");
 			ret = -EIO;
@@ -870,7 +877,7 @@ static int prepare_ipc_shm(int pid)
 
 		pr_info_ipc_shm(shm);
 
-		ret = prepare_ipc_shm_seg(fd, shm);
+		ret = prepare_ipc_shm_seg(img, shm);
 		ipc_shm_entry__free_unpacked(shm, NULL);
 
 		if (ret < 0) {
@@ -878,24 +885,27 @@ static int prepare_ipc_shm(int pid)
 			goto err;
 		}
 	}
-	return close_safe(&fd);
+
+	close_image(img);
+	return 0;
 err:
-	close_safe(&fd);
+	close_image(img);
 	return ret;
 }
 
 static int prepare_ipc_var(int pid)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	IpcVarEntry *var;
 
 	pr_info("Restoring IPC variables\n");
-	fd = open_image(CR_FD_IPC_VAR, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_IPC_VAR, O_RSTR, pid);
+	if (!img)
 		return -1;
 
-	ret = pb_read_one(fd, &var, PB_IPC_VAR);
-	close_safe(&fd);
+	ret = pb_read_one(img, &var, PB_IPC_VAR);
+	close_image(img);
 	if (ret <= 0) {
 		pr_err("Failed to read IPC namespace variables\n");
 		return -EFAULT;
diff --git a/irmap.c b/irmap.c
index 388e473..ab8247e 100644
--- a/irmap.c
+++ b/irmap.c
@@ -298,11 +298,12 @@ int irmap_queue_cache(unsigned int dev, unsigned long ino,
 
 int irmap_predump_run(void)
 {
-	int ret = 0, fd;
+	int ret = 0;
+	struct cr_img *img;
 	struct irmap_predump *ip;
 
-	fd = open_image_at(AT_FDCWD, CR_FD_IRMAP_CACHE, O_DUMP);
-	if (fd < 0)
+	img = open_image_at(AT_FDCWD, CR_FD_IRMAP_CACHE, O_DUMP);
+	if (!img)
 		return -1;
 
 	pr_info("Running irmap pre-dump\n");
@@ -323,13 +324,13 @@ int irmap_predump_run(void)
 			ic.inode = ip->ino;
 			ic.path = ip->fh.path;
 
-			ret = pb_write_one(fd, &ic, PB_IRMAP_CACHE);
+			ret = pb_write_one(img, &ic, PB_IRMAP_CACHE);
 			if (ret)
 				break;
 		}
 	}
 
-	close(fd);
+	close_image(img);
 	return ret;
 }
 
@@ -366,17 +367,17 @@ static int irmap_cache_one(IrmapCacheEntry *ie)
 	return 0;
 }
 
-static int open_irmap_cache(int *fd)
+static int open_irmap_cache(struct cr_img **img)
 {
 	int dir = AT_FDCWD;
 
 	pr_info("Searching irmap cache in work dir\n");
 in:
-	*fd = open_image_at(dir, CR_FD_IRMAP_CACHE, O_RSTR | O_OPT);
+	*img = open_image_at(dir, CR_FD_IRMAP_CACHE, O_RSTR | O_OPT);
 	if (dir != AT_FDCWD)
 		close(dir);
 
-	if (*fd >= 0) {
+	if (*img) {
 		pr_info("... done\n");
 		return 1;
 	}
@@ -388,7 +389,7 @@ in:
 			goto in;
 	}
 
-	if (*fd != -ENOENT)
+	if (errno != ENOENT)
 		return -1;
 
 	pr_info("No irmap cache\n");
@@ -397,9 +398,10 @@ in:
 
 int irmap_load_cache(void)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 
-	ret = open_irmap_cache(&fd);
+	ret = open_irmap_cache(&img);
 	if (ret <= 0)
 		return ret;
 
@@ -407,7 +409,7 @@ int irmap_load_cache(void)
 	while (1) {
 		IrmapCacheEntry *ic;
 
-		ret = pb_read_one_eof(fd, &ic, PB_IRMAP_CACHE);
+		ret = pb_read_one_eof(img, &ic, PB_IRMAP_CACHE);
 		if (ret <= 0)
 			break;
 
@@ -418,6 +420,6 @@ int irmap_load_cache(void)
 		irmap_cache_entry__free_unpacked(ic, NULL);
 	}
 
-	close(fd);
+	close_image(img);
 	return ret;
 }
diff --git a/mem.c b/mem.c
index 918437f..e1d570a 100644
--- a/mem.c
+++ b/mem.c
@@ -384,18 +384,20 @@ static inline int collect_filemap(struct vma_area *vma)
 int prepare_mm_pid(struct pstree_item *i)
 {
 	pid_t pid = i->pid.virt;
-	int fd, ret = -1, vn = 0;
+	int ret = -1, vn = 0;
+	struct cr_img *img;
 	struct rst_info *ri = i->rst;
 
-	fd = open_image(CR_FD_MM, O_RSTR | O_OPT, pid);
-	if (fd < 0) {
+	img = open_image(CR_FD_MM, O_RSTR | O_OPT, pid);
+	if (!img) {
 		if (errno == ENOENT)
 			return 0;
 		return -1;
 	}
 
-	ret = pb_read_one(fd, &ri->mm, PB_MM);
-	close(fd);
+	ret = pb_read_one(img, &ri->mm, PB_MM);
+	close_image(img);
+
 	if (ret < 0)
 		return -1;
 
@@ -403,18 +405,18 @@ int prepare_mm_pid(struct pstree_item *i)
 		return -1;
 
 	pr_debug("Found %zd VMAs in image\n", ri->mm->n_vmas);
-	fd = -1;
+	img = NULL;
 	if (ri->mm->n_vmas == 0) {
 		/*
 		 * Old image. Read VMAs from vma-.img
 		 */
-		fd = open_image(CR_FD_VMAS, O_RSTR, pid);
-		if (fd < 0)
+		img = open_image(CR_FD_VMAS, O_RSTR, pid);
+		if (!img)
 			return -1;
 	}
 
 
-	while (vn < ri->mm->n_vmas || fd >= 0) {
+	while (vn < ri->mm->n_vmas || img != NULL) {
 		struct vma_area *vma;
 
 		ret = -1;
@@ -424,13 +426,13 @@ int prepare_mm_pid(struct pstree_item *i)
 
 		ret = 0;
 		ri->vmas.nr++;
-		if (fd == -1)
+		if (!img)
 			vma->e = ri->mm->vmas[vn++];
 		else {
-			ret = pb_read_one_eof(fd, &vma->e, PB_VMA);
+			ret = pb_read_one_eof(img, &vma->e, PB_VMA);
 			if (ret <= 0) {
 				xfree(vma);
-				close(fd);
+				close_image(img);
 				break;
 			}
 		}
diff --git a/mount.c b/mount.c
index 8c60693..4da0d6f 100644
--- a/mount.c
+++ b/mount.c
@@ -692,7 +692,8 @@ static int tmpfs_dump(struct mount_info *pm)
 {
 	int ret = -1;
 	char tmpfs_path[PSFDS];
-	int fd = -1, fd_img = -1;
+	int fd = -1;
+	struct cr_img *img;
 
 	fd = open_mountpoint(pm);
 	if (fd < 0)
@@ -703,13 +704,13 @@ static int tmpfs_dump(struct mount_info *pm)
 		goto out;
 	}
 
-	fd_img = open_image(CR_FD_TMPFS_DEV, O_DUMP, pm->s_dev);
-	if (fd_img < 0)
+	img = open_image(CR_FD_TMPFS_DEV, O_DUMP, pm->s_dev);
+	if (!img)
 		goto out;
 
 	sprintf(tmpfs_path, "/proc/self/fd/%d", fd);
 
-	ret = cr_system(-1, fd_img, -1, "tar", (char *[])
+	ret = cr_system(-1, img_raw_fd(img), -1, "tar", (char *[])
 			{ "tar", "--create",
 			"--gzip",
 			"--one-file-system",
@@ -722,8 +723,8 @@ static int tmpfs_dump(struct mount_info *pm)
 	if (ret)
 		pr_err("Can't dump tmpfs content\n");
 
+	close_image(img);
 out:
-	close_safe(&fd_img);
 	close_safe(&fd);
 	return ret;
 }
@@ -731,18 +732,18 @@ out:
 static int tmpfs_restore(struct mount_info *pm)
 {
 	int ret;
-	int fd_img;
+	struct cr_img *img;
 
-	fd_img = open_image(CR_FD_TMPFS_DEV, O_RSTR, pm->s_dev);
-	if (fd_img < 0 && errno == ENOENT)
-		fd_img = open_image(CR_FD_TMPFS_IMG, O_RSTR, pm->mnt_id);
-	if (fd_img < 0)
+	img = open_image(CR_FD_TMPFS_DEV, O_RSTR, pm->s_dev);
+	if (!img && errno == ENOENT)
+		img = open_image(CR_FD_TMPFS_IMG, O_RSTR, pm->mnt_id);
+	if (!img)
 		return -1;
 
-	ret = cr_system(fd_img, -1, -1, "tar",
+	ret = cr_system(img_raw_fd(img), -1, -1, "tar",
 			(char *[]) {"tar", "--extract", "--gzip",
 				"--directory", pm->mountpoint, NULL});
-	close(fd_img);
+	close_image(img);
 
 	if (ret) {
 		pr_err("Can't restore tmpfs content\n");
@@ -906,7 +907,7 @@ uns:
 	return &fstypes[0];
 }
 
-static int dump_one_mountpoint(struct mount_info *pm, int fd)
+static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img)
 {
 	MntEntry me = MNT_ENTRY__INIT;
 
@@ -954,7 +955,7 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd)
 	} else
 		me.root = pm->root;
 
-	if (pb_write_one(fd, &me, PB_MNT))
+	if (pb_write_one(img, &me, PB_MNT))
 		return -1;
 
 	return 0;
@@ -994,21 +995,22 @@ err:
 static int dump_mnt_ns(struct ns_id *ns, struct mount_info *pms)
 {
 	struct mount_info *pm;
-	int img_fd = -1, ret = -1;
+	int ret = -1;
+	struct cr_img *img;
 	int ns_id = ns->id;
 
 	pr_info("Dumping mountpoints\n");
-	img_fd = open_image(CR_FD_MNTS, O_DUMP, ns_id);
-	if (img_fd < 0)
+	img = open_image(CR_FD_MNTS, O_DUMP, ns_id);
+	if (!img)
 		goto err;
 
 	for (pm = pms; pm && pm->nsid == ns; pm = pm->next)
-		if (dump_one_mountpoint(pm, img_fd))
+		if (dump_one_mountpoint(pm, img))
 			goto err_i;
 
 	ret = 0;
 err_i:
-	close(img_fd);
+	close_image(img);
 err:
 	return ret;
 }
@@ -1594,7 +1596,8 @@ static int rst_collect_local_mntns(void)
 static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
 {
 	MntEntry *me = NULL;
-	int img, ret, root_len = 1;
+	int ret, root_len = 1;
+	struct cr_img *img;
 	char root[PATH_MAX] = ".";
 
 	img = open_image(CR_FD_MNTS, O_RSTR, nsid->id);
@@ -1693,11 +1696,11 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
 	if (me)
 		mnt_entry__free_unpacked(me, NULL);
 
-	close(img);
+	close_image(img);
 
 	return 0;
 err:
-	close_safe(&img);
+	close_image(img);
 	return -1;
 }
 
diff --git a/namespaces.c b/namespaces.c
index 5d3ff99..8021cff 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -239,7 +239,7 @@ static unsigned int get_ns_id(int pid, struct ns_desc *nd)
 
 int dump_one_ns_file(int lfd, u32 id, const struct fd_parms *p)
 {
-	int fd = img_from_set(glob_imgset, CR_FD_NS_FILES);
+	struct cr_img *img = img_from_set(glob_imgset, CR_FD_NS_FILES);
 	NsFileEntry nfe = NS_FILE_ENTRY__INIT;
 	struct fd_link *link = p->link;
 	unsigned int nsid;
@@ -255,7 +255,7 @@ int dump_one_ns_file(int lfd, u32 id, const struct fd_parms *p)
 	nfe.ns_cflag	= link->ns_d->cflag;
 	nfe.flags	= p->flags;
 
-	return pb_write_one(fd, &nfe, PB_NS_FILE);
+	return pb_write_one(img, &nfe, PB_NS_FILE);
 }
 
 const struct fdtype_ops nsfile_dump_ops = {
@@ -557,16 +557,17 @@ int prepare_namespace(struct pstree_item *item, unsigned long clone_flags)
 int try_show_namespaces(int ns_pid)
 {
 	struct cr_imgset *imgset;
-	int i, fd, ret;
+	int i, ret;
+	struct cr_img *img;
 	TaskKobjIdsEntry *ids;
 
 	pr_msg("Namespaces for %d:\n", ns_pid);
 
-	fd = open_image(CR_FD_IDS, O_RSTR, ns_pid);
-	if (fd < 0)
+	img = open_image(CR_FD_IDS, O_RSTR, ns_pid);
+	if (!img)
 		return -1;
-	ret = pb_read_one(fd, &ids, PB_IDS);
-	close(fd);
+	ret = pb_read_one(img, &ids, PB_IDS);
+	close_image(img);
 	if (ret < 0)
 		return -1;
 
@@ -574,13 +575,11 @@ int try_show_namespaces(int ns_pid)
 	if (imgset) {
 		pr_msg("-------------------NETNS---------------------\n");
 		for (i = _CR_FD_NETNS_FROM + 1; i < _CR_FD_NETNS_TO; i++) {
-			int fd;
-
-			fd = img_from_set(imgset, i);
-			if (fd == -1)
+			img = img_from_set(imgset, i);
+			if (!img)
 				continue;
 
-			cr_parse_fd(fd, imgset_template[i].magic);
+			cr_parse_fd(img, imgset_template[i].magic);
 		}
 		close_cr_imgset(&imgset);
 	}
@@ -589,27 +588,27 @@ int try_show_namespaces(int ns_pid)
 	if (imgset) {
 		pr_msg("-------------------IPCNS---------------------\n");
 		for (i = _CR_FD_IPCNS_FROM + 1; i < _CR_FD_IPCNS_TO; i++) {
-			fd = img_from_set(imgset, i);
-			if (fd == -1)
+			img = img_from_set(imgset, i);
+			if (!img)
 				continue;
 
-			cr_parse_fd(fd, imgset_template[i].magic);
+			cr_parse_fd(img, imgset_template[i].magic);
 		}
 		close_cr_imgset(&imgset);
 	}
 
-	fd = open_image(CR_FD_UTSNS, O_SHOW, ids->uts_ns_id);
-	if (fd >= 0) {
+	img = open_image(CR_FD_UTSNS, O_SHOW, ids->uts_ns_id);
+	if (img) {
 		pr_msg("-------------------UTSNS---------------------\n");
-		cr_parse_fd(fd, imgset_template[CR_FD_UTSNS].magic);
-		close(fd);
+		cr_parse_fd(img, imgset_template[CR_FD_UTSNS].magic);
+		close_image(img);
 	}
 
-	fd = open_image(CR_FD_MNTS, O_SHOW, ids->mnt_ns_id);
-	if (fd > 0) {
+	img = open_image(CR_FD_MNTS, O_SHOW, ids->mnt_ns_id);
+	if (img) {
 		pr_msg("-------------------MNTNS---------------------\n");
-		cr_parse_fd(fd, imgset_template[CR_FD_MNTS].magic);
-		close(fd);
+		cr_parse_fd(img, imgset_template[CR_FD_MNTS].magic);
+		close_image(img);
 	}
 
 	pr_msg("---[ end of %d namespaces ]---\n", ns_pid);
diff --git a/net.c b/net.c
index d0010d8..fdfd40b 100644
--- a/net.c
+++ b/net.c
@@ -369,22 +369,23 @@ static int restore_link(NetDeviceEntry *nde, int nlsk)
 
 static int restore_links(int pid)
 {
-	int fd, nlsk, ret;
+	int nlsk, ret;
+	struct cr_img *img;
 	NetDeviceEntry *nde;
 
-	fd = open_image(CR_FD_NETDEV, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_NETDEV, O_RSTR, pid);
+	if (!img)
 		return -1;
 
 	nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
 	if (nlsk < 0) {
 		pr_perror("Can't create nlk socket");
-		close_safe(&fd);
+		close_image(img);
 		return -1;
 	}
 
 	while (1) {
-		ret = pb_read_one_eof(fd, &nde, PB_NETDEV);
+		ret = pb_read_one_eof(img, &nde, PB_NETDEV);
 		if (ret <= 0)
 			break;
 
@@ -395,7 +396,7 @@ static int restore_links(int pid)
 	}
 
 	close(nlsk);
-	close(fd);
+	close_image(img);
 	return ret;
 }
 
@@ -438,27 +439,31 @@ static int run_iptables_tool(char *def_cmd, int fdin, int fdout)
 
 static inline int dump_ifaddr(struct cr_imgset *fds)
 {
-	return run_ip_tool("addr", "save", -1, img_from_set(fds, CR_FD_IFADDR));
+	struct cr_img *img = img_from_set(fds, CR_FD_IFADDR);
+	return run_ip_tool("addr", "save", -1, img_raw_fd(img));
 }
 
 static inline int dump_route(struct cr_imgset *fds)
 {
-	return run_ip_tool("route", "save", -1, img_from_set(fds, CR_FD_ROUTE));
+	struct cr_img *img = img_from_set(fds, CR_FD_ROUTE);
+	return run_ip_tool("route", "save", -1, img_raw_fd(img));
 }
 
 static inline int dump_iptables(struct cr_imgset *fds)
 {
-	return run_iptables_tool("iptables-save", -1, img_from_set(fds, CR_FD_IPTABLES));
+	struct cr_img *img = img_from_set(fds, CR_FD_IPTABLES);
+	return run_iptables_tool("iptables-save", -1, img_raw_fd(img));
 }
 
 static int restore_ip_dump(int type, int pid, char *cmd)
 {
-	int fd, ret;
+	int ret = -1;
+	struct cr_img *img;
 
-	ret = fd = open_image(type, O_RSTR, pid);
-	if (fd >= 0) {
-		ret = run_ip_tool(cmd, "restore", fd, -1);
-		close(fd);
+	img = open_image(type, O_RSTR, pid);
+	if (img) {
+		ret = run_ip_tool(cmd, "restore", img_raw_fd(img), -1);
+		close_image(img);
 	}
 
 	return ret;
@@ -476,12 +481,13 @@ static inline int restore_route(int pid)
 
 static inline int restore_iptables(int pid)
 {
-	int ret, fd;
+	int ret = -1;
+	struct cr_img *img;
 
-	ret = fd = open_image(CR_FD_IPTABLES, O_RSTR, pid);
-	if (fd >= 0) {
-		ret = run_iptables_tool("iptables-restore", fd, -1);
-		close(fd);
+	img = open_image(CR_FD_IPTABLES, O_RSTR, pid);
+	if (img) {
+		ret = run_iptables_tool("iptables-restore", img_raw_fd(img), -1);
+		close_image(img);
 	}
 
 	return ret;
diff --git a/page-read.c b/page-read.c
index 3cb43de..f67bdfe 100644
--- a/page-read.c
+++ b/page-read.c
@@ -20,7 +20,7 @@ static int get_page_vaddr(struct page_read *pr, struct iovec *iov)
 	int ret;
 	u64 img_va;
 
-	ret = read_img_eof(pr->fd_pg, &img_va);
+	ret = read_img_eof(pr->pmi, &img_va);
 	if (ret <= 0)
 		return ret;
 
@@ -34,7 +34,7 @@ static int read_page(struct page_read *pr, unsigned long vaddr, void *buf)
 {
 	int ret;
 
-	ret = read(pr->fd_pg, buf, PAGE_SIZE);
+	ret = read(img_raw_fd(pr->pmi), buf, PAGE_SIZE);
 	if (ret != PAGE_SIZE) {
 		pr_err("Can't read mapping page %d\n", ret);
 		return -1;
@@ -60,7 +60,7 @@ static int get_pagemap(struct page_read *pr, struct iovec *iov)
 	int ret;
 	PagemapEntry *pe;
 
-	ret = pb_read_one_eof(pr->fd, &pe, PB_PAGEMAP);
+	ret = pb_read_one_eof(pr->pmi, &pe, PB_PAGEMAP);
 	if (ret <= 0)
 		return ret;
 
@@ -91,7 +91,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
 
 	pr_debug("\tpr%u Skip %lx bytes from page-dump\n", pr->id, len);
 	if (!pr->pe->in_parent)
-		lseek(pr->fd_pg, len, SEEK_CUR);
+		lseek(img_raw_fd(pr->pi), len, SEEK_CUR);
 	pr->cvaddr += len;
 }
 
@@ -145,10 +145,11 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu
 		if (ret == -1)
 			return ret;
 	} else {
-		off_t current_vaddr = lseek(pr->fd_pg, 0, SEEK_CUR);
+		int fd = img_raw_fd(pr->pi);
+		off_t current_vaddr = lseek(fd, 0, SEEK_CUR);
 		pr_debug("\tpr%u Read page %lx from self %lx/%"PRIx64"\n", pr->id,
 				vaddr, pr->cvaddr, current_vaddr);
-		ret = read(pr->fd_pg, buf, PAGE_SIZE);
+		ret = read(fd, buf, PAGE_SIZE);
 		if (ret != PAGE_SIZE) {
 			pr_perror("Can't read mapping page %d", ret);
 			return -1;
@@ -184,8 +185,9 @@ static void close_page_read(struct page_read *pr)
 		xfree(pr->parent);
 	}
 
-	close(pr->fd_pg);
-	close(pr->fd);
+	close_image(pr->pmi);
+	if (pr->pi)
+		close_image(pr->pi);
 }
 
 static int try_open_parent(int dfd, int pid, struct page_read *pr, int flags)
@@ -227,25 +229,26 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int flags, bool sh
 	pr->bunch.iov_len = 0;
 	pr->bunch.iov_base = NULL;
 
-	pr->fd = open_image_at(dfd, shmem ? CR_FD_SHMEM_PAGEMAP : CR_FD_PAGEMAP, O_RSTR, (long)pid);
-	if (pr->fd < 0) {
-		pr->fd_pg = open_image_at(dfd, shmem ? CR_FD_SHM_PAGES_OLD : CR_FD_PAGES_OLD, flags, pid);
-		if (pr->fd_pg < 0)
+	pr->pmi = open_image_at(dfd, shmem ? CR_FD_SHMEM_PAGEMAP : CR_FD_PAGEMAP, O_RSTR, (long)pid);
+	if (!pr->pmi) {
+		pr->pmi = open_image_at(dfd, shmem ? CR_FD_SHM_PAGES_OLD : CR_FD_PAGES_OLD, flags, pid);
+		if (!pr->pmi)
 			return -1;
 
 		pr->get_pagemap = get_page_vaddr;
 		pr->put_pagemap = NULL;
 		pr->read_page = read_page;
+		pr->pi = NULL;
 	} else {
 		static unsigned ids = 1;
 
 		if (!shmem && try_open_parent(dfd, pid, pr, flags)) {
-			close(pr->fd);
+			close_image(pr->pmi);
 			return -1;
 		}
 
-		pr->fd_pg = open_pages_image_at(dfd, flags, pr->fd);
-		if (pr->fd_pg < 0) {
+		pr->pi = open_pages_image_at(dfd, flags, pr->pmi);
+		if (!pr->pi) {
 			close_page_read(pr);
 			return -1;
 		}
diff --git a/page-xfer.c b/page-xfer.c
index 5bd21bb..41ef1c5 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -431,7 +431,7 @@ static int write_pagemap_to_server(struct page_xfer *xfer,
 	pi.dst_id = xfer->dst_id;
 	iovec2psi(iov, &pi);
 
-	if (write(xfer->fd, &pi, sizeof(pi)) != sizeof(pi)) {
+	if (write(xfer->sk, &pi, sizeof(pi)) != sizeof(pi)) {
 		pr_perror("Can't write pagemap to server");
 		return -1;
 	}
@@ -444,7 +444,7 @@ static int write_pages_to_server(struct page_xfer *xfer,
 {
 	pr_debug("Splicing %lu bytes / %lu pages into socket\n", len, len / PAGE_SIZE);
 
-	if (splice(p, NULL, xfer->fd, NULL, len, SPLICE_F_MOVE) != len) {
+	if (splice(p, NULL, xfer->sk, NULL, len, SPLICE_F_MOVE) != len) {
 		pr_perror("Can't write pages to socket");
 		return -1;
 	}
@@ -460,7 +460,7 @@ static int write_hole_to_server(struct page_xfer *xfer, struct iovec *iov)
 	pi.dst_id = xfer->dst_id;
 	iovec2psi(iov, &pi);
 
-	if (write(xfer->fd, &pi, sizeof(pi)) != sizeof(pi)) {
+	if (write(xfer->sk, &pi, sizeof(pi)) != sizeof(pi)) {
 		pr_perror("Can't write pagehole to server");
 		return -1;
 	}
@@ -470,14 +470,14 @@ static int write_hole_to_server(struct page_xfer *xfer, struct iovec *iov)
 
 static void close_server_xfer(struct page_xfer *xfer)
 {
-	xfer->fd = -1;
+	xfer->sk = -1;
 }
 
 static int open_page_server_xfer(struct page_xfer *xfer, int fd_type, long id)
 {
 	struct page_server_iov pi;
 
-	xfer->fd = page_server_sk;
+	xfer->sk = page_server_sk;
 	xfer->write_pagemap = write_pagemap_to_server;
 	xfer->write_pages = write_pages_to_server;
 	xfer->write_hole = write_hole_to_server;
@@ -489,7 +489,7 @@ static int open_page_server_xfer(struct page_xfer *xfer, int fd_type, long id)
 	pi.vaddr = 0;
 	pi.nr_pages = 0;
 
-	if (write(xfer->fd, &pi, sizeof(pi)) != sizeof(pi)) {
+	if (write(xfer->sk, &pi, sizeof(pi)) != sizeof(pi)) {
 		pr_perror("Can't write to page server");
 		return -1;
 	}
@@ -511,14 +511,15 @@ static int write_pagemap_loc(struct page_xfer *xfer,
 			return ret;
 		}
 	}
-	return pb_write_one(xfer->fd, &pe, PB_PAGEMAP);
+	return pb_write_one(xfer->pmi, &pe, PB_PAGEMAP);
 }
 
 static int write_pages_loc(struct page_xfer *xfer,
 		int p, unsigned long len)
 {
 	ssize_t ret;
-	ret = splice(p, NULL, xfer->fd_pg, NULL, len, SPLICE_F_MOVE);
+
+	ret = splice(p, NULL, img_raw_fd(xfer->pi), NULL, len, SPLICE_F_MOVE);
 	if (ret == -1) {
 		pr_perror("Unable to spice data");
 		return -1;
@@ -592,7 +593,7 @@ static int write_pagehole_loc(struct page_xfer *xfer, struct iovec *iov)
 	pe.has_in_parent = true;
 	pe.in_parent = true;
 
-	if (pb_write_one(xfer->fd, &pe, PB_PAGEMAP) < 0)
+	if (pb_write_one(xfer->pmi, &pe, PB_PAGEMAP) < 0)
 		return -1;
 
 	return 0;
@@ -605,8 +606,8 @@ static void close_page_xfer(struct page_xfer *xfer)
 		xfree(xfer->parent);
 		xfer->parent = NULL;
 	}
-	close(xfer->fd_pg);
-	close(xfer->fd);
+	close_image(xfer->pi);
+	close_image(xfer->pmi);
 }
 
 int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
@@ -667,13 +668,13 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
 
 static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, long id)
 {
-	xfer->fd = open_image(fd_type, O_DUMP, id);
-	if (xfer->fd < 0)
+	xfer->pmi = open_image(fd_type, O_DUMP, id);
+	if (!xfer->pmi)
 		return -1;
 
-	xfer->fd_pg = open_pages_image(O_DUMP, xfer->fd);
-	if (xfer->fd_pg < 0) {
-		close(xfer->fd);
+	xfer->pi = open_pages_image(O_DUMP, xfer->pmi);
+	if (!xfer->pi) {
+		close_image(xfer->pmi);
 		return -1;
 	}
 
diff --git a/parasite-syscall.c b/parasite-syscall.c
index ca4a913..215380a 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -576,7 +576,8 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_imgset *cr_imgset)
 {
 	struct parasite_dump_sa_args *args;
-	int ret, sig, fd;
+	int ret, sig;
+	struct cr_img *img;
 	SaEntry se = SA_ENTRY__INIT;
 
 	args = parasite_args(ctl, struct parasite_dump_sa_args);
@@ -585,7 +586,7 @@ int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_imgset *cr_
 	if (ret < 0)
 		return ret;
 
-	fd = img_from_set(cr_imgset, CR_FD_SIGACT);
+	img = img_from_set(cr_imgset, CR_FD_SIGACT);
 
 	for (sig = 1; sig <= SIGMAX; sig++) {
 		int i = sig - 1;
@@ -598,7 +599,7 @@ int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_imgset *cr_
 		ASSIGN_TYPED(se.restorer, encode_pointer(args->sas[i].rt_sa_restorer));
 		ASSIGN_TYPED(se.mask, args->sas[i].rt_sa_mask.sig[0]);
 
-		if (pb_write_one(fd, &se, PB_SIGACT) < 0)
+		if (pb_write_one(img, &se, PB_SIGACT) < 0)
 			return -1;
 	}
 
diff --git a/pipes.c b/pipes.c
index 51b95da..ddcc5cf 100644
--- a/pipes.c
+++ b/pipes.c
@@ -43,7 +43,7 @@ static void show_saved_pipe_fds(struct pipe_info *pi)
 		pr_info("   `- FD %d pid %d\n", fle->fe->fd, fle->pid);
 }
 
-static int pipe_data_read(int fd, struct pipe_data_rst *r)
+static int pipe_data_read(struct cr_img *img, struct pipe_data_rst *r)
 {
 	unsigned long bytes = r->pde->bytes;
 
@@ -66,16 +66,17 @@ static int pipe_data_read(int fd, struct pipe_data_rst *r)
 		return -1;
 	}
 
-	return read_img_buf(fd, r->data, bytes);
+	return read_img_buf(img, r->data, bytes);
 }
 
 int collect_pipe_data(int img_type, struct pipe_data_rst **hash)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	struct pipe_data_rst *r = NULL;
 
-	fd = open_image(img_type, O_RSTR);
-	if (fd < 0)
+	img = open_image(img_type, O_RSTR);
+	if (!img)
 		return -1;
 
 	while (1) {
@@ -84,11 +85,11 @@ int collect_pipe_data(int img_type, struct pipe_data_rst **hash)
 		if (!r)
 			break;
 
-		ret = pb_read_one_eof(fd, &r->pde, PB_PIPE_DATA);
+		ret = pb_read_one_eof(img, &r->pde, PB_PIPE_DATA);
 		if (ret <= 0)
 			break;
 
-		ret = pipe_data_read(fd, r);
+		ret = pipe_data_read(img, r);
 		if (ret < 0)
 			break;
 
@@ -104,7 +105,7 @@ int collect_pipe_data(int img_type, struct pipe_data_rst **hash)
 		pipe_data_entry__free_unpacked(r->pde, NULL);
 	xfree(r);
 
-	close(fd);
+	close_image(img);
 	return ret;
 }
 
@@ -403,7 +404,7 @@ int collect_pipes(void)
 
 int dump_one_pipe_data(struct pipe_data_dump *pd, int lfd, const struct fd_parms *p)
 {
-	int img;
+	struct cr_img *img;
 	int pipe_size, i, bytes;
 	int steal_pipe[2];
 	int ret = -1;
@@ -460,7 +461,7 @@ int dump_one_pipe_data(struct pipe_data_dump *pd, int lfd, const struct fd_parms
 	if (bytes) {
 		int wrote;
 
-		wrote = splice(steal_pipe[0], NULL, img, NULL, bytes, 0);
+		wrote = splice(steal_pipe[0], NULL, img_raw_fd(img), NULL, bytes, 0);
 		if (wrote < 0) {
 			pr_perror("Can't push pipe data");
 			goto err_close;
diff --git a/protobuf.c b/protobuf.c
index c3ffcca..0bd04bc 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -460,14 +460,14 @@ static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl)
 	}
 }
 
-static inline void pb_no_payload(int fd, void *obj) { }
+static inline void pb_no_payload(struct cr_img *i, void *obj) { }
 
-void do_pb_show_plain(int fd, int type, int single_entry,
-		void (*payload_hadler)(int fd, void *obj),
+void do_pb_show_plain(struct cr_img *img, int type, int single_entry,
+		void (*payload_hadler)(struct cr_img *, void *obj),
 		const char *pretty_fmt)
 {
 	pb_pr_ctl_t ctl = {NULL, single_entry, pretty_fmt};
-	void (*handle_payload)(int fd, void *obj);
+	void (*handle_payload)(struct cr_img *, void *obj);
 
 	if (!cr_pb_descs[type].pb_desc) {
 		pr_err("Wrong object requested %d\n", type);
@@ -479,12 +479,12 @@ void do_pb_show_plain(int fd, int type, int single_entry,
 	while (1) {
 		void *obj;
 
-		if (pb_read_one_eof(fd, &obj, type) <= 0)
+		if (pb_read_one_eof(img, &obj, type) <= 0)
 			break;
 
 		ctl.arg = (void *)cr_pb_descs[type].pb_desc;
 		pb_show_msg(obj, &ctl);
-		handle_payload(fd, obj);
+		handle_payload(img, obj);
 		cr_pb_descs[type].free(obj, NULL);
 		if (single_entry)
 			break;
@@ -512,8 +512,9 @@ static char *image_name(int fd)
  * Don't forget to free memory granted to unpacked object in calling code if needed
  */
 
-int do_pb_read_one(int fd, void **pobj, int type, bool eof)
+int do_pb_read_one(struct cr_img *img, void **pobj, int type, bool eof)
 {
+	int fd = img->_fd;
 	u8 local[PB_PKOBJ_LOCAL_SIZE];
 	void *buf = (void *)&local;
 	u32 size;
@@ -586,8 +587,9 @@ err:
  *  0 on success
  * -1 on error
  */
-int pb_write_one(int fd, void *obj, int type)
+int pb_write_one(struct cr_img *img, void *obj, int type)
 {
+	int fd = img->_fd;
 	u8 local[PB_PKOBJ_LOCAL_SIZE];
 	void *buf = (void *)&local;
 	u32 size, packed;
@@ -633,15 +635,16 @@ err:
 int collect_image(struct collect_image_info *cinfo)
 {
 	bool optional = !!(cinfo->flags & COLLECT_OPTIONAL);
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	void *(*o_alloc)(size_t size) = malloc;
 	void (*o_free)(void *ptr) = free;
 
 	pr_info("Collecting %d/%d (flags %x)\n",
 			cinfo->fd_type, cinfo->pb_type, cinfo->flags);
 
-	fd = open_image(cinfo->fd_type, O_RSTR | (optional ? O_OPT : 0));
-	if (fd < 0) {
+	img = open_image(cinfo->fd_type, O_RSTR | (optional ? O_OPT : 0));
+	if (!img) {
 		if (optional && errno == ENOENT)
 			return 0;
 		else
@@ -666,7 +669,7 @@ int collect_image(struct collect_image_info *cinfo)
 		} else
 			obj = NULL;
 
-		ret = pb_read_one_eof(fd, &msg, cinfo->pb_type);
+		ret = pb_read_one_eof(img, &msg, cinfo->pb_type);
 		if (ret <= 0) {
 			o_free(obj);
 			break;
@@ -683,7 +686,7 @@ int collect_image(struct collect_image_info *cinfo)
 			cr_pb_descs[cinfo->pb_type].free(msg, NULL);
 	}
 
-	close(fd);
+	close_image(img);
 	pr_debug(" `- ... done\n");
 	return ret;
 }
diff --git a/pstree.c b/pstree.c
index ba9f965..29d59f2 100644
--- a/pstree.c
+++ b/pstree.c
@@ -205,7 +205,7 @@ int dump_pstree(struct pstree_item *root_item)
 	struct pstree_item *item = root_item;
 	PstreeEntry e = PSTREE_ENTRY__INIT;
 	int ret = -1, i;
-	int pstree_fd;
+	struct cr_img *img;
 
 	pr_info("\n");
 	pr_info("Dumping pstree (pid: %d)\n", root_item->pid.real);
@@ -228,8 +228,8 @@ int dump_pstree(struct pstree_item *root_item)
 		}
 	}
 
-	pstree_fd = open_image(CR_FD_PSTREE, O_DUMP);
-	if (pstree_fd < 0)
+	img = open_image(CR_FD_PSTREE, O_DUMP);
+	if (!img)
 		return -1;
 
 	for_each_pstree_item(item) {
@@ -248,7 +248,7 @@ int dump_pstree(struct pstree_item *root_item)
 		for (i = 0; i < item->nr_threads; i++)
 			e.threads[i] = item->threads[i].virt;
 
-		ret = pb_write_one(pstree_fd, &e, PB_PSTREE);
+		ret = pb_write_one(img, &e, PB_PSTREE);
 		xfree(e.threads);
 
 		if (ret)
@@ -258,7 +258,7 @@ int dump_pstree(struct pstree_item *root_item)
 
 err:
 	pr_info("----------------------------------------\n");
-	close(pstree_fd);
+	close_image(img);
 	return ret;
 }
 
@@ -318,19 +318,20 @@ static int prepare_pstree_for_shell_job(void)
 
 static int read_pstree_image(void)
 {
-	int ret = 0, i, ps_fd;
+	int ret = 0, i;
+	struct cr_img *img;
 	struct pstree_item *pi, *parent = NULL;
 
 	pr_info("Reading image tree\n");
 
-	ps_fd = open_image(CR_FD_PSTREE, O_RSTR);
-	if (ps_fd < 0)
+	img = open_image(CR_FD_PSTREE, O_RSTR);
+	if (!img)
 		return -1;
 
 	while (1) {
 		PstreeEntry *e;
 
-		ret = pb_read_one_eof(ps_fd, &e, PB_PSTREE);
+		ret = pb_read_one_eof(img, &e, PB_PSTREE);
 		if (ret <= 0)
 			break;
 
@@ -404,17 +405,17 @@ static int read_pstree_image(void)
 		pstree_entry__free_unpacked(e, NULL);
 
 		{
-			int fd;
+			struct cr_img *img;
 
-			fd = open_image(CR_FD_IDS, O_RSTR, pi->pid.virt);
-			if (fd < 0) {
+			img = open_image(CR_FD_IDS, O_RSTR, pi->pid.virt);
+			if (!img) {
 				if (errno == ENOENT)
 					continue;
 				goto err;
 			}
-			ret = pb_read_one(fd, &pi->ids, PB_IDS);
-			close(fd);
-		}
+			ret = pb_read_one(img, &pi->ids, PB_IDS);
+			close_image(img);
+			}
 
 		if (ret != 1)
 			goto err;
@@ -425,7 +426,7 @@ static int read_pstree_image(void)
 		}
 	}
 err:
-	close(ps_fd);
+	close_image(img);
 	return ret;
 }
 
diff --git a/shmem.c b/shmem.c
index 1b3d51d..526d9a9 100644
--- a/shmem.c
+++ b/shmem.c
@@ -113,7 +113,7 @@ static int shmem_wait_and_open(int pid, struct shmem_info *si)
 
 static int restore_shmem_content(void *addr, struct shmem_info *si)
 {
-	int ret = 0;
+	int ret = 0, fd_pg;
 	struct page_read pr;
 	unsigned long off_real;
 
@@ -121,6 +121,7 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
 	if (ret)
 		goto err_unmap;
 
+	fd_pg = img_raw_fd(pr.pi);
 	while (1) {
 		unsigned long vaddr;
 		unsigned nr_pages;
@@ -136,9 +137,9 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
 		if (vaddr + nr_pages * PAGE_SIZE > si->size)
 			break;
 
-		off_real = lseek(pr.fd_pg, 0, SEEK_CUR);
+		off_real = lseek(fd_pg, 0, SEEK_CUR);
 
-		ret = read(pr.fd_pg, addr + vaddr, nr_pages * PAGE_SIZE);
+		ret = read(fd_pg, addr + vaddr, nr_pages * PAGE_SIZE);
 		if (ret != nr_pages * PAGE_SIZE) {
 			ret = -1;
 			break;
diff --git a/sk-queue.c b/sk-queue.c
index c2f8640..6a39c4b 100644
--- a/sk-queue.c
+++ b/sk-queue.c
@@ -36,12 +36,13 @@ static LIST_HEAD(packets_list);
 int read_sk_queues(void)
 {
 	struct sk_packet *pkt;
-	int ret, fd;
+	int ret;
+	struct cr_img *img;
 
 	pr_info("Trying to read socket queues image\n");
 
-	fd = open_image(CR_FD_SK_QUEUES, O_RSTR);
-	if (fd < 0)
+	img = open_image(CR_FD_SK_QUEUES, O_RSTR);
+	if (!img)
 		return -1;
 
 	while (1) {
@@ -51,19 +52,19 @@ int read_sk_queues(void)
 			pr_err("Failed to allocate packet header\n");
 			break;
 		}
-		ret = pb_read_one_eof(fd, &pkt->entry, PB_SK_QUEUES);
+		ret = pb_read_one_eof(img, &pkt->entry, PB_SK_QUEUES);
 		if (ret <= 0)
 			break;
 
-		pkt->img_off = lseek(fd, 0, SEEK_CUR);
+		pkt->img_off = lseek(img_raw_fd(img), 0, SEEK_CUR);
 		/*
 		 * NOTE: packet must be added to the tail. Otherwise sequence
 		 * will be broken.
 		 */
 		list_add_tail(&pkt->list, &packets_list);
-		lseek(fd, pkt->entry->length, SEEK_CUR);
+		lseek(img_raw_fd(img), pkt->entry->length, SEEK_CUR);
 	}
-	close(fd);
+	close_image(img);
 	xfree(pkt);
 
 	return ret;
@@ -178,24 +179,25 @@ err_brk:
 	return ret;
 }
 
-void sk_queue_data_handler(int fd, void *obj)
+void sk_queue_data_handler(struct cr_img *img, void *obj)
 {
 	SkPacketEntry *e = obj;
-	print_image_data(fd, e->length, opts.show_pages_content);
+	print_image_data(img, e->length, opts.show_pages_content);
 }
 
 int restore_sk_queue(int fd, unsigned int peer_id)
 {
 	struct sk_packet *pkt, *tmp;
-	int ret, img_fd;
+	int ret;
+	struct cr_img *img;
 
 	pr_info("Trying to restore recv queue for %u\n", peer_id);
 
 	if (restore_prepare_socket(fd))
 		return -1;
 
-	img_fd = open_image(CR_FD_SK_QUEUES, O_RSTR);
-	if (img_fd < 0)
+	img = open_image(CR_FD_SK_QUEUES, O_RSTR);
+	if (!img)
 		return -1;
 
 	list_for_each_entry_safe(pkt, tmp, &packets_list, list) {
@@ -220,12 +222,12 @@ int restore_sk_queue(int fd, unsigned int peer_id)
 		if (buf ==NULL)
 			goto err;
 
-		if (lseek(img_fd, pkt->img_off, SEEK_SET) == -1) {
+		if (lseek(img_raw_fd(img), pkt->img_off, SEEK_SET) == -1) {
 			pr_perror("lseek() failed");
 			xfree(buf);
 			goto err;
 		}
-		if (read_img_buf(img_fd, buf, entry->length) != 1) {
+		if (read_img_buf(img, buf, entry->length) != 1) {
 			xfree(buf);
 			goto err;
 		}
@@ -246,9 +248,9 @@ int restore_sk_queue(int fd, unsigned int peer_id)
 		xfree(pkt);
 	}
 
-	close(img_fd);
+	close_image(img);
 	return 0;
 err:
-	close_safe(&img_fd);
+	close_image(img);
 	return -1;
 }
diff --git a/sk-tcp.c b/sk-tcp.c
index 29d8618..fcc0a57 100644
--- a/sk-tcp.c
+++ b/sk-tcp.c
@@ -310,7 +310,8 @@ err_sopt:
 
 static int dump_tcp_conn_state(struct inet_sk_desc *sk)
 {
-	int ret, img_fd, aux;
+	int ret, aux;
+	struct cr_img *img;
 	TcpStreamEntry tse = TCP_STREAM_ENTRY__INIT;
 	char *in_buf, *out_buf;
 
@@ -371,29 +372,29 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
 	 * Push the stuff to image
 	 */
 
-	img_fd = open_image(CR_FD_TCP_STREAM, O_DUMP, sk->sd.ino);
-	if (img_fd < 0)
+	img = open_image(CR_FD_TCP_STREAM, O_DUMP, sk->sd.ino);
+	if (!img)
 		goto err_img;
 
-	ret = pb_write_one(img_fd, &tse, PB_TCP_STREAM);
+	ret = pb_write_one(img, &tse, PB_TCP_STREAM);
 	if (ret < 0)
 		goto err_iw;
 
 	if (in_buf) {
-		ret = write_img_buf(img_fd, in_buf, tse.inq_len);
+		ret = write_img_buf(img, in_buf, tse.inq_len);
 		if (ret < 0)
 			goto err_iw;
 	}
 
 	if (out_buf) {
-		ret = write_img_buf(img_fd, out_buf, tse.outq_len);
+		ret = write_img_buf(img, out_buf, tse.outq_len);
 		if (ret < 0)
 			goto err_iw;
 	}
 
 	pr_info("Done\n");
 err_iw:
-	close(img_fd);
+	close_image(img);
 err_img:
 err_opt:
 	xfree(out_buf);
@@ -452,7 +453,7 @@ static int restore_tcp_seqs(int sk, TcpStreamEntry *tse)
 	return 0;
 }
 
-static int __send_tcp_queue(int sk, int queue, u32 len, int imgfd)
+static int __send_tcp_queue(int sk, int queue, u32 len, struct cr_img *img)
 {
 	int ret, err = -1;
 	int off, max;
@@ -462,7 +463,7 @@ static int __send_tcp_queue(int sk, int queue, u32 len, int imgfd)
 	if (!buf)
 		return -1;
 
-	if (read_img_buf(imgfd, buf, len) < 0)
+	if (read_img_buf(img, buf, len) < 0)
 		goto err;
 
 	max = (queue == TCP_SEND_QUEUE) ? tcp_max_wshare : tcp_max_rshare;
@@ -487,7 +488,7 @@ err:
 	return err;
 }
 
-static int send_tcp_queue(int sk, int queue, u32 len, int imgfd)
+static int send_tcp_queue(int sk, int queue, u32 len, struct cr_img *img)
 {
 	pr_debug("\tRestoring TCP %d queue data %u bytes\n", queue, len);
 
@@ -496,10 +497,10 @@ static int send_tcp_queue(int sk, int queue, u32 len, int imgfd)
 		return -1;
 	}
 
-	return __send_tcp_queue(sk, queue, len, imgfd);
+	return __send_tcp_queue(sk, queue, len, img);
 }
 
-static int restore_tcp_queues(int sk, TcpStreamEntry *tse, int fd)
+static int restore_tcp_queues(int sk, TcpStreamEntry *tse, struct cr_img *img)
 {
 	u32 len;
 
@@ -507,7 +508,7 @@ static int restore_tcp_queues(int sk, TcpStreamEntry *tse, int fd)
 		return -1;
 
 	len = tse->inq_len;
-	if (len && send_tcp_queue(sk, TCP_RECV_QUEUE, len, fd))
+	if (len && send_tcp_queue(sk, TCP_RECV_QUEUE, len, img))
 		return -1;
 
 	/*
@@ -518,7 +519,7 @@ static int restore_tcp_queues(int sk, TcpStreamEntry *tse, int fd)
 	 * restored in repair mode.
 	 */
 	len = tse->outq_len - tse->unsq_len;
-	if (len && send_tcp_queue(sk, TCP_SEND_QUEUE, len, fd))
+	if (len && send_tcp_queue(sk, TCP_SEND_QUEUE, len, img))
 		return -1;
 
 	/*
@@ -527,7 +528,7 @@ static int restore_tcp_queues(int sk, TcpStreamEntry *tse, int fd)
 	 */
 	len = tse->unsq_len;
 	tcp_repair_off(sk);
-	if (len && __send_tcp_queue(sk, TCP_SEND_QUEUE, len, fd))
+	if (len && __send_tcp_queue(sk, TCP_SEND_QUEUE, len, img))
 		return -1;
 	if (tcp_repair_on(sk))
 		return -1;
@@ -588,16 +589,17 @@ static int restore_tcp_opts(int sk, TcpStreamEntry *tse)
 
 static int restore_tcp_conn_state(int sk, struct inet_sk_info *ii)
 {
-	int ifd, aux;
+	int aux;
+	struct cr_img *img;
 	TcpStreamEntry *tse;
 
 	pr_info("Restoring TCP connection id %x ino %x\n", ii->ie->id, ii->ie->ino);
 
-	ifd = open_image(CR_FD_TCP_STREAM, O_RSTR, ii->ie->ino);
-	if (ifd < 0)
+	img = open_image(CR_FD_TCP_STREAM, O_RSTR, ii->ie->ino);
+	if (!img)
 		goto err;
 
-	if (pb_read_one(ifd, &tse, PB_TCP_STREAM) < 0)
+	if (pb_read_one(img, &tse, PB_TCP_STREAM) < 0)
 		goto err_c;
 
 	if (restore_tcp_seqs(sk, tse))
@@ -612,7 +614,7 @@ static int restore_tcp_conn_state(int sk, struct inet_sk_info *ii)
 	if (restore_tcp_opts(sk, tse))
 		goto err_c;
 
-	if (restore_tcp_queues(sk, tse, ifd))
+	if (restore_tcp_queues(sk, tse, img))
 		goto err_c;
 
 	if (tse->has_nodelay && tse->nodelay) {
@@ -628,12 +630,12 @@ static int restore_tcp_conn_state(int sk, struct inet_sk_info *ii)
 	}
 
 	tcp_stream_entry__free_unpacked(tse, NULL);
-	close(ifd);
+	close_image(img);
 	return 0;
 
 err_c:
 	tcp_stream_entry__free_unpacked(tse, NULL);
-	close(ifd);
+	close_image(img);
 err:
 	return -1;
 }
@@ -719,13 +721,13 @@ out:
 	return ret;
 }
 
-void show_tcp_stream(int fd, void *obj)
+void show_tcp_stream(struct cr_img *img, void *obj)
 {
 	TcpStreamEntry *e = obj;
 	if (opts.show_pages_content) {
 		pr_msg("In-queue:");
-		print_image_data(fd, e->inq_len, 1);
+		print_image_data(img, e->inq_len, 1);
 		pr_msg("Out-queue:");
-		print_image_data(fd, e->outq_len, 1);
+		print_image_data(img, e->outq_len, 1);
 	}
 }
diff --git a/sockets.c b/sockets.c
index f72ef8b..103774f 100644
--- a/sockets.c
+++ b/sockets.c
@@ -439,7 +439,7 @@ void release_skopts(SkOptsEntry *soe)
 	xfree(soe->so_bound_dev);
 }
 
-int dump_socket(struct fd_parms *p, int lfd, const int fdinfo)
+int dump_socket(struct fd_parms *p, int lfd, struct cr_img *img)
 {
 	int family;
 	const struct fdtype_ops *ops;
@@ -468,7 +468,7 @@ int dump_socket(struct fd_parms *p, int lfd, const int fdinfo)
 		return -1;
 	}
 
-	return do_dump_gen_file(p, lfd, ops, fdinfo);
+	return do_dump_gen_file(p, lfd, ops, img);
 }
 
 static int inet_receive_one(struct nlmsghdr *h, void *arg)
diff --git a/stats.c b/stats.c
index 011c359..2a80bb3 100644
--- a/stats.c
+++ b/stats.c
@@ -105,7 +105,7 @@ void write_stats(int what)
 	DumpStatsEntry ds_entry = DUMP_STATS_ENTRY__INIT;
 	RestoreStatsEntry rs_entry = RESTORE_STATS_ENTRY__INIT;
 	char *name;
-	int fd;
+	struct cr_img *img;
 
 	pr_info("Writing stats\n");
 	if (what == DUMP_STATS) {
@@ -138,10 +138,10 @@ void write_stats(int what)
 	} else
 		return;
 
-	fd = open_image_at(AT_FDCWD, CR_FD_STATS, O_DUMP, name);
-	if (fd >= 0) {
-		pb_write_one(fd, &stats, PB_STATS);
-		close(fd);
+	img = open_image_at(AT_FDCWD, CR_FD_STATS, O_DUMP, name);
+	if (img) {
+		pb_write_one(img, &stats, PB_STATS);
+		close_image(img);
 	}
 }
 
diff --git a/tun.c b/tun.c
index 82cecc4..bec25c2 100644
--- a/tun.c
+++ b/tun.c
@@ -266,7 +266,8 @@ static struct tun_link *get_tun_link_fd(char *name, unsigned flags)
 
 static int dump_tunfile(int lfd, u32 id, const struct fd_parms *p)
 {
-	int ret, img = img_from_set(glob_imgset, CR_FD_TUNFILE);
+	int ret;
+	struct cr_img *img;
 	TunfileEntry tfe = TUNFILE_ENTRY__INIT;
 	struct ifreq ifr;
 
@@ -305,6 +306,7 @@ static int dump_tunfile(int lfd, u32 id, const struct fd_parms *p)
 			return -1;
 	}
 
+	img = img_from_set(glob_imgset, CR_FD_TUNFILE);
 	return pb_write_one(img, &tfe, PB_TUNFILE);
 }
 
diff --git a/uts_ns.c b/uts_ns.c
index b495bbb..b17dde9 100644
--- a/uts_ns.c
+++ b/uts_ns.c
@@ -14,12 +14,13 @@
 
 int dump_uts_ns(int ns_pid, int ns_id)
 {
-	int ret, img_fd;
+	int ret;
+	struct cr_img *img;
 	struct utsname ubuf;
 	UtsnsEntry ue = UTSNS_ENTRY__INIT;
 
-	img_fd = open_image(CR_FD_UTSNS, O_DUMP, ns_id);
-	if (img_fd < 0)
+	img = open_image(CR_FD_UTSNS, O_DUMP, ns_id);
+	if (!img)
 		return -1;
 
 	ret = switch_ns(ns_pid, &uts_ns_desc, NULL);
@@ -35,15 +36,16 @@ int dump_uts_ns(int ns_pid, int ns_id)
 	ue.nodename = ubuf.nodename;
 	ue.domainname = ubuf.domainname;
 
-	ret = pb_write_one(img_fd, &ue, PB_UTSNS);
+	ret = pb_write_one(img, &ue, PB_UTSNS);
 err:
-	close(img_fd);
+	close_image(img);
 	return ret < 0 ? -1 : 0;
 }
 
 int prepare_utsns(int pid)
 {
-	int fd, ret;
+	int ret;
+	struct cr_img *img;
 	UtsnsEntry *ue;
 	struct sysctl_req req[3] = {
 		{ "kernel/hostname" },
@@ -51,11 +53,11 @@ int prepare_utsns(int pid)
 		{ },
 	};
 
-	fd = open_image(CR_FD_UTSNS, O_RSTR, pid);
-	if (fd < 0)
+	img = open_image(CR_FD_UTSNS, O_RSTR, pid);
+	if (!img)
 		return -1;
 
-	ret = pb_read_one(fd, &ue, PB_UTSNS);
+	ret = pb_read_one(img, &ue, PB_UTSNS);
 	if (ret < 0)
 		goto out;
 
@@ -67,7 +69,7 @@ int prepare_utsns(int pid)
 	ret = sysctl_op(req, CTL_WRITE);
 	utsns_entry__free_unpacked(ue, NULL);
 out:
-	close(fd);
+	close_image(img);
 	return ret;
 }
 
-- 
1.8.4.2




More information about the CRIU mailing list