From eb9181b33bdda2e1ce81094d77913f7b68e26156 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 22 Mar 2015 15:59:33 +0100 Subject: [PATCH] mount_root: keep track of overlay initialization state (via xattr) Remove all files (except sysupgrade.tgz) if /etc/init.d/done was not called Signed-off-by: Felix Fietkau --- jffs2reset.c | 1 + libfstools/libfstools.h | 10 +++++++++ libfstools/overlay.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++- mount_root.c | 5 +++++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/jffs2reset.c b/jffs2reset.c index c9d4f5f..1080883 100644 --- a/jffs2reset.c +++ b/jffs2reset.c @@ -62,6 +62,7 @@ jffs2_reset(int argc, char **argv) mp = find_mount_point(v->blk, 1); if (mp) { ULOG_INFO("%s is mounted as %s, only erasing files\n", v->blk, mp); + fs_state_set("/overlay", FS_STATE_PENDING); overlay_delete(mp, false); mount(mp, "/", NULL, MS_REMOUNT, 0); } else { diff --git a/libfstools/libfstools.h b/libfstools/libfstools.h index 1d41eea..31d9f9e 100644 --- a/libfstools/libfstools.h +++ b/libfstools/libfstools.h @@ -28,6 +28,13 @@ enum { FS_UBIFS, }; +enum fs_state { + FS_STATE_UNKNOWN, + FS_STATE_PENDING, + FS_STATE_READY, + __FS_STATE_LAST = FS_STATE_READY, +}; + extern char const *extroot_prefix; extern int mount_extroot(void); extern int mount_snapshot(struct volume *v); @@ -50,4 +57,7 @@ extern void foreachdir(const char *dir, int (*cb)(const char*)); extern void overlay_delete(const char *dir, bool keep_sysupgrade); +enum fs_state fs_state_get(const char *dir); +int fs_state_set(const char *dir, enum fs_state state); + #endif diff --git a/libfstools/overlay.c b/libfstools/overlay.c index 7c9b480..3269a52 100644 --- a/libfstools/overlay.c +++ b/libfstools/overlay.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -34,6 +35,18 @@ static bool keep_sysupgrade; +static ssize_t +fs_getxattr(const char *path, const char *name, void *value, size_t size) +{ + return syscall(__NR_getxattr, path, name, value, size); +} + +static ssize_t +fs_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) +{ + return syscall(__NR_setxattr, path, name, value, size, flags); +} + static int handle_rmdir(const char *dir) { @@ -235,7 +248,13 @@ jffs2_switch(struct volume *v) } break; } - return ret; + + if (ret) + return ret; + + sync(); + fs_state_set("/overlay", FS_STATE_READY); + return 0; } static int overlay_mount_fs(struct volume *v) @@ -266,6 +285,28 @@ static int overlay_mount_fs(struct volume *v) return -1; } +enum fs_state fs_state_get(const char *dir) +{ + uint32_t val; + + if (fs_getxattr(dir, "user.fs_state", &val, sizeof(val)) != sizeof(val)) + return FS_STATE_UNKNOWN; + + if (val > __FS_STATE_LAST) + return FS_STATE_UNKNOWN; + + return val; +} + + +int fs_state_set(const char *dir, enum fs_state state) +{ + uint32_t val = state; + + return fs_setxattr(dir, "user.fs_state", &val, sizeof(val), 0); +} + + int mount_overlay(struct volume *v) { char *mp; @@ -287,6 +328,21 @@ int mount_overlay(struct volume *v) return 0; } + switch(fs_state_get("/tmp/overlay")) { + case FS_STATE_UNKNOWN: + fs_state_set("/tmp/overlay", FS_STATE_PENDING); + if (fs_state_get("/tmp/overlay") != FS_STATE_PENDING) { + ULOG_ERR("unable to set filesystem state\n"); + break; + } + case FS_STATE_PENDING: + ULOG_INFO("overlay filesystem has not been fully initialized yet\n"); + overlay_delete("/tmp/overlay", true); + break; + case FS_STATE_READY: + break; + } + ULOG_INFO("switching to jffs2 overlay\n"); if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) { ULOG_ERR("switching to jffs2 failed - fallback to ramoverlay\n"); diff --git a/mount_root.c b/mount_root.c index bfbe217..7b69c7f 100644 --- a/mount_root.c +++ b/mount_root.c @@ -103,6 +103,11 @@ done(int argc, char *argv[1]) case FS_NONE: case FS_DEADCODE: return jffs2_switch(v); + + case FS_JFFS2: + case FS_UBIFS: + fs_state_set("/overlay", FS_STATE_READY); + break; } return 0; -- 2.11.0