libfstools: move mount points when switching to JFFS2
authorRafał Miłecki <rafal@milecki.pl>
Mon, 16 Apr 2018 14:11:47 +0000 (16:11 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Mon, 16 Apr 2018 17:10:17 +0000 (19:10 +0200)
Switching from "tmpfs" to "jffs2" happens after JFFS2 formatting is
done. During that time user can use filesystem (thanks to RAM) and the
role of switch2jffs() is to copy all changes to the JFFS2 overlay
partition.

What wasn't handled so far was moving mount points. User can create
custom mounts, cp command won't copy them and umounting "tmpfs" will
cause these mounts to go away. To preserve them switch2jffs() has to
find all custom mount points and move them to the new filesystem.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: John Crispin <john@phrozen.org>
libfstools/overlay.c

index a41364c5e3e14b8ce319052f685612759fc82724..ebc43f70257a24d00719f8dd2af7a48180a2d41f 100644 (file)
@@ -112,6 +112,24 @@ foreachdir(const char *dir, int (*cb)(const char*))
        cb(dir);
 }
 
+static void foreach_mount(int (*cb)(const char *, const char *))
+{
+       FILE *fp = fopen("/proc/mounts", "r");
+       static char line[256];
+
+       if (!fp)
+               return;
+
+       while (fgets(line, sizeof(line), fp)) {
+               char device[32], mount_point[32];
+
+               if (sscanf(line, "%31s %31s %*s %*s %*u %*u", device, mount_point) == 2)
+                       cb(device, mount_point);
+       }
+
+       fclose(fp);
+}
+
 void
 overlay_delete(const char *dir, bool _keep_sysupgrade)
 {
@@ -135,6 +153,19 @@ overlay_mount(struct volume *v, char *fs)
        return 0;
 }
 
+/**
+ * move_mount - move mount point to the new root
+ */
+static int move_mount(const char *device, const char *mount_point)
+{
+       static const char *prefix = "/tmp/root/";
+
+       if (strncmp(mount_point, prefix, strlen(prefix)))
+               return 0;
+
+       return mount_move(prefix, "/", mount_point + strlen(prefix));
+}
+
 static int
 switch2jffs(struct volume *v)
 {
@@ -174,7 +205,20 @@ switch2jffs(struct volume *v)
                return -1;
        }
 
-       return fopivot("/overlay", "/rom");
+       ret = fopivot("/overlay", "/rom");
+
+       /*
+        * Besides copying overlay data from "tmpfs" to "jffs2" we should also
+        * move mount points that user could create during JFFS2 formatting.
+        * This has to happen after fopivot call because:
+        * 1) It's trivial to find mount points to move then (/tmp/root/...).
+        * 2) We can't do that earlier using /rom/overlay/upper/ as overlay(fs)
+        *    doesn't support mounts. Mounting to upper dir don't make overlay
+        *    /propagate/ files to the target dir.
+        */
+       foreach_mount(move_mount);
+
+       return ret;
 }
 
 int