[CRIU] [PATCH v3 1/6] files-reg: Account number of unlinked parent components of ghost file
Kirill Tkhai
ktkhai at virtuozzo.com
Tue Dec 29 06:05:08 PST 2015
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
files-reg.c | 69 ++++++++++++++++++++++++++++++++++++++-------
protobuf/ghost-file.proto | 1 +
2 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/files-reg.c b/files-reg.c
index 0f89be5..3e09ae0 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -48,6 +48,7 @@ struct ghost_file {
u32 dev;
u32 ino;
+ u32 nr_up;
struct file_remap remap;
};
@@ -223,6 +224,7 @@ static int open_remap_ghost(struct reg_file_info *rfi,
gf->dev = gfe->dev;
gf->ino = gfe->ino;
gf->remap.rmnt_id = rfi->rfe->mnt_id;
+ gf->nr_up = gfe->has_nr_up ? gfe->nr_up : 0;
if (S_ISDIR(gfe->mode))
strncpy(gf->remap.rpath, rfi->path, PATH_MAX);
@@ -526,7 +528,50 @@ static struct collect_image_info remap_cinfo = {
.collect = collect_one_remap,
};
-static int dump_ghost_file(int _fd, u32 id, const struct stat *st, dev_t phys_dev)
+static int count_unlinked_parents(GhostFileEntry *gfe, const char *path, int mntns_root)
+{
+ struct stat st;
+ char buf[PATH_MAX], *p;
+ int count = 0;
+
+ strcpy(buf, path);
+
+ p = strrchr(buf, '/');
+ if (!p) {
+ pr_err("No parent for %s", buf);
+ count = -1;
+ goto out;
+ }
+
+ while (p > buf) {
+ *p = '\0';
+ if (fstatat(mntns_root, buf, &st, 0) == 0)
+ goto populate;
+
+ if (errno != ENOENT) {
+ pr_perror("Can't stat %s", buf);
+ count = -1;
+ goto out;
+ }
+
+ count++;
+
+ while (--p > buf && *p != '/')
+ continue;
+ }
+
+populate:
+ if (count) {
+ gfe->has_nr_up = true;
+ gfe->nr_up = count;
+ pr_debug("Ghost file %s has %d unlinked parent component(s)", path, count);
+ }
+out:
+ return count;
+}
+
+static int dump_ghost_file(char *path, int _fd, u32 id, const struct stat *st,
+ dev_t phys_dev, int mntns_root)
{
struct cr_img *img;
GhostFileEntry gfe = GHOST_FILE_ENTRY__INIT;
@@ -553,6 +598,9 @@ static int dump_ghost_file(int _fd, u32 id, const struct stat *st, dev_t phys_de
gfe.dev = phys_dev;
gfe.ino = st->st_ino;
+ if (count_unlinked_parents(&gfe, path, mntns_root) < 0)
+ return -1;
+
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
gfe.has_rdev = true;
gfe.rdev = st->st_rdev;
@@ -616,8 +664,8 @@ struct file_remap *lookup_ghost_remap(u32 dev, u32 ino)
return NULL;
}
-static int dump_ghost_remap(char *path, const struct stat *st,
- int lfd, u32 id, struct ns_id *nsid)
+static int dump_ghost_remap(char *path, const struct stat *st, int lfd,
+ u32 id, struct ns_id *nsid, int mntns_root)
{
struct ghost_file *gf;
RemapFilePathEntry rpe = REMAP_FILE_PATH_ENTRY__INIT;
@@ -631,7 +679,7 @@ static int dump_ghost_remap(char *path, const struct stat *st,
return -1;
}
- phys_dev = phys_stat_resolve_dev(nsid, st->st_dev, path);
+ phys_dev = phys_stat_resolve_dev(nsid, st->st_dev, path + 1);
list_for_each_entry(gf, &ghost_files, list)
if ((gf->dev == phys_dev) && (gf->ino == st->st_ino))
goto dump_entry;
@@ -645,7 +693,7 @@ static int dump_ghost_remap(char *path, const struct stat *st,
gf->id = ghost_file_ids++;
list_add_tail(&gf->list, &ghost_files);
- if (dump_ghost_file(lfd, gf->id, st, phys_dev))
+ if (dump_ghost_file(path, lfd, gf->id, st, phys_dev, mntns_root))
return -1;
dump_entry:
@@ -918,6 +966,10 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms,
return 0;
}
+ mntns_root = mntns_get_root_fd(nsid);
+ if (mntns_root < 0)
+ return -1;
+
if (ost->st_nlink == 0) {
/*
* Unpleasant, but easy case. File is completely invisible
@@ -926,7 +978,8 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms,
* also open.
*/
strip_deleted(link);
- return dump_ghost_remap(rpath + 1, ost, lfd, id, nsid);
+
+ return dump_ghost_remap(rpath, ost, lfd, id, nsid, mntns_root);
}
if (nfs_silly_rename(rpath, parms)) {
@@ -941,10 +994,6 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms,
return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id, nsid);
}
- mntns_root = mntns_get_root_fd(nsid);
- if (mntns_root < 0)
- return -1;
-
ret = fstatat(mntns_root, rpath, &pst, 0);
if (ret < 0) {
/*
diff --git a/protobuf/ghost-file.proto b/protobuf/ghost-file.proto
index db056db..6325c99 100644
--- a/protobuf/ghost-file.proto
+++ b/protobuf/ghost-file.proto
@@ -11,4 +11,5 @@ message ghost_file_entry {
optional uint32 rdev = 6 [(criu).dev = true, (criu).odev = true];
optional timeval atim = 7;
optional timeval mtim = 8;
+ optional uint32 nr_up = 9; /* Number of unlinked parent directories */
}
More information about the CRIU
mailing list