mount-util: Compact list of sub mounts after dropping
When nested mounts appear under a sysext hierarchy like this: mkdir -p /opt/trigger/ mount -t tmpfs tmpfs /opt/trigger mkdir -p /opt/trigger/inner mount -t tmpfs tmpfs /opt/trigger/inner Then systemd-sysext merge hit an assertion reported in https://github.com/flatcar/Flatcar/issues/2111 because when it iterates over the list of sub mounts it doesn't expect entries with NULL in the path from the dropped entries. Instead of having to deal with entries with path NULL, better sort the holes from dropping to the end and then reduce the array length.
This commit is contained in:
+23
-8
@@ -1754,21 +1754,36 @@ DEFINE_ARRAY_FREE_FUNC(sub_mount_array_free, SubMount, sub_mount_clear);
|
||||
static int sub_mount_compare(const SubMount *a, const SubMount *b) {
|
||||
assert(a);
|
||||
assert(b);
|
||||
assert(a->path);
|
||||
assert(b->path);
|
||||
|
||||
/* sub_mount_drop() creates NULL paths which we order to the end so that after the sort we can
|
||||
* truncate the array. Done manually because path_compare() orders NULL before non-NULL. */
|
||||
if (!a->path || !b->path)
|
||||
return CMP(!a->path, !b->path);
|
||||
|
||||
return path_compare(a->path, b->path);
|
||||
}
|
||||
|
||||
static void sub_mount_drop(SubMount *s, size_t n) {
|
||||
assert(s || n == 0);
|
||||
static void sub_mount_drop(SubMount *s, size_t *n) {
|
||||
assert(n);
|
||||
assert(s || *n == 0);
|
||||
|
||||
for (size_t m = 0, i = 1; i < n; i++) {
|
||||
/* Works on a sorted array. Drops mounts that are covered by the preceding entry's recursive
|
||||
* open_tree() clone, clearing the slot in place. Then sorts again for the NULL paths to be shifted
|
||||
* past the kept count. */
|
||||
|
||||
size_t kept = *n > 0;
|
||||
for (size_t m = 0, i = 1; i < *n; i++)
|
||||
if (path_startswith(s[i].path, s[m].path))
|
||||
sub_mount_clear(s + i);
|
||||
else
|
||||
else {
|
||||
m = i;
|
||||
}
|
||||
kept++;
|
||||
}
|
||||
|
||||
if (kept < *n)
|
||||
typesafe_qsort(s, *n, sub_mount_compare);
|
||||
|
||||
*n = kept;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1843,7 +1858,7 @@ int get_sub_mounts(const char *prefix, SubMount **ret_mounts, size_t *ret_n_moun
|
||||
}
|
||||
|
||||
typesafe_qsort(mounts, n, sub_mount_compare);
|
||||
sub_mount_drop(mounts, n);
|
||||
sub_mount_drop(mounts, &n);
|
||||
|
||||
*ret_mounts = TAKE_PTR(mounts);
|
||||
*ret_n_mounts = n;
|
||||
|
||||
Reference in New Issue
Block a user