From d2fe9c19d764b57d806e8bd2fe4592c19f06654d Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Thu, 18 Nov 2021 16:08:08 +0900 Subject: [PATCH] ext2: Add some necessary mutexes around block and inode allocation --- modules/ext2.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/modules/ext2.c b/modules/ext2.c index d7d0b519..d0dde12c 100644 --- a/modules/ext2.c +++ b/modules/ext2.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -202,6 +203,8 @@ typedef struct { uint8_t * cache_data; int flags; + + sched_mutex_t * mutex; } ext2_fs_t; #define EXT2_FLAG_READWRITE 0x0002 @@ -502,6 +505,8 @@ static size_t allocate_block(ext2_fs_t * this) { size_t group = 0; uint8_t * bg_buffer = malloc(this->block_size); + mutex_acquire(this->mutex); + for (unsigned int i = 0; i < BGDS; ++i) { if (BGD[i].free_blocks_count > 0) { read_block(this, BGD[i].block_bitmap, (uint8_t *)bg_buffer); @@ -515,6 +520,7 @@ static size_t allocate_block(ext2_fs_t * this) { } if (!block_no) { + mutex_release(this->mutex); debug_print(CRITICAL, "No available blocks, disk is out of space!"); free(bg_buffer); return 0; @@ -536,6 +542,8 @@ static size_t allocate_block(ext2_fs_t * this) { memset(bg_buffer, 0x00, this->block_size); write_block(this, block_no, bg_buffer); + mutex_release(this->mutex); + free(bg_buffer); return block_no; @@ -603,6 +611,7 @@ static unsigned int inode_write_block(ext2_fs_t * this, ext2_inodetable_t * inod debug_print(WARNING, "clearing and allocating up to required blocks (block=%d, %d)", block, inode->blocks); char * empty = NULL; + while (block >= inode->blocks / (this->block_size / 512)) { allocate_inode_block(this, inode, inode_no, inode->blocks / (this->block_size / 512)); refresh_inode(this, inode, inode_no); @@ -751,6 +760,8 @@ static unsigned int allocate_inode(ext2_fs_t * this) { uint32_t group = 0; uint8_t * bg_buffer = malloc(this->block_size); + mutex_acquire(this->mutex); + for (unsigned int i = 0; i < BGDS; ++i) { if (BGD[i].free_inodes_count > 0) { debug_print(NOTICE, "Group %d has %d free inodes.", i, BGD[i].free_inodes_count); @@ -764,6 +775,7 @@ static unsigned int allocate_inode(ext2_fs_t * this) { } } if (!node_no) { + mutex_release(this->mutex); debug_print(ERROR, "Ran out of inodes!"); return 0; } @@ -781,6 +793,8 @@ static unsigned int allocate_inode(ext2_fs_t * this) { SB->free_inodes_count--; rewrite_superblock(this); + mutex_release(this->mutex); + return node_no; } @@ -1097,17 +1111,32 @@ static int unlink_ext2(fs_node_t * node, char * name) { dir_offset += d_ent->rec_len; total_offset += d_ent->rec_len; } - free(inode); if (!direntry) { + free(inode); free(block); return -ENOENT; } + unsigned int new_inode = direntry->inode; direntry->inode = 0; - inode_write_block(this, inode, node->inode, block_nr, block); + free(inode); free(block); + inode = read_inode(this, new_inode); + + if (inode->links_count == 1) { + dprintf("ext2: TODO: unlinking '%s' (inode=%u) which now has no links; should delete\n", + name, new_inode); + } + + if (inode->links_count > 0) { + inode->links_count--; + write_inode(this, inode, new_inode); + } + + free(inode); + return 0; } @@ -1539,6 +1568,8 @@ static fs_node_t * mount_ext2(fs_node_t * block_device, int flags) { /* We need to keep an owned refcount to this device if it was something we opened... */ //vfs_lock(this->block_device); + this->mutex = mutex_init("ext2 fs"); + SB = malloc(this->block_size); debug_print(INFO, "Reading superblock...");