Commit 6345b6aa authored by Kirill Tkhai's avatar Kirill Tkhai Committed by Pavel Emelyanov

files-reg: Create ghost files in first existing parent directory

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 first existing
parent directory of the patch. This guarantees, the ghost file
will be in the same mount with target file (rfi_remap() needs
that, because it uses link()).
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 685953e4
...@@ -95,6 +95,33 @@ err: ...@@ -95,6 +95,33 @@ err:
return -1; return -1;
} }
/* Trim "a/b/c/d" to "a/b/d" */
static int trim_last_parent(char *path)
{
char *fname, *p;
p = strrchr(path, '/');
fname = p + 1;
if (!p || *fname == '\0')
return -1;
while (p >= path && *p == '/')
p--;
if (p < path)
return -1;
while (p >= path && *p != '/')
p--;
p++;
while (*fname != '\0')
*p++ = *fname++;
*p = '\0';
return 0;
}
static int mkreg_ghost(char *path, u32 mode, struct ghost_file *gf, struct cr_img *img) static int mkreg_ghost(char *path, u32 mode, struct ghost_file *gf, struct cr_img *img)
{ {
int gfd, ret; int gfd, ret;
...@@ -142,45 +169,67 @@ err: ...@@ -142,45 +169,67 @@ err:
static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_img *img) static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_img *img)
{ {
int ret, len, root_len, try = 0;
char path[PATH_MAX]; char path[PATH_MAX];
int ret; char *msg;
ret = rst_get_mnt_root(gf->remap.rmnt_id, path, sizeof(path)); root_len = ret = rst_get_mnt_root(gf->remap.rmnt_id, path, sizeof(path));
if (ret < 0) { if (ret < 0) {
pr_err("The %d mount is not found for ghost\n", gf->remap.rmnt_id); pr_err("The %d mount is not found for ghost\n", gf->remap.rmnt_id);
goto err; goto err;
} }
snprintf(path + ret, sizeof(path) - ret, "/%s", gf->remap.rpath); len = snprintf(path + ret, sizeof(path) - ret, "/%s", gf->remap.rpath) + ret;
ret = -1; ret = -1;
again:
if (S_ISFIFO(gfe->mode)) { if (S_ISFIFO(gfe->mode)) {
if (mknod(path, gfe->mode, 0)) { if ((ret = mknod(path, gfe->mode, 0)) < 0)
pr_perror("Can't create node for ghost file"); msg = "Can't create node for ghost file";
goto err;
}
} else if (S_ISCHR(gfe->mode) || S_ISBLK(gfe->mode)) { } else if (S_ISCHR(gfe->mode) || S_ISBLK(gfe->mode)) {
if (!gfe->has_rdev) { if (!gfe->has_rdev) {
pr_err("No rdev for ghost device\n"); pr_err("No rdev for ghost device\n");
goto err; goto err;
} }
if ((ret = mknod(path, gfe->mode, gfe->rdev)) < 0)
if (mknod(path, gfe->mode, gfe->rdev)) { msg = "Can't create node for ghost dev";
pr_perror("Can't create node for ghost dev");
goto err;
}
} else if (S_ISDIR(gfe->mode)) { } else if (S_ISDIR(gfe->mode)) {
if (mkdir(path, gfe->mode)) { if ((ret = mkdir(path, gfe->mode)) < 0) {
pr_perror("Can't make ghost dir"); pr_perror("Can't make ghost dir");
goto err; goto err;
} }
} else { } else {
if (mkreg_ghost(path, gfe->mode, gf, img)) { if ((ret = mkreg_ghost(path, gfe->mode, gf, img)) < 0)
pr_perror("Can't create ghost regfile\n"); msg = "Can't create ghost regfile\n";
}
if (ret < 0) {
/* Use grand parent, if parent directory does not exist */
if (errno == ENOENT) {
if (trim_last_parent(path) < 0) {
pr_err("trim failed: @%s@\n", path);
goto err;
}
len = strlen(path);
goto again;
}
/* Use numeric suffix, if a namesake already exists */
if (errno != EEXIST) {
pr_perror("%s", msg);
goto err; goto err;
} }
if (++try == INT_MAX) {
pr_err("Can't find available file name\n");
goto err;
}
sprintf(path + len, ".%x", try);
goto again;
} }
strcpy(gf->remap.rpath, path + root_len + 1);
pr_debug("Remap rpath is %s\n", gf->remap.rpath);
ret = -1; ret = -1;
if (ghost_apply_metadata(path, gfe)) if (ghost_apply_metadata(path, gfe))
goto err; goto err;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment