diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c index d9db7ff..8ad9efb 100644 --- a/kernel/fs/ext2.c +++ b/kernel/fs/ext2.c @@ -21,7 +21,7 @@ vfs_fs_t ext2_driver = {ext2_mount_super, ext2_umount_super, ext2_stat, ext2__get_root_dir_inode, ext2__link_deref, ext2__free_inodes, ext2__total_inodes, ext2__free_blocks, ext2__total_blocks, - ext2_alloc_inode, ext2_alloc_block, + ext2_alloc_inode, ext2_free_inode, ext2_alloc_block, ext2_free_block, ext2__open_dir, ext2__read_dir, ext2__close_dir, ext2__open_file, ext2__read_file, ext2__close_file, ext2__open_block_file, ext2__read_block_file, ext2__block_file_seek, ext2__close_block_file}; @@ -168,7 +168,7 @@ int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode) } -// check the status of an inode +// check the status of an inode (1-based inode number) // -1: invalid inode number // 0: free inode // 1: allocated inode @@ -348,6 +348,23 @@ u32_t ext2_alloc_inode(vfs_mount_t *mount) return 0; } +int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number) +{ + ext2_super_block_t *super = mount->super; + if (inode_number < 11 || inode_number > super->s_inodes_count) + return -1; // invalid inode number + if (ext2_inode_status(mount, inode_number) != 1) + return -2; // inode not allocated + inode_number--; // now a 0-based inode number + int bg = inode_number / super->s_inodes_per_group; + ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg); + ext2_free_node(mount, group_desc.bg_inode_bitmap, inode_number % super->s_inodes_per_group); + group_desc.bg_free_inodes_count++; + ext2_write_group_desc(mount, bg, &group_desc); + super->s_free_inodes_count++; + return 0; +} + // allocate a block and return its number u32_t ext2_alloc_block(vfs_mount_t *mount) { @@ -370,6 +387,23 @@ u32_t ext2_alloc_block(vfs_mount_t *mount) return 0; } +int ext2_free_block(vfs_mount_t *mount, u32_t block_number) +{ + ext2_super_block_t *super = mount->super; + if (block_number < super->s_first_data_block || block_number > (super->s_blocks_count + super->s_first_data_block - 1)) + return -1; // invalid block number + if (ext2_block_status(mount, block_number) != 1) + return -2; // block not allocated + block_number -= super->s_first_data_block; // now a 0-based block number + int bg = block_number / super->s_blocks_per_group; + ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg); + ext2_free_node(mount, group_desc.bg_block_bitmap, block_number % super->s_blocks_per_group); + group_desc.bg_free_blocks_count++; + ext2_write_group_desc(mount, bg, &group_desc); + super->s_free_blocks_count++; + return 0; +} + int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size) { ext2_inode_t inode; @@ -378,9 +412,9 @@ int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size) ext2_super_block_t *super = mount->super; int current_blocks = (inode.i_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size); int new_blocks = (new_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size); - if ( num_blocks == current_size ) + if ( new_blocks == current_blocks ) return 0; - + // TODO: resize } // reserve a node of a inode or block bitmap and mark its entry allocated @@ -429,6 +463,22 @@ u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap return 0; } +int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number) +{ + ext2_super_block_t *super = mount->super; + u32_t block_num = node_number >> (13 + super->s_log_block_size); + byte *block = kmalloc(1024 << super->s_log_block_size); + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block_num, super), + 2 << super->s_log_block_size, block); + u32_t node_bit_offset = node_number % (8192 << super->s_log_block_size); + u32_t node_byte_offset = node_bit_offset >> 3; + block[node_byte_offset] &= (0xFF ^ (1 << (node_bit_offset & 0x7))); + block_write(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block_num, super), + 2 << super->s_log_block_size, block); + kfree(block); + return 0; +} + // return how many block groups are on the filesystem int ext2_num_block_groups(ext2_super_block_t *super) { diff --git a/kernel/fs/ext2.h b/kernel/fs/ext2.h index 104556d..8395a33 100644 --- a/kernel/fs/ext2.h +++ b/kernel/fs/ext2.h @@ -191,11 +191,17 @@ int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode); int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block); u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode); int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number); + int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number); int ext2_block_status(vfs_mount_t *mount, u32_t block_number); + u32_t ext2_alloc_inode(vfs_mount_t *mount); +int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number); u32_t ext2_alloc_block(vfs_mount_t *mount); +int ext2_free_block(vfs_mount_t *mount, u32_t block_number); + u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size); +int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number); int ext2_num_block_groups(ext2_super_block_t *super); void ext2_write_super(vfs_mount_t *mount); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index e8c748a..d8e3bee 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -286,13 +286,27 @@ vfs_inode_t vfs_alloc_inode(vfs_mount_t *mount) return 0; } -int vfs_alloc_block(vfs_mount_t *mount) +int vfs_free_inode(vfs_mount_t *mount, u32_t inode_number) +{ + if (fses[mount->fs]->free_inode) + return fses[mount->fs]->free_inode(mount, inode_number); + return -256; +} + +u32_t vfs_alloc_block(vfs_mount_t *mount) { if (fses[mount->fs]->alloc_block) return fses[mount->fs]->alloc_block(mount); return 0; } +int vfs_free_block(vfs_mount_t *mount, u32_t block_number) +{ + if (fses[mount->fs]->free_block) + return fses[mount->fs]->free_block(mount, block_number); + return -256; +} + int vfs_link_deref(vfs_inode_t vfs_inode, char *link) { vfs_stat_t stat; diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index c067154..5c0c0c5 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -100,8 +100,11 @@ typedef struct int (*total_inodes)(vfs_mount_t *mount); int (*free_blocks)(vfs_mount_t *mount); int (*total_blocks)(vfs_mount_t *mount); + u32_t (*alloc_inode)(vfs_mount_t *mount); + int (*free_inode)(vfs_mount_t *mount, u32_t inode_number); u32_t (*alloc_block)(vfs_mount_t *mount); + int (*free_block)(vfs_mount_t *mount, u32_t block_number); int (*open_dir)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir); int (*read_dir)(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry); @@ -137,8 +140,11 @@ int vfs_total_inodes(vfs_mount_t *mount); int vfs_free_blocks(vfs_mount_t *mount); int vfs_total_blocks(vfs_mount_t *mount); +/* Temporary for debugging */ vfs_inode_t vfs_alloc_inode(vfs_mount_t *mount); -int vfs_alloc_block(vfs_mount_t *mount); +int vfs_free_inode(vfs_mount_t *mount, u32_t inode_number); +u32_t vfs_alloc_block(vfs_mount_t *mount); +int vfs_free_block(vfs_mount_t *mount, u32_t block_number); int vfs_link_deref(vfs_inode_t vfs_inode, char *link); diff --git a/kernel/kernel.c b/kernel/kernel.c index b896bd2..ee277d4 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -174,6 +174,19 @@ void k_init() } else kprintf("Error: Could not open directory\n"); + vfs_mount_t *rootm = vfs_get_mount(0); + kprintf("Total/Free inodes: %d/%d\tTotal/Free blocks: %d/%d\n", + vfs_total_inodes(rootm), vfs_free_inodes(rootm), vfs_total_blocks(rootm), vfs_free_blocks(rootm)); + u32_t block = vfs_alloc_block(rootm); + kprintf("VFS got block %d\n", block); + kprintf("Total/Free inodes: %d/%d\tTotal/Free blocks: %d/%d\n", + vfs_total_inodes(rootm), vfs_free_inodes(rootm), vfs_total_blocks(rootm), vfs_free_blocks(rootm)); + kprintf("Freeing block... %d\n", vfs_free_block(rootm, block)); + kprintf("Total/Free inodes: %d/%d\tTotal/Free blocks: %d/%d\n", + vfs_total_inodes(rootm), vfs_free_inodes(rootm), vfs_total_blocks(rootm), vfs_free_blocks(rootm)); + kprintf("Freeing block (again)... %d\n", vfs_free_block(rootm, block)); + kprintf("Total/Free inodes: %d/%d\tTotal/Free blocks: %d/%d\n", + vfs_total_inodes(rootm), vfs_free_inodes(rootm), vfs_total_blocks(rootm), vfs_free_blocks(rootm)); criticalCounter--; }