[CRIU] Re: [RFC] splitting files.c
Pavel Emelyanov
xemul at parallels.com
Wed Jun 20 11:20:22 EDT 2012
On 06/20/2012 06:25 PM, Cyrill Gorcunov wrote:
> Hi guys, while mocking up with fifos and paths handling I found that our
> regular-files dumping code is a bit spread over files.c and cr-dump.c
> files. So I thought it would be good to cope reg-files in one place,
> that's how files-reg.c appeared.
>
> What do you think, is it worth to?
Worth. Make it work and I'll commit the patch. But please -- only code move
and _required_ adds/removes. No "clean tabs/braces/spaces/names/whatever while
I am at it".
> Cyrill
> ---
> From: Cyrill Gorcunov <gorcunov at openvz.org>
> Subject: [PATCH] files: Move regular files handling code to files-reg
>
> Instead of spreading regular files handling code over
> files.c and cr-dump.c move it to files-reg.c.
>
> This allows to extend regular file handling code in
> future without disturbing other source files and
> make code logically coupled, where files.c is mostly
> a place for general file handling code unrelated to
> file type specifics.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> Makefile | 1 +
> cr-dump.c | 188 +----------------------
> files-reg.c | 433 +++++++++++++++++++++++++++++++++++++++++++++++++++
> files.c | 228 ---------------------------
> include/files-reg.h | 16 ++
> 5 files changed, 451 insertions(+), 415 deletions(-)
> create mode 100644 files-reg.c
> create mode 100644 include/files-reg.h
>
> diff --git a/Makefile b/Makefile
> index 44b6854..3853028 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -44,6 +44,7 @@ OBJS += sk-tcp.o
> OBJS += sk-unix.o
> OBJS += sk-queue.o
> OBJS += files.o
> +OBJS += files-reg.o
> OBJS += pipes.o
> OBJS += file-ids.o
> OBJS += namespaces.o
> diff --git a/cr-dump.c b/cr-dump.c
> index 9edc17c..2b2f99b 100644
> --- a/cr-dump.c
> +++ b/cr-dump.c
> @@ -35,6 +35,7 @@
> #include "parasite.h"
> #include "parasite-syscall.h"
> #include "files.h"
> +#include "files-reg.h"
> #include "pipes.h"
> #include "shmem.h"
> #include "sk-inet.h"
> @@ -46,7 +47,6 @@
> # error No x86-32 support yet
> #endif
>
> -static char big_buffer[PATH_MAX];
> static char loc_buf[PAGE_SIZE];
>
> static struct pstree_item *root_item = NULL;
> @@ -140,180 +140,6 @@ static int collect_fds(pid_t pid, int *fd, int *nr_fd)
> return 0;
> }
>
> -/*
> - * Ghost files are those not visible from the FS. Dumping them is
> - * nasty and the only way we have -- just carry its contents with
> - * us. Any brave soul to implement link unlinked file back?
> - */
> -struct ghost_file {
> - u32 dev;
> - u32 ino;
> - u32 id;
> - struct list_head list;
> -};
> -
> -static u32 ghost_file_ids = 1;
> -static LIST_HEAD(ghost_files);
> -/*
> - * This constant is selected without any calculations. Just do not
> - * want to pick up too big files with us in the image.
> - */
> -#define MAX_GHOST_FILE_SIZE (1 * 1024 * 1024)
> -
> -static int dump_ghost_file(int _fd, u32 id, const struct stat *st)
> -{
> - int img, fd;
> - struct ghost_file_entry gfe;
> - char lpath[32];
> -
> - pr_info("Dumping ghost file contents (id %#x)\n", id);
> -
> - img = open_image(CR_FD_GHOST_FILE, O_DUMP, id);
> - if (img < 0)
> - return -1;
> -
> - /*
> - * Reopen file locally since it may have no read
> - * permissions when drained
> - */
> - snprintf(lpath, sizeof(lpath), "/proc/self/fd/%d", _fd);
> - fd = open(lpath, O_RDONLY);
> - if (fd < 0) {
> - pr_perror("Can't open ghost original file");
> - return -1;
> - }
> -
> - gfe.uid = st->st_uid;
> - gfe.gid = st->st_gid;
> - gfe.mode = st->st_mode;
> -
> - if (write_img(img, &gfe))
> - return -1;
> -
> - if (copy_file(fd, img, st->st_size))
> - return -1;
> -
> - close(fd);
> - close(img);
> - return 0;
> -}
> -
> -static int dump_ghost_remap(char *path, const struct stat *st, int lfd, u32 id)
> -{
> - struct ghost_file *gf;
> - struct remap_file_path_entry rpe;
> -
> - pr_info("Dumping ghost file for fd %d id %#x\n", lfd, id);
> -
> - if (st->st_size > MAX_GHOST_FILE_SIZE) {
> - pr_err("Can't dump ghost file %s of %lu size\n",
> - path, st->st_size);
> - return -1;
> - }
> -
> - list_for_each_entry(gf, &ghost_files, list)
> - if ((gf->dev == st->st_dev) && (gf->ino == st->st_ino))
> - goto dump_entry;
> -
> - gf = xmalloc(sizeof(*gf));
> - if (gf == NULL)
> - return -1;
> -
> - gf->dev = st->st_dev;
> - gf->ino = st->st_ino;
> - gf->id = ghost_file_ids++;
> - list_add_tail(&gf->list, &ghost_files);
> -
> - if (dump_ghost_file(lfd, gf->id, st))
> - return -1;
> -
> -dump_entry:
> - rpe.orig_id = id;
> - rpe.remap_id = gf->id | REMAP_GHOST;
> -
> - return write_img(fdset_fd(glob_fdset, CR_FD_REMAP_FPATH), &rpe);
> -}
> -
> -static int check_path_remap(char *path, const struct stat *ost, int lfd, u32 id)
> -{
> - int ret;
> - struct stat pst;
> -
> - if (ost->st_nlink == 0)
> - /*
> - * Unpleasant, but easy case. File is completely invisible
> - * from the FS. Just dump its contents and that's it. But
> - * be careful whether anybody still has any of its hardlinks
> - * also open.
> - */
> - return dump_ghost_remap(path, ost, lfd, id);
> -
> - ret = stat(path, &pst);
> - if (ret < 0) {
> - /*
> - * FIXME linked file, but path is not accessible (unless any
> - * other error occurred). We can create a temporary link to it
> - * uning linkat with AT_EMPTY_PATH flag and remap it to this
> - * name.
> - */
> - pr_perror("Can't stat path");
> - return -1;
> - }
> -
> - if ((pst.st_ino != ost->st_ino) || (pst.st_dev != ost->st_dev)) {
> - /*
> - * FIXME linked file, but the name we see it by is reused
> - * by somebody else.
> - */
> - pr_err("Unaccessible path opened %u:%u, need %u:%u\n",
> - (int)pst.st_dev, (int)pst.st_ino,
> - (int)ost->st_dev, (int)ost->st_ino);
> - return -1;
> - }
> -
> - /*
> - * File is linked and visible by the name it is opened by
> - * this task. Go ahead and dump it.
> - */
> - return 0;
> -}
> -
> -static int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
> -{
> - char fd_str[128];
> - int len, rfd;
> - struct reg_file_entry rfe;
> -
> - snprintf(fd_str, sizeof(fd_str), "/proc/self/fd/%d", lfd);
> - len = readlink(fd_str, big_buffer, sizeof(big_buffer) - 1);
> - if (len < 0) {
> - pr_perror("Can't readlink %s", fd_str);
> - return len;
> - }
> -
> - big_buffer[len] = '\0';
> - pr_info("Dumping path for %d fd via self %d [%s]\n",
> - p->fd, lfd, big_buffer);
> -
> - if (check_path_remap(big_buffer, &p->stat, lfd, id))
> - return -1;
> -
> - rfe.len = len;
> - rfe.flags = p->flags;
> - rfe.pos = p->pos;
> - rfe.id = id;
> - rfe.fown = p->fown;
> -
> - rfd = fdset_fd(glob_fdset, CR_FD_REG_FILES);
> -
> - if (write_img(rfd, &rfe))
> - return -1;
> - if (write_img_buf(rfd, big_buffer, len))
> - return -1;
> -
> - return 0;
> -}
> -
> u32 make_gen_id(const struct fd_parms *p)
> {
> return MAKE_FD_GENID(p->stat.st_dev, p->stat.st_ino, p->pos);
> @@ -348,18 +174,6 @@ err:
> return ret;
> }
>
> -static const struct fdtype_ops regfile_ops = {
> - .type = FDINFO_REG,
> - .make_gen_id = make_gen_id,
> - .dump = dump_one_reg_file,
> -};
> -
> -static int dump_reg_file(struct fd_parms *p, int lfd,
> - const struct cr_fdset *cr_fdset)
> -{
> - return do_dump_gen_file(p, lfd, ®file_ops, cr_fdset);
> -}
> -
> static int dump_task_exe_link(pid_t pid, struct mm_entry *mm)
> {
> struct fd_parms params = { };
> diff --git a/files-reg.c b/files-reg.c
> new file mode 100644
> index 0000000..3407bee
> --- /dev/null
> +++ b/files-reg.c
> @@ -0,0 +1,433 @@
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <errno.h>
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +
> +#include "crtools.h"
> +
> +#include "files.h"
> +#include "image.h"
> +#include "list.h"
> +#include "util.h"
> +
> +#include "files-reg.h"
> +
> +struct reg_file_info {
> + struct file_desc d;
> +
> + struct reg_file_entry rfe;
> + char *remap_path;
> + char *path;
> +};
> +
> +struct ghost_file {
> + struct list_head list;
> + u32 id;
> + char *path;
> +};
> +
> +/*
> + * Ghost files are those not visible from the FS. Dumping them is
> + * nasty and the only way we have -- just carry its contents with
> + * us. Any brave soul to implement link unlinked file back?
> + */
> +struct ghost_file_dumpee {
> + struct list_head list;
> + u32 id;
> + u32 dev;
> + u32 ino;
> +};
> +
> +static u32 ghost_file_ids = 1;
> +static LIST_HEAD(ghost_files);
> +
> +/*
> + * This constant is selected without any calculations. Just do not
> + * want to pick up too big files with us in the image.
> + */
> +#define MAX_GHOST_FILE_SIZE (1 * 1024 * 1024)
> +
> +void clear_ghost_files(void)
> +{
> + struct ghost_file *gf;
> +
> + pr_info("Unlinking ghosts\n");
> + list_for_each_entry(gf, &ghost_files, list) {
> + pr_info("\t`- %s\n", gf->path);
> + unlink(gf->path);
> + }
> +}
> +
> +static int open_remap_ghost(struct reg_file_info *rfi, struct remap_file_path_entry *rfe)
> +{
> + struct ghost_file_entry gfe;
> + struct ghost_file *gf;
> + int gfd, ifd;
> +
> + list_for_each_entry(gf, &ghost_files, list) {
> + if (gf->id == rfe->remap_id)
> + goto gf_found;
> + }
> +
> + /*
> + * Ghost not found. We will create one in the same dir
> + * as the very first client of it thus resolving any
> + * issues with cross-device links.
> + */
> + pr_info("Opening ghost file %#x for %s\n", rfe->remap_id, rfi->path);
> +
> + gf = xmalloc(sizeof(*gf));
> + if (!gf)
> + return -1;
> + gf->path = xmalloc(PATH_MAX);
> + if (!gf->path)
> + goto err;
> +
> + ifd = open_image_ro(CR_FD_GHOST_FILE, rfe->remap_id);
> + if (ifd < 0)
> + goto err;
> +
> + if (read_img(ifd, &gfe) < 0)
> + goto err;
> +
> + snprintf(gf->path, PATH_MAX, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
> + gfd = open(gf->path, O_WRONLY | O_CREAT | O_EXCL, gfe.mode);
> + if (gfd < 0) {
> + pr_perror("Can't open ghost file");
> + goto err;
> + }
> +
> + if (fchown(gfd, gfe.uid, gfe.gid) < 0) {
> + pr_perror("Can't reset user/group on ghost %#x\n", rfe->remap_id);
> + goto err;
> + }
> +
> + if (copy_file(ifd, gfd, 0) < 0)
> + goto err;
> +
> + close(ifd);
> + close(gfd);
> +
> + gf->id = rfe->remap_id;
> + list_add_tail(&gf->list, &ghost_files);
> +
> +gf_found:
> + rfi->remap_path = gf->path;
> + return 0;
> +
> +err:
> + xfree(gf->path);
> + xfree(gf);
> + return -1;
> +}
> +
> +static int collect_remaps(void)
> +{
> + int fd, ret = 0;
> +
> + fd = open_image_ro(CR_FD_REMAP_FPATH);
> + if (fd < 0)
> + return -1;
> +
> + while (1) {
> + struct remap_file_path_entry rfe;
> + struct reg_file_info *rfi;
> + struct file_desc *fdesc;
> +
> + ret = read_img_eof(fd, &rfe);
> + if (ret <= 0)
> + break;
> +
> + ret = -1;
> + if (!(rfe.remap_id & REMAP_GHOST)) {
> + pr_err("Non ghost remap not supported @%#x\n", rfe.orig_id);
> + break;
> + }
> +
> + fdesc = find_file_desc_raw(FDINFO_REG, rfe.orig_id);
> + if (fdesc == NULL) {
> + pr_err("Remap for non existing file %#x\n",
> + rfe.orig_id);
> + break;
> + }
> +
> + rfe.remap_id &= ~REMAP_GHOST;
> + rfi = container_of(fdesc, struct reg_file_info, d);
> + pr_info("Configuring remap %#x -> %#x\n", rfi->rfe.id, rfe.remap_id);
> + ret = open_remap_ghost(rfi, &rfe);
> + if (ret < 0)
> + break;
> + }
> +
> + close(fd);
> + return ret;
> +}
> +
> +static int dump_ghost_file(int _fd, u32 id, const struct stat *st)
> +{
> + struct ghost_file_entry gfe;
> + char lpath[32];
> + int img, fd;
> +
> + pr_info("Dumping ghost file contents (id %#x)\n", id);
> +
> + img = open_image(CR_FD_GHOST_FILE, O_DUMP, id);
> + if (img < 0)
> + return -1;
> +
> + /*
> + * Reopen file locally since it may have no read
> + * permissions when drained
> + */
> + snprintf(lpath, sizeof(lpath), "/proc/self/fd/%d", _fd);
> + fd = open(lpath, O_RDONLY);
> + if (fd < 0) {
> + pr_perror("Can't open ghost original file");
> + return -1;
> + }
> +
> + gfe.uid = st->st_uid;
> + gfe.gid = st->st_gid;
> + gfe.mode= st->st_mode;
> +
> + if (write_img(img, &gfe))
> + return -1;
> +
> + if (copy_file(fd, img, st->st_size))
> + return -1;
> +
> + close(fd);
> + close(img);
> + return 0;
> +}
> +
> +static int dump_ghost_remap(char *path, const struct stat *st, int lfd, u32 id)
> +{
> + struct remap_file_path_entry rpe;
> + struct ghost_file_dumpee *gf;
> +
> + pr_info("Dumping ghost file for fd %d id %#x\n", lfd, id);
> +
> + if (st->st_size > MAX_GHOST_FILE_SIZE) {
> + pr_err("Can't dump ghost file %s of %lu size\n",
> + path, st->st_size);
> + return -1;
> + }
> +
> + list_for_each_entry(gf, &ghost_files, list) {
> + if ((gf->dev == st->st_dev) && (gf->ino == st->st_ino))
> + goto dump_entry;
> + }
> +
> + gf = xmalloc(sizeof(*gf));
> + if (gf == NULL)
> + return -1;
> +
> + gf->dev = st->st_dev;
> + gf->ino = st->st_ino;
> + gf->id = ghost_file_ids++;
> +
> + list_add_tail(&gf->list, &ghost_files);
> +
> + if (dump_ghost_file(lfd, gf->id, st))
> + return -1;
> +
> +dump_entry:
> + rpe.orig_id = id;
> + rpe.remap_id = gf->id | REMAP_GHOST;
> +
> + return write_img(fdset_fd(glob_fdset, CR_FD_REMAP_FPATH), &rpe);
> +}
> +
> +static int check_path_remap(char *path, const struct stat *ost, int lfd, u32 id)
> +{
> + int ret;
> + struct stat pst;
> +
> + if (ost->st_nlink == 0) {
> + /*
> + * Unpleasant, but easy case. File is completely invisible
> + * from the FS. Just dump its contents and that's it. But
> + * be careful whether anybody still has any of its hardlinks
> + * also open.
> + */
> + return dump_ghost_remap(path, ost, lfd, id);
> + }
> +
> + ret = stat(path, &pst);
> + if (ret < 0) {
> + /*
> + * FIXME linked file, but path is not accessible (unless any
> + * other error occurred). We can create a temporary link to it
> + * uning linkat with AT_EMPTY_PATH flag and remap it to this
> + * name.
> + */
> + pr_perror("Can't stat path");
> + return -1;
> + }
> +
> + if ((pst.st_ino != ost->st_ino) || (pst.st_dev != ost->st_dev)) {
> + /*
> + * FIXME linked file, but the name we see it by is reused
> + * by somebody else.
> + */
> + pr_err("Unaccessible path opened %u:%u, need %u:%u\n",
> + (int)pst.st_dev, (int)pst.st_ino,
> + (int)ost->st_dev, (int)ost->st_ino);
> + return -1;
> + }
> +
> + /*
> + * File is linked and visible by the name it is opened by
> + * this task. Go ahead and dump it.
> + */
> + return 0;
> +}
> +
> +int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
> +{
> + struct reg_file_entry rfe;
> + char path[PATH_MAX];
> + char fd_str[128];
> + int len, rfd;
> +
> + snprintf(fd_str, sizeof(fd_str), "/proc/self/fd/%d", lfd);
> + len = readlink(fd_str, path, sizeof(path) - 1);
> + if (len < 0) {
> + pr_perror("Can't readlink %s", fd_str);
> + return len;
> + }
> +
> + path[len] = '\0';
> + pr_info("Dumping path for %d fd via self %d [%s]\n",
> + p->fd, lfd, path);
> +
> + if (check_path_remap(path, &p->stat, lfd, id))
> + return -1;
> +
> + rfe.id = id;
> + rfe.flags = p->flags;
> + rfe.len = len;
> + rfe.pos = p->pos;
> + rfe.fown = p->fown;
> +
> + rfd = fdset_fd(glob_fdset, CR_FD_REG_FILES);
> +
> + if (write_img(rfd, &rfe))
> + return -1;
> + if (write_img_buf(rfd, path, len))
> + return -1;
> +
> + return 0;
> +}
> +
> +static const struct fdtype_ops regfile_ops = {
> + .type = FDINFO_REG,
> + .make_gen_id = make_gen_id,
> + .dump = dump_one_reg_file,
> +};
> +
> +int dump_reg_file(struct fd_parms *p, int lfd, const struct cr_fdset *set)
> +{
> + return do_dump_gen_file(p, lfd, ®file_ops, set);
> +}
> +
> +static int open_fe_fd(struct file_desc *d)
> +{
> + struct reg_file_info *rfi;
> + int tmp;
> +
> + rfi = container_of(d, struct reg_file_info, d);
> + if (rfi->remap_path) {
> + if (link(rfi->remap_path, rfi->path) < 0) {
> + pr_perror("Can't link %s -> %s\n",
> + rfi->remap_path, rfi->path);
> + return -1;
> + }
> + }
> +
> + tmp = open(rfi->path, rfi->rfe.flags);
> + if (tmp < 0) {
> + pr_perror("Can't open file %s", rfi->path);
> + return -1;
> + }
> +
> + if (rfi->remap_path)
> + unlink(rfi->path);
> +
> + lseek(tmp, rfi->rfe.pos, SEEK_SET);
> +
> + if (restore_fown(tmp, &rfi->rfe.fown))
> + return -1;
> +
> + return tmp;
> +}
> +
> +int open_reg_by_id(u32 id)
> +{
> + struct file_desc *d;
> +
> + d = find_file_desc_raw(FDINFO_REG, id);
> + if (!d) {
> + pr_perror("Can't find regfile for %#x\n", id);
> + return -1;
> + }
> +
> + return open_fe_fd(d);
> +}
> +
> +static struct file_desc_ops reg_desc_ops = {
> + .type = FDINFO_REG,
> + .open = open_fe_fd,
> +};
> +
> +int collect_reg_files(void)
> +{
> + struct reg_file_info *rfi = NULL;
> + int fd, ret = -1;
> +
> + fd = open_image_ro(CR_FD_REG_FILES);
> + if (fd < 0)
> + return -1;
> +
> + while (1) {
> + int len;
> +
> + rfi = xmalloc(sizeof(*rfi));
> + ret = -1;
> + if (rfi == NULL)
> + break;
> +
> + rfi->path = NULL;
> + ret = read_img_eof(fd, &rfi->rfe);
> + if (ret <= 0)
> + break;
> +
> + len = rfi->rfe.len;
> + rfi->path = xmalloc(len + 1);
> + ret = -1;
> + if (rfi->path == NULL)
> + break;
> +
> + ret = read_img_buf(fd, rfi->path, len);
> + if (ret < 0)
> + break;
> +
> + rfi->remap_path = NULL;
> + rfi->path[len] = '\0';
> +
> + pr_info("Collected [%s] ID %#x\n", rfi->path, rfi->rfe.id);
> + file_desc_add(&rfi->d, rfi->rfe.id, ®_desc_ops);
> + }
> +
> + if (rfi) {
> + xfree(rfi->path);
> + xfree(rfi);
> + }
> +
> + close(fd);
> +
> + return collect_remaps();
> +}
> diff --git a/files.c b/files.c
> index 82b9fad..e504d2e 100644
> --- a/files.c
> +++ b/files.c
> @@ -81,13 +81,6 @@ struct fdinfo_list_entry *file_master(struct file_desc *d)
> struct fdinfo_list_entry, desc_list);
> }
>
> -struct reg_file_info {
> - struct reg_file_entry rfe;
> - char *remap_path;
> - char *path;
> - struct file_desc d;
> -};
> -
> void show_saved_files(void)
> {
> int i;
> @@ -157,184 +150,6 @@ int rst_file_params(int fd, fown_t *fown, int flags)
> return 0;
> }
>
> -static int open_fe_fd(struct file_desc *d);
> -
> -static struct file_desc_ops reg_desc_ops = {
> - .type = FDINFO_REG,
> - .open = open_fe_fd,
> -};
> -
> -struct ghost_file {
> - u32 id;
> - char *path;
> - struct list_head list;
> -};
> -
> -static LIST_HEAD(ghost_files);
> -
> -void clear_ghost_files(void)
> -{
> - struct ghost_file *gf;
> -
> - pr_info("Unlinking ghosts\n");
> -
> - list_for_each_entry(gf, &ghost_files, list) {
> - pr_info("\t`- %s\n", gf->path);
> - unlink(gf->path);
> - }
> -}
> -
> -static int open_remap_ghost(struct reg_file_info *rfi,
> - struct remap_file_path_entry *rfe)
> -{
> - struct ghost_file *gf;
> - struct ghost_file_entry gfe;
> - int gfd, ifd;
> -
> - list_for_each_entry(gf, &ghost_files, list)
> - if (gf->id == rfe->remap_id)
> - goto gf_found;
> -
> - /*
> - * Ghost not found. We will create one in the same dir
> - * as the very first client of it thus resolving any
> - * issues with cross-device links.
> - */
> -
> - pr_info("Opening ghost file %#x for %s\n", rfe->remap_id, rfi->path);
> -
> - gf = xmalloc(sizeof(*gf));
> - if (!gf)
> - return -1;
> - gf->path = xmalloc(PATH_MAX);
> - if (!gf->path)
> - return -1;
> -
> - ifd = open_image_ro(CR_FD_GHOST_FILE, rfe->remap_id);
> - if (ifd < 0)
> - return -1;
> -
> - if (read_img(ifd, &gfe) < 0)
> - return -1;
> -
> - snprintf(gf->path, PATH_MAX, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
> - gfd = open(gf->path, O_WRONLY | O_CREAT | O_EXCL, gfe.mode);
> - if (gfd < 0) {
> - pr_perror("Can't open ghost file");
> - return -1;
> - }
> -
> - if (fchown(gfd, gfe.uid, gfe.gid) < 0) {
> - pr_perror("Can't reset user/group on ghost %#x\n", rfe->remap_id);
> - return -1;
> - }
> -
> - if (copy_file(ifd, gfd, 0) < 0)
> - return -1;
> -
> - close(ifd);
> - close(gfd);
> -
> - gf->id = rfe->remap_id;
> - list_add_tail(&gf->list, &ghost_files);
> -gf_found:
> - rfi->remap_path = gf->path;
> - return 0;
> -}
> -
> -static int collect_remaps(void)
> -{
> - int fd, ret = 0;
> -
> - fd = open_image_ro(CR_FD_REMAP_FPATH);
> - if (fd < 0)
> - return -1;
> -
> - while (1) {
> - struct remap_file_path_entry rfe;
> - struct file_desc *fdesc;
> - struct reg_file_info *rfi;
> -
> - ret = read_img_eof(fd, &rfe);
> - if (ret <= 0)
> - break;
> -
> - ret = -1;
> -
> - if (!(rfe.remap_id & REMAP_GHOST)) {
> - pr_err("Non ghost remap not supported @%#x\n",
> - rfe.orig_id);
> - break;
> - }
> -
> - fdesc = find_file_desc_raw(FDINFO_REG, rfe.orig_id);
> - if (fdesc == NULL) {
> - pr_err("Remap for non existing file %#x\n",
> - rfe.orig_id);
> - break;
> - }
> -
> - rfe.remap_id &= ~REMAP_GHOST;
> - rfi = container_of(fdesc, struct reg_file_info, d);
> - pr_info("Configuring remap %#x -> %#x\n", rfi->rfe.id, rfe.remap_id);
> - ret = open_remap_ghost(rfi, &rfe);
> - if (ret < 0)
> - break;
> - }
> -
> - close(fd);
> - return ret;
> -}
> -
> -int collect_reg_files(void)
> -{
> - struct reg_file_info *rfi = NULL;
> - int fd, ret = -1;
> -
> - fd = open_image_ro(CR_FD_REG_FILES);
> - if (fd < 0)
> - return -1;
> -
> - while (1) {
> - int len;
> -
> - rfi = xmalloc(sizeof(*rfi));
> - ret = -1;
> - if (rfi == NULL)
> - break;
> -
> - rfi->path = NULL;
> - ret = read_img_eof(fd, &rfi->rfe);
> - if (ret <= 0)
> - break;
> -
> - len = rfi->rfe.len;
> - rfi->path = xmalloc(len + 1);
> - ret = -1;
> - if (rfi->path == NULL)
> - break;
> -
> - ret = read_img_buf(fd, rfi->path, len);
> - if (ret < 0)
> - break;
> -
> - rfi->remap_path = NULL;
> - rfi->path[len] = '\0';
> -
> - pr_info("Collected [%s] ID %#x\n", rfi->path, rfi->rfe.id);
> - file_desc_add(&rfi->d, rfi->rfe.id, ®_desc_ops);
> - }
> -
> - if (rfi) {
> - xfree(rfi->path);
> - xfree(rfi);
> - }
> -
> - close(fd);
> -
> - return collect_remaps();
> -}
> -
> static int collect_fd(int pid, struct fdinfo_entry *e, struct rst_info *rst_info)
> {
> struct fdinfo_list_entry *l, *le = &fdinfo_list[nr_fdinfo_list];
> @@ -403,49 +218,6 @@ int prepare_fd_pid(int pid, struct rst_info *rst_info)
> return ret;
> }
>
> -static int open_fe_fd(struct file_desc *d)
> -{
> - struct reg_file_info *rfi;
> - int tmp;
> -
> - rfi = container_of(d, struct reg_file_info, d);
> -
> - if (rfi->remap_path)
> - if (link(rfi->remap_path, rfi->path) < 0) {
> - pr_perror("Can't link %s -> %s\n",
> - rfi->remap_path, rfi->path);
> - return -1;
> - }
> -
> - tmp = open(rfi->path, rfi->rfe.flags);
> - if (tmp < 0) {
> - pr_perror("Can't open file %s", rfi->path);
> - return -1;
> - }
> -
> - if (rfi->remap_path)
> - unlink(rfi->path);
> -
> - lseek(tmp, rfi->rfe.pos, SEEK_SET);
> -
> - if (restore_fown(tmp, &rfi->rfe.fown))
> - return -1;
> -
> - return tmp;
> -}
> -int open_reg_by_id(u32 id)
> -{
> - struct file_desc *fd;
> -
> - fd = find_file_desc_raw(FDINFO_REG, id);
> - if (fd == NULL) {
> - pr_perror("Can't find regfile for %#x\n", id);
> - return -1;
> - }
> -
> - return open_fe_fd(fd);
> -}
> -
> #define SETFL_MASK (O_APPEND | O_ASYNC | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
> int set_fd_flags(int fd, int flags)
> {
> diff --git a/include/files-reg.h b/include/files-reg.h
> new file mode 100644
> index 0000000..04b2862
> --- /dev/null
> +++ b/include/files-reg.h
> @@ -0,0 +1,16 @@
> +#ifndef FILES_REG_H__
> +#define FILES_REG_H__
> +
> +#include "types.h"
> +
> +struct cr_fdset;
> +struct fd_parms;
> +
> +extern int open_reg_by_id(u32 id);
> +extern void clear_ghost_files(void);
> +extern int collect_reg_files(void);
> +
> +extern int dump_reg_file(struct fd_parms *p, int lfd, const struct cr_fdset *set);
> +extern int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p);
> +
> +#endif /* FILES_REG_H__ */
> --
> 1.7.7.6
>
> .
>
More information about the CRIU
mailing list