mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
ghost: Remove ghost files if restore fails
Issue #18. When restore fails ghost files remain there. And to remove them we have to know their list, paths to original files (to construct the ghost name) and the namespace ghost lives in. For the latter we keep the restore task namespace at hands till the final stage and setns into it to kill ghosts. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
a7c9f3011d
commit
efa7dcf7c2
3 changed files with 96 additions and 2 deletions
17
cr-restore.c
17
cr-restore.c
|
|
@ -1732,7 +1732,7 @@ static void ignore_kids(void)
|
|||
static int restore_root_task(struct pstree_item *init)
|
||||
{
|
||||
enum trace_flags flag = TRACE_ALL;
|
||||
int ret, fd;
|
||||
int ret, fd, mnt_ns_fd = -1;
|
||||
|
||||
fd = open("/proc", O_DIRECTORY | O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
|
@ -1808,6 +1808,14 @@ static int restore_root_task(struct pstree_item *init)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (root_ns_mask & CLONE_NEWNS) {
|
||||
mnt_ns_fd = open_proc(init->pid.real, "ns/mnt");
|
||||
if (mnt_ns_fd < 0) {
|
||||
pr_perror("Can't open init's mntns fd");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = run_scripts(ACT_SETUP_NS);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -1837,6 +1845,12 @@ static int restore_root_task(struct pstree_item *init)
|
|||
*/
|
||||
task_entries->nr_threads -= atomic_read(&task_entries->nr_zombies);
|
||||
|
||||
if (mnt_ns_fd >= 0)
|
||||
/*
|
||||
* Don't try_clean_remaps here, since restore went OK
|
||||
* and all ghosts were removed by the openers.
|
||||
*/
|
||||
close(mnt_ns_fd);
|
||||
cleanup_mnt_ns();
|
||||
|
||||
ret = stop_usernsd();
|
||||
|
|
@ -1923,6 +1937,7 @@ out_kill:
|
|||
|
||||
out:
|
||||
fini_cgroup();
|
||||
try_clean_remaps(mnt_ns_fd);
|
||||
cleanup_mnt_ns();
|
||||
stop_usernsd();
|
||||
__restore_switch_stage(CR_STATE_FAIL);
|
||||
|
|
|
|||
80
files-reg.c
80
files-reg.c
|
|
@ -157,6 +157,12 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline void ghost_path(char *path, int plen,
|
||||
struct reg_file_info *rfi, RemapFilePathEntry *rfe)
|
||||
{
|
||||
snprintf(path, plen, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
|
||||
}
|
||||
|
||||
static int open_remap_ghost(struct reg_file_info *rfi,
|
||||
RemapFilePathEntry *rfe)
|
||||
{
|
||||
|
|
@ -203,7 +209,7 @@ static int open_remap_ghost(struct reg_file_info *rfi,
|
|||
if (S_ISDIR(gfe->mode))
|
||||
strncpy(gf->remap.rpath, rfi->path, PATH_MAX);
|
||||
else
|
||||
snprintf(gf->remap.rpath, PATH_MAX, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
|
||||
ghost_path(gf->remap.rpath, PATH_MAX, rfi, rfe);
|
||||
|
||||
if (create_ghost(gf, gfe, img))
|
||||
goto close_ifd;
|
||||
|
|
@ -379,6 +385,78 @@ int prepare_remaps(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void try_clean_ghost(struct remap_info *ri)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int mnt_id, ret;
|
||||
|
||||
mnt_id = ri->rfi->rfe->mnt_id; /* rirfirfe %) */
|
||||
ret = rst_get_mnt_root(mnt_id, path, sizeof(path));
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
ghost_path(path + ret, sizeof(path) - 1, ri->rfi, ri->rfe);
|
||||
if (!unlink(path)) {
|
||||
pr_info(" `- X [%s] ghost\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can also find out the ghost type by stat()-ing
|
||||
* it or by reading the ghost image, but this way
|
||||
* is the fastest one.
|
||||
*/
|
||||
|
||||
if ((errno == EISDIR)) {
|
||||
strncpy(path + ret, ri->rfi->path, sizeof(path) - 1);
|
||||
if (!rmdir(path)) {
|
||||
pr_info(" `- Xd [%s] ghost\n", path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pr_perror(" `- XFail [%s] ghost", path);
|
||||
}
|
||||
|
||||
void try_clean_remaps(int ns_fd)
|
||||
{
|
||||
struct remap_info *ri;
|
||||
int old_ns = -1;
|
||||
|
||||
if (list_empty(&remaps))
|
||||
goto out;
|
||||
|
||||
if (ns_fd >= 0) {
|
||||
pr_info("Switching to new ns to clean ghosts\n");
|
||||
|
||||
old_ns = open_proc(PROC_SELF, "ns/mnt");
|
||||
if (old_ns < 0) {
|
||||
pr_perror("`- Can't keep old ns");
|
||||
return;
|
||||
}
|
||||
|
||||
if (setns(ns_fd, CLONE_NEWNS) < 0) {
|
||||
close(old_ns);
|
||||
pr_perror("`- Can't switch");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(ri, &remaps, list)
|
||||
if (ri->rfe->remap_type == REMAP_TYPE__GHOST)
|
||||
try_clean_ghost(ri);
|
||||
|
||||
if (old_ns >= 0) {
|
||||
if (setns(old_ns, CLONE_NEWNS) < 0)
|
||||
pr_perror("Fail to switch back!");
|
||||
close(old_ns);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ns_fd >= 0)
|
||||
close(ns_fd);
|
||||
}
|
||||
|
||||
static struct collect_image_info remap_cinfo = {
|
||||
.fd_type = CR_FD_REMAP_FPATH,
|
||||
.pb_type = PB_REMAP_FPATH,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ extern int collect_remaps_and_regfiles(void);
|
|||
extern void delete_link_remaps(void);
|
||||
extern void free_link_remaps(void);
|
||||
extern int prepare_remaps(void);
|
||||
extern void try_clean_remaps(int ns_fd);
|
||||
|
||||
extern int strip_deleted(struct fd_link *link);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue