From: Simon Glass <simon.glass@canonical.com> Add ext4l_write_block() to enable writing blocks to disk, which is needed for ext4_commit_super() during read-write mounts. Also update submit_bh() to call the write function and return proper error codes. Set the BH_Mapped flag in sb_getblk() and bdev_getblk() since ext4 checks this flag in ext4_commit_super() to verify the buffer is valid. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/ext4_uboot.h | 2 +- fs/ext4l/support.c | 55 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h index 4dd03494586..6dd498c8f52 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -2150,7 +2150,7 @@ struct blockgroup_lock { }; /* Buffer submission stubs - declarations for stub.c implementations */ -void submit_bh(int op_flags, struct buffer_head *bh); +int submit_bh(int op_flags, struct buffer_head *bh); struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, unsigned int size, gfp_t gfp); int trylock_buffer(struct buffer_head *bh); diff --git a/fs/ext4l/support.c b/fs/ext4l/support.c index 9e93426b565..05efa8d067c 100644 --- a/fs/ext4l/support.c +++ b/fs/ext4l/support.c @@ -352,6 +352,40 @@ int ext4l_read_block(sector_t block, size_t size, void *buffer) return 0; } +/** + * ext4l_write_block() - Write a block to the block device + * @block: Block number (filesystem block, not sector) + * @size: Block size in bytes + * @buffer: Source buffer + * Return: 0 on success, negative on error + */ +int ext4l_write_block(sector_t block, size_t size, void *buffer) +{ + struct blk_desc *blk_dev; + struct disk_partition *part; + lbaint_t sector; + lbaint_t sector_count; + unsigned long n; + + blk_dev = ext4l_get_blk_dev(); + part = ext4l_get_partition(); + if (!blk_dev) + return -EIO; + + /* Convert block to sector */ + sector = (block * size) / blk_dev->blksz + part->start; + sector_count = size / blk_dev->blksz; + + if (sector_count == 0) + sector_count = 1; + + n = blk_dwrite(blk_dev, sector, sector_count, buffer); + if (n != sector_count) + return -EIO; + + return 0; +} + /** * sb_getblk() - Get a buffer, using cache if available * @sb: Super block @@ -379,6 +413,9 @@ struct buffer_head *sb_getblk(struct super_block *sb, sector_t block) bh->b_bdev = sb->s_bdev; bh->b_size = sb->s_blocksize; + /* Mark buffer as having a valid disk mapping */ + set_buffer_mapped(bh); + /* Don't read - just allocate with zeroed data */ memset(bh->b_data, '\0', bh->b_size); @@ -474,6 +511,9 @@ struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, bh->b_bdev = bdev; bh->b_size = size; + /* Mark buffer as having a valid disk mapping */ + set_buffer_mapped(bh); + /* Don't read - just allocate with zeroed data */ memset(bh->b_data, 0, bh->b_size); @@ -520,8 +560,9 @@ struct buffer_head *__bread(struct block_device *bdev, sector_t block, * submit_bh() - Submit a buffer_head for I/O * @op: Operation (REQ_OP_READ, REQ_OP_WRITE, etc.) * @bh: Buffer head to submit + * Return: 0 on success, negative on error */ -void submit_bh(int op, struct buffer_head *bh) +int submit_bh(int op, struct buffer_head *bh) { int ret; int op_type = op & 0xff; /* Mask out flags, keep operation type */ @@ -530,13 +571,19 @@ void submit_bh(int op, struct buffer_head *bh) ret = ext4l_read_block(bh->b_blocknr, bh->b_size, bh->b_data); if (ret) { clear_buffer_uptodate(bh); - return; + return ret; } set_buffer_uptodate(bh); } else if (op_type == REQ_OP_WRITE) { - /* Write support not implemented yet */ - clear_buffer_uptodate(bh); + ret = ext4l_write_block(bh->b_blocknr, bh->b_size, bh->b_data); + if (ret) { + clear_buffer_uptodate(bh); + return ret; + } + /* Mark buffer as clean (not dirty) after write */ } + + return 0; } /** -- 2.43.0