[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