Commit e54d0d26 authored by Pavel Tikhomirov's avatar Pavel Tikhomirov Committed by Andrei Vagin

mount: fix regression where open_mountpoint failed on readonly fs

If we fail to create temporary directory for doing a clean mount we can
make mount clean reusing the code which enters new mountns to umount
overmounts. As when last process exits mntns all mounts are implicitly
cleaned from children, see in kernel source - sys_exit->do_exit
->exit_task_namespaces->switch_task_namespaces->free_nsproxy
->put_mnt_ns->umount_tree->drop_collected_mounts->umount_tree:

    /* Hide the mounts from mnt_mounts */
    list_for_each_entry(p, &tmp_list, mnt_list) {
            list_del_init(&p->mnt_child);
    }

Fixes commit b6cfb1ce2948 ("mount: make open_mountpoint handle overmouts
properly")

https://github.com/checkpoint-restore/criu/issues/520Signed-off-by: 's avatarPavel Tikhomirov <ptikhomirov@virtuozzo.com>
Acked-by: 's avatarAdrian Reber <areber@redhat.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 382756a4
...@@ -1325,10 +1325,18 @@ int ns_open_mountpoint(void *arg) ...@@ -1325,10 +1325,18 @@ int ns_open_mountpoint(void *arg)
if (umount_overmounts(mi)) if (umount_overmounts(mi))
goto err; goto err;
/* Save fd which we opened for parent due to CLONE_FILES flag */ /*
*fd = get_clean_fd(mi); * Save fd which we opened for parent due to CLONE_FILES flag
if (*fd < 0) *
* Mount can still have children in it, but we don't need to clean it
* explicitly as when last process exits mntns all mounts in it are
* cleaned from their children, and we are exactly the last process.
*/
*fd = open(mi->mountpoint, O_DIRECTORY|O_RDONLY);
if (*fd < 0) {
pr_perror("Unable to open %s", mi->mountpoint);
goto err; goto err;
}
return 0; return 0;
err: err:
...@@ -1367,18 +1375,22 @@ int open_mountpoint(struct mount_info *pm) ...@@ -1367,18 +1375,22 @@ int open_mountpoint(struct mount_info *pm)
if (!mnt_is_overmounted(pm)) { if (!mnt_is_overmounted(pm)) {
pr_info("\tmount has children %s\n", pm->mountpoint); pr_info("\tmount has children %s\n", pm->mountpoint);
fd = get_clean_fd(pm); fd = get_clean_fd(pm);
if (fd < 0) }
goto err;
} else { /*
* Mount is overmounted or probably we can't create a temporary
* direcotry for a cleaned mount
*/
if (fd < 0) {
int pid, status; int pid, status;
struct clone_arg ca = { struct clone_arg ca = {
.mi = pm, .mi = pm,
.fd = &fd .fd = &fd
}; };
pr_info("\tmount is overmounted %s\n", pm->mountpoint); pr_info("\tmount is overmounted or has children %s\n",
pm->mountpoint);
/* /*
* We are overmounted - not accessible in a regular way. We * We are overmounted - not accessible in a regular way. We
......
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