From patchwork Thu Jan 8 18:51:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1352 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767898368; bh=RIM9EgBN5UkKDrJzfug/AnetT7zX4VsoF+OUFkR/4ps=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=OzUH+JFfmDRsR8gbqCrydyhCNOI/2LBbp87+rfwEfgQm/80m752dX1Y/p432xPTBP S9VLob0vS32MJvO3vHzixX6MEusGv3jUcMoDl82f8HEaK88xTimVvCJGxQybTA0Vtu uPWsJ9gfebbXSsEslBmyDf2m77waygmzU94Fe3Pwgdr7vd5NaU1IquOmXhtANB4tsA C9ZTgsZwQdiYiLWdDk8iUtSjIBjABxJIM6joxs8WfHjw8B1qy0c3Gn7gTWfLUknQwg u3x1Z4pim0ejtuh/YAt7DvK5+sfSJB8jsF3U+6Pr0/s2EFJTMoYKccv443qAvIeqha kguQMb3aJQiHQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C2971691CE for ; Thu, 8 Jan 2026 11:52:48 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 7R1E_AppOaKK for ; Thu, 8 Jan 2026 11:52:48 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767898368; bh=RIM9EgBN5UkKDrJzfug/AnetT7zX4VsoF+OUFkR/4ps=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=OzUH+JFfmDRsR8gbqCrydyhCNOI/2LBbp87+rfwEfgQm/80m752dX1Y/p432xPTBP S9VLob0vS32MJvO3vHzixX6MEusGv3jUcMoDl82f8HEaK88xTimVvCJGxQybTA0Vtu uPWsJ9gfebbXSsEslBmyDf2m77waygmzU94Fe3Pwgdr7vd5NaU1IquOmXhtANB4tsA C9ZTgsZwQdiYiLWdDk8iUtSjIBjABxJIM6joxs8WfHjw8B1qy0c3Gn7gTWfLUknQwg u3x1Z4pim0ejtuh/YAt7DvK5+sfSJB8jsF3U+6Pr0/s2EFJTMoYKccv443qAvIeqha kguQMb3aJQiHQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B0400691C8 for ; Thu, 8 Jan 2026 11:52:48 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767898367; bh=cwsNX8fEgLT6vVE+zye5ieZ8qoOg9HOUJBjGM1vw0ow=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pQJsyKQyMz487xu6V+fAVBV7G99PhRuKOfH47SQz3gEkRV+rIpFb0t/9NNPx84Zbm a6o/CZK98+DMzJByqxhA5EWGCqiKfYNsgtfjrQdVbxSd+lVXOZVWikiUoQd0j7T2n+ 3HZFvAhRMTVc0NBnxWD1HC3d9wSXj04PjGqmTohH4tU4caIFwYRUsP3wNbcL6mKbxK h/iuCsgcPccGaDxZnDQ1/XsC1bOV2/WmFY69PZDHe6KGzAqFHGRuPXLoKdNwiGxkFG fSm1rZ8sbUWgcKUcn2U1/odPCdSJpCVoyxSwB8iWlY9dyVf1G5GKvVoGnlVg1yJZEK xFOltHY2d3LEA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B960B69101; Thu, 8 Jan 2026 11:52:47 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 2ccWSoYv1MI2; Thu, 8 Jan 2026 11:52:47 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767898363; bh=AdfTZO0TscH15PYyjWeLdYaLXRRc9iewajH4+JuBmzQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=I6idZJHeVE/Nw0kVT7uNMGIJJ+jxSzuX4p8iiZVdBauarX+RDTqXc9f9zh8hSmPPw DW57UY0jVxAfg1LKyoTk1BEKkdL/acqWQnjE3HRDC6+rxygoNfRhZeRy1xHZor+dt3 WDs4EFLIknIlLLe4jlvrSzGIxLnjY39TUEDRA9PJtvPU4VYZqrBE8AlQX7NyhTvui+ 3/sbG2Z/GXYc6OMiVxaDMvATtRr7/DUu3e9Lbv2AawnbexcDvSptfRS1rtdk9qFuR1 rKM4ogAkX6ocym1uHAceDnmkDqQsc71uTsUopiQHOZ9CmWCkX7qnyQFozxPUf/8EYi FI10lZpAZgfjA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 584C369057; Thu, 8 Jan 2026 11:52:43 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Thu, 8 Jan 2026 11:51:26 -0700 Message-ID: <20260108185149.1995917-12-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260108185149.1995917-1-sjg@u-boot.org> References: <20260108185149.1995917-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 3XSGWPWVZSX6YL67G5IJX6UPMJL33EIY X-Message-ID-Hash: 3XSGWPWVZSX6YL67G5IJX6UPMJL33EIY X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 11/21] ext4l: Add optional inline data and indirect-block support List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass 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 Signed-off-by: Simon Glass --- 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;