kernel: rootfs auto-mount on ubi

Similar to the rootfs hacks on NOR flash devices, this series
introduces support for auto-attaching (ubi device), auto-creating
(ubiblock device) and mounting the "rootfs" (ubifs or squashfs)
volume.
This is needed so OpenWrt can start without relying on the bootloader
to pass the ubi.mtd, ubi.block, rootfs and rootfstype parameters, but
instead auto-detect the root filesystem according to a simple convention.

OpenWrt-specific:
490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch
491-ubi-auto-create-ubiblock-device-for-rootfs.patch
492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch
493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch

sent upstream:
552-ubifs-respect-silent-mount-flag.patch
http://lists.infradead.org/pipermail/linux-mtd/2014-May/053893.html

v2: actually retry with MS_RDONLY when mounting read-only ubifs root

Signed-off-by: Daniel Golle <daniel@makrotopia.org>

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@41119 3c298f89-4303-0410-b956-a3cf2f4a3e73
master
John Crispin 2014-06-11 12:59:10 +00:00
parent f9d01db1cd
commit 41aefc9332
5 changed files with 418 additions and 0 deletions

View File

@ -0,0 +1,68 @@
From 8a52e4100d7c3a4a1dfddfa02b8864a9b0068c13 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 17 May 2014 03:36:18 +0200
Subject: [PATCH 1/5] ubi: auto-attach mtd device named "ubi" or "data" on boot
To: openwrt-devel@lists.openwrt.org
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/build.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 6e30a3c..999a36b 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1209,6 +1209,36 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
return mtd;
}
+/*
+ * This function tries attaching mtd partitions named either "ubi" or "data"
+ * during boot.
+ */
+static void __init ubi_auto_attach(void)
+{
+ int err;
+ struct mtd_info *mtd;
+ /* try attaching mtd device named "ubi" or "data" */
+ mtd = open_mtd_device("ubi");
+ if (IS_ERR(mtd))
+ mtd = open_mtd_device("data");
+
+ if (!IS_ERR(mtd)) {
+ /* auto-add only media types where UBI makes sense */
+ if (mtd->type == MTD_NANDFLASH ||
+ mtd->type == MTD_DATAFLASH ||
+ mtd->type == MTD_MLCNANDFLASH) {
+ mutex_lock(&ubi_devices_mutex);
+ ubi_msg("auto-attach mtd%d", mtd->index);
+ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0);
+ mutex_unlock(&ubi_devices_mutex);
+ if (err < 0) {
+ ubi_err("cannot attach mtd%d", mtd->index);
+ put_mtd_device(mtd);
+ }
+ }
+ }
+}
+
static int __init ubi_init(void)
{
int err, i, k;
@@ -1298,6 +1328,12 @@ static int __init ubi_init(void)
}
}
+ /* auto-attach mtd devices only if built-in to the kernel and no ubi.mtd
+ * parameter was given */
+ if (config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
+ !ubi_is_module() && !mtd_devs)
+ ubi_auto_attach();
+
err = ubiblock_init();
if (err) {
ubi_err("block: cannot initialize, error %d", err);
--
1.9.2

View File

@ -0,0 +1,74 @@
From 0f3966579815f889bb2fcb4846152c35f65e79c4 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 15 May 2014 21:06:33 +0200
Subject: [PATCH 2/5] ubi: auto-create ubiblock device for rootfs
To: openwrt-devel@lists.openwrt.org
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/block.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 8d659e6..2dbe2f4 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -593,6 +593,44 @@ static int __init ubiblock_create_from_param(void)
return ret;
}
+#define UBIFS_NODE_MAGIC 0x06101831
+static inline int ubi_vol_is_ubifs(struct ubi_volume_desc *desc)
+{
+ int ret;
+ uint32_t magic_of, magic;
+ ret = ubi_read(desc, 0, (char *)&magic_of, 0, 4);
+ if (ret)
+ return 0;
+ magic = le32_to_cpu(magic_of);
+ return magic == UBIFS_NODE_MAGIC;
+}
+
+static void __init ubiblock_create_auto_rootfs(void)
+{
+ int ubi_num, ret, is_ubifs;
+ struct ubi_volume_desc *desc;
+ struct ubi_volume_info vi;
+
+ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) {
+ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY);
+ if (IS_ERR(desc))
+ continue;
+
+ ubi_get_volume_info(desc, &vi);
+ is_ubifs = ubi_vol_is_ubifs(desc);
+ ubi_close_volume(desc);
+ if (is_ubifs)
+ break;
+
+ ret = ubiblock_create(&vi);
+ if (ret)
+ ubi_err("block: can't add '%s' volume, err=%d\n",
+ vi.name, ret);
+ /* always break if we get here */
+ break;
+ }
+}
+
static void ubiblock_remove_all(void)
{
struct ubiblock *next;
@@ -623,6 +661,10 @@ int __init ubiblock_init(void)
if (ret)
goto err_remove;
+ /* auto-attach "rootfs" volume if existing and non-ubifs */
+ if (config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV))
+ ubiblock_create_auto_rootfs();
+
/*
* Block devices are only created upon user requests, so we ignore
* existing volumes.
--
1.9.2

View File

@ -0,0 +1,58 @@
From eea9e1785e4c05c2a3444506aabafa0ae958538f Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 17 May 2014 03:35:02 +0200
Subject: [PATCH 4/5] try auto-mounting ubi0:rootfs in init/do_mounts.c
To: openwrt-devel@lists.openwrt.org
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
init/do_mounts.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 82f2288..faba9c6 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -432,7 +432,27 @@ retry:
out:
put_page(page);
}
-
+
+static int __init mount_ubi_rootfs(void)
+{
+ int flags = MS_SILENT;
+ int err, tried = 0;
+
+ while (tried < 2) {
+ err = do_mount_root("ubi0:rootfs", "ubifs", flags, \
+ root_mount_data);
+ switch (err) {
+ case -EACCES:
+ flags |= MS_RDONLY;
+ tried++;
+ default:
+ return err;
+ }
+ }
+
+ return -EINVAL;
+}
+
#ifdef CONFIG_ROOT_NFS
#define NFSROOT_TIMEOUT_MIN 5
@@ -526,6 +546,10 @@ void __init mount_root(void)
change_floppy("root floppy");
}
#endif
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
+ if (!mount_ubi_rootfs())
+ return;
+#endif
#ifdef CONFIG_BLOCK
create_dev("/dev/root", ROOT_DEV);
mount_block_root("/dev/root", root_mountflags);
--
1.9.2

View File

@ -0,0 +1,42 @@
From cd68d1b12b5ea4c01a664c064179ada42bf55d3d Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 15 May 2014 20:55:42 +0200
Subject: [PATCH 5/5] ubi: set ROOT_DEV to ubiblock "rootfs" if unset
To: openwrt-devel@lists.openwrt.org
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/block.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 2dbe2f4..eaa29f8 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -48,6 +48,7 @@
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <asm/div64.h>
+#include <linux/root_dev.h>
#include "ubi-media.h"
#include "ubi.h"
@@ -444,6 +445,15 @@ int ubiblock_create(struct ubi_volume_info *vi)
add_disk(dev->gd);
ubi_msg("%s created from ubi%d:%d(%s)",
dev->gd->disk_name, dev->ubi_num, dev->vol_id, vi->name);
+
+ if (!strcmp(vi->name, "rootfs") &&
+ config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
+ ROOT_DEV == 0) {
+ pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n",
+ dev->ubi_num, dev->vol_id, vi->name);
+ ROOT_DEV = MKDEV(gd->major, gd->first_minor);
+ }
+
return 0;
out_free_queue:
--
1.9.2

View File

@ -0,0 +1,176 @@
From 248b89b95d27659c5360ef5b68cca21d096ee909 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 17 May 2014 03:16:54 +0200
Subject: [PATCH 3/5] ubifs: respect MS_SILENT mount flag
To: dedekind1@gmail.com,
linux-mtd@lists.infradead.org
When attempting to mount a non-ubifs formatted volume, lots of error
messages (including a stack dump) are thrown to the kernel log even if
the MS_SILENT mount flag is set.
Fix this by checking the MS_SILENT flag in ubifs_read_sb_node and
passing it down to ubifs_read_node, which now got an additional
parameter for that purpose.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
fs/ubifs/commit.c | 4 ++--
fs/ubifs/io.c | 23 ++++++++++++++---------
fs/ubifs/sb.c | 5 +++--
fs/ubifs/tnc_misc.c | 4 ++--
fs/ubifs/ubifs.h | 2 +-
5 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index ff82293..865d13f 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -542,7 +542,7 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
if (!idx)
return -ENOMEM;
- err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
+ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs, 0);
if (err)
goto out;
@@ -610,7 +610,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
list_add_tail(&i->list, &list);
/* Read the index node */
idx = &i->idx;
- err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
+ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs, 0);
if (err)
goto out_free;
/* Validate index node */
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index e18b988..51c4072 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -912,7 +912,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
if (!overlap) {
/* We may safely unlock the write-buffer and read the data */
spin_unlock(&wbuf->lock);
- return ubifs_read_node(c, buf, type, len, lnum, offs);
+ return ubifs_read_node(c, buf, type, len, lnum, offs, 0);
}
/* Don't read under wbuf */
@@ -966,13 +966,14 @@ out:
* @len: node length (not aligned)
* @lnum: logical eraseblock number
* @offs: offset within the logical eraseblock
+ * @silent: suppress error messages
*
* This function reads a node of known type and and length, checks it and
* stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched
* and a negative error code in case of failure.
*/
int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
- int lnum, int offs)
+ int lnum, int offs, int silent)
{
int err, l;
struct ubifs_ch *ch = buf;
@@ -988,30 +989,34 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
return err;
if (type != ch->node_type) {
- ubifs_err("bad node type (%d but expected %d)",
+ if (!silent) ubifs_err("bad node type (%d but expected %d)",
ch->node_type, type);
goto out;
}
err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
if (err) {
- ubifs_err("expected node type %d", type);
+ if (!silent)
+ ubifs_err("expected node type %d", type);
return err;
}
l = le32_to_cpu(ch->len);
if (l != len) {
- ubifs_err("bad node length %d, expected %d", l, len);
+ if (!silent)
+ ubifs_err("bad node length %d, expected %d", l, len);
goto out;
}
return 0;
out:
- ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
- ubi_is_mapped(c->ubi, lnum));
- ubifs_dump_node(c, buf);
- dump_stack();
+ if (!silent) {
+ ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum,
+ offs, ubi_is_mapped(c->ubi, lnum));
+ ubifs_dump_node(c, buf);
+ dump_stack();
+ }
return -EINVAL;
}
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 4c37607..b46847d 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -482,14 +482,15 @@ failed:
struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
{
struct ubifs_sb_node *sup;
- int err;
+ int silent, err;
sup = kmalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_NOFS);
if (!sup)
return ERR_PTR(-ENOMEM);
+ silent = !!(c->vfs_sb->s_flags & MS_SILENT);
err = ubifs_read_node(c, sup, UBIFS_SB_NODE, UBIFS_SB_NODE_SZ,
- UBIFS_SB_LNUM, 0);
+ UBIFS_SB_LNUM, 0, silent);
if (err) {
kfree(sup);
return ERR_PTR(err);
diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c
index f6bf899..e128689 100644
--- a/fs/ubifs/tnc_misc.c
+++ b/fs/ubifs/tnc_misc.c
@@ -280,7 +280,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
if (!idx)
return -ENOMEM;
- err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
+ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs, 0);
if (err < 0) {
kfree(idx);
return err;
@@ -472,7 +472,7 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
zbr->lnum, zbr->offs);
else
err = ubifs_read_node(c, node, type, zbr->len, zbr->lnum,
- zbr->offs);
+ zbr->offs, 0);
if (err) {
dbg_tnck(key, "key ");
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index e8c8cfe..85fdd11 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1481,7 +1481,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs);
int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
- int lnum, int offs);
+ int lnum, int offs, int silent);
int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
int lnum, int offs);
int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
--
1.9.2