image: add support for EROFS rootfs image

Add support for generating EROFS rootfs images.

The EROFS filesystem can offer competitive I/O performance while
minimizing final image size when using the MicroLZMA compressor.

Target platform: linux-x86_generic (target-i386_pentium4_musl)

Filesystem     Image Size
=============  ==========
root.erofs     4882432
root.ext4      109051904
root.squashfs  4903302

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
Gao Xiang 2025-06-26 01:45:22 +08:00
parent 70265ac2ca
commit 1a75fbe431
10 changed files with 231 additions and 0 deletions

View File

@ -384,6 +384,7 @@ menu "Global build settings"
config TARGET_ROOTFS_SECURITY_LABELS
bool
select KERNEL_SQUASHFS_XATTR
select KERNEL_EROFS_FS_SECURITY
select KERNEL_EXT4_FS_SECURITY
select KERNEL_F2FS_FS_SECURITY
select KERNEL_UBIFS_FS_SECURITY

View File

@ -89,6 +89,23 @@ menu "Target Images"
comment "Root filesystem images"
menuconfig TARGET_ROOTFS_EROFS
bool "erofs"
default y if USES_EROFS
select KERNEL_EROFS_FS
help
Build a EROFS root filesystem.
config TARGET_EROFS_PCLUSTER_SIZE
int "physical cluster size (in KiB)"
depends on TARGET_ROOTFS_EROFS
default 64 if LOW_MEMORY_FOOTPRINT
default 1024 if (SMALL_FLASH && !LOW_MEMORY_FOOTPRINT)
default 256
help
Specify the EROFS physical cluster size (must be equal
to or a multiple of the filesystem block size).
menuconfig TARGET_ROOTFS_EXT4FS
bool "ext4"
default y if USES_EXT4

View File

@ -1305,6 +1305,23 @@ config KERNEL_BTRFS_FS
Say Y here if you want to make the kernel to be able to boot off a
BTRFS partition.
config KERNEL_EROFS_FS
bool "Compile the kernel with built-in EROFS support"
help
Say Y here if you want to make the kernel to be able to boot off a
EROFS partition.
config KERNEL_EROFS_FS_XATTR
bool "EROFS XATTR support"
config KERNEL_EROFS_FS_ZIP
bool
default y if KERNEL_EROFS_FS
config KERNEL_EROFS_FS_ZIP_LZMA
bool
default y if KERNEL_EROFS_FS
menu "Filesystem ACL and attr support options"
config USE_FS_ACL_ATTR
bool "Use filesystem ACL and attr support by default"
@ -1325,6 +1342,11 @@ menu "Filesystem ACL and attr support options"
select KERNEL_FS_POSIX_ACL
default y if USE_FS_ACL_ATTR
config KERNEL_EROFS_FS_POSIX_ACL
bool "Enable POSIX ACL for EROFS Filesystems"
select KERNEL_FS_POSIX_ACL
default y if USE_FS_ACL_ATTR
config KERNEL_EXT4_FS_POSIX_ACL
bool "Enable POSIX ACL for Ext4 Filesystems"
select KERNEL_FS_POSIX_ACL
@ -1478,6 +1500,11 @@ config KERNEL_LSM
default "lockdown,yama,loadpin,safesetid,integrity,selinux"
depends on KERNEL_SECURITY_SELINUX
config KERNEL_EROFS_FS_SECURITY
bool "EROFS Security Labels"
default y if !SMALL_FLASH
select KERNEL_EROFS_FS_XATTR
config KERNEL_EXT4_FS_SECURITY
bool "Ext4 Security Labels"
default y if !SMALL_FLASH

View File

@ -87,11 +87,21 @@ endif
JFFS2_BLOCKSIZE ?= 64k 128k
EROFS_PCLUSTERSIZE = $(shell echo $$(($(CONFIG_TARGET_EROFS_PCLUSTER_SIZE)*1024)))
EROFSOPT := -Efragments,dedupe,ztailpacking -Uclear --all-root
EROFSOPT += $(if $(SOURCE_DATE_EPOCH),-T$(SOURCE_DATE_EPOCH) --ignore-mtime)
EROFSOPT += $(if $(CONFIG_SELINUX),,-x-1)
EROFSCOMP := lz4hc,12
ifeq ($(CONFIG_EROFS_FS_ZIP_LZMA),y)
EROFSCOMP := lzma,109
endif
fs-types-$(CONFIG_TARGET_ROOTFS_SQUASHFS) += squashfs
fs-types-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addprefix jffs2-,$(JFFS2_BLOCKSIZE))
fs-types-$(CONFIG_TARGET_ROOTFS_JFFS2_NAND) += $(addprefix jffs2-nand-,$(NAND_BLOCKSIZE))
fs-types-$(CONFIG_TARGET_ROOTFS_EXT4FS) += ext4
fs-types-$(CONFIG_TARGET_ROOTFS_UBIFS) += ubifs
fs-types-$(CONFIG_TARGET_ROOTFS_EROFS) += erofs
fs-subtypes-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addsuffix -raw,$(addprefix jffs2-,$(JFFS2_BLOCKSIZE)))
TARGET_FILESYSTEMS := $(fs-types-y)
@ -275,6 +285,13 @@ define Image/mkfs/ext4
$@ $(call mkfs_target_dir,$(1))/
endef
# Don't use the mkfs.erofs builtin $SOURCE_DATE_EPOCH behavior
define Image/mkfs/erofs
env -u SOURCE_DATE_EPOCH $(STAGING_DIR_HOST)/bin/mkfs.erofs -z$(EROFSCOMP) \
-C$(EROFS_PCLUSTERSIZE) $(EROFSOPT) \
$@ $(call mkfs_target_dir,$(1))
endef
define Image/Manifest
$(call opkg,$(TARGET_DIR_ORIG)) list-installed > \
$(BIN_DIR)/$(IMG_PREFIX)$(if $(PROFILE_SANITIZED),-$(PROFILE_SANITIZED)).manifest

View File

@ -0,0 +1,139 @@
From e8cd820cdbb8fba990fd79efda90c5dc10d8e45c Mon Sep 17 00:00:00 2001
From: Gao Xiang <xiang@kernel.org>
Subject: [PATCH] libfstools: add support for EroFS based images
Add support to libfstools to parse and support EroFS based images to
permit correct mounting of OverlayFS with it. (in addition to SquashFS
support)
While at it rework the code to better handle the 2 different filesystem
introducing a similar pattern.
Signed-off-by: Gao Xiang <xiang@kernel.org>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
libfstools/rootdisk.c | 83 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 77 insertions(+), 6 deletions(-)
--- a/libfstools/rootdisk.c
+++ b/libfstools/rootdisk.c
@@ -15,6 +15,8 @@
#include <linux/loop.h>
+#define SQUASHFS_MAGIC "hsqs"
+#define EROFS_MAGIC 0xE0F5E1E2
#define ROOTDEV_OVERLAY_ALIGN (64ULL * 1024ULL)
#define F2FS_MINSIZE (100ULL * 1024ULL * 1024ULL)
@@ -24,6 +26,14 @@ struct squashfs_super_block {
uint64_t bytes_used;
};
+struct erofs_super_block {
+ uint32_t s_magic;
+ uint32_t pad0[2];
+ uint8_t blkszbits;
+ uint8_t pad1[23];
+ uint32_t blocks;
+};
+
struct rootdev_volume {
struct volume v;
uint64_t offset;
@@ -93,10 +103,66 @@ static int get_squashfs(struct squashfs_
return 0;
}
-static struct volume *rootdisk_volume_find(char *name)
+static int check_squashfs(uint64_t *offset)
{
+ const char *s_magic = SQUASHFS_MAGIC;
struct squashfs_super_block sb;
+ int ret;
+
+ ret = get_squashfs(&sb);
+ if (ret)
+ return ret;
+
+ if (memcmp(&sb.s_magic, s_magic, sizeof(sb.s_magic)))
+ return -1;
+
+ *offset = le64_to_cpu(sb.bytes_used);
+ return 0;
+}
+
+static int get_erofs(struct erofs_super_block *sb)
+{
+ FILE *f;
+ int len;
+
+ f = fopen(rootdev, "r");
+ if (!f)
+ return -1;
+
+ if (fseek(f, 1024, SEEK_SET))
+ return -1;
+
+ len = fread(sb, sizeof(*sb), 1, f);
+ fclose(f);
+
+ if (len != 1)
+ return -1;
+
+ return 0;
+}
+
+static int check_erofs(uint64_t *offset)
+{
+ uint32_t s_magic = cpu_to_le32(EROFS_MAGIC);
+ struct erofs_super_block sb;
+ int ret;
+
+ ret = get_erofs(&sb);
+ if (ret)
+ return ret;
+
+ if (memcmp(&sb.s_magic, &s_magic, sizeof(sb.s_magic)))
+ return -1;
+
+ *offset = (uint64_t)le32_to_cpu(sb.blocks) << sb.blkszbits;
+ return 0;
+}
+
+static struct volume *rootdisk_volume_find(char *name)
+{
struct rootdev_volume *p;
+ uint64_t offset;
+ int ret;
if (strcmp(name, "rootfs_data") != 0)
return NULL;
@@ -108,17 +174,22 @@ static struct volume *rootdisk_volume_fi
if (!rootdev)
return NULL;
- if (get_squashfs(&sb))
- return NULL;
-
- if (memcmp(&sb.s_magic, "hsqs", sizeof(sb.s_magic)) != 0)
+ /*
+ * We support both SquashFS and EroFS.
+ * First check for SquashFS and then check
+ * for EroFS on new images.
+ */
+ ret = check_squashfs(&offset);
+ if (ret < 0 || !offset)
+ ret = check_erofs(&offset);
+ if (ret < 0 || !offset)
return NULL;
p = calloc(1, sizeof(*p));
p->v.drv = &rootdisk_driver;
p->v.name = "rootfs_data";
- p->offset = le64_to_cpu(sb.bytes_used);
+ p->offset = offset;
p->offset = ((p->offset + (ROOTDEV_OVERLAY_ALIGN - 1)) &
~(ROOTDEV_OVERLAY_ALIGN - 1));

View File

@ -18,6 +18,7 @@ sub target_config_features(@) {
/^dt$/ and $ret .= "\tselect USES_DEVICETREE\n";
/^dt-overlay$/ and $ret .= "\tselect HAS_DT_OVERLAY_SUPPORT\n";
/^emmc$/ and $ret .= "\tselect EMMC_SUPPORT\n";
/^erofs$/ and $ret .= "\tselect USES_EROFS\n";
/^ext4$/ and $ret .= "\tselect USES_EXT4\n";
/^fpu$/ and $ret .= "\tselect HAS_FPU\n";
/^gpio$/ and $ret .= "\tselect GPIO_SUPPORT\n";

View File

@ -69,6 +69,9 @@ config USES_JFFS2_NAND
config USES_EXT4
bool
config USES_EROFS
bool
config USES_TARGZ
bool

View File

@ -1978,6 +1978,12 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_EPOLL=y
# CONFIG_EQUALIZER is not set
# CONFIG_EROFS_FS is not set
# CONFIG_EROFS_FS_DEBUG is not set
# CONFIG_EROFS_FS_XATTR is not set
# CONFIG_EROFS_FS_POSIX_ACL is not set
# CONFIG_EROFS_FS_SECURITY is not set
# CONFIG_EROFS_FS_ZIP is not set
# CONFIG_EROFS_FS_ONDEMAND is not set
# CONFIG_ET131X is not set
CONFIG_ETHERNET=y
# CONFIG_ETHOC is not set

View File

@ -1896,6 +1896,17 @@ CONFIG_ELFCORE=y
CONFIG_EPOLL=y
# CONFIG_EQUALIZER is not set
# CONFIG_EROFS_FS is not set
# CONFIG_EROFS_FS_DEBUG is not set
# CONFIG_EROFS_FS_XATTR is not set
# CONFIG_EROFS_FS_POSIX_ACL is not set
# CONFIG_EROFS_FS_SECURITY is not set
# CONFIG_EROFS_FS_BACKED_BY_FILE is not set
# CONFIG_EROFS_FS_ZIP is not set
# CONFIG_EROFS_FS_ZIP_DEFLATE is not set
# CONFIG_EROFS_FS_ZIP_ZSTD is not set
# CONFIG_EROFS_FS_ONDEMAND is not set
CONFIG_EROFS_FS_PCPU_KTHREAD=y
CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y
# CONFIG_ET131X is not set
CONFIG_ETHERNET=y
# CONFIG_ETHOC is not set

View File

@ -1840,6 +1840,15 @@ CONFIG_ELFCORE=y
CONFIG_EPOLL=y
# CONFIG_EQUALIZER is not set
# CONFIG_EROFS_FS is not set
# CONFIG_EROFS_FS_DEBUG is not set
# CONFIG_EROFS_FS_XATTR is not set
# CONFIG_EROFS_FS_POSIX_ACL is not set
# CONFIG_EROFS_FS_SECURITY is not set
# CONFIG_EROFS_FS_ZIP is not set
# CONFIG_EROFS_FS_ZIP_DEFLATE is not set
# CONFIG_EROFS_FS_ONDEMAND is not set
CONFIG_EROFS_FS_PCPU_KTHREAD=y
CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y
# CONFIG_ET131X is not set
CONFIG_ETHERNET=y
# CONFIG_ETHOC is not set