ext2: Add some necessary mutexes around block and inode allocation

This commit is contained in:
K. Lange 2021-11-18 16:08:08 +09:00
parent b48326cd23
commit d2fe9c19d7

View File

@ -15,6 +15,7 @@
#include <kernel/spinlock.h>
#include <kernel/tokenize.h>
#include <kernel/module.h>
#include <kernel/mutex.h>
#include <sys/ioctl.h>
@ -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...");