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/spinlock.h>
#include <kernel/tokenize.h> #include <kernel/tokenize.h>
#include <kernel/module.h> #include <kernel/module.h>
#include <kernel/mutex.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -202,6 +203,8 @@ typedef struct {
uint8_t * cache_data; uint8_t * cache_data;
int flags; int flags;
sched_mutex_t * mutex;
} ext2_fs_t; } ext2_fs_t;
#define EXT2_FLAG_READWRITE 0x0002 #define EXT2_FLAG_READWRITE 0x0002
@ -502,6 +505,8 @@ static size_t allocate_block(ext2_fs_t * this) {
size_t group = 0; size_t group = 0;
uint8_t * bg_buffer = malloc(this->block_size); uint8_t * bg_buffer = malloc(this->block_size);
mutex_acquire(this->mutex);
for (unsigned int i = 0; i < BGDS; ++i) { for (unsigned int i = 0; i < BGDS; ++i) {
if (BGD[i].free_blocks_count > 0) { if (BGD[i].free_blocks_count > 0) {
read_block(this, BGD[i].block_bitmap, (uint8_t *)bg_buffer); 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) { if (!block_no) {
mutex_release(this->mutex);
debug_print(CRITICAL, "No available blocks, disk is out of space!"); debug_print(CRITICAL, "No available blocks, disk is out of space!");
free(bg_buffer); free(bg_buffer);
return 0; return 0;
@ -536,6 +542,8 @@ static size_t allocate_block(ext2_fs_t * this) {
memset(bg_buffer, 0x00, this->block_size); memset(bg_buffer, 0x00, this->block_size);
write_block(this, block_no, bg_buffer); write_block(this, block_no, bg_buffer);
mutex_release(this->mutex);
free(bg_buffer); free(bg_buffer);
return block_no; 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); debug_print(WARNING, "clearing and allocating up to required blocks (block=%d, %d)", block, inode->blocks);
char * empty = NULL; char * empty = NULL;
while (block >= inode->blocks / (this->block_size / 512)) { while (block >= inode->blocks / (this->block_size / 512)) {
allocate_inode_block(this, inode, inode_no, 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); refresh_inode(this, inode, inode_no);
@ -751,6 +760,8 @@ static unsigned int allocate_inode(ext2_fs_t * this) {
uint32_t group = 0; uint32_t group = 0;
uint8_t * bg_buffer = malloc(this->block_size); uint8_t * bg_buffer = malloc(this->block_size);
mutex_acquire(this->mutex);
for (unsigned int i = 0; i < BGDS; ++i) { for (unsigned int i = 0; i < BGDS; ++i) {
if (BGD[i].free_inodes_count > 0) { if (BGD[i].free_inodes_count > 0) {
debug_print(NOTICE, "Group %d has %d free inodes.", i, BGD[i].free_inodes_count); 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) { if (!node_no) {
mutex_release(this->mutex);
debug_print(ERROR, "Ran out of inodes!"); debug_print(ERROR, "Ran out of inodes!");
return 0; return 0;
} }
@ -781,6 +793,8 @@ static unsigned int allocate_inode(ext2_fs_t * this) {
SB->free_inodes_count--; SB->free_inodes_count--;
rewrite_superblock(this); rewrite_superblock(this);
mutex_release(this->mutex);
return node_no; return node_no;
} }
@ -1097,17 +1111,32 @@ static int unlink_ext2(fs_node_t * node, char * name) {
dir_offset += d_ent->rec_len; dir_offset += d_ent->rec_len;
total_offset += d_ent->rec_len; total_offset += d_ent->rec_len;
} }
free(inode);
if (!direntry) { if (!direntry) {
free(inode);
free(block); free(block);
return -ENOENT; return -ENOENT;
} }
unsigned int new_inode = direntry->inode;
direntry->inode = 0; direntry->inode = 0;
inode_write_block(this, inode, node->inode, block_nr, block); inode_write_block(this, inode, node->inode, block_nr, block);
free(inode);
free(block); 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; 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... */ /* We need to keep an owned refcount to this device if it was something we opened... */
//vfs_lock(this->block_device); //vfs_lock(this->block_device);
this->mutex = mutex_init("ext2 fs");
SB = malloc(this->block_size); SB = malloc(this->block_size);
debug_print(INFO, "Reading superblock..."); debug_print(INFO, "Reading superblock...");