[CRIU] [PATCH v4 5/6] files-reg: Recreate deleted parent directories during restore of ghost file
Pavel Emelyanov
xemul at virtuozzo.com
Wed Jan 27 07:15:41 PST 2016
>>> + int err, count = 0;
>>> + struct stat st;
>>> +
>>> + sprintf_parent_dir(pdir, path);
>>> +
>>> + if (fstatat(mntns_root, pdir, &st, AT_EMPTY_PATH) == 0)
>>
>> Is this fstatat() required? The below mkdir() would return EEXISTS anyway.
>
> fstatat() checks parent path, and it's a likely case when the whole hierarhy exists.
>
> mkdir() creates directories from grand..grand parent to parent:
>
> /dir
> /dir/subdir
> /dir/subdir/childsubdir
> ...
>
> I don't think it's good to use mkdir for the whole hierarhy for every file.
Ah! OK, this makes sense. Plz, write this as code comment to the fstatat() call.
> Maybe you mean something else?
>
>>> + return 0;
>>> + if (errno != ENOENT) {
>>> + pr_perror("Can't stat %s", pdir);
>>> + return -1;
>>> + }
>>> +
>>> + p = pdir;
>>> + do {
>>> + p = strchr(p, '/');
>>> + if (p)
>>> + *p = '\0';
>>> +
>>> + err = mkdirat(mntns_root, pdir, 0777);
>>> + if (err && errno != EEXIST) {
>>> + pr_perror("Can't create dir: %s AT %d", pdir, mntns_root);
>>> + goto cleanup;
>>> + } else if (!err) {
>>> + pr_debug("Created parent dir: %s AT %d\n", pdir, mntns_root);
>>> + count++;
>>> + }
>>> +
>>> + if (p)
>>> + *p++ = '/';
>>> + } while (p);
>>> +
>>> + return count;
>>> +cleanup:
>>> + rm_parent_dirs(mntns_root, pdir, count);
>>> + return -1;
>>> +}
>>> +
>>> /*
>>> * This routine properly resolves d's path handling ghost/link-remaps.
>>> * The open_cb is a routine that does actual open, it differs for
>>> * files, directories, fifos, etc.
>>> */
>>>
>>> -static int rfi_remap(struct reg_file_info *rfi)
>>> +static int rfi_remap(struct reg_file_info *rfi, int *level)
>>> {
>>> struct mount_info *mi, *rmi, *tmi;
>>> char _path[PATH_MAX], *path = _path;
>>> @@ -1269,14 +1346,23 @@ static int rfi_remap(struct reg_file_info *rfi)
>>> mntns_root = mntns_get_root_fd(tmi->nsid);
>>>
>>> out_root:
>>> - return linkat_hard(mntns_root, rpath, mntns_root, path, rfi->remap->owner);
>>> + *level = make_parent_dirs_if_need(mntns_root, path);
>>> + if (*level < 0)
>>> + return -1;
>>> +
>>> + if (linkat_hard(mntns_root, rpath, mntns_root, path, rfi->remap->owner) < 0) {
>>> + rm_parent_dirs(mntns_root, path, *level);
>>> + return -1;
>>> + }
>>> +
>>> + return 0;
>>> }
>>>
>>> int open_path(struct file_desc *d,
>>> int(*open_cb)(int mntns_root, struct reg_file_info *, void *), void *arg)
>>> {
>>> + int tmp, mntns_root, level;
>>> struct reg_file_info *rfi;
>>> - int tmp, mntns_root;
>>> char *orig_path = NULL;
>>>
>>> if (inherited_fd(d, &tmp))
>>> @@ -1292,7 +1378,7 @@ int open_path(struct file_desc *d,
>>> */
>>> orig_path = rfi->path;
>>> rfi->path = rfi->remap->rpath;
>>> - } else if (rfi_remap(rfi) < 0) {
>>> + } else if (rfi_remap(rfi, &level) < 0) {
>>> static char tmp_path[PATH_MAX];
>>>
>>> if (errno != EEXIST) {
>>> @@ -1316,7 +1402,7 @@ int open_path(struct file_desc *d,
>>> snprintf(tmp_path, sizeof(tmp_path), "%s.cr_link", orig_path);
>>> pr_debug("Fake %s -> %s link\n", rfi->path, rfi->remap->rpath);
>>>
>>> - if (rfi_remap(rfi) < 0) {
>>> + if (rfi_remap(rfi, &level) < 0) {
>>> pr_perror("Can't create even fake link!");
>>> return -1;
>>> }
>>> @@ -1356,6 +1442,7 @@ int open_path(struct file_desc *d,
>>> if (rfi->remap) {
>>> if (!rfi->remap->is_dir) {
>>> unlinkat(mntns_root, rfi->path, 0);
>>> + rm_parent_dirs(mntns_root, rfi->path, level);
>>> }
>>>
>>> BUG_ON(!rfi->remap->users);
>>>
>>> .
>>>
>>
> .
>
More information about the CRIU
mailing list