[CRIU] [PATCH 2/2] img: Don't create empty images

Pavel Emelyanov xemul at parallels.com
Tue Mar 10 11:47:27 PDT 2015


Currently on dump we generate too many image files, effectively
all the stuff from the GLOB set is created. The thing is that
sometimes some of created images can be empty (just contain the
magic number at the head). Thos images are useless and just
waste the space.

When applied after the "empty images" set, this introduces the
lazy images -- when we call open_image() the actual file is
only created (and the magic number is written into it) when the
very first object goes into it.

For example for the simplest test we have, then static/env00
one, the created image files are

   core-7290.img
   creds-7290.img
   fdinfo-2.img
   fs-7290.img
   ids-7290.img
   inventory.img
   mm-7290.img
   pagemap-7290.img
   pages-1.img
   pstree.img
   reg-files.img
   sigacts-7290.img

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 image.c         | 52 ++++++++++++++++++++++++++++++++++++++++++++--------
 include/image.h | 17 ++++++++++++++++-
 protobuf.c      |  3 +++
 3 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/image.c b/image.c
index 106c283..33e0d5b 100644
--- a/image.c
+++ b/image.c
@@ -202,28 +202,48 @@ struct cr_imgset *cr_glob_imgset_open(int mode)
 	return cr_imgset_open(-1 /* ignored */, GLOB, mode);
 }
 
+static struct cr_img *do_open_image(struct cr_img *img, int dfd, int type, unsigned long flags, char *path);
+
 struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...)
 {
 	struct cr_img *img;
-	unsigned long oflags = flags;
+	unsigned long oflags;
 	char path[PATH_MAX];
 	va_list args;
-	int ret;
+	bool lazy = false;
 
-	if (dfd == -1)
+	if (dfd == -1) {
 		dfd = get_service_fd(IMG_FD_OFF);
+		lazy = (flags & O_CREAT);
+	}
 
 	img = xmalloc(sizeof(*img));
 	if (!img)
-		goto errn;
+		return NULL;
 
-	oflags |= imgset_template[type].oflags;
-	flags &= ~(O_NOBUF);
+	oflags = flags | imgset_template[type].oflags;
 
 	va_start(args, flags);
 	vsnprintf(path, PATH_MAX, imgset_template[type].fmt, args);
 	va_end(args);
 
+	if (lazy) {
+		img->fd = LAZY_IMG_FD;
+		img->type = type;
+		img->oflags = oflags;
+		img->path = xstrdup(path);
+		return img;
+	}
+
+	return do_open_image(img, dfd, type, oflags, path);
+}
+
+static struct cr_img *do_open_image(struct cr_img *img, int dfd, int type, unsigned long oflags, char *path)
+{
+	int ret, flags;
+
+	flags = oflags & ~(O_NOBUF);
+
 	ret = openat(dfd, path, flags, CR_FD_PERM);
 	if (ret < 0) {
 		if (!(flags & O_CREAT) && (errno == ENOENT)) {
@@ -271,17 +291,33 @@ skip_magic:
 
 err:
 	xfree(img);
-errn:
 	return NULL;
+
 err_close:
 	close_image(img);
 	return NULL;
 }
 
+int open_image_lazy(struct cr_img *img)
+{
+	int dfd;
+	char *path = img->path;
+
+	dfd = get_service_fd(IMG_FD_OFF);
+	if (do_open_image(img, dfd, img->type, img->oflags, path) == NULL)
+		return -1;
+
+	xfree(path);
+	return 0;
+}
+
 void close_image(struct cr_img *img)
 {
-	if (!empty_image(img))
+	if (lazy_image(img))
+		xfree(img->path);
+	else if (!empty_image(img))
 		bclose(&img->_x);
+
 	xfree(img);
 }
 
diff --git a/include/image.h b/include/image.h
index 798e891..ce9f95d 100644
--- a/include/image.h
+++ b/include/image.h
@@ -124,16 +124,30 @@ extern bool ns_per_id;
 #define O_RSTR	(O_RDONLY)
 
 struct cr_img {
-	struct bfd _x;
+	union {
+		struct bfd _x;
+		struct {
+			int fd; /* should be first to coincide with _x.fd */
+			int type;
+			unsigned long oflags;
+			char *path;
+		};
+	};
 };
 
 #define EMPTY_IMG_FD	(-404)
+#define LAZY_IMG_FD	(-505)
 
 static inline bool empty_image(struct cr_img *img)
 {
 	return img && img->_x.fd == EMPTY_IMG_FD;
 }
 
+static inline bool lazy_image(struct cr_img *img)
+{
+	return img->_x.fd == LAZY_IMG_FD;
+}
+
 static inline int img_raw_fd(struct cr_img *img)
 {
 	BUG_ON(bfd_buffered(&img->_x));
@@ -145,6 +159,7 @@ extern void close_image_dir(void);
 
 extern struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...);
 #define open_image(typ, flags, ...) open_image_at(-1, typ, flags, ##__VA_ARGS__)
+extern int open_image_lazy(struct cr_img *img);
 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);
diff --git a/protobuf.c b/protobuf.c
index 4a65579..ae003da 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -603,6 +603,9 @@ int pb_write_one(struct cr_img *img, void *obj, int type)
 		return -1;
 	}
 
+	if (lazy_image(img) && open_image_lazy(img))
+		return -1;
+
 	size = cr_pb_descs[type].getpksize(obj);
 	if (size > (u32)sizeof(local)) {
 		buf = xmalloc(size);
-- 
1.8.4.2




More information about the CRIU mailing list