fs: ext2: Interpret s_errors field in superblocks
Added funtion that takes specified action when file system corruption is detected. Possible actions are: do nothing, make mount point read-only, panic. Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
This commit is contained in:
parent
2e2a3cbd44
commit
b3eec79f5b
@ -680,8 +680,10 @@ int64_t ext2_alloc_block(struct ext2_data *fs)
|
||||
struct ext2_disk_superblock *sb = EXT2_DATA_SBLOCK(fs);
|
||||
uint32_t set = ext2_bitmap_count_set(BGROUP_BLOCK_BITMAP(fs->bgroup), sb->s_blocks_count);
|
||||
|
||||
__ASSERT(set == sb->s_blocks_count - sb->s_free_blocks_count,
|
||||
"Number of used inodes should be equal to bits set in bitmap");
|
||||
if (set != (sb->s_blocks_count - sb->s_free_blocks_count)) {
|
||||
error_behavior(fs, "Wrong number of used blocks in superblock and bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fs->sblock->flags |= EXT2_BLOCK_DIRTY;
|
||||
fs->bgroup->block->flags |= EXT2_BLOCK_DIRTY;
|
||||
@ -726,12 +728,15 @@ int32_t ext2_alloc_inode(struct ext2_data *fs)
|
||||
}
|
||||
|
||||
/* Add 1 because inodes are counted from 1 not 0. */
|
||||
int32_t total = group * EXT2_DATA_SBLOCK(fs)->s_inodes_per_group + r + 1;
|
||||
int32_t global_idx = group * EXT2_DATA_SBLOCK(fs)->s_inodes_per_group + r + 1;
|
||||
|
||||
/* Inode table entry for found inode must be cleared. */
|
||||
__ASSERT(check_zero_inode(fs, total) == 0, "Inode is not cleared in inode table!");
|
||||
if (check_zero_inode(fs, global_idx) != 0) {
|
||||
error_behavior(fs, "Inode is not cleared in inode table!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_DBG("Found free inode %d in group %d (total: %d)", r, group, total);
|
||||
LOG_DBG("Found free inode %d in group %d (global_idx: %d)", r, group, global_idx);
|
||||
|
||||
rc = ext2_bitmap_set(BGROUP_INODE_BITMAP(fs->bgroup), r, fs->block_size);
|
||||
if (rc < 0) {
|
||||
@ -744,8 +749,10 @@ int32_t ext2_alloc_inode(struct ext2_data *fs)
|
||||
struct ext2_disk_superblock *sb = EXT2_DATA_SBLOCK(fs);
|
||||
uint32_t set = ext2_bitmap_count_set(BGROUP_INODE_BITMAP(fs->bgroup), sb->s_inodes_count);
|
||||
|
||||
__ASSERT(set == sb->s_inodes_count - sb->s_free_inodes_count,
|
||||
"Number of used inodes should be equal to bits set in bitmap");
|
||||
if (set != sb->s_inodes_count - sb->s_free_inodes_count) {
|
||||
error_behavior(fs, "Wrong number of used inodes in superblock and bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fs->sblock->flags |= EXT2_BLOCK_DIRTY;
|
||||
fs->bgroup->block->flags |= EXT2_BLOCK_DIRTY;
|
||||
@ -754,7 +761,7 @@ int32_t ext2_alloc_inode(struct ext2_data *fs)
|
||||
LOG_DBG("Free inodes (bg): %d", current_disk_bgroup(fs->bgroup)->bg_free_inodes_count);
|
||||
LOG_DBG("Free inodes (sb): %d", EXT2_DATA_SBLOCK(fs)->s_free_inodes_count);
|
||||
|
||||
return total;
|
||||
return global_idx;
|
||||
}
|
||||
|
||||
int ext2_free_block(struct ext2_data *fs, uint32_t block)
|
||||
@ -789,8 +796,10 @@ int ext2_free_block(struct ext2_data *fs, uint32_t block)
|
||||
struct ext2_disk_superblock *sb = EXT2_DATA_SBLOCK(fs);
|
||||
uint32_t set = ext2_bitmap_count_set(BGROUP_BLOCK_BITMAP(fs->bgroup), sb->s_blocks_count);
|
||||
|
||||
__ASSERT(set == sb->s_blocks_count - sb->s_free_blocks_count,
|
||||
"Number of used inodes should be equal to bits set in bitmap");
|
||||
if (set != sb->s_blocks_count - sb->s_free_blocks_count) {
|
||||
error_behavior(fs, "Wrong number of used blocks in superblock and bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fs->sblock->flags |= EXT2_BLOCK_DIRTY;
|
||||
fs->bgroup->block->flags |= EXT2_BLOCK_DIRTY;
|
||||
@ -837,8 +846,10 @@ int ext2_free_inode(struct ext2_data *fs, uint32_t ino, bool directory)
|
||||
struct ext2_disk_superblock *sb = EXT2_DATA_SBLOCK(fs);
|
||||
uint32_t set = ext2_bitmap_count_set(BGROUP_INODE_BITMAP(fs->bgroup), sb->s_inodes_count);
|
||||
|
||||
__ASSERT(set == sb->s_inodes_count - sb->s_free_inodes_count,
|
||||
"Number of used inodes should be equal to bits set in bitmap");
|
||||
if (set != sb->s_inodes_count - sb->s_free_inodes_count) {
|
||||
error_behavior(fs, "Wrong number of used inodes in superblock and bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_INF("Inode %d is free", ino);
|
||||
|
||||
|
||||
@ -34,6 +34,34 @@ K_HEAP_DEFINE(ext2_heap, CONFIG_EXT2_HEAP_SIZE);
|
||||
|
||||
/* Helper functions --------------------------------------------------------- */
|
||||
|
||||
void error_behavior(struct ext2_data *fs, const char *msg)
|
||||
{
|
||||
LOG_ERR("File system corrupted: %s", msg);
|
||||
|
||||
/* If file system is not initialized panic */
|
||||
if (!fs->sblock) {
|
||||
LOG_ERR("File system data not found. Panic...");
|
||||
k_panic();
|
||||
}
|
||||
|
||||
switch (EXT2_DATA_SBLOCK(fs)->s_errors) {
|
||||
case EXT2_ERRORS_CONTINUE:
|
||||
/* Do nothing */
|
||||
break;
|
||||
case EXT2_ERRORS_RO:
|
||||
LOG_WRN("Marking file system as read only");
|
||||
fs->flags |= EXT2_DATA_FLAGS_RO;
|
||||
break;
|
||||
case EXT2_ERRORS_PANIC:
|
||||
LOG_ERR("Panic...");
|
||||
k_panic();
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unrecognized errors behavior in superblock s_errors field. Panic...");
|
||||
k_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void *ext2_heap_alloc(size_t size)
|
||||
{
|
||||
return k_heap_alloc(&ext2_heap, size, K_NO_WAIT);
|
||||
@ -252,10 +280,8 @@ int ext2_verify_superblock(struct ext2_disk_superblock *sb)
|
||||
return -EROFS;
|
||||
|
||||
case EXT2_ERRORS_PANIC:
|
||||
LOG_ERR("File system can't be mounted");
|
||||
/* panic or return that fs is invalid */
|
||||
__ASSERT(sb->s_state == EXT2_VALID_FS, "Error detected in superblock");
|
||||
return -EINVAL;
|
||||
LOG_ERR("File system can't be mounted. Panic...");
|
||||
k_panic();
|
||||
default:
|
||||
LOG_WRN("Unknown option for superblock s_errors field.");
|
||||
}
|
||||
@ -326,13 +352,17 @@ int ext2_init_fs(struct ext2_data *fs)
|
||||
|
||||
set = ext2_bitmap_count_set(BGROUP_BLOCK_BITMAP(fs->bgroup), fs_blocks);
|
||||
|
||||
__ASSERT(set == sb->s_blocks_count - sb->s_free_blocks_count - sb->s_first_data_block,
|
||||
"Number of used blocks should be equal to bits set in bitmap");
|
||||
if (set != sb->s_blocks_count - sb->s_free_blocks_count - sb->s_first_data_block) {
|
||||
error_behavior(fs, "Wrong number of used blocks in superblock and bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set = ext2_bitmap_count_set(BGROUP_INODE_BITMAP(fs->bgroup), sb->s_inodes_count);
|
||||
|
||||
__ASSERT(set == sb->s_inodes_count - sb->s_free_inodes_count,
|
||||
"Number of used inodes should be equal to bits set in bitmap");
|
||||
if (set != sb->s_inodes_count - sb->s_free_inodes_count) {
|
||||
error_behavior(fs, "Wrong number of used inodes in superblock and bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
ext2_drop_block(fs, fs->sblock);
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
|
||||
#include "ext2_struct.h"
|
||||
|
||||
void error_behavior(struct ext2_data *fs, const char *msg);
|
||||
|
||||
/* Memory allocation for ext2 implementation */
|
||||
void *ext2_heap_alloc(size_t size);
|
||||
void ext2_heap_free(void *ptr);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user