mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-30 05:21:57 +00:00
file: add a general approach for inherited files
How to restore an external file? The problem is that a file can be opened with different flags (O_APPNED, O_RDWR, O_RONLY, etc). These flags can't be changed for a file descriptor, so we can't just duplicate an inherit fd, when we meet an external file. A file is external, when we can't access them directly. CRIU is able to restore a file descriptor, if it knows how to open it, so we need to provide a way to open an external file. The idea of this patch is that we can open an external file via /proc/self/fd/X where X is an inherit fd. This approach works for files and fifo. An example how it can be used: criu -o dump.log -D dump/fifo.py/6/1 -v4 -t 6 --external file[72:a3e7] criu -o restore.log -D dump/fifo.py/6/1 -v4 --restore-sibling --inherit-fd fd[4]:file[72:a3e7] --restore-detached https://github.com/xemul/criu/issues/104 Cc: Saied Kazemi <saied@google.com> Signed-off-by: Andrew Vagin <avagin@virtuozzo.com> Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This commit is contained in:
parent
a98014f306
commit
c26da2fd59
3 changed files with 33 additions and 4 deletions
|
|
@ -799,6 +799,7 @@ usage:
|
|||
" --external RES dump objects from this list as external resources:\n"
|
||||
" Formats of RES:\n"
|
||||
" tty[rdev:dev]\n"
|
||||
" file[mnt_id:inode]\n"
|
||||
" --inherit-fd fd[<num>]:<existing>\n"
|
||||
" Inherit file descriptors. This allows to treat file descriptor\n"
|
||||
" <num> as being already opened via <existing> one and instead of\n"
|
||||
|
|
@ -806,6 +807,7 @@ usage:
|
|||
" tty[rdev:dev]\n"
|
||||
" pipe[inode]\n"
|
||||
" socket[inode]\n"
|
||||
" file[mnt_id:inode]\n"
|
||||
" --empty-ns {net}\n"
|
||||
" Create a namespace, but don't restore its properies.\n"
|
||||
" An user will retore them from action scripts.\n"
|
||||
|
|
|
|||
|
|
@ -1074,6 +1074,7 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
|
|||
struct fd_link _link, *link;
|
||||
struct ns_id *nsid;
|
||||
struct cr_img *rimg;
|
||||
char ext_id[64];
|
||||
|
||||
RegFileEntry rfe = REG_FILE_ENTRY__INIT;
|
||||
|
||||
|
|
@ -1084,6 +1085,17 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
|
|||
} else
|
||||
link = p->link;
|
||||
|
||||
|
||||
|
||||
snprintf(ext_id, sizeof(ext_id), "file[%x:%"PRIx64"]", p->mnt_id, p->stat.st_ino);
|
||||
if (external_lookup_id(ext_id)) {
|
||||
/* the first symbol will be cut on restore to get an relative path*/
|
||||
rfe.name = xstrdup(ext_id);
|
||||
rfe.ext = true;
|
||||
rfe.has_ext = true;
|
||||
goto ext;
|
||||
}
|
||||
|
||||
nsid = lookup_nsid_by_mnt_id(p->mnt_id);
|
||||
if (nsid == NULL) {
|
||||
pr_err("Can't lookup mount=%d for fd=%d path=%s\n",
|
||||
|
|
@ -1109,12 +1121,12 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
|
|||
|
||||
if (check_path_remap(link, p, lfd, id, nsid))
|
||||
return -1;
|
||||
|
||||
rfe.name = &link->name[1];
|
||||
ext:
|
||||
rfe.id = id;
|
||||
rfe.flags = p->flags;
|
||||
rfe.pos = p->pos;
|
||||
rfe.fown = (FownEntry *)&p->fown;
|
||||
rfe.name = &link->name[1];
|
||||
|
||||
if (S_ISREG(p->stat.st_mode) && should_check_size(rfe.flags)) {
|
||||
rfe.has_size = true;
|
||||
|
|
@ -1350,11 +1362,24 @@ int open_path(struct file_desc *d,
|
|||
int tmp, mntns_root, level;
|
||||
struct reg_file_info *rfi;
|
||||
char *orig_path = NULL;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (inherited_fd(d, &tmp))
|
||||
return tmp;
|
||||
|
||||
rfi = container_of(d, struct reg_file_info, d);
|
||||
|
||||
if (rfi->rfe->ext) {
|
||||
tmp = inherit_fd_lookup_id(rfi->rfe->name);
|
||||
if (tmp >= 0) {
|
||||
mntns_root = open_pid_proc(PROC_SELF);
|
||||
snprintf(path, sizeof(path), "fd/%d", tmp);
|
||||
orig_path = rfi->path;
|
||||
rfi->path = path;
|
||||
goto ext;
|
||||
}
|
||||
}
|
||||
|
||||
if (rfi->remap) {
|
||||
mutex_lock(ghost_file_mutex);
|
||||
if (rfi->remap->is_dir) {
|
||||
|
|
@ -1396,6 +1421,7 @@ int open_path(struct file_desc *d,
|
|||
}
|
||||
|
||||
mntns_root = mntns_get_root_by_mnt_id(rfi->rfe->mnt_id);
|
||||
ext:
|
||||
tmp = open_cb(mntns_root, rfi, arg);
|
||||
if (tmp < 0) {
|
||||
pr_perror("Can't open file %s", rfi->path);
|
||||
|
|
@ -1438,10 +1464,10 @@ int open_path(struct file_desc *d,
|
|||
unlinkat(mntns_root, rfi->remap->rpath, rfi->remap->is_dir ? AT_REMOVEDIR : 0);
|
||||
}
|
||||
|
||||
if (orig_path)
|
||||
rfi->path = orig_path;
|
||||
mutex_unlock(ghost_file_mutex);
|
||||
}
|
||||
if (orig_path)
|
||||
rfi->path = orig_path;
|
||||
|
||||
if (restore_fown(tmp, rfi->rfe->fown))
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ message reg_file_entry {
|
|||
required string name = 6;
|
||||
optional sint32 mnt_id = 7 [default = -1];
|
||||
optional uint64 size = 8;
|
||||
optional bool ext = 9;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue