[CRIU] [PATCH 1/6] files: Add ability to use read link in dump_one_reg_file
Pavel Emelyanov
xemul at parallels.com
Tue May 14 16:41:45 EDT 2013
On 05/13/2013 07:38 PM, Cyrill Gorcunov wrote:
>
> To be able to dump procfs namespace entries we will need to
> analyze the link name first and then figure out if the file
> referred indeed a procfs entry or it's plain regular file.
>
> This means we read link early, and to escape double reading
> of same link, once we read it we remember it in fd_parms
> structure which we pass to dump_one_reg_file.
>
> Still the dump_one_reg_file is not solely used from inside
> of dump_one_file, but from a number of other places (fifo,
> special files) where fd_parms is filled only partially
> and fill_fd_params is not even called. Thus dump_one_reg_file
> must be ready for such scenario and read the link name by own
> if the caller has not provided one.
>
> To achieve all this we do
>
> - extend fd_parms structure to have a reference on a new
> fd_link structure, thus if caller already read the link
> name it might assign the reference and call for dump_one_reg_file
>
> - tune up dump_one_reg_file to fill own copy of fd_link
> structure if the caller has not provied one
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> files-reg.c | 24 +++++++++++++-----------
> files.c | 25 ++++++++++++++++++++++++-
> include/files.h | 9 +++++++++
> 3 files changed, 46 insertions(+), 12 deletions(-)
>
> diff --git a/files-reg.c b/files-reg.c
> index 684cfd3..a473fab 100644
> --- a/files-reg.c
> +++ b/files-reg.c
> @@ -432,36 +432,38 @@ static int check_path_remap(char *rpath, int plen, const struct stat *ost, int l
>
> int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
> {
> - char rpath[PATH_MAX + 1] = ".", *path = rpath + 1;
> - int len, rfd;
> + struct fd_link _link, *link;
> + int rfd;
>
> RegFileEntry rfe = REG_FILE_ENTRY__INIT;
>
> - len = read_fd_link(lfd, path, sizeof(rpath) - 1);
> - if (len < 0) {
> - pr_err("Can't read link\n");
> - return len;
> + if (!p->link) {
> + if (fill_fdlink(lfd, p, &_link))
Make fill_fdlink assign p->link = &link and thus if would look like
if (!p->link)
fill_fdlink(lfd, p, &_link);
link = p->link;
and (see below) ...
> + return -1;
> + link = &_link;
> + } else {
> + link = p->link;
> }
>
> pr_info("Dumping path for %d fd via self %d [%s]\n",
> - p->fd, lfd, path);
> + p->fd, lfd, &link->name[1]);
>
> /*
> * The regular path we can handle should start with slash.
> */
> - if (path[0] != '/') {
> - pr_err("The path [%s] is not supported\n", path);
> + if (link->name[1] != '/') {
> + pr_err("The path [%s] is not supported\n", &link->name[1]);
> return -1;
> }
>
> - if (check_path_remap(rpath, len, &p->stat, lfd, id))
> + if (check_path_remap(link->name, link->len, &p->stat, lfd, id))
> return -1;
>
> rfe.id = id;
> rfe.flags = p->flags;
> rfe.pos = p->pos;
> rfe.fown = (FownEntry *)&p->fown;
> - rfe.name = path;
> + rfe.name = &link->name[1];
>
> rfd = fdset_fd(glob_fdset, CR_FD_REG_FILES);
>
> diff --git a/files.c b/files.c
> index 786eca7..24eb34a 100644
> --- a/files.c
> +++ b/files.c
> @@ -135,6 +135,23 @@ int do_dump_gen_file(struct fd_parms *p, int lfd,
> return pb_write_one(fdinfo, &e, PB_FDINFO);
> }
>
> +int fill_fdlink(int lfd, const struct fd_parms *p, struct fd_link *link)
> +{
> + char *path = &link->name[1];
> + size_t len;
> +
> + link->name[0] = '.';
> +
> + len = read_fd_link(lfd, path, sizeof(link->name) - 1);
> + if (len < 0) {
> + pr_err("Can't read link for pid %d fd %d\n", p->pid, p->fd);
> + return -1;
> + }
> +
> + link->len = len + 1;
> + return 0;
> +}
> +
> static int fill_fd_params(struct parasite_ctl *ctl, int fd, int lfd,
> struct fd_opts *opts, struct fd_parms *p)
> {
> @@ -244,8 +261,14 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
> return dump_unsupp_fd(&p);
> }
>
> - if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode))
> + if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode)) {
> + struct fd_link link;
> +
> + if (fill_fdlink(lfd, &p, &link))
> + return -1;
> + p.link = &link;
This place would be shorter.
> return dump_reg_file(&p, lfd, fdinfo);
> + }
>
> if (S_ISFIFO(p.stat.st_mode)) {
> if (statfs.f_type == PIPEFS_MAGIC)
> diff --git a/include/files.h b/include/files.h
> index 5ecc550..6331911 100644
> --- a/include/files.h
> +++ b/include/files.h
> @@ -17,6 +17,11 @@ struct cr_fdset;
> struct rst_info;
> struct parasite_ctl;
>
> +struct fd_link {
> + char name[PATH_MAX + 1];
Is it nice to put 2 more PAGE_SIZE things on stack?
> + size_t len;
> +};
> +
> struct fd_parms {
> int fd;
> unsigned long pos;
> @@ -25,6 +30,7 @@ struct fd_parms {
> struct stat stat;
> pid_t pid;
> FownEntry fown;
> + struct fd_link *link;
>
> struct parasite_ctl *ctl;
> };
> @@ -33,8 +39,11 @@ struct fd_parms {
> { \
> .fd = FD_DESC_INVALID, \
> .fown = FOWN_ENTRY__INIT, \
> + .link = NULL, \
> }
>
> +extern int fill_fdlink(int lfd, const struct fd_parms *p, struct fd_link *link);
> +
> struct file_desc;
>
> struct fdinfo_list_entry {
More information about the CRIU
mailing list