diff options
author | Felix Fietkau <nbd@openwrt.org> | 2015-03-22 15:59:33 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2015-03-22 15:59:34 +0100 |
commit | eb9181b33bdda2e1ce81094d77913f7b68e26156 (patch) | |
tree | 136300a04f0c82509bf92245b240e181a5566e0a /libfstools/overlay.c | |
parent | aa59a26581d5350ef065854bd0b8a86de910700b (diff) | |
download | fstools-eb9181b33bdda2e1ce81094d77913f7b68e26156.tar.gz |
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 <nbd@openwrt.org>
Diffstat (limited to 'libfstools/overlay.c')
-rw-r--r-- | libfstools/overlay.c | 58 |
1 files changed, 57 insertions, 1 deletions
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 <sys/stat.h> #include <sys/types.h> #include <sys/mount.h> +#include <sys/syscall.h> #include <asm/byteorder.h> @@ -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"); |