Skip to content

Commit efa7dcf

Browse files
committed
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 <[email protected]>
1 parent a7c9f30 commit efa7dcf

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

cr-restore.c

+16-1
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ static void ignore_kids(void)
17321732
static int restore_root_task(struct pstree_item *init)
17331733
{
17341734
enum trace_flags flag = TRACE_ALL;
1735-
int ret, fd;
1735+
int ret, fd, mnt_ns_fd = -1;
17361736

17371737
fd = open("/proc", O_DIRECTORY | O_RDONLY);
17381738
if (fd < 0) {
@@ -1808,6 +1808,14 @@ static int restore_root_task(struct pstree_item *init)
18081808
if (ret)
18091809
goto out;
18101810

1811+
if (root_ns_mask & CLONE_NEWNS) {
1812+
mnt_ns_fd = open_proc(init->pid.real, "ns/mnt");
1813+
if (mnt_ns_fd < 0) {
1814+
pr_perror("Can't open init's mntns fd");
1815+
goto out;
1816+
}
1817+
}
1818+
18111819
ret = run_scripts(ACT_SETUP_NS);
18121820
if (ret)
18131821
goto out;
@@ -1837,6 +1845,12 @@ static int restore_root_task(struct pstree_item *init)
18371845
*/
18381846
task_entries->nr_threads -= atomic_read(&task_entries->nr_zombies);
18391847

1848+
if (mnt_ns_fd >= 0)
1849+
/*
1850+
* Don't try_clean_remaps here, since restore went OK
1851+
* and all ghosts were removed by the openers.
1852+
*/
1853+
close(mnt_ns_fd);
18401854
cleanup_mnt_ns();
18411855

18421856
ret = stop_usernsd();
@@ -1923,6 +1937,7 @@ static int restore_root_task(struct pstree_item *init)
19231937

19241938
out:
19251939
fini_cgroup();
1940+
try_clean_remaps(mnt_ns_fd);
19261941
cleanup_mnt_ns();
19271942
stop_usernsd();
19281943
__restore_switch_stage(CR_STATE_FAIL);

files-reg.c

+79-1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_im
157157
return ret;
158158
}
159159

160+
static inline void ghost_path(char *path, int plen,
161+
struct reg_file_info *rfi, RemapFilePathEntry *rfe)
162+
{
163+
snprintf(path, plen, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
164+
}
165+
160166
static int open_remap_ghost(struct reg_file_info *rfi,
161167
RemapFilePathEntry *rfe)
162168
{
@@ -203,7 +209,7 @@ static int open_remap_ghost(struct reg_file_info *rfi,
203209
if (S_ISDIR(gfe->mode))
204210
strncpy(gf->remap.rpath, rfi->path, PATH_MAX);
205211
else
206-
snprintf(gf->remap.rpath, PATH_MAX, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
212+
ghost_path(gf->remap.rpath, PATH_MAX, rfi, rfe);
207213

208214
if (create_ghost(gf, gfe, img))
209215
goto close_ifd;
@@ -379,6 +385,78 @@ int prepare_remaps(void)
379385
return ret;
380386
}
381387

388+
static void try_clean_ghost(struct remap_info *ri)
389+
{
390+
char path[PATH_MAX];
391+
int mnt_id, ret;
392+
393+
mnt_id = ri->rfi->rfe->mnt_id; /* rirfirfe %) */
394+
ret = rst_get_mnt_root(mnt_id, path, sizeof(path));
395+
if (ret < 0)
396+
return;
397+
398+
ghost_path(path + ret, sizeof(path) - 1, ri->rfi, ri->rfe);
399+
if (!unlink(path)) {
400+
pr_info(" `- X [%s] ghost\n", path);
401+
return;
402+
}
403+
404+
/*
405+
* We can also find out the ghost type by stat()-ing
406+
* it or by reading the ghost image, but this way
407+
* is the fastest one.
408+
*/
409+
410+
if ((errno == EISDIR)) {
411+
strncpy(path + ret, ri->rfi->path, sizeof(path) - 1);
412+
if (!rmdir(path)) {
413+
pr_info(" `- Xd [%s] ghost\n", path);
414+
return;
415+
}
416+
}
417+
418+
pr_perror(" `- XFail [%s] ghost", path);
419+
}
420+
421+
void try_clean_remaps(int ns_fd)
422+
{
423+
struct remap_info *ri;
424+
int old_ns = -1;
425+
426+
if (list_empty(&remaps))
427+
goto out;
428+
429+
if (ns_fd >= 0) {
430+
pr_info("Switching to new ns to clean ghosts\n");
431+
432+
old_ns = open_proc(PROC_SELF, "ns/mnt");
433+
if (old_ns < 0) {
434+
pr_perror("`- Can't keep old ns");
435+
return;
436+
}
437+
438+
if (setns(ns_fd, CLONE_NEWNS) < 0) {
439+
close(old_ns);
440+
pr_perror("`- Can't switch");
441+
return;
442+
}
443+
}
444+
445+
list_for_each_entry(ri, &remaps, list)
446+
if (ri->rfe->remap_type == REMAP_TYPE__GHOST)
447+
try_clean_ghost(ri);
448+
449+
if (old_ns >= 0) {
450+
if (setns(old_ns, CLONE_NEWNS) < 0)
451+
pr_perror("Fail to switch back!");
452+
close(old_ns);
453+
}
454+
455+
out:
456+
if (ns_fd >= 0)
457+
close(ns_fd);
458+
}
459+
382460
static struct collect_image_info remap_cinfo = {
383461
.fd_type = CR_FD_REMAP_FPATH,
384462
.pb_type = PB_REMAP_FPATH,

include/files-reg.h

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern int collect_remaps_and_regfiles(void);
5050
extern void delete_link_remaps(void);
5151
extern void free_link_remaps(void);
5252
extern int prepare_remaps(void);
53+
extern void try_clean_remaps(int ns_fd);
5354

5455
extern int strip_deleted(struct fd_link *link);
5556

0 commit comments

Comments
 (0)