2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-30 22:05:36 +00:00

mount: skip fstype and source checks for external mounts in mounts_sb_equal

Fstype and source fields can be changed by resolve_external_mounts() or
by try_resolve_ext_mount() for external mounts, but we can have other
mounts from same superblock which are not detected as external, for
instance bind of subdirectory from device-external or bind of
mountpoint-external mount to other mountpoint. So we need to still be
able to find bindmounts between mounts with changed fstype or source and
unchanged mounts.

So let's make fstype/source checks in mounts_sb_equal ignored for
external mounts. Leave only fstype->sb_equal checks if have them.

Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>

Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/fadc38d84
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/f9700cb12

Changes: merge two commits in one and rework, remove ":)", reword
commit-message to make patch self-sufficient.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Alexander Mikhalitsyn
2020-04-21 18:12:00 +03:00
committed by Andrei Vagin
parent 8d5300aa9b
commit 30261a7515

View File

@@ -294,17 +294,30 @@ bool phys_stat_dev_match(dev_t st_dev, dev_t phys_dev, struct ns_id *ns, const c
*/
static bool mounts_sb_equal(struct mount_info *a, struct mount_info *b)
{
if (a->fstype != b->fstype)
return false;
if (a->s_dev != b->s_dev)
return false;
if (strcmp(a->source, b->source) != 0)
return false;
/*
* If one of compared mounts is external its mount info can have fstype
* and source fields changed by resolve_external_mounts() or
* try_resolve_ext_mount(), but we still want to detect bindmounts of
* this external mount, so let's skip source and fstype checks for it.
*/
if (!a->external && !b->external) {
if (strcmp(a->source, b->source) != 0)
return false;
if (a->fstype->sb_equal) /* :) */
return b->fstype->sb_equal(a, b);
if (a->fstype != b->fstype)
return false;
if (a->fstype->sb_equal)
return a->fstype->sb_equal(a, b);
} else {
if (a->fstype->sb_equal)
return a->fstype->sb_equal(a, b);
else if (b->fstype->sb_equal)
return b->fstype->sb_equal(a, b);
}
if (strcmp(a->options, b->options))
return false;