Commit efa7dcf7 authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a7c9f301
......@@ -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);
......
......@@ -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);
......
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