diff mbox series

[LEDE-DEV,fstools] libfstools: move mount points when switching to JFFS2

Message ID 20180416141147.20658-1-zajec5@gmail.com
State Accepted
Headers show
Series [LEDE-DEV,fstools] libfstools: move mount points when switching to JFFS2 | expand

Commit Message

Rafał Miłecki April 16, 2018, 2:11 p.m. UTC
From: Rafał Miłecki <rafal@milecki.pl>

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>
---
 libfstools/overlay.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

Comments

John Crispin April 16, 2018, 3:13 p.m. UTC | #1
On 16/04/18 16:11, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> 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 | 46 +++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/libfstools/overlay.c b/libfstools/overlay.c
> index a41364c..ebc43f7 100644
> --- a/libfstools/overlay.c
> +++ b/libfstools/overlay.c
> @@ -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
diff mbox series

Patch

diff --git a/libfstools/overlay.c b/libfstools/overlay.c
index a41364c..ebc43f7 100644
--- a/libfstools/overlay.c
+++ b/libfstools/overlay.c
@@ -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