Commit f7f76d6b authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 45a0cc42
......@@ -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);
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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)
......
......@@ -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);
}
......
......@@ -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));
......
......@@ -403,23 +403,27 @@ in:
if (dir != AT_FDCWD)
close(dir);
if (*img) {
pr_info("... done\n");
return 1;
}
if (empty_image(*img)) {
close_image(*img);
if (dir == AT_FDCWD) {
pr_info("Searching irmap cache in parent\n");
dir = openat(get_service_fd(IMG_FD_OFF),
CR_PARENT_LINK, O_RDONLY);
if (dir >= 0)
goto in;
if (errno != ENOENT)
return -1;
}
if (errno == ENOENT && dir == AT_FDCWD) {
pr_info("Searching irmap cache in parent\n");
dir = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY);
if (dir >= 0)
goto in;
pr_info("No irmap cache\n");
return 0;
}
if (errno != ENOENT)
if (!*img)
return -1;
pr_info("No irmap cache\n");
return 0;
pr_info("... done\n");
return 1;
}
int irmap_load_cache(void)
......
......@@ -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;
......
......@@ -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",
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment