]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: when moving a mount point, all sub mount entries in utab should also be...
authorFranck Bui <fbui@suse.com>
Fri, 22 Apr 2022 09:30:09 +0000 (11:30 +0200)
committerFranck Bui <fbui@suse.com>
Fri, 22 Apr 2022 09:31:05 +0000 (11:31 +0200)
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

index b685535151abd6e996e37d28b5a434161f04829f..51f2fae260ccdc665cd7f56a38246b678bc411cc 100644 (file)
@@ -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)