aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2021-09-12 17:00:09 +0200
committerMarvin Borner2021-09-12 17:00:09 +0200
commit421cebff27c591fe6e7102334e7a02dec197af94 (patch)
treea3e96386d870b5e5cb2d4bf143581070eac321bf
parentf582a27638479da361c0f2e24501d6662e08b522 (diff)
Dynamic inode size detection using extensions
-rw-r--r--kernel/features/fs.c50
-rw-r--r--kernel/inc/fs.h16
2 files changed, 49 insertions, 17 deletions
diff --git a/kernel/features/fs.c b/kernel/features/fs.c
index 7902d56..145c47a 100644
--- a/kernel/features/fs.c
+++ b/kernel/features/fs.c
@@ -217,41 +217,63 @@ CLEAR void vfs_install(void)
* EXT2
*/
-INLINE static void ext2_buffer_read(u32 block, void *buf, struct vfs_dev *dev)
+static void ext2_buffer_read(u32 block, void *buf, struct vfs_dev *dev)
{
dev->read(buf, block * SECTOR_COUNT, SECTOR_COUNT, dev);
}
-static void ext2_superblock(struct ext2_superblock *buf, struct vfs_dev *dev)
+static u8 ext2_verify(struct vfs_dev *dev)
{
u8 data[BLOCK_SIZE] = { 0 };
ext2_buffer_read(EXT2_SUPER, data, dev);
- memcpy(buf, data, sizeof(*buf));
+ struct ext2_superblock *sb = (struct ext2_superblock *)data;
+ return sb->magic == EXT2_MAGIC;
+}
+
+static struct ext2_superblock *ext2_superblock(struct vfs_dev *dev)
+{
+ struct ext2_superblock *sb;
- assert(buf->magic == EXT2_MAGIC);
+ if (dev->vfs->data) {
+ sb = dev->vfs->data;
+ } else {
+ sb = malloc(BLOCK_SIZE); // TODO: Destroy malloced superblock?
+ ext2_buffer_read(EXT2_SUPER, sb, dev);
+ dev->vfs->data = sb;
+ }
+
+ assert(sb->magic == EXT2_MAGIC);
+ return sb;
+}
+
+static u32 ext2_inode_size(struct vfs_dev *dev)
+{
+ struct ext2_superblock *sb = ext2_superblock(dev);
+ if (sb->major_version == 1)
+ return sb->inode_size;
+ return 128; // Or 256?
}
static struct ext2_inode *ext2_inode(u32 i, struct ext2_inode *in_buf, struct vfs_dev *dev)
{
- struct ext2_superblock sb = { 0 };
- ext2_superblock(&sb, dev);
+ struct ext2_superblock *sb = ext2_superblock(dev);
+ u32 inode_size = ext2_inode_size(dev);
u8 data[BLOCK_SIZE] = { 0 };
ext2_buffer_read(EXT2_SUPER + 1, data, dev);
struct ext2_bgd *bgd = (struct ext2_bgd *)data;
- u32 block_group = (i - 1) / sb.inodes_per_group;
- u32 index = (i - 1) % sb.inodes_per_group;
- u32 block = (index * EXT2_INODE_SIZE) / BLOCK_SIZE;
+ u32 block_group = (i - 1) / sb->inodes_per_group;
+ u32 index = (i - 1) % sb->inodes_per_group;
+ u32 block = (index * inode_size) / BLOCK_SIZE;
bgd += block_group;
u8 buf[BLOCK_SIZE] = { 0 };
ext2_buffer_read(bgd->inode_table + block, buf, dev);
struct ext2_inode *in =
- (struct ext2_inode *)((u32)buf +
- (index % (BLOCK_SIZE / EXT2_INODE_SIZE)) * EXT2_INODE_SIZE);
+ (struct ext2_inode *)((u32)buf + (index % (BLOCK_SIZE / inode_size)) * inode_size);
- memcpy(in_buf, in, sizeof(*in_buf));
+ memcpy(in_buf, in, inode_size);
return in_buf;
}
@@ -477,9 +499,7 @@ static res ext2_perm(const char *path, enum vfs_perm perm, struct vfs_dev *dev)
CLEAR u8 ext2_load(struct vfs_dev *dev)
{
- struct ext2_superblock sb = { 0 };
- ext2_superblock(&sb, dev);
- if (sb.magic != EXT2_MAGIC)
+ if (!ext2_verify(dev))
return 0;
struct vfs *vfs = zalloc(sizeof(*vfs));
diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h
index 04d3624..210f0c2 100644
--- a/kernel/inc/fs.h
+++ b/kernel/inc/fs.h
@@ -112,6 +112,20 @@ struct ext2_superblock {
u32 major_version;
u16 res_block_uid;
u16 res_block_gid;
+ // From here on only if major_version >=1
+ u32 first_inode;
+ u16 inode_size;
+ u16 block_group_number;
+ u32 compatible_features;
+ u32 incompatible_features;
+ u32 ro_compatible_features;
+ u8 uuid[16];
+ char volume_name[16];
+ char last_mounted_dir[64];
+ u32 algorithm_usage;
+ u8 preallocate_blocks;
+ u8 preallocate_dir_blocks;
+ u8 padding[50]; // idk? Doesn't really matter
};
struct ext2_bgd {
@@ -152,8 +166,6 @@ struct ext2_inode {
u8 extension[128]; // TODO: 2038 extension time support
};
-#define EXT2_INODE_SIZE (sizeof(struct ext2_inode))
-
struct ext2_dirent {
u32 inode_num;
u16 total_len;