img: Introduce empty images

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

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

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

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Pavel Emelyanov 2015-03-06 18:02:43 +03:00
parent 45a0cc4234
commit f7f76d6ba6
12 changed files with 82 additions and 104 deletions

View file

@ -1292,12 +1292,8 @@ int prepare_cgroup(void)
CgroupEntry *ce;
img = open_image(CR_FD_CGROUP, O_RSTR);
if (!img) {
if (errno == ENOENT) /* backward compatibility */
return 0;
else
return -1;
}
if (!img)
return -1;
ret = pb_read_one_eof(img, &ce, PB_CGROUP);
close_image(img);

View file

@ -2170,12 +2170,8 @@ static int prepare_posix_timers_from_fd(int pid)
struct restore_posix_timer *t;
img = open_image(CR_FD_POSIX_TIMERS, O_RSTR, pid);
if (!img) {
if (errno == ENOENT) /* backward compatibility */
return 0;
else
return -1;
}
if (!img)
return -1;
while (1) {
PosixTimerEntry *pte;
@ -2420,14 +2416,8 @@ static int prepare_rlimits_from_fd(int pid)
* Old image -- read from the file.
*/
img = open_image(CR_FD_RLIMIT, O_RSTR, pid);
if (!img) {
if (errno == ENOENT) {
pr_info("Skip rlimits for %d\n", pid);
return 0;
}
if (!img)
return -1;
}
while (1) {
RlimitEntry *re;
@ -2512,12 +2502,8 @@ static int open_signal_image(int type, pid_t pid, unsigned int *nr)
struct cr_img *img;
img = open_image(type, O_RSTR, pid);
if (!img) {
if (errno == ENOENT) /* backward compatibility */
return 0;
else
return -1;
}
if (!img)
return -1;
*nr = 0;
while (1) {

View file

@ -342,12 +342,8 @@ static int restore_file_locks_legacy(int pid)
FileLockEntry *fle;
img = open_image(CR_FD_FILE_LOCKS_PID, O_RSTR, pid);
if (!img) {
if (errno == ENOENT)
return 0;
else
return -1;
}
if (!img)
return -1;
while (1) {
ret = pb_read_one_eof(img, &fle, PB_FILE_LOCK);

31
files.c
View file

@ -610,11 +610,8 @@ int prepare_fd_pid(struct pstree_item *item)
if (!fdinfo_per_id) {
img = open_image(CR_FD_FDINFO, O_RSTR, pid);
if (!img) {
if (errno == ENOENT)
return 0;
if (!img)
return -1;
}
} else {
if (item->ids == NULL) /* zombie */
return 0;
@ -1115,19 +1112,16 @@ int prepare_fs_pid(struct pstree_item *item)
struct rst_info *ri = rsti(item);
struct cr_img *img;
FsEntry *fe;
int ret = -1;
img = open_image(CR_FD_FS, O_RSTR, pid);
if (!img) {
if (errno == ENOENT)
goto ok;
else
goto out;
}
if (pb_read_one(img, &fe, PB_FS) < 0)
goto out_i;
if (!img)
goto out;
ret = pb_read_one_eof(img, &fe, PB_FS);
close_image(img);
if (ret <= 0)
goto out;
ri->cwd = collect_special_file(fe->cwd_id);
if (!ri->cwd) {
@ -1144,18 +1138,11 @@ int prepare_fs_pid(struct pstree_item *item)
ri->has_umask = fe->has_umask;
ri->umask = fe->umask;
fs_entry__free_unpacked(fe, NULL);
ok:
return 0;
ret = 0;
out_f:
fs_entry__free_unpacked(fe, NULL);
return -1;
out_i:
close_image(img);
out:
return -1;
return ret;
}
int shared_fdt_prepare(struct pstree_item *item)

12
image.c
View file

@ -226,10 +226,13 @@ struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...)
ret = openat(dfd, path, flags, CR_FD_PERM);
if (ret < 0) {
if (errno == ENOENT)
if (!(flags & O_CREAT) && (errno == ENOENT)) {
pr_info("No %s image\n", path);
else
pr_perror("Unable to open %s", path);
img->_x.fd = EMPTY_IMG_FD;
goto skip_magic;
}
pr_perror("Unable to open %s", path);
goto err;
}
@ -270,7 +273,8 @@ err_close:
void close_image(struct cr_img *img)
{
bclose(&img->_x);
if (!empty_image(img))
bclose(&img->_x);
xfree(img);
}

View file

@ -127,6 +127,13 @@ struct cr_img {
struct bfd _x;
};
#define EMPTY_IMG_FD (-404)
static inline bool empty_image(struct cr_img *img)
{
return img && img->_x.fd == EMPTY_IMG_FD;
}
static inline int img_raw_fd(struct cr_img *img)
{
BUG_ON(bfd_buffered(&img->_x));

30
irmap.c
View file

@ -403,23 +403,27 @@ in:
if (dir != AT_FDCWD)
close(dir);
if (*img) {
pr_info("... done\n");
return 1;
if (empty_image(*img)) {
close_image(*img);
if (dir == AT_FDCWD) {
pr_info("Searching irmap cache in parent\n");
dir = openat(get_service_fd(IMG_FD_OFF),
CR_PARENT_LINK, O_RDONLY);
if (dir >= 0)
goto in;
if (errno != ENOENT)
return -1;
}
pr_info("No irmap cache\n");
return 0;
}
if (errno == ENOENT && dir == AT_FDCWD) {
pr_info("Searching irmap cache in parent\n");
dir = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY);
if (dir >= 0)
goto in;
}
if (errno != ENOENT)
if (!*img)
return -1;
pr_info("No irmap cache\n");
return 0;
pr_info("... done\n");
return 1;
}
int irmap_load_cache(void)

12
mem.c
View file

@ -396,17 +396,13 @@ int prepare_mm_pid(struct pstree_item *i)
struct rst_info *ri = rsti(i);
img = open_image(CR_FD_MM, O_RSTR, pid);
if (!img) {
if (errno == ENOENT)
return 0;
if (!img)
return -1;
}
ret = pb_read_one(img, &ri->mm, PB_MM);
ret = pb_read_one_eof(img, &ri->mm, PB_MM);
close_image(img);
if (ret < 0)
return -1;
if (ret <= 0)
return ret;
if (collect_special_file(ri->mm->exe_file_id) == NULL)
return -1;

View file

@ -937,9 +937,11 @@ static int tmpfs_restore(struct mount_info *pm)
struct cr_img *img;
img = open_image(CR_FD_TMPFS_DEV, O_RSTR, pm->s_dev);
if (!img && errno == ENOENT)
if (empty_image(img)) {
close_image(img);
img = open_image(CR_FD_TMPFS_IMG, O_RSTR, pm->mnt_id);
if (!img)
}
if (!img || empty_image(img))
return -1;
ret = cr_system(img_raw_fd(img), -1, -1, "tar",

View file

@ -256,11 +256,12 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
pr->bunch.iov_base = NULL;
pr->pmi = open_image_at(dfd, i_typ, O_RSTR, (long)pid);
if (!pr->pmi) {
if (errno == ENOENT)
goto open_old;
else
return -1;
if (!pr->pmi)
return -1;
if (empty_image(pr->pmi)) {
close_image(pr->pmi);
goto open_old;
}
if ((i_typ != CR_FD_SHMEM_PAGEMAP) && try_open_parent(dfd, pid, pr, pr_flags)) {
@ -287,11 +288,12 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
open_old:
pr->pmi = open_image_at(dfd, i_typ_o, flags, pid);
if (!pr->pmi) {
if (errno == ENOENT)
return 0;
else
return -1;
if (!pr->pmi)
return -1;
if (empty_image(pr->pmi)) {
close_image(pr->pmi);
return 0;
}
pr->get_pagemap = get_page_vaddr;

View file

@ -528,7 +528,10 @@ int do_pb_read_one(struct cr_img *img, void **pobj, int type, bool eof)
*pobj = NULL;
ret = bread(&img->_x, &size, sizeof(size));
if (unlikely(empty_image(img)))
ret = 0;
else
ret = bread(&img->_x, &size, sizeof(size));
if (ret == 0) {
if (eof) {
return 0;
@ -642,12 +645,8 @@ int collect_image(struct collect_image_info *cinfo)
cinfo->fd_type, cinfo->pb_type, cinfo->flags);
img = open_image(cinfo->fd_type, O_RSTR);
if (!img) {
if (errno == ENOENT)
return 0;
else
return -1;
}
if (!img)
return -1;
cinfo->flags |= COLLECT_HAPPENED;
if (cinfo->flags & COLLECT_SHARED) {

View file

@ -427,16 +427,15 @@ static int read_pstree_image(void)
struct cr_img *img;
img = open_image(CR_FD_IDS, O_RSTR, pi->pid.virt);
if (!img) {
if (errno == ENOENT)
continue;
if (!img)
goto err;
}
ret = pb_read_one(img, &pi->ids, PB_IDS);
ret = pb_read_one_eof(img, &pi->ids, PB_IDS);
close_image(img);
}
}
if (ret != 1)
if (ret == 0)
continue;
if (ret < 0)
goto err;
if (pi->ids->has_mnt_ns_id) {