From a04149fbb7c1952da1194d1514e298ff07dbc7ca Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Fri, 22 Apr 2022 11:30:09 +0200 Subject: [PATCH 1/2] libmount: when moving a mount point, all sub mount entries in utab should also be updated Given that /run/mount/utab stores paths, this file needs to be adjusted when a mount tree is moved. However the moved tree may contains sub mount points in which case their utab entries (if any) need to also be translated. This patch takes care of that. As suggested in https://github.com/systemd/systemd/issues/15266, a better approach might be to store mount IDs instead of paths since mount IDs remain unchanged when mount trees are moved. Fixes: #1659 --- libmount/src/tab_update.c | 44 +++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c index b68553515..51f2fae26 100644 --- a/libmount/src/tab_update.c +++ b/libmount/src/tab_update.c @@ -30,6 +30,7 @@ #include "mountP.h" #include "mangle.h" #include "pathnames.h" +#include "strutils.h" struct libmnt_update { char *target; @@ -762,13 +763,44 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l tb = __mnt_new_table_from_file(upd->filename, upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); if (tb) { - struct libmnt_fs *cur = mnt_table_find_target(tb, - mnt_fs_get_srcpath(upd->fs), MNT_ITER_BACKWARD); - if (cur) { - rc = mnt_fs_set_target(cur, mnt_fs_get_target(upd->fs)); - if (!rc) - rc = update_table(upd, tb); + const char *upd_source = mnt_fs_get_srcpath(upd->fs); + const char *upd_target = mnt_fs_get_target(upd->fs); + struct libmnt_iter itr; + struct libmnt_fs *fs; + + mnt_reset_iter(&itr, MNT_ITER_BACKWARD); + while(mnt_table_next_fs(tb, &itr, &fs) == 0) { + char *p, *e; + size_t len; + + e = startswith(mnt_fs_get_target(fs), upd_source); + if (!e) + continue; + + len = strlen(upd_target) + strlen(e) + 2; + p = malloc(len); + if (!p) + rc = -ENOMEM; + else { + char *cn; + + strcpy(p, upd_target); + strcat(p, "/"); + strcat(p, e); + + cn = mnt_resolve_path(p, NULL); + rc = mnt_fs_set_target(fs, cn); + + free(cn); + free(p); + } + + if (rc < 0) + break; } + + if (!rc) + rc = update_table(upd, tb); } if (lc) -- 2.35.1