[CRIU] [PATCH v3 4/6] files-reg: Create ghost files in existing parent directory
Kirill Tkhai
ktkhai at virtuozzo.com
Tue Dec 29 06:05:38 PST 2015
Since a deleted file may belong to a deleted directory
(which, in turn, may belong to another deleted, etc),
it's necessary to recreate all missing dentries in the path.
Doing this in mkreg_ghost() is not a good idea, because
another ghost file may need some of the dentries in the path,
and this requires to do refcouting of recreated directories.
To avoid this, we restore a ghost file in the directory,
which is GhostFileEntry::nr_up order parent for the file.
This guarantees, the ghost file will be in the same mount
with target file (rfi_remap() uses link() and it needs this).
v2: Create ghost file in parent directory instead of in "/".
v3: Use GhostFileEntry::nr_up instead of first existing parent.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
files-reg.c | 49 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/files-reg.c b/files-reg.c
index 2f41a84..1e83a00 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -96,14 +96,54 @@ static int note_link_remap(char *path, struct ns_id *nsid)
return -1;
}
+static int trim_parents(char *path, int nr)
+{
+ char *last, *p;
+
+ if (nr == 0)
+ return 0;
+
+ p = last = strrchr(path, '/');
+ if (!last)
+ return -1;
+
+ while (nr > 0 && --p >= path) {
+ if (*p == '/')
+ nr--;
+ }
+
+ if (nr) {
+ pr_err("Can't trim %d parent dir in %s", nr, path);
+ return -1;
+ }
+
+ while (*++last != '\0')
+ *++p = *last;
+ *++p = '\0';
+
+ return 0;
+}
+
static int mkreg_ghost(char *path, GhostFileEntry *gfe, struct ghost_file *gf, struct cr_img *img)
{
- int gfd, ret;
+ int gfd, ret, len, i = 0;
- gfd = open(path, O_WRONLY | O_CREAT | O_EXCL, gfe->mode);
- if (gfd < 0)
+ if (trim_parents(path, gfe->nr_up) < 0)
return -1;
+ len = strlen(path);
+again:
+ gfd = open(path, O_WRONLY | O_CREAT | O_EXCL, gfe->mode);
+
+ if (gfd < 0) {
+ if (errno != EEXIST || ++i == INT_MAX)
+ return -1;
+ sprintf(path + len, ".%x", i);
+ goto again;
+ }
+
+ strcpy(gf->remap.rpath, path);
+
ret = copy_file(img_raw_fd(img), gfd, 0);
close(gfd);
@@ -149,7 +189,8 @@ static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_im
if (mkreg_ghost(path, gfe, gf, img)) {
pr_perror("Can't create ghost regfile\n");
goto err;
- }
+ }
+ /* path may be changed */
}
if (chown(path, gfe->uid, gfe->gid) < 0) {
More information about the CRIU
mailing list