Add ext2 VFS implementation
diff --git a/src/kernel/dri/fs/ext2/ext2.c b/src/kernel/dri/fs/ext2/ext2.c
index 9ecbe51..9952948 100644
--- a/src/kernel/dri/fs/ext2/ext2.c
+++ b/src/kernel/dri/fs/ext2/ext2.c
@@ -19,11 +19,6 @@
};
#undef F
-inline uint ext2_block_size(struct ext2_superblock *sb)
-{
- return 1024 << sb->block_size_shift;
-}
-
void ext2_read_block(struct ext2_superblock *sb, void *buffer, uint block)
{
uint block_size = ext2_block_size(sb) / 512;
@@ -68,9 +63,26 @@
}
}
-struct ext2_block_group_descriptor ext2_load_block_group_descriptor(
+void ext2_write_bgd(struct ext2_superblock *sb, uint block_group,
+ struct ext2_block_group_descriptor *d)
+{
+ ext2_load_or_write_bgd(sb, block_group, d, true);
+}
+
+struct ext2_block_group_descriptor ext2_load_bgd(
struct ext2_superblock *sb, uint block_group)
{
+ struct ext2_block_group_descriptor bgd;
+ ext2_load_or_write_bgd(sb, block_group, &bgd, false);
+
+ return bgd;
+}
+
+void ext2_load_or_write_bgd(struct ext2_superblock *sb,
+ uint block_group,
+ struct ext2_block_group_descriptor *d,
+ bool set)
+{
/**
* The BGDT (not to be confused with the GDT) is located the block after the
* superblock. On any block size EXCEPT 1024 (the minimum, remember that the
@@ -95,9 +107,17 @@
uint lba = (block_size / 512) * bgdt_block + hd_page;
- ata_pio_read_sectors(&descriptors, lba, 1);
+ ata_pio_read_sectors(descriptors, lba, 1);
- return descriptors[bgd_offset];
+ if (set)
+ {
+ descriptors[bgd_offset] = *d;
+ ata_pio_write_sectors(lba, 1, (ushort *)descriptors);
+ }
+ else
+ {
+ *d = descriptors[bgd_offset];
+ }
}
static bool print_entry(uint inode, const char *name, uint l, void *sb)
@@ -194,7 +214,7 @@
// Load this from the block group descriptor table
struct ext2_block_group_descriptor descriptor =
- ext2_load_block_group_descriptor(sb, block_group);
+ ext2_load_bgd(sb, block_group);
// We need to figure out what FS block the inode is on, we know how many
// inodes there are total in this BGD and the number per page, so this is
@@ -579,7 +599,7 @@
for (int bg_num = 0; bg_num < num_block_groups; bg_num++)
{
struct ext2_block_group_descriptor bgd =
- ext2_load_block_group_descriptor(sb, 0);
+ ext2_load_bgd(sb, 0);
const uint block_size = ext2_block_size(sb);
// + 1 because we need to round up (ie 1025 for 1024 size blocks will
@@ -609,7 +629,7 @@
for (int bg_num = 0; bg_num < num_block_groups; bg_num++)
{
struct ext2_block_group_descriptor bgd =
- ext2_load_block_group_descriptor(sb, 0);
+ ext2_load_bgd(sb, 0);
const uint block_size = ext2_block_size(sb);
// + 1 because we need to round up (ie 1025 for 1024 size blocks will
@@ -706,3 +726,25 @@
return d.inode;
}
+
+uint ext2_alloc_new_block(struct ext2_superblock *sb,
+ uint block_group)
+{
+ struct ext2_block_group_descriptor bgd =
+ ext2_load_bgd(sb, block_group);
+
+ if (bgd.unallocated_blocks == 0)
+ // TODO: handle out of blocks
+ return ext2_alloc_new_block(sb, block_group + 1);
+
+ // We can safely pass ~0 here as long as the FS is well formed
+ // because we know there is at least 1 free block
+ uint block = ext2_first_zero_bit(sb, bgd.block_bitmap, ~0, 0);
+
+ ext2_set_in_bitmap(sb, bgd.block_bitmap, block, true);
+ bgd.unallocated_blocks--;
+
+ ext2_write_bgd(sb, block_group, &bgd);
+
+ return block;
+}