From: Simon Glass <simon.glass@canonical.com> Add a 4KB membuf to record ext4 messages for later retrieval. This allows programmatic access to filesystem messages without requiring CONFIG_EXT4L_DEBUG to be enabled. - Add ext4l_msg_buf and ext4l_msg_data in interface.c - Add ext4l_record_msg() to record messages - Add ext4l_get_msg_buf() to access the buffer - Modify __ext4_msg() to always record messages, print only if debug Note that this increases the number of strings in the ext4l implementation. For production it might be useful to make this an option, although the messages can be quite important. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4_uboot.h | 9 +++++---- fs/ext4l/interface.c | 39 +++++++++++++++++++++++++++++++++++++++ fs/ext4l/super.c | 28 ++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index 4b019b77d27..116f0475217 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -38,15 +38,14 @@ #include <u-boot/crc.h> /* For crc32() used by crc32_be */ /* - * Enable ext4_msg() and other diagnostic macros to print full messages. - * This is needed for CONFIG_EXT4L_DEBUG to show useful error messages. + * 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. */ -#ifdef CONFIG_EXT4L_DEBUG #define EXT4L_PRINTF 1 -#endif /* * __CHAR_UNSIGNED__ - directory hash algorithm selection @@ -2864,6 +2863,8 @@ int ext4l_read_block(sector_t block, size_t size, void *buffer); /* ext4l interface functions (interface.c) */ struct blk_desc *ext4l_get_blk_dev(void); struct disk_partition *ext4l_get_partition(void); +void ext4l_record_msg(const char *msg, int len); +struct membuf *ext4l_get_msg_buf(void); #define sb_is_blkdev_sb(sb) ({ (void)(sb); 0; }) diff --git a/fs/ext4l/interface.c b/fs/ext4l/interface.c index 2ea3915c637..9b6f4c0b02b 100644 --- a/fs/ext4l/interface.c +++ b/fs/ext4l/interface.c @@ -10,6 +10,7 @@ */ #include <blk.h> +#include <membuf.h> #include <part.h> #include <malloc.h> #include <linux/errno.h> @@ -19,6 +20,9 @@ #include "ext4_uboot.h" #include "ext4.h" +/* Message buffer size */ +#define EXT4L_MSG_BUF_SIZE 4096 + /* Global state */ static struct blk_desc *ext4l_dev_desc; static struct disk_partition ext4l_part; @@ -31,6 +35,10 @@ static int ext4l_mounted; /* Global super_block pointer for filesystem operations */ static struct super_block *ext4l_sb; +/* Message recording buffer */ +static struct membuf ext4l_msg_buf; +static char ext4l_msg_data[EXT4L_MSG_BUF_SIZE]; + /** * ext4l_get_blk_dev() - Get the current block device * Return: Block device descriptor or NULL if not mounted @@ -91,6 +99,34 @@ void ext4l_clear_blk_dev(void) ext4l_mounted = 0; } +/** + * ext4l_msg_init() - Initialize the message buffer + */ +static void ext4l_msg_init(void) +{ + membuf_init(&ext4l_msg_buf, ext4l_msg_data, EXT4L_MSG_BUF_SIZE); +} + +/** + * ext4l_record_msg() - Record a message in the buffer + * @msg: Message string to record + * @len: Length of message + */ +void ext4l_record_msg(const char *msg, int len) +{ + membuf_put(&ext4l_msg_buf, msg, len); +} + +/** + * ext4l_get_msg_buf() - Get the message buffer + * + * Return: Pointer to the message buffer + */ +struct membuf *ext4l_get_msg_buf(void) +{ + return &ext4l_msg_buf; +} + int ext4l_probe(struct blk_desc *fs_dev_desc, struct disk_partition *fs_partition) { @@ -105,6 +141,9 @@ int ext4l_probe(struct blk_desc *fs_dev_desc, if (!fs_dev_desc) return -EINVAL; + /* Initialise message buffer for recording ext4 messages */ + ext4l_msg_init(); + /* Initialise CRC32C table for checksum verification */ ext4l_crc32c_init(); diff --git a/fs/ext4l/super.c b/fs/ext4l/super.c index 47e0b2c92e8..57653c8acb7 100644 --- a/fs/ext4l/super.c +++ b/fs/ext4l/super.c @@ -943,11 +943,9 @@ void __ext4_std_error(struct super_block *sb, const char *function, void __ext4_msg(struct super_block *sb, const char *prefix, const char *fmt, ...) { - struct va_format vaf; + char buf[256]; va_list args; - - if (!IS_ENABLED(CONFIG_EXT4L_DEBUG)) - return; + int len; if (sb) { atomic_inc(&EXT4_SB(sb)->s_msg_count); @@ -956,14 +954,28 @@ void __ext4_msg(struct super_block *sb, return; } + /* Format the message into a buffer */ va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; if (sb) - printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf); + len = snprintf(buf, sizeof(buf), "%sEXT4-fs (%s): ", + prefix, sb->s_id); else - printk("%sEXT4-fs: %pV\n", prefix, &vaf); + len = snprintf(buf, sizeof(buf), "%sEXT4-fs: ", prefix); + len += vsnprintf(buf + len, sizeof(buf) - len, fmt, args); va_end(args); + + /* Add newline if there's space */ + if (len < sizeof(buf) - 1) { + buf[len++] = '\n'; + buf[len] = '\0'; + } + + /* Record in message buffer */ + ext4l_record_msg(buf, len); + + /* Also print if debug is enabled */ + if (IS_ENABLED(CONFIG_EXT4L_DEBUG)) + printf("%s", buf); } static int ext4_warning_ratelimit(struct super_block *sb) -- 2.43.0