[PATCH 00/21] ext4l: Add Kconfig options to reduce binary size (part P)
From: Simon Glass <simon.glass@canonical.com> This series adds various Kconfig options to the ext4l filesystem driver to allow disabling optional features and reduce binary size. New configuration options include: - CONFIG_EXT4L_DEBUG: Control verbose error messages - CONFIG_EXT4_FS_POSIX_ACL: POSIX access control lists - CONFIG_EXT4_FS_SECURITY: Security labels (SELinux, etc.) - CONFIG_EXT4_MBALLOC: Multiblock allocator - CONFIG_EXT4_MBALLOC_PREFETCH: Block prefetching - CONFIG_EXT4_FAST_COMMIT_REPLAY: Fast commit journal replay - CONFIG_EXT4_MOUNT_OPTS: Mount option parsing The series also excludes write-related functions from read-only builds and makes extended attributes and inline-data support optional. Some tweaks are included to enable ext4l to build on ARM. Finally, ext4l is enabled on firefly-rk3288 as an example configuration. Some initial results on code size: - ext4l is currently 170K larger than ext4 with write-support - this series reduces the read-only penalty to 91K and with write-support to 116K This is still a substantial code-size increase, despite the efforts of this series. There is definitely more that could be done, but I haven't seen any more large opportunties yet. There is still a fair bit of cleanup needed in the stubs, in particular with the ext4_uboot.h file. I expect there will be at least a few more series after this one. Simon Glass (21): ext4l: Use div64.h instead of defining locally ext4l: Make use of log.2 instead of defining locally ext4l: Move __kernel_fsid_t to posix_types.h ext4l: Use math64.h instead of defining locally ext4l: Use 64-bit operations for block calculations ext4l: sandbox: Use volatile in set_bit() etc. ext4l: Correct type of invalidate_folio() ext4l: Tie verbose messages to CONFIG_EXT4L_DEBUG ext4l: Add Kconfig options for optional features ext4l: Make extended attributes (xattr) optional ext4l: Add optional inline data and indirect-block support ext4l: Add a CONFIG_EXT4_MBALLOC_PREFETCH option ext4l: Add a CONFIG_EXT4_FAST_COMMIT_REPLAY option ext4l: Add a CONFIG_EXT4_FS_POSIX_ACL option ext4l: Add a CONFIG_EXT4_FS_SECURITY option ext4l: Add a CONFIG_EXT4_MBALLOC option ext4l: Exclude write functions from read-only builds ext4l: Exclude transaction commits from read-only builds ext4l: Skip the journal flush in read-only builds ext4l: Add a CONFIG_EXT4_MOUNT_OPTS option configs: firefly-rk3288: Enable ext4l filesystem arch/sandbox/include/asm/bitops.h | 6 +- arch/sandbox/include/asm/posix_types.h | 4 + configs/firefly-rk3288_defconfig | 2 + fs/ext4/Kconfig | 1 + fs/ext4l/Kconfig | 157 ++++++++++++++++- fs/ext4l/Makefile | 20 ++- fs/ext4l/ext4.h | 224 +++++++++++++++++++++++-- fs/ext4l/ext4_uboot.h | 48 +----- fs/ext4l/fast_commit.c | 4 + fs/ext4l/file.c | 2 +- fs/ext4l/interface.c | 11 +- fs/ext4l/mballoc.c | 5 +- fs/ext4l/namei.c | 28 ++-- fs/ext4l/stub.c | 21 +-- fs/ext4l/super.c | 94 ++++++++--- fs/ext4l/symlink.c | 6 +- fs/ext4l/xattr.h | 83 +++++++++ fs/jbd2/checkpoint.c | 4 + fs/jbd2/journal.c | 17 +- 19 files changed, 605 insertions(+), 132 deletions(-) -- 2.43.0 base-commit: dd28f706425d776c089df316d1b8a56997112e9a branch: extp
From: Simon Glass <simon.glass@canonical.com> U-Boot has a do_div() macro which is supported on most boards. Use that instead of defining a new one. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4_uboot.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index c013b9605a4..04b76af7f09 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -36,6 +36,7 @@ #include <linux/seq_file.h> #include <linux/rbtree.h> /* Real rbtree implementation */ #include <u-boot/crc.h> /* For crc32() used by crc32_be */ +#include <div64.h> /* * Enable ext4_msg() and other diagnostic macros to pass full messages. @@ -439,15 +440,6 @@ int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, #define sb_issue_zeroout(sb, blk, num, gfp) ({ (void)(sb); (void)(blk); (void)(num); (void)(gfp); 0; }) #define blkdev_issue_flush(bdev) ({ (void)(bdev); 0; }) -/* do_div - divide u64 by u32 */ -#define do_div(n, base) ({ \ - unsigned int __base = (base); \ - unsigned int __rem; \ - __rem = ((unsigned long long)(n)) % __base; \ - (n) = ((unsigned long long)(n)) / __base; \ - __rem; \ -}) - /* Inode locking - stubs */ #define inode_is_locked(i) (1) #define i_size_write(i, s) do { (i)->i_size = (s); } while (0) -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Make use of the existing linux/log.h header which is supported on most boards. Drop the unnecessary code in the header and stub files. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4_uboot.h | 14 ++------------ fs/ext4l/stub.c | 15 --------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index 04b76af7f09..c975396dec4 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -19,6 +19,7 @@ #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-variable" +#include <div64.h> #include <linux/types.h> #include <linux/bitops.h> #include <vsprintf.h> /* For panic() */ @@ -28,6 +29,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/list.h> +#include <linux/log2.h> #include <linux/init.h> #include <linux/workqueue.h> #include <linux/cred.h> @@ -36,7 +38,6 @@ #include <linux/seq_file.h> #include <linux/rbtree.h> /* Real rbtree implementation */ #include <u-boot/crc.h> /* For crc32() used by crc32_be */ -#include <div64.h> /* * Enable ext4_msg() and other diagnostic macros to pass full messages. @@ -1458,10 +1459,6 @@ typedef unsigned int projid_t; __ret == __old; \ }) -/* ilog2 - log base 2 */ -#include <log.h> -#define ilog2(n) (fls(n) - 1) - /* hash_64 - simple 64-bit hash */ #define hash_64(val, bits) ((unsigned long)((val) >> (64 - (bits)))) @@ -2370,10 +2367,6 @@ void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep, /* Memory allocation - declarations for stub.c */ void *kvzalloc(size_t size, gfp_t flags); #define kvmalloc(size, flags) kvzalloc(size, flags) -unsigned long roundup_pow_of_two(unsigned long n); - -/* Power of 2 check - declaration for stub.c */ -int is_power_of_2(unsigned long n); /* Time operations */ #define ktime_get_ns() (0ULL) @@ -2651,9 +2644,6 @@ struct seq_operations { /* Block layer constants */ #define BLK_MAX_SEGMENT_SIZE 65536 -/* order_base_2 - log2 rounded up */ -#define order_base_2(n) ilog2(roundup_pow_of_two(n)) - /* num_possible_cpus - number of possible CPUs (always 1 in U-Boot) */ #define num_possible_cpus() 1 diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c index d328c6821a9..af0bb045d5f 100644 --- a/fs/ext4l/stub.c +++ b/fs/ext4l/stub.c @@ -360,15 +360,6 @@ void ext4_force_shutdown(void *sb, int flags) } /* Memory stubs */ -unsigned long roundup_pow_of_two(unsigned long n) -{ - unsigned long ret = 1; - - while (ret < n) - ret <<= 1; - return ret; -} - void *kvzalloc(size_t size, gfp_t flags) { return calloc(1, size); @@ -525,12 +516,6 @@ int sb_set_blocksize(struct super_block *sb, int size) return size; } -/* Power of 2 check */ -int is_power_of_2(unsigned long n) -{ - return n != 0 && (n & (n - 1)) == 0; -} - /* strscpy_pad is now a macro in ext4_uboot.h */ /* kmemdup_nul is defined earlier in this file */ -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Other archs provide the struct __kernel_fsid_t definition in linux/posix_types.h, but sandbox does not. Add it so we can remove the ext4l version. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- arch/sandbox/include/asm/posix_types.h | 4 ++++ fs/ext4l/ext4_uboot.h | 5 ----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/sandbox/include/asm/posix_types.h b/arch/sandbox/include/asm/posix_types.h index e1442c455bd..fe12ec9cc01 100644 --- a/arch/sandbox/include/asm/posix_types.h +++ b/arch/sandbox/include/asm/posix_types.h @@ -55,4 +55,8 @@ typedef unsigned short __kernel_old_gid_t; typedef long long __kernel_loff_t; #endif +typedef struct { + int val[2]; +} __kernel_fsid_t; + #endif diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index c975396dec4..f3dede424df 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -2067,11 +2067,6 @@ struct fid { }; }; -/* __kernel_fsid_t - must be before kstatfs */ -typedef struct { - int val[2]; -} __kernel_fsid_t; - /* uuid_to_fsid - convert UUID to fsid */ static inline __kernel_fsid_t uuid_to_fsid(const u8 *uuid) { -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> U-Boot has a linux/math64.h header which is supported on most boards. Use that instead of defining a new function. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4_uboot.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index f3dede424df..5676f76d4b4 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -31,6 +31,7 @@ #include <linux/list.h> #include <linux/log2.h> #include <linux/init.h> +#include <linux/math64.h> #include <linux/workqueue.h> #include <linux/cred.h> #include <linux/fs.h> @@ -3095,12 +3096,6 @@ static inline struct new_utsname *init_utsname(void) /* test_and_set_bit_lock - test and set a bit atomically */ #define test_and_set_bit_lock(nr, addr) test_and_set_bit(nr, addr) -/* div64_u64 - 64-bit by 64-bit division */ -static inline u64 div64_u64(u64 dividend, u64 divisor) -{ - return dividend / divisor; -} - /* time_is_before_jiffies - check if time is before current jiffies */ #define time_is_before_jiffies(a) ({ (void)(a); 0; }) -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> The current implementation is designed for 64-bit machines. Use the available functions and macros so that probing and reading work correctly on all machines. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/interface.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/ext4l/interface.c b/fs/ext4l/interface.c index f581c32359e..9a3fda48300 100644 --- a/fs/ext4l/interface.c +++ b/fs/ext4l/interface.c @@ -18,6 +18,7 @@ #include <u-boot/uuid.h> #include <linux/errno.h> #include <linux/jbd2.h> +#include <linux/math64.h> #include <linux/types.h> #include "ext4_uboot.h" @@ -387,7 +388,7 @@ int ext4l_probe(struct blk_desc *fs_dev_desc, /* Read sectors containing the superblock */ if (blk_dread(fs_dev_desc, - (part_offset + BLOCK_SIZE) / fs_dev_desc->blksz, + div_u64(part_offset + BLOCK_SIZE, fs_dev_desc->blksz), 2, buf) != 2) { ret = -EIO; goto err_free_buf; @@ -414,7 +415,7 @@ int ext4l_probe(struct blk_desc *fs_dev_desc, * If write returns 0, the device is read-only (e.g. LUKS/blkmap_crypt) */ if (blk_dwrite(fs_dev_desc, - (part_offset + BLOCK_SIZE) / fs_dev_desc->blksz, + div_u64(part_offset + BLOCK_SIZE, fs_dev_desc->blksz), 2, buf) != 2) { sb->s_bdev->read_only = true; sb->s_flags |= SB_RDONLY; @@ -846,9 +847,11 @@ int ext4l_read(const char *filename, void *buf, loff_t offset, loff_t len, dst = buf; while (bytes_left > 0) { + u32 rem; + /* Calculate logical block number and offset within block */ - block = offset / blksize; - blk_off = offset % blksize; + block = div_u64_rem(offset, blksize, &rem); + blk_off = rem; /* Read the block */ bh = ext4_bread(NULL, inode, block, 0); -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Other archs use a volatile address so update sandbox to match. This will prevent warnings in common code. Update the ext4 stub functions too. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- arch/sandbox/include/asm/bitops.h | 6 +++--- fs/ext4l/stub.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/sandbox/include/asm/bitops.h b/arch/sandbox/include/asm/bitops.h index f27d5e98c56..2fdc0116da0 100644 --- a/arch/sandbox/include/asm/bitops.h +++ b/arch/sandbox/include/asm/bitops.h @@ -34,11 +34,11 @@ /* * Function prototypes to keep gcc -Wall happy. */ -extern void set_bit(int nr, void *addr); +extern void set_bit(int nr, volatile void *addr); -extern void clear_bit(int nr, void *addr); +extern void clear_bit(int nr, volatile void *addr); -extern void change_bit(int nr, void *addr); +extern void change_bit(int nr, volatile void *addr); static inline void __change_bit(int nr, void *addr) { diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c index af0bb045d5f..2084faa3b50 100644 --- a/fs/ext4l/stub.c +++ b/fs/ext4l/stub.c @@ -79,21 +79,21 @@ typedef struct journal_s journal_t; * Bit operations - sandbox declares these extern but doesn't implement them. * These work on bitmaps where nr is the absolute bit number. */ -void set_bit(int nr, void *addr) +void set_bit(int nr, volatile void *addr) { unsigned long *p = (unsigned long *)addr + (nr / BITS_PER_LONG); *p |= (1UL << (nr % BITS_PER_LONG)); } -void clear_bit(int nr, void *addr) +void clear_bit(int nr, volatile void *addr) { unsigned long *p = (unsigned long *)addr + (nr / BITS_PER_LONG); *p &= ~(1UL << (nr % BITS_PER_LONG)); } -void change_bit(int nr, void *addr) +void change_bit(int nr, volatile void *addr) { unsigned long *p = (unsigned long *)addr + (nr / BITS_PER_LONG); -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> This function in struct address_space_operations should use size_t for its last two args, to match the ext4l code. Fix it. Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4_uboot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index 5676f76d4b4..21caecc2ada 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -1368,7 +1368,7 @@ struct address_space_operations { int (*read_folio)(struct file *, struct folio *); void (*readahead)(struct readahead_control *); sector_t (*bmap)(struct address_space *, sector_t); - void (*invalidate_folio)(struct folio *, unsigned long, unsigned long); + void (*invalidate_folio)(struct folio *, size_t, size_t); bool (*release_folio)(struct folio *, gfp_t); int (*write_begin)(const struct kiocb *, struct address_space *, loff_t, unsigned, struct folio **, void **); int (*write_end)(const struct kiocb *, struct address_space *, loff_t, unsigned, unsigned, struct folio *, void *); -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> The ext4 code contains many detailed error messages that consume about 20K of rodata. These messages are helpful for debugging mount failures but not essential for normal operation. Use CONFIG_EXT4L_DEBUG directly in ext4.h so that when debug is disabled, the message macros (ext4_msg, ext4_error, ext4_warning, etc.) use generic empty strings instead of detailed format strings. This allows the compiler to eliminate the string literals from rodata. Add a separate CONFIG_EXT4L_PRINT option to control whether messages are printed to the console. Messages are always recorded internally for programmatic access; this option only affects console output. Mount failures are still reported, but without specific details about what went wrong. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 18 +++++++++++++++++- fs/ext4l/ext4.h | 6 +++++- fs/ext4l/ext4_uboot.h | 10 ---------- fs/ext4l/super.c | 4 ++-- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index be989208ec5..1f1e9bdb3ed 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -29,8 +29,24 @@ config EXT4_JOURNAL config EXT4L_DEBUG bool "Enable ext4l debug messages" depends on FS_EXT4L + default y if SANDBOX help Enable debug and informational messages from the ext4l filesystem. - This includes mount messages and other ext4_msg() output. + This includes mount messages, error details, and other ext4_msg() + output with full format strings. + + Disabling this option replaces detailed error messages with generic + strings, saving about 20K of rodata. Mount failures will still be + reported but without specific details about what went wrong. + + If unsure, say N. + +config EXT4L_PRINT + bool "Print ext4l messages to console" + depends on EXT4L_DEBUG + help + Print ext4l messages to the console in addition to recording them. + Messages are always recorded and can be retrieved programmatically; + this option controls whether they are also printed. If unsure, say N. diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index 34dbc4f12b8..8a42d8f9bde 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -3266,7 +3266,11 @@ void __ext4_grp_locked_error(const char *, unsigned int, #define ext4_abort(sb, err, fmt, a...) \ __ext4_error((sb), __func__, __LINE__, true, (err), 0, (fmt), ## a) -#ifdef EXT4L_PRINTF +/* + * When CONFIG_EXT4L_DEBUG is enabled, pass full messages through the error + * macros. When disabled, use empty strings to save rodata space. + */ +#ifdef CONFIG_EXT4L_DEBUG #define ext4_error_inode(inode, func, line, block, fmt, ...) \ __ext4_error_inode(inode, func, line, block, 0, fmt, ##__VA_ARGS__) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index 21caecc2ada..a34f5d74dfa 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -40,16 +40,6 @@ #include <linux/rbtree.h> /* Real rbtree implementation */ #include <u-boot/crc.h> /* For crc32() used by crc32_be */ -/* - * Enable ext4_msg() and other diagnostic macros to pass full messages. - * This is required for message recording to work. Without this, the - * ext4_msg macro passes empty strings to __ext4_msg(). - * - * Use EXT4L_PRINTF instead of CONFIG_PRINTK since U-Boot requires CONFIG_ - * options to be defined in Kconfig. - */ -#define EXT4L_PRINTF 1 - /* * __CHAR_UNSIGNED__ - directory hash algorithm selection * diff --git a/fs/ext4l/super.c b/fs/ext4l/super.c index 48c87eb0e97..b2c95118220 100644 --- a/fs/ext4l/super.c +++ b/fs/ext4l/super.c @@ -971,8 +971,8 @@ void __ext4_msg(struct super_block *sb, /* Record in message buffer */ ext4l_record_msg(buf, len); - /* Also print if debug is enabled */ - if (IS_ENABLED(CONFIG_EXT4L_DEBUG)) + /* Also print if requested */ + if (IS_ENABLED(CONFIG_EXT4L_PRINT)) printf("%s", buf); } -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add configuration options to disable unused ext4 features: - CONFIG_EXT4_RESIZE: Online filesystem resize - CONFIG_EXT4_MIGRATE: Indirect/extent migration - CONFIG_EXT4_MOVE_EXTENT: Move extent ioctl These features are only called from ioctl.c and are not needed for U-Boot's basic filesystem operations. They default to disabled, but could be resurrected if another API could be provided. Provide an inline stub for ext4_kvfree_array_rcu() when resize is disabled, since it is called from mballoc.c and super.c There is very little code-size impact of this change, since the code is already eliminated by the linker. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 28 ++++++++++++++++++++++++++++ fs/ext4l/Makefile | 14 +++++++++----- fs/ext4l/ext4.h | 8 ++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index 1f1e9bdb3ed..7bb1cbe7537 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -49,4 +49,32 @@ config EXT4L_PRINT Messages are always recorded and can be retrieved programmatically; this option controls whether they are also printed. +config EXT4_RESIZE + bool "Enable ext4 online resize support" + depends on FS_EXT4L + help + Enable support for online filesystem resize. This allows + growing an ext4 filesystem while it is mounted. + + This adds about 10K to the image size. Not needed for U-Boot + in most cases. If unsure, say N. + +config EXT4_MIGRATE + bool "Enable ext4 extent migration support" + depends on FS_EXT4L + help + Enable support for migrating inodes between indirect block + mapping and extent mapping formats. + + This adds about 2.5K to the image size. Not needed for U-Boot + in most cases. If unsure, say N. + +config EXT4_MOVE_EXTENT + bool "Enable ext4 move extent ioctl support" + depends on FS_EXT4L + help + Enable support for the EXT4_IOC_MOVE_EXT ioctl which moves + extents between files. + + This adds about 1.5K to the image size. Not needed for U-Boot. If unsure, say N. diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 7bb843c3fad..262384b6bbb 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -5,10 +5,14 @@ obj-y := interface.o support.o stub.o +# Core ext4 objects (always needed) obj-y += balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \ extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \ - indirect.o inline.o inode.o mballoc.o migrate.o \ - mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \ - super.o symlink.o xattr.o \ - xattr_hurd.o xattr_trusted.o \ - xattr_user.o fast_commit.o orphan.o + indirect.o inline.o inode.o mballoc.o mmp.o namei.o \ + page-io.o readpage.o super.o symlink.o xattr.o \ + xattr_hurd.o xattr_trusted.o xattr_user.o fast_commit.o orphan.o + +# Optional features +obj-$(CONFIG_EXT4_RESIZE) += resize.o +obj-$(CONFIG_EXT4_MIGRATE) += migrate.o +obj-$(CONFIG_EXT4_MOVE_EXTENT) += move_extent.o diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index 8a42d8f9bde..26795a595df 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -3185,7 +3185,15 @@ extern int ext4_generic_delete_entry(struct inode *dir, extern bool ext4_empty_dir(struct inode *inode); /* resize.c */ +#ifdef CONFIG_EXT4_RESIZE extern void ext4_kvfree_array_rcu(void *to_free); +#else +static inline void ext4_kvfree_array_rcu(void *to_free) +{ + kvfree(to_free); +} +#endif + extern int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input); extern int ext4_group_extend(struct super_block *sb, -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add CONFIG_EXT4_XATTR to allow disabling support for extended attributes. This saves about 14K on Thumb2 (e.g. firefly-rk3288). When disabled, inline stub functions return -EOPNOTSUPP or 0 as appropriate. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 10 ++++++ fs/ext4l/Makefile | 5 +-- fs/ext4l/ext4_uboot.h | 2 ++ fs/ext4l/super.c | 2 +- fs/ext4l/xattr.h | 83 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 3 deletions(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index 7bb1cbe7537..ee7b9bb2dd6 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -78,3 +78,13 @@ config EXT4_MOVE_EXTENT This adds about 1.5K to the image size. Not needed for U-Boot. If unsure, say N. + +config EXT4_XATTR + bool "Enable ext4 extended attributes support" + depends on FS_EXT4L + help + Enable support for extended attributes (xattrs) on ext4 + filesystems. This is required for ACLs, security labels, + and user-defined attributes. + + This adds about 14K to the image size. If unsure, say N. diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 262384b6bbb..720181908f8 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -9,10 +9,11 @@ obj-y := interface.o support.o stub.o obj-y += balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \ extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \ indirect.o inline.o inode.o mballoc.o mmp.o namei.o \ - page-io.o readpage.o super.o symlink.o xattr.o \ - xattr_hurd.o xattr_trusted.o xattr_user.o fast_commit.o orphan.o + page-io.o readpage.o super.o symlink.o fast_commit.o orphan.o # Optional features obj-$(CONFIG_EXT4_RESIZE) += resize.o obj-$(CONFIG_EXT4_MIGRATE) += migrate.o obj-$(CONFIG_EXT4_MOVE_EXTENT) += move_extent.o +obj-$(CONFIG_EXT4_XATTR) += xattr.o xattr_hurd.o xattr_trusted.o \ + xattr_user.o diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index a34f5d74dfa..4a7e41a75a1 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -420,9 +420,11 @@ struct super_block; struct buffer_head; struct qstr; +#ifdef CONFIG_EXT4_XATTR int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, struct buffer_head *block_bh, size_t value_len, bool is_create); +#endif /* ext4_init_security is provided by xattr.h */ /* inode state stubs */ diff --git a/fs/ext4l/super.c b/fs/ext4l/super.c index b2c95118220..d3e1b85ac5d 100644 --- a/fs/ext4l/super.c +++ b/fs/ext4l/super.c @@ -5421,7 +5421,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) needs_recovery = 0; } - if (!test_opt(sb, NO_MBCACHE)) { + if (!test_opt(sb, NO_MBCACHE) && IS_ENABLED(CONFIG_EXT4_XATTR)) { sbi->s_ea_block_cache = ext4_xattr_create_cache(); if (!sbi->s_ea_block_cache) { ext4_msg(sb, KERN_ERR, diff --git a/fs/ext4l/xattr.h b/fs/ext4l/xattr.h index 1fedf44d4fb..f7b6de1743e 100644 --- a/fs/ext4l/xattr.h +++ b/fs/ext4l/xattr.h @@ -175,6 +175,7 @@ static inline void ext4_write_unlock_xattr(struct inode *inode, int *save) up_write(&EXT4_I(inode)->xattr_sem); } +#ifdef CONFIG_EXT4_XATTR extern ssize_t ext4_listxattr(struct dentry *, char *, size_t); extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t); @@ -216,6 +217,88 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, #define xattr_check_inode(inode, header, end) \ __xattr_check_inode((inode), (header), (end), __func__, __LINE__) +#else /* !CONFIG_EXT4_XATTR */ + +static inline ssize_t ext4_listxattr(struct dentry *d, char *b, size_t s) +{ + return -EOPNOTSUPP; +} + +static inline int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, + struct ext4_xattr_inode_array **array, + int extra_credits) +{ + return 0; +} + +static inline void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *a) +{ +} + +static inline void ext4_evict_ea_inode(struct inode *inode) +{ +} + +#define ext4_xattr_handlers NULL + +static inline struct mb_cache *ext4_xattr_create_cache(void) +{ + return NULL; +} + +static inline void ext4_xattr_destroy_cache(struct mb_cache *c) +{ +} + +static inline int +__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, + void *end, const char *function, unsigned int line) +{ + return 0; +} + +#define xattr_check_inode(inode, header, end) \ + __xattr_check_inode((inode), (header), (end), __func__, __LINE__) + +static inline int __ext4_xattr_set_credits(struct super_block *sb, + struct inode *inode, + struct buffer_head *block_bh, + size_t value_len, bool is_create) +{ + return 0; +} + +static inline int ext4_expand_extra_isize_ea(struct inode *inode, + int new_extra_isize, + struct ext4_inode *raw_inode, + handle_t *handle) +{ + return 0; +} + +static inline int ext4_xattr_ibody_find(struct inode *inode, + struct ext4_xattr_info *i, + struct ext4_xattr_ibody_find *is) +{ + return -EOPNOTSUPP; +} + +static inline int ext4_xattr_ibody_get(struct inode *inode, int name_index, + const char *name, void *buffer, + size_t buffer_size) +{ + return -EOPNOTSUPP; +} + +static inline int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + struct ext4_xattr_info *i, + struct ext4_xattr_ibody_find *is) +{ + return -EOPNOTSUPP; +} + +#endif /* CONFIG_EXT4_XATTR */ + #ifdef CONFIG_EXT4_FS_SECURITY extern int ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, const struct qstr *qstr); -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add CONFIG_EXT4_INLINE_DATA for inline data support (stores small files in the inode). This depends on xattr and adds ~8K. Disabled by default; filesystems with inline_data are rejected if disabled. Add CONFIG_EXT4_INDIRECT for legacy indirect block mapping used by ext2/ext3. Modern ext4 uses extents instead. Adds ~5K. Enabled by default for ext2/ext3 compatibility. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 22 +++++++++ fs/ext4l/Makefile | 4 +- fs/ext4l/ext4.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++ fs/ext4l/super.c | 16 +++++++ 4 files changed, 159 insertions(+), 1 deletion(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index ee7b9bb2dd6..e494c66e8dc 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -88,3 +88,25 @@ config EXT4_XATTR and user-defined attributes. This adds about 14K to the image size. If unsure, say N. + +config EXT4_INLINE_DATA + bool "Enable ext4 inline data support" + depends on FS_EXT4L && EXT4_XATTR + help + Enable support for inline data, which stores small files + directly in the inode. This is an uncommon feature that + requires creating the filesystem with -O inline_data. + + Filesystems with inline_data feature will be rejected if + this is disabled. Adds about 8K. If unsure, say N. + +config EXT4_INDIRECT + bool "Enable ext4 indirect block support (ext2/3 compatibility)" + depends on FS_EXT4L + default y + help + Enable support for indirect block mapping used by ext2/ext3 + filesystems. Modern ext4 filesystems use extents instead. + + Filesystems without the extents feature will be rejected if + this is disabled. Adds about 5K. If unsure, say N. diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 720181908f8..85ddaaa104e 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -8,7 +8,7 @@ obj-y := interface.o support.o stub.o # Core ext4 objects (always needed) obj-y += balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \ extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \ - indirect.o inline.o inode.o mballoc.o mmp.o namei.o \ + inode.o mballoc.o mmp.o namei.o \ page-io.o readpage.o super.o symlink.o fast_commit.o orphan.o # Optional features @@ -17,3 +17,5 @@ obj-$(CONFIG_EXT4_MIGRATE) += migrate.o obj-$(CONFIG_EXT4_MOVE_EXTENT) += move_extent.o obj-$(CONFIG_EXT4_XATTR) += xattr.o xattr_hurd.o xattr_trusted.o \ xattr_user.o +obj-$(CONFIG_EXT4_INLINE_DATA) += inline.o +obj-$(CONFIG_EXT4_INDIRECT) += indirect.o diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index 26795a595df..d01955bf59a 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -3132,12 +3132,30 @@ static inline bool is_special_ino(struct super_block *sb, unsigned long ino) } /* indirect.c */ +#ifdef CONFIG_EXT4_INDIRECT extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, int flags); extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks); extern void ext4_ind_truncate(handle_t *, struct inode *inode); extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode, ext4_lblk_t start, ext4_lblk_t end); +#else +static inline int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, + struct ext4_map_blocks *map, int flags) +{ + return -EOPNOTSUPP; +} +static inline int ext4_ind_trans_blocks(struct inode *inode, int nrblocks) +{ + return 0; +} +static inline void ext4_ind_truncate(handle_t *h, struct inode *inode) {} +static inline int ext4_ind_remove_space(handle_t *handle, struct inode *inode, + ext4_lblk_t start, ext4_lblk_t end) +{ + return -EOPNOTSUPP; +} +#endif /* ioctl.c */ extern long ext4_ioctl(struct file *, unsigned int, unsigned long); @@ -3675,6 +3693,7 @@ extern const struct file_operations ext4_file_operations; extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); /* inline.c */ +#ifdef CONFIG_EXT4_INLINE_DATA extern int ext4_get_max_inline_size(struct inode *inode); extern int ext4_find_inline_data_nolock(struct inode *inode); extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode); @@ -3733,6 +3752,105 @@ static inline int ext4_has_inline_data(struct inode *inode) return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) && EXT4_I(inode)->i_inline_off; } +#else /* !CONFIG_EXT4_INLINE_DATA */ +static inline int ext4_get_max_inline_size(struct inode *inode) { return 0; } +static inline int ext4_find_inline_data_nolock(struct inode *inode) { return 0; } +static inline int ext4_destroy_inline_data(handle_t *h, struct inode *i) +{ + return 0; +} +static inline void ext4_update_final_de(void *de_buf, int old_size, + int new_size) {} +static inline int ext4_readpage_inline(struct inode *inode, struct folio *folio) +{ + return -EOPNOTSUPP; +} +static inline int ext4_try_to_write_inline_data(struct address_space *mapping, + struct inode *inode, + loff_t pos, unsigned len, + struct folio **foliop) +{ + return 0; +} +static inline int ext4_write_inline_data_end(struct inode *inode, loff_t pos, + unsigned len, unsigned copied, + struct folio *folio) +{ + return 0; +} +static inline int ext4_generic_write_inline_data(struct address_space *mapping, + struct inode *inode, + loff_t pos, unsigned len, + struct folio **foliop, + void **fsdata, bool da) +{ + return 0; +} +static inline int ext4_try_add_inline_entry(handle_t *handle, + struct ext4_filename *fname, + struct inode *dir, + struct inode *inode) +{ + return 0; +} +static inline int ext4_try_create_inline_dir(handle_t *handle, + struct inode *parent, + struct inode *inode) +{ + return 0; +} +static inline int ext4_read_inline_dir(struct file *filp, + struct dir_context *ctx, + int *has_inline_data) +{ + return 0; +} +static inline int ext4_inlinedir_to_tree(struct file *dir_file, + struct inode *dir, ext4_lblk_t block, + struct dx_hash_info *hinfo, + __u32 start_hash, __u32 start_minor_hash, + int *has_inline_data) +{ + return 0; +} +static inline struct buffer_head *ext4_find_inline_entry(struct inode *dir, + struct ext4_filename *fname, + struct ext4_dir_entry_2 **res_dir, + int *has_inline_data) +{ + return NULL; +} +static inline int ext4_delete_inline_entry(handle_t *handle, struct inode *dir, + struct ext4_dir_entry_2 *de_del, + struct buffer_head *bh, + int *has_inline_data) +{ + return 0; +} +static inline bool empty_inline_dir(struct inode *dir, int *has_inline_data) +{ + return true; +} +static inline struct buffer_head *ext4_get_first_inline_block(struct inode *in, + struct ext4_dir_entry_2 **parent_de, + int *retval) +{ + return NULL; +} +static inline void *ext4_read_inline_link(struct inode *inode) { return NULL; } +struct iomap; +static inline int ext4_inline_data_iomap(struct inode *inode, struct iomap *m) +{ + return 0; +} +static inline int ext4_inline_data_truncate(struct inode *inode, + int *has_inline) +{ + return 0; +} +static inline int ext4_convert_inline_data(struct inode *inode) { return 0; } +static inline int ext4_has_inline_data(struct inode *inode) { return 0; } +#endif /* CONFIG_EXT4_INLINE_DATA */ /* namei.c */ extern const struct inode_operations ext4_dir_inode_operations; diff --git a/fs/ext4l/super.c b/fs/ext4l/super.c index d3e1b85ac5d..4bad3677db3 100644 --- a/fs/ext4l/super.c +++ b/fs/ext4l/super.c @@ -3553,6 +3553,22 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) return 0; } + if (!IS_ENABLED(CONFIG_EXT4_INLINE_DATA) && + ext4_has_feature_inline_data(sb)) { + ext4_msg(sb, KERN_ERR, + "Filesystem with inline_data feature cannot be " + "mounted without CONFIG_EXT4_INLINE_DATA"); + return 0; + } + + if (!IS_ENABLED(CONFIG_EXT4_INDIRECT) && + !ext4_has_feature_extents(sb)) { + ext4_msg(sb, KERN_ERR, + "Filesystem without extents feature requires " + "CONFIG_EXT4_INDIRECT for indirect block support"); + return 0; + } + if (readonly) return 1; -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add a Kconfig option to make mballoc prefetch support optional. The prefetch functions (ext4_mb_prefetch, ext4_mb_prefetch_fini) are used in Linux to optimise read performance by pre-loading block bitmaps during lazy initialisation. When disabled, guard the calls with IS_ENABLED() checks so gc-sections can remove the prefetch code. This removes the prefetch functions from the binary, reducing the external references to mballoc. Disable this by default as U-Boot is unlikely to gain any performance from this feature. It saves about 300 bytes. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 15 +++++++++++++++ fs/ext4l/mballoc.c | 5 ++++- fs/ext4l/super.c | 3 ++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index e494c66e8dc..3d7578f5073 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -110,3 +110,18 @@ config EXT4_INDIRECT Filesystems without the extents feature will be rejected if this is disabled. Adds about 5K. If unsure, say N. + +config EXT4_MBALLOC_PREFETCH + bool "Enable ext4 block bitmap prefetch support" + depends on FS_EXT4L + help + Enable prefetching of block allocation bitmaps to improve + allocation performance. When enabled, the multiblock allocator + will read ahead block bitmaps during allocation and lazy + initialization. + + Disabling this saves space by allowing the multiblock allocator + prefetch code to be removed. Read performance may be slightly + reduced during lazy initialization. + + If unsure, say Y. diff --git a/fs/ext4l/mballoc.c b/fs/ext4l/mballoc.c index 1643fd54f27..86ab374d686 100644 --- a/fs/ext4l/mballoc.c +++ b/fs/ext4l/mballoc.c @@ -2858,6 +2858,9 @@ static void ext4_mb_might_prefetch(struct ext4_allocation_context *ac, { struct ext4_sb_info *sbi; + if (!IS_ENABLED(CONFIG_EXT4_MBALLOC_PREFETCH)) + return; + if (ac->ac_prefetch_grp != group) return; @@ -3069,7 +3072,7 @@ out: ac->ac_b_ex.fe_len, ac->ac_o_ex.fe_len, ac->ac_status, ac->ac_flags, ac->ac_criteria, err); - if (ac->ac_prefetch_nr) + if (IS_ENABLED(CONFIG_EXT4_MBALLOC_PREFETCH) && ac->ac_prefetch_nr) ext4_mb_prefetch_fini(sb, ac->ac_prefetch_grp, ac->ac_prefetch_nr); return err; diff --git a/fs/ext4l/super.c b/fs/ext4l/super.c index 4bad3677db3..98785935f19 100644 --- a/fs/ext4l/super.c +++ b/fs/ext4l/super.c @@ -3663,7 +3663,8 @@ static int ext4_run_li_request(struct ext4_li_request *elr) int nr = EXT4_SB(sb)->s_mb_prefetch; u64 start_time; - if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) { + if (IS_ENABLED(CONFIG_EXT4_MBALLOC_PREFETCH) && + elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) { elr->lr_next_group = ext4_mb_prefetch(sb, group, nr, &prefetch_ios); ext4_mb_prefetch_fini(sb, elr->lr_next_group, nr); trace_ext4_prefetch_bitmaps(sb, group, elr->lr_next_group, nr); -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add a new Kconfig option to control fast commit replay support. Fast commit replay is needed to recover filesystems that were not cleanly unmounted and have pending fast commit records. However, this adds to code size (~8K). Enable it by default, since filesystems are likely to need this. When disabled: - Filesystems with pending fast commits cannot be recovered - Only safe if filesystems are created with -O ^fast_commit or always cleanly unmounted Guard the replay functions in fast_commit.c and provide inline stubs in ext4.h. Update firefly-rk3288_defconfig to disable this feature for space savings. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 17 +++++++++++++++++ fs/ext4l/ext4.h | 27 ++++++++++++++++++++++----- fs/ext4l/fast_commit.c | 4 ++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index 3d7578f5073..22b290778b7 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -125,3 +125,20 @@ config EXT4_MBALLOC_PREFETCH reduced during lazy initialization. If unsure, say Y. + +config EXT4_FAST_COMMIT_REPLAY + bool "Enable ext4 fast commit replay support" + depends on FS_EXT4L + default y + help + Enable support for replaying fast commit records during mount. + Fast commit is a journal optimization that records fine-grained + changes. If a filesystem was not cleanly unmounted and has + pending fast commit records, this option is needed to recover. + + Disabling this saves space (~8K) but means filesystems with + pending fast commits cannot be recovered. Only disable if you're + certain your filesystems won't have fast commit records (e.g., + created with -O ^fast_commit). + + If unsure, say Y. diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index d01955bf59a..b8e9f2d8c95 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -2946,6 +2946,28 @@ extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate); int ext4_fc_info_show(struct seq_file *seq, void *v); void ext4_fc_init(struct super_block *sb, journal_t *journal); void ext4_fc_init_inode(struct inode *inode); + +#ifdef CONFIG_EXT4_FAST_COMMIT_REPLAY +bool ext4_fc_replay_check_excluded(struct super_block *sb, ext4_fsblk_t block); +void ext4_fc_replay_cleanup(struct super_block *sb); +int ext4_fc_record_regions(struct super_block *sb, int ino, + ext4_lblk_t lblk, ext4_fsblk_t pblk, + int len, int replay); +#else +static inline bool ext4_fc_replay_check_excluded(struct super_block *sb, + ext4_fsblk_t block) +{ + return false; +} +static inline void ext4_fc_replay_cleanup(struct super_block *sb) {} +static inline int ext4_fc_record_regions(struct super_block *sb, int ino, + ext4_lblk_t lblk, ext4_fsblk_t pblk, + int len, int replay) +{ + return 0; +} +#endif + void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t start, ext4_lblk_t end); void __ext4_fc_track_unlink(handle_t *handle, struct inode *inode, @@ -2960,14 +2982,9 @@ void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); void ext4_fc_track_inode(handle_t *handle, struct inode *inode); void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t *handle); void ext4_fc_del(struct inode *inode); -bool ext4_fc_replay_check_excluded(struct super_block *sb, ext4_fsblk_t block); -void ext4_fc_replay_cleanup(struct super_block *sb); int ext4_fc_commit(journal_t *journal, tid_t commit_tid); int __init ext4_fc_init_dentry_cache(void); void ext4_fc_destroy_dentry_cache(void); -int ext4_fc_record_regions(struct super_block *sb, int ino, - ext4_lblk_t lblk, ext4_fsblk_t pblk, - int len, int replay); /* mballoc.c */ extern const struct seq_operations ext4_mb_seq_groups_ops; diff --git a/fs/ext4l/fast_commit.c b/fs/ext4l/fast_commit.c index ea5be3a079c..4383579ccb1 100644 --- a/fs/ext4l/fast_commit.c +++ b/fs/ext4l/fast_commit.c @@ -1360,6 +1360,7 @@ static void ext4_fc_cleanup(journal_t *journal, int full, tid_t tid) trace_ext4_fc_stats(sb); } +#ifdef CONFIG_EXT4_FAST_COMMIT_REPLAY /* Ext4 Replay Path Routines */ /* Helper struct for dentry replay routines */ @@ -2277,6 +2278,7 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh, } return ret; } +#endif /* CONFIG_EXT4_FAST_COMMIT_REPLAY */ void ext4_fc_init(struct super_block *sb, journal_t *journal) { @@ -2285,7 +2287,9 @@ void ext4_fc_init(struct super_block *sb, journal_t *journal) * could still have fast commit blocks that need to be replayed even if * fast commit has now been turned off. */ +#ifdef CONFIG_EXT4_FAST_COMMIT_REPLAY journal->j_fc_replay_callback = ext4_fc_replay; +#endif if (!test_opt2(sb, JOURNAL_FAST_COMMIT)) return; journal->j_fc_cleanup_callback = ext4_fc_cleanup; -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add Kconfig option to make POSIX ACL support optional. The acl.c and acl.h files already have proper #ifdef CONFIG_EXT4_FS_POSIX_ACL guards with stub functions when disabled. ACLs require extended attributes, so this option depends on EXT4_XATTR. It is unlikely to be useful in U-Boot but is included for completeness. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 11 +++++++++++ fs/ext4l/Makefile | 1 + 2 files changed, 12 insertions(+) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index 22b290778b7..1dce08d9474 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -142,3 +142,14 @@ config EXT4_FAST_COMMIT_REPLAY created with -O ^fast_commit). If unsure, say Y. + +config EXT4_FS_POSIX_ACL + bool "Enable ext4 POSIX Access Control Lists" + depends on FS_EXT4L && EXT4_XATTR + help + Enable POSIX Access Control Lists (ACLs) support for ext4 + filesystems. ACLs provide more fine-grained access control + than the standard Unix permission model. + + ACLs require extended attributes support (EXT4_XATTR). + If unsure, say N. diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 85ddaaa104e..fd86ce56d2e 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_EXT4_XATTR) += xattr.o xattr_hurd.o xattr_trusted.o \ xattr_user.o obj-$(CONFIG_EXT4_INLINE_DATA) += inline.o obj-$(CONFIG_EXT4_INDIRECT) += indirect.o +obj-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add Kconfig option to make security labels support optional. The xattr_security.c file and xattr.h already have proper #ifdef guards with stub functions when disabled. Security labels require extended attributes, so this option depends on EXT4_XATTR. They are unlikely to be useful in U-Boot but is included for completeness. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 11 +++++++++++ fs/ext4l/Makefile | 1 + 2 files changed, 12 insertions(+) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index 1dce08d9474..b7520aaab16 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -153,3 +153,14 @@ config EXT4_FS_POSIX_ACL ACLs require extended attributes support (EXT4_XATTR). If unsure, say N. + +config EXT4_FS_SECURITY + bool "Enable ext4 security labels" + depends on FS_EXT4L && EXT4_XATTR + help + Enable security labels support for ext4 filesystems. This + provides an extended attribute handler for file security + labels used by security modules like SELinux. + + Security labels require extended attributes support (EXT4_XATTR). + If unsure, say N. diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index fd86ce56d2e..0f5ee832f2e 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_EXT4_XATTR) += xattr.o xattr_hurd.o xattr_trusted.o \ obj-$(CONFIG_EXT4_INLINE_DATA) += inline.o obj-$(CONFIG_EXT4_INDIRECT) += indirect.o obj-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o +obj-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> The multiblock allocator (mballoc.c) is required for write operations but adds about 22K to the binary. For read-only builds, this code is unnecessary. Add a CONFIG_EXT4_MBALLOC option that makes mballoc.c conditional. When disabled, inline stubs return appropriate error codes (-EROFS for block allocation, -EOPNOTSUPP for trim) to allow the rest of ext4 to function for read operations. The option is always y when EXT4_WRITE is enabled, and the MBALLOC_PREFETCH option now depends on MBALLOC being enabled. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4/Kconfig | 1 + fs/ext4l/Kconfig | 13 +++++++++++- fs/ext4l/Makefile | 3 ++- fs/ext4l/ext4.h | 54 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index d7798cfb6b9..8ead2244a3c 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -9,6 +9,7 @@ config FS_EXT4 config EXT4_WRITE bool "Enable ext4 filesystem write support" depends on FS_EXT4 || FS_EXT4L + select EXT4_MBALLOC if FS_EXT4L help This provides support for creating and writing new files to an existing ext4 filesystem partition. diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index b7520aaab16..fcd5953b6dd 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -111,9 +111,20 @@ config EXT4_INDIRECT Filesystems without the extents feature will be rejected if this is disabled. Adds about 5K. If unsure, say N. +config EXT4_MBALLOC + bool "Enable ext4 multiblock allocator" + depends on FS_EXT4L + help + Enable the multiblock allocator (mballoc) which is required for + writing to ext4 filesystems. This handles block allocation for + new files and extending existing files. + + For read-only builds, this can be disabled to save about 22K. + If unsure, say Y if you need write support, N for read-only. + config EXT4_MBALLOC_PREFETCH bool "Enable ext4 block bitmap prefetch support" - depends on FS_EXT4L + depends on FS_EXT4L && EXT4_MBALLOC help Enable prefetching of block allocation bitmaps to improve allocation performance. When enabled, the multiblock allocator diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 0f5ee832f2e..8c5ffb8557c 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -8,10 +8,11 @@ obj-y := interface.o support.o stub.o # Core ext4 objects (always needed) obj-y += balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \ extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \ - inode.o mballoc.o mmp.o namei.o \ + inode.o mmp.o namei.o \ page-io.o readpage.o super.o symlink.o fast_commit.o orphan.o # Optional features +obj-$(CONFIG_EXT4_MBALLOC) += mballoc.o obj-$(CONFIG_EXT4_RESIZE) += resize.o obj-$(CONFIG_EXT4_MIGRATE) += migrate.o obj-$(CONFIG_EXT4_MOVE_EXTENT) += move_extent.o diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index b8e9f2d8c95..8d4e20e538a 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -2987,6 +2987,7 @@ int __init ext4_fc_init_dentry_cache(void); void ext4_fc_destroy_dentry_cache(void); /* mballoc.c */ +#ifdef CONFIG_EXT4_MBALLOC extern const struct seq_operations ext4_mb_seq_groups_ops; extern const struct seq_operations ext4_mb_seq_structs_summary_ops; extern int ext4_seq_mb_stats_show(struct seq_file *seq, void *offset); @@ -2997,6 +2998,19 @@ extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *, extern void ext4_discard_preallocations(struct inode *); extern int __init ext4_init_mballoc(void); extern void ext4_exit_mballoc(void); +#else +static inline int ext4_mb_init(struct super_block *sb) { return 0; } +static inline void ext4_mb_release(struct super_block *sb) {} +static inline ext4_fsblk_t ext4_mb_new_blocks(handle_t *h, + struct ext4_allocation_request *ar, int *err) +{ + *err = -EROFS; + return 0; +} +static inline void ext4_discard_preallocations(struct inode *i) {} +static inline int ext4_init_mballoc(void) { return 0; } +static inline void ext4_exit_mballoc(void) {} +#endif extern int __init ext4_init_es(void); extern void ext4_exit_es(void); @@ -3028,29 +3042,57 @@ struct ext4_fs_context { ext4_fsblk_t s_sb_block; }; +#ifdef CONFIG_EXT4_MBALLOC extern ext4_group_t ext4_mb_prefetch(struct super_block *sb, ext4_group_t group, unsigned int nr, int *cnt); extern void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group, unsigned int nr); - -extern void ext4_free_blocks(handle_t *handle, struct inode *inode, - struct buffer_head *bh, ext4_fsblk_t block, - unsigned long count, int flags); extern int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups); extern int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t i, struct ext4_group_desc *desc); +extern void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block, + int len, bool state); +extern void ext4_free_blocks(handle_t *handle, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t block, + unsigned long count, int flags); extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, ext4_fsblk_t block, unsigned long count); extern int ext4_trim_fs(struct super_block *, struct fstrim_range *); extern void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid); -extern void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block, - int len, bool state); static inline bool ext4_mb_cr_expensive(enum criteria cr) { return cr >= CR_GOAL_LEN_SLOW; } +#else +static inline ext4_group_t ext4_mb_prefetch(struct super_block *sb, + ext4_group_t group, unsigned int nr, int *cnt) +{ + *cnt = 0; + return group; +} +static inline void ext4_mb_prefetch_fini(struct super_block *sb, + ext4_group_t group, unsigned int nr) {} +static inline int ext4_mb_alloc_groupinfo(struct super_block *sb, + ext4_group_t ngroups) { return 0; } +static inline int ext4_mb_add_groupinfo(struct super_block *sb, + ext4_group_t i, struct ext4_group_desc *desc) { return 0; } +static inline void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block, + int len, bool state) {} +static inline void ext4_free_blocks(handle_t *handle, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t block, + unsigned long count, int flags) {} +static inline int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, + ext4_fsblk_t block, unsigned long count) { return -EROFS; } +static inline int ext4_trim_fs(struct super_block *sb, struct fstrim_range *r) +{ + return -EOPNOTSUPP; +} +static inline void ext4_process_freed_data(struct super_block *sb, + tid_t commit_tid) {} +static inline bool ext4_mb_cr_expensive(enum criteria cr) { return false; } +#endif /* inode.c */ void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw, -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> The inode_operations structs contain function pointers for write operations (create, unlink, mkdir, rename, setattr, etc.). Even when CONFIG_EXT4_WRITE is disabled, these function pointers cause the linker to include much of the write-related code. Add an EXT4_WR_OP() macro that returns the function pointer when CONFIG_EXT4_WRITE is enabled, or NULL when disabled. Apply this macro to write operation entries in structs ext4_dir_inode_operations, ext4_special_inode_operations, ext4_file_inode_operations and the symlink inode_operations structs. This reduces ext4l code size by about 15K on Thumb2 when write-support is disabled. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4.h | 11 +++++++++++ fs/ext4l/file.c | 2 +- fs/ext4l/namei.c | 28 ++++++++++++++-------------- fs/ext4l/symlink.c | 6 +++--- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index 8d4e20e538a..9c182ad0d89 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -22,6 +22,17 @@ #include <linux/jbd2.h> #include <linux/compiler.h> +/* + * Macro for write operation function pointers in inode_operations structs. + * When CONFIG_EXT4_WRITE is disabled, these return NULL so the linker + * doesn't pull in the write functions. + */ +#ifdef CONFIG_EXT4_WRITE +#define EXT4_WR_OP(func) (func) +#else +#define EXT4_WR_OP(func) NULL +#endif + /* * The fourth extended filesystem constants/structures */ diff --git a/fs/ext4l/file.c b/fs/ext4l/file.c index 8cbc8c5f785..6f775c498cf 100644 --- a/fs/ext4l/file.c +++ b/fs/ext4l/file.c @@ -966,7 +966,7 @@ const struct file_operations ext4_file_operations = { /* U-Boot simplified inode operations */ const struct inode_operations ext4_file_inode_operations = { - .setattr = ext4_setattr, + .setattr = EXT4_WR_OP(ext4_setattr), .getattr = ext4_file_getattr, .listxattr = ext4_listxattr, .fiemap = ext4_fiemap, diff --git a/fs/ext4l/namei.c b/fs/ext4l/namei.c index bede355d497..b8b6016a136 100644 --- a/fs/ext4l/namei.c +++ b/fs/ext4l/namei.c @@ -4199,30 +4199,30 @@ static int ext4_rename2(struct mnt_idmap *idmap, * directories can handle most operations... */ const struct inode_operations ext4_dir_inode_operations = { - .create = ext4_create, + .create = EXT4_WR_OP(ext4_create), .lookup = ext4_lookup, - .link = ext4_link, - .unlink = ext4_unlink, - .symlink = ext4_symlink, - .mkdir = ext4_mkdir, - .rmdir = ext4_rmdir, - .mknod = ext4_mknod, - .tmpfile = ext4_tmpfile, - .rename = ext4_rename2, - .setattr = ext4_setattr, + .link = EXT4_WR_OP(ext4_link), + .unlink = EXT4_WR_OP(ext4_unlink), + .symlink = EXT4_WR_OP(ext4_symlink), + .mkdir = EXT4_WR_OP(ext4_mkdir), + .rmdir = EXT4_WR_OP(ext4_rmdir), + .mknod = EXT4_WR_OP(ext4_mknod), + .tmpfile = EXT4_WR_OP(ext4_tmpfile), + .rename = EXT4_WR_OP(ext4_rename2), + .setattr = EXT4_WR_OP(ext4_setattr), .getattr = ext4_getattr, .listxattr = ext4_listxattr, .get_inode_acl = ext4_get_acl, - .set_acl = ext4_set_acl, + .set_acl = EXT4_WR_OP(ext4_set_acl), .fiemap = ext4_fiemap, .fileattr_get = ext4_fileattr_get, - .fileattr_set = ext4_fileattr_set, + .fileattr_set = EXT4_WR_OP(ext4_fileattr_set), }; const struct inode_operations ext4_special_inode_operations = { - .setattr = ext4_setattr, + .setattr = EXT4_WR_OP(ext4_setattr), .getattr = ext4_getattr, .listxattr = ext4_listxattr, .get_inode_acl = ext4_get_acl, - .set_acl = ext4_set_acl, + .set_acl = EXT4_WR_OP(ext4_set_acl), }; diff --git a/fs/ext4l/symlink.c b/fs/ext4l/symlink.c index 2e4d0942a3b..dd3b82b5da2 100644 --- a/fs/ext4l/symlink.c +++ b/fs/ext4l/symlink.c @@ -115,21 +115,21 @@ static const char *ext4_get_link(struct dentry *dentry, struct inode *inode, const struct inode_operations ext4_encrypted_symlink_inode_operations = { .get_link = ext4_encrypted_get_link, - .setattr = ext4_setattr, + .setattr = EXT4_WR_OP(ext4_setattr), .getattr = ext4_encrypted_symlink_getattr, .listxattr = ext4_listxattr, }; const struct inode_operations ext4_symlink_inode_operations = { .get_link = ext4_get_link, - .setattr = ext4_setattr, + .setattr = EXT4_WR_OP(ext4_setattr), .getattr = ext4_getattr, .listxattr = ext4_listxattr, }; const struct inode_operations ext4_fast_symlink_inode_operations = { .get_link = simple_get_link, - .setattr = ext4_setattr, + .setattr = EXT4_WR_OP(ext4_setattr), .getattr = ext4_getattr, .listxattr = ext4_listxattr, }; -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add IS_ENABLED(CONFIG_EXT4_WRITE) guards to jbd2 journal code to exclude write-only functions from read-only ext4l builds. The kjournald2 thread and jbd2_journal_commit_transaction() are only needed when writing to the journal. For read-only builds, skip thread creation and checkpoint/commit operations during journal destroy. This saves approximately 4K on Thumb2 builds. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/jbd2/journal.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index f6478c6ca94..0d38f00e555 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -232,6 +232,14 @@ static int jbd2_journal_start_thread(journal_t *journal) { struct task_struct *t; + /* + * The journal thread handles asynchronous commits. For read-only + * builds, we don't need it - commits happen synchronously in + * jbd2_journal_stop() when write support is enabled. + */ + if (!IS_ENABLED(CONFIG_EXT4_WRITE)) + return 0; + t = kthread_run(kjournald2, journal, "jbd2/%s", journal->j_devname); if (IS_ERR(t)) @@ -2117,14 +2125,15 @@ int jbd2_journal_destroy(journal_t *journal) journal_kill_thread(journal); /* Force a final log commit */ - if (journal->j_running_transaction) + if (IS_ENABLED(CONFIG_EXT4_WRITE) && journal->j_running_transaction) jbd2_journal_commit_transaction(journal); /* Force any old transactions to disk */ /* Totally anal locking here... */ spin_lock(&journal->j_list_lock); - while (journal->j_checkpoint_transactions != NULL) { + while (IS_ENABLED(CONFIG_EXT4_WRITE) && + journal->j_checkpoint_transactions != NULL) { spin_unlock(&journal->j_list_lock); mutex_lock_io(&journal->j_checkpoint_mutex); err = jbd2_log_do_checkpoint(journal); -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Add IS_ENABLED(CONFIG_EXT4_WRITE) guards to jbd2_journal_flush() and __jbd2_log_wait_for_space() to skip these operations in read-only builds. Journal flushing writes pending transactions to disk, which is not needed when the filesystem is mounted read-only. Similarly, waiting for journal space is only relevant when allocating space for new transactions. This eliminates jbd2_log_do_checkpoint() and saves approximately 1K on Thumb2 builds. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/jbd2/checkpoint.c | 4 ++++ fs/jbd2/journal.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 994e454bb5b..5b794df3384 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -48,6 +48,10 @@ __releases(&journal->j_state_lock) int nblocks, space_left; /* assert_spin_locked(&journal->j_state_lock); */ + /* Only needed for write operations */ + if (!IS_ENABLED(CONFIG_EXT4_WRITE)) + return; + nblocks = journal->j_max_transaction_buffers; while (jbd2_log_space_left(journal) < nblocks) { write_unlock(&journal->j_state_lock); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 0d38f00e555..e5bc62ba337 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -2409,6 +2409,10 @@ int jbd2_journal_flush(journal_t *journal, unsigned int flags) int err = 0; transaction_t *transaction = NULL; + /* Nothing to flush in read-only builds */ + if (!IS_ENABLED(CONFIG_EXT4_WRITE)) + return 0; + write_lock(&journal->j_state_lock); /* Force everything buffered to the log... */ -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> The ext4 mount-option-parsing infrastructure includes specification tables (ext4_param_specs, ext4_mount_opts) and related functions that add about 23K of rodata. For U-Boot's typical use case of mounting with default options, this parsing is unnecessary. Even if the options are needed in the future, it might be good enough to use the flags direcrly. Add a CONFIG_EXT4_MOUNT_OPTS option that, when disabled: - Stubs out ext4_parse_param() to accept any options silently - Removes the parameter-specification tables - Stubs ext4_show_options() and related functions This reduces code size by about 3.5K Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Kconfig | 14 ++++++++++ fs/ext4l/super.c | 69 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index fcd5953b6dd..4d0f6d95926 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -49,6 +49,20 @@ config EXT4L_PRINT Messages are always recorded and can be retrieved programmatically; this option controls whether they are also printed. +config EXT4_MOUNT_OPTS + bool "Enable mount option parsing" + depends on FS_EXT4L + help + Enable parsing of ext4 mount options (e.g., "data=ordered", + "barrier=1"). This requires the mount option specification + tables which add about 2KB of rodata. + + When disabled, ext4 uses fixed default options suitable for + read-only operation. This saves space but prevents customising + mount behaviour. + + If unsure, say N. + config EXT4_RESIZE bool "Enable ext4 online resize support" depends on FS_EXT4L diff --git a/fs/ext4l/super.c b/fs/ext4l/super.c index 98785935f19..9d8fee07907 100644 --- a/fs/ext4l/super.c +++ b/fs/ext4l/super.c @@ -61,7 +61,12 @@ static int ext4_reconfigure(struct fs_context *fc); static void ext4_fc_free(struct fs_context *fc); static int ext4_init_fs_context(struct fs_context *fc); static void ext4_kill_sb(struct super_block *sb); +#ifdef CONFIG_EXT4_MOUNT_OPTS static const struct fs_parameter_spec ext4_param_specs[]; +#define EXT4_PARAM_SPECS ext4_param_specs +#else +#define EXT4_PARAM_SPECS NULL +#endif /* * Lock ordering @@ -102,7 +107,7 @@ static struct file_system_type ext2_fs_type = { .owner = THIS_MODULE, .name = "ext2", .init_fs_context = ext4_init_fs_context, - .parameters = ext4_param_specs, + .parameters = EXT4_PARAM_SPECS, .kill_sb = ext4_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; @@ -118,7 +123,7 @@ static struct file_system_type ext3_fs_type = { .owner = THIS_MODULE, .name = "ext3", .init_fs_context = ext4_init_fs_context, - .parameters = ext4_param_specs, + .parameters = EXT4_PARAM_SPECS, .kill_sb = ext4_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; @@ -1663,6 +1668,24 @@ enum { #endif }; +#define MOPT_SET 0x0001 +#define MOPT_CLEAR 0x0002 +#define MOPT_NOSUPPORT 0x0004 +#define MOPT_EXPLICIT 0x0008 +#ifdef CONFIG_QUOTA +#define MOPT_Q 0 +#define MOPT_QFMT 0x0010 +#else +#define MOPT_Q MOPT_NOSUPPORT +#define MOPT_QFMT MOPT_NOSUPPORT +#endif +#define MOPT_NO_EXT2 0x0020 +#define MOPT_NO_EXT3 0x0040 +#define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3) +#define MOPT_SKIP 0x0080 +#define MOPT_2 0x0100 + +#ifdef CONFIG_EXT4_MOUNT_OPTS static const struct constant_table ext4_param_errors[] = { {"continue", EXT4_MOUNT_ERRORS_CONT}, {"panic", EXT4_MOUNT_ERRORS_PANIC}, @@ -1803,24 +1826,6 @@ static const struct fs_parameter_spec ext4_param_specs[] = { {} }; - -#define MOPT_SET 0x0001 -#define MOPT_CLEAR 0x0002 -#define MOPT_NOSUPPORT 0x0004 -#define MOPT_EXPLICIT 0x0008 -#ifdef CONFIG_QUOTA -#define MOPT_Q 0 -#define MOPT_QFMT 0x0010 -#else -#define MOPT_Q MOPT_NOSUPPORT -#define MOPT_QFMT MOPT_NOSUPPORT -#endif -#define MOPT_NO_EXT2 0x0020 -#define MOPT_NO_EXT3 0x0040 -#define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3) -#define MOPT_SKIP 0x0080 -#define MOPT_2 0x0100 - static const struct mount_opts { int token; int mount_opt; @@ -1895,6 +1900,7 @@ static const struct mount_opts { {Opt_abort, EXT4_MOUNT2_ABORT, MOPT_SET | MOPT_2}, {Opt_err, 0, 0} }; +#endif /* CONFIG_EXT4_MOUNT_OPTS */ #if IS_ENABLED(CONFIG_UNICODE) static const struct ext4_sb_encodings { @@ -2084,6 +2090,7 @@ EXT4_SET_CTX(mount_opt2); EXT4_CLEAR_CTX(mount_opt2); EXT4_TEST_CTX(mount_opt2); +#ifdef CONFIG_EXT4_MOUNT_OPTS static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param) { struct ext4_fs_context *ctx = fc->fs_private; @@ -2377,6 +2384,13 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param) return 0; } +#else +/* Stub when mount option parsing is disabled - use defaults */ +static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param) +{ + return 0; +} +#endif /* CONFIG_EXT4_MOUNT_OPTS */ static int parse_options(struct fs_context *fc, char *options) { @@ -2862,6 +2876,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, #endif } +#ifdef CONFIG_EXT4_MOUNT_OPTS static const char *token2str(int token) { const struct fs_parameter_spec *spec; @@ -2871,7 +2886,6 @@ static const char *token2str(int token) break; return spec->name; } - /* * Show an option if * - it's set to a non-default value OR @@ -3018,6 +3032,17 @@ int ext4_seq_options_show(struct seq_file *seq, void *offset) seq_putc(seq, '\n'); return rc; } +#else +static int ext4_show_options(struct seq_file *seq, struct dentry *root) +{ + return 0; +} + +int ext4_seq_options_show(struct seq_file *seq, void *offset) +{ + return 0; +} +#endif /* CONFIG_EXT4_MOUNT_OPTS */ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, int read_only) @@ -7397,7 +7422,7 @@ static struct file_system_type ext4_fs_type = { .owner = THIS_MODULE, .name = "ext4", .init_fs_context = ext4_init_fs_context, - .parameters = ext4_param_specs, + .parameters = EXT4_PARAM_SPECS, .kill_sb = ext4_kill_sb, .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_MGTIME, }; -- 2.43.0
From: Simon Glass <simon.glass@canonical.com> Enable the Linux-ported ext4 filesystem (ext4l) for firefly-rk3288. This requires CONFIG_EXPERT and CONFIG_FS to satisfy the Kconfig dependencies. The ext4l driver provides better compatibility with modern ext4 filesystems compared to the legacy U-Boot ext4 implementation. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- configs/firefly-rk3288_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig index 4d07e0b2635..8f1a0cb59e9 100644 --- a/configs/firefly-rk3288_defconfig +++ b/configs/firefly-rk3288_defconfig @@ -96,6 +96,8 @@ CONFIG_DISPLAY=y CONFIG_VIDEO_ROCKCHIP=y CONFIG_DISPLAY_ROCKCHIP_HDMI=y CONFIG_CONSOLE_SCROLL_LINES=10 +CONFIG_FS=y +CONFIG_FS_EXT4L=y CONFIG_CMD_DHRYSTONE=y CONFIG_SPL_CRC32=y CONFIG_ERRNO_STR=y -- 2.43.0
participants (1)
-
Simon Glass