Skip to content

Instantly share code, notes, and snippets.

@aep
Created April 27, 2018 12:44
Show Gist options
  • Save aep/09eaf088b54c2d3e93d1b3a638e1de99 to your computer and use it in GitHub Desktop.
Save aep/09eaf088b54c2d3e93d1b3a638e1de99 to your computer and use it in GitHub Desktop.
fstools: use ramoverlay if no rootfs_data and rootfs is ro
- libfstools/mtd.c no longer fails if volume is ro.
- mount_root ramoverlay if no rootfs_data and rootfs is ro
Signed-off-by: Arvid E. Picciani <[email protected]>
---
libfstools/mtd.c | 35 ++++++++++++++++++++++-------------
libfstools/volume.c | 24 ++++++++++++++++++++++++
libfstools/volume.h | 1 +
mount_root.c | 11 +++++++++++
4 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/libfstools/mtd.c b/libfstools/mtd.c
index 77c71ee..4ff10ca 100644
--- a/libfstools/mtd.c
+++ b/libfstools/mtd.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <mtd/mtd-user.h>
+#include <stdint.h>
#include "libfstools.h"
@@ -32,15 +33,18 @@ struct mtd_volume {
int fd;
int idx;
char *chr;
+ int is_writable;
};
static struct driver mtd_driver;
-static int mtd_open(const char *mtd, int block)
+static int mtd_open(const char *mtd, int block, int open_writable)
{
FILE *fp;
char dev[PATH_MAX];
- int i, ret, flags = O_RDWR | O_SYNC;
+ int i, ret, flags = O_SYNC;
+ if (open_writable)
+ flags |= O_RDWR;
if ((fp = fopen("/proc/mtd", "r"))) {
while (fgets(dev, sizeof(dev), fp)) {
@@ -70,24 +74,29 @@ static void mtd_volume_close(struct mtd_volume *p)
p->fd = 0;
}
-static int mtd_volume_load(struct mtd_volume *p)
+static int mtd_volume_load(struct mtd_volume *p, int open_writable)
{
struct volume *v = &p->v;
struct mtd_info_user mtdInfo;
struct erase_info_user mtdLockInfo;
if (p->fd) {
- lseek(p->fd, 0, SEEK_SET);
- return 0;
+ if (!open_writable || p->is_writable) {
+ lseek(p->fd, 0, SEEK_SET);
+ return 0;
+ } else {
+ close(p->fd);
+ p->fd = 0;
+ }
}
if (!p->chr)
return -1;
- p->fd = mtd_open(p->chr, 0);
+ p->fd = mtd_open(p->chr, 0, open_writable);
if (p->fd < 0) {
p->fd = 0;
- ULOG_ERR("Could not open mtd device: %s\n", p->chr);
+ ULOG_ERR("Could not open mtd device%s: %s\n", open_writable ? " writable": "", p->chr);
return -1;
}
@@ -174,7 +183,7 @@ static struct volume *mtd_volume_find(char *name)
snprintf(buffer, sizeof(buffer), "/dev/mtd%s", idx);
p->chr = strdup(buffer);
- if (mtd_volume_load(p)) {
+ if (mtd_volume_load(p, 0)) {
ULOG_ERR("reading %s failed\n", v->name);
free(p);
return NULL;
@@ -190,7 +199,7 @@ static int mtd_volume_identify(struct volume *v)
__u16 jffs2;
size_t sz;
- if (mtd_volume_load(p)) {
+ if (mtd_volume_load(p, 0)) {
ULOG_ERR("reading %s failed\n", v->name);
return -1;
}
@@ -228,7 +237,7 @@ static int mtd_volume_erase(struct volume *v, int offset, int len)
struct erase_info_user eiu;
int first_block, num_blocks;
- if (mtd_volume_load(p))
+ if (mtd_volume_load(p, 1))
return -1;
if (offset % v->block_size || len % v->block_size) {
@@ -270,7 +279,7 @@ static int mtd_volume_init(struct volume *v)
struct mtd_info_user mtdinfo;
int ret;
- if (mtd_volume_load(p))
+ if (mtd_volume_load(p, 0))
return -1;
ret = ioctl(p->fd, MEMGETINFO, &mtdinfo);
@@ -291,7 +300,7 @@ static int mtd_volume_read(struct volume *v, void *buf, int offset, int length)
{
struct mtd_volume *p = container_of(v, struct mtd_volume, v);;
- if (mtd_volume_load(p))
+ if (mtd_volume_load(p, 0))
return -1;
if (lseek(p->fd, offset, SEEK_SET) == (off_t) -1) {
@@ -311,7 +320,7 @@ static int mtd_volume_write(struct volume *v, void *buf, int offset, int length)
{
struct mtd_volume *p = container_of(v, struct mtd_volume, v);;
- if (mtd_volume_load(p))
+ if (mtd_volume_load(p, 1))
return -1;
if (lseek(p->fd, offset, SEEK_SET) == (off_t) -1) {
diff --git a/libfstools/volume.c b/libfstools/volume.c
index 0d293d5..9b8a6af 100644
--- a/libfstools/volume.c
+++ b/libfstools/volume.c
@@ -14,6 +14,10 @@
#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stropts.h>
#include "libfstools.h"
#include "volume.h"
@@ -41,3 +45,23 @@ struct volume* volume_find(char *name)
return NULL;
}
+
+int
+volume_is_ro(struct volume *v)
+{
+ if (!v || !v->blk)
+ return 0;
+
+ int flag = 0;
+ int fd = open(v->blk, O_RDONLY);
+
+ if (fd < 0)
+ return 0;
+
+ if (ioctl (fd, BLKROGET, &flag) == -1)
+ flag = 0;
+
+ close(fd);
+ return flag;
+}
+
diff --git a/libfstools/volume.h b/libfstools/volume.h
index 912b711..6460dad 100644
--- a/libfstools/volume.h
+++ b/libfstools/volume.h
@@ -62,6 +62,7 @@ struct volume {
extern struct volume* volume_find(char *name);
extern void volume_register_driver(struct driver *drv);
+extern int volume_is_ro(struct volume *v);
static inline int volume_init(struct volume *v)
{
diff --git a/mount_root.c b/mount_root.c
index dffb0a6..6dccf24 100644
--- a/mount_root.c
+++ b/mount_root.c
@@ -33,6 +33,7 @@ start(int argc, char *argv[1])
struct volume *root;
struct volume *data = volume_find("rootfs_data");
struct stat s;
+ int overlay_from_ramfs = 0;
if (!getenv("PREINIT") && stat("/tmp/.preinit", &s))
return -1;
@@ -42,6 +43,11 @@ start(int argc, char *argv[1])
volume_init(root);
ULOG_NOTE("mounting /dev/root\n");
mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT, 0);
+
+ // if root is read only and there's no roofs_data, get an overlay from either extroot or ramfs
+ if (volume_is_ro(root)) {
+ overlay_from_ramfs = 1;
+ }
}
/*
@@ -55,6 +61,11 @@ start(int argc, char *argv[1])
return 0;
}
+ if (overlay_from_ramfs) {
+ ULOG_WARN("no rootfs_data and rootfs is read only, using tmpfs overlay\n");
+ return ramoverlay();
+ }
+
/* There isn't extroot, so just try to mount "rootfs_data" */
volume_init(data);
switch (volume_identify(data)) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment