From 855c339457b782843a790e1e67e017e9b219dd46 Mon Sep 17 00:00:00 2001 From: HotMercury <75716244+HotMercury@users.noreply.github.com> Date: Sat, 18 May 2024 23:23:42 +0800 Subject: [PATCH] Fix potential EIO error (#51) If we use 'dd if=/dev/random of=test.img bs=1M count=32' rather than 'if=/dev/zero' and mount it, it will cause an EIO error and get stuck in a loop. This commit addresses an issue where the 'ls' command would read random, meaningless values from 'simplefs_file_ei_block' for uninitialized blocks. This occurred because the blocks contained residual data, leading to erroneous outputs. Changes: 1. Clear the root extent block during the 'mkfs' process to prevent erroneous 'simplefs_file_ei_block' data. 2. Ensure that file data blocks are cleared immediately upon allocation to prevent erroneous 'simplefs_file' data. Close #20 and #50 --- bitmap.h | 22 ++++++++++++++++++---- file.c | 3 +-- inode.c | 10 +++++----- mkfs.c | 17 +++++++++++++++-- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/bitmap.h b/bitmap.h index f7fa938..ba08931 100644 --- a/bitmap.h +++ b/bitmap.h @@ -40,14 +40,28 @@ static inline uint32_t get_free_inode(struct simplefs_sb_info *sbi) } /* Return 'len' unused block(s) number and mark it used. + * Clean the block content. * Return 0 if no enough free block(s) were found. */ -static inline uint32_t get_free_blocks(struct simplefs_sb_info *sbi, - uint32_t len) +static inline uint32_t get_free_blocks(struct super_block *sb, uint32_t len) { + struct simplefs_sb_info *sbi = SIMPLEFS_SB(sb); uint32_t ret = get_first_free_bits(sbi->bfree_bitmap, sbi->nr_blocks, len); - if (ret) - sbi->nr_free_blocks -= len; + if (!ret) /* No enough free blocks */ + return 0; + + sbi->nr_free_blocks -= len; + for (uint32_t i = 0; i < len; i++) { + struct buffer_head *bh = sb_bread(sb, ret + i); + if (!bh) { + pr_err("get_free_blocks: sb_bread failed for block %d\n", ret + i); + sbi->nr_free_blocks += len; + return -EIO; + } + memset(bh->b_data, 0, SIMPLEFS_BLOCK_SIZE); + mark_buffer_dirty(bh); + brelse(bh); + } return ret; } diff --git a/file.c b/file.c index ad74999..dac533b 100644 --- a/file.c +++ b/file.c @@ -20,7 +20,6 @@ static int simplefs_file_get_block(struct inode *inode, int create) { struct super_block *sb = inode->i_sb; - struct simplefs_sb_info *sbi = SIMPLEFS_SB(sb); struct simplefs_inode_info *ci = SIMPLEFS_INODE(inode); struct simplefs_file_ei_block *index; struct buffer_head *bh_index; @@ -52,7 +51,7 @@ static int simplefs_file_get_block(struct inode *inode, ret = 0; goto brelse_index; } - bno = get_free_blocks(sbi, 8); + bno = get_free_blocks(sb, 8); if (!bno) { ret = -ENOSPC; goto brelse_index; diff --git a/inode.c b/inode.c index 5750016..ef60889 100644 --- a/inode.c +++ b/inode.c @@ -248,7 +248,7 @@ static struct inode *simplefs_new_inode(struct inode *dir, mode_t mode) ci = SIMPLEFS_INODE(inode); /* Get a free block for this new inode's index */ - bno = get_free_blocks(sbi, 1); + bno = get_free_blocks(sb, 1); if (!bno) { ret = -ENOSPC; goto put_inode; @@ -381,7 +381,7 @@ static int simplefs_create(struct inode *dir, fi = eblock->nr_files % SIMPLEFS_FILES_PER_BLOCK; if (!eblock->extents[ei].ee_start) { - bno = get_free_blocks(SIMPLEFS_SB(sb), 8); + bno = get_free_blocks(sb, 8); if (!bno) { ret = -ENOSPC; goto iput; @@ -753,7 +753,7 @@ static int simplefs_rename(struct inode *old_dir, /* insert in new parent directory */ /* Get new freeblocks for extent if needed*/ if (new_pos < 0) { - bno = get_free_blocks(SIMPLEFS_SB(sb), 8); + bno = get_free_blocks(sb, 8); if (!bno) { ret = -ENOSPC; goto release_new; @@ -909,7 +909,7 @@ static int simplefs_link(struct dentry *old_dentry, fi = eblock->nr_files % SIMPLEFS_FILES_PER_BLOCK; if (eblock->extents[ei].ee_start == 0) { - bno = get_free_blocks(SIMPLEFS_SB(sb), 8); + bno = get_free_blocks(sb, 8); if (!bno) { ret = -ENOSPC; goto end; @@ -1002,7 +1002,7 @@ static int simplefs_symlink(struct inode *dir, fi = eblock->nr_files % SIMPLEFS_FILES_PER_BLOCK; if (eblock->extents[ei].ee_start == 0) { - bno = get_free_blocks(SIMPLEFS_SB(sb), 8); + bno = get_free_blocks(sb, 8); if (!bno) { ret = -ENOSPC; goto end; diff --git a/mkfs.c b/mkfs.c index f0af711..01a6e0b 100644 --- a/mkfs.c +++ b/mkfs.c @@ -235,7 +235,20 @@ static int write_bfree_blocks(int fd, struct superblock *sb) static int write_data_blocks(int fd, struct superblock *sb) { - /* FIXME: unimplemented */ + char *buffer = calloc(1, SIMPLEFS_BLOCK_SIZE); + if (!buffer) { + perror("Failed to allocate memory"); + return -1; + } + + ssize_t ret = write(fd, buffer, SIMPLEFS_BLOCK_SIZE); + if (ret != SIMPLEFS_BLOCK_SIZE) { + perror("Failed to write data block"); + free(buffer); + return -1; + } + + free(buffer); return 0; } @@ -315,7 +328,7 @@ int main(int argc, char **argv) goto free_sb; } - /* Write data blocks */ + /* clear a root index block */ ret = write_data_blocks(fd, sb); if (ret) { perror("write_data_blocks():");