129 lines
3.1 KiB
C++
129 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <BAN/HashMap.h>
|
|
#include <kernel/Device/Device.h>
|
|
#include <kernel/FS/FileSystem.h>
|
|
#include <kernel/FS/Ext2/Inode.h>
|
|
|
|
namespace Kernel
|
|
{
|
|
|
|
class Ext2FS final : public FileSystem
|
|
{
|
|
public:
|
|
class BlockBufferWrapper
|
|
{
|
|
BAN_NON_COPYABLE(BlockBufferWrapper);
|
|
BAN_NON_MOVABLE(BlockBufferWrapper);
|
|
|
|
public:
|
|
BlockBufferWrapper(BAN::Span<uint8_t> buffer, bool& used)
|
|
: m_buffer(buffer)
|
|
, m_used(used)
|
|
{
|
|
ASSERT(m_used);
|
|
}
|
|
~BlockBufferWrapper()
|
|
{
|
|
m_used = false;
|
|
}
|
|
|
|
size_t size() const { return m_buffer.size(); }
|
|
|
|
uint8_t* data() { return m_buffer.data(); }
|
|
const uint8_t* data() const { return m_buffer.data(); }
|
|
|
|
BAN::ByteSpan span() { return m_buffer; }
|
|
BAN::ConstByteSpan span() const { return m_buffer.as_const(); }
|
|
|
|
uint8_t& operator[](size_t index) { return m_buffer[index]; }
|
|
uint8_t operator[](size_t index) const { return m_buffer[index]; }
|
|
|
|
private:
|
|
BAN::Span<uint8_t> m_buffer;
|
|
bool& m_used;
|
|
};
|
|
|
|
public:
|
|
static BAN::ErrorOr<bool> probe(BAN::RefPtr<BlockDevice>);
|
|
static BAN::ErrorOr<BAN::RefPtr<Ext2FS>> create(BAN::RefPtr<BlockDevice>);
|
|
|
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
|
|
|
virtual dev_t dev() const override { return m_block_device->rdev(); };
|
|
|
|
private:
|
|
Ext2FS(BAN::RefPtr<BlockDevice> block_device)
|
|
: m_block_device(block_device)
|
|
{}
|
|
|
|
BAN::ErrorOr<void> initialize_superblock();
|
|
BAN::ErrorOr<void> initialize_root_inode();
|
|
|
|
BAN::ErrorOr<uint32_t> create_inode(const Ext2::Inode&);
|
|
BAN::ErrorOr<void> delete_inode(uint32_t ino);
|
|
BAN::ErrorOr<void> resize_inode(uint32_t, size_t);
|
|
|
|
BAN::ErrorOr<void> read_block(uint32_t, BlockBufferWrapper&);
|
|
BAN::ErrorOr<void> write_block(uint32_t, const BlockBufferWrapper&);
|
|
BAN::ErrorOr<void> sync_superblock();
|
|
BAN::ErrorOr<void> sync_block(uint32_t block);
|
|
|
|
BlockBufferWrapper get_block_buffer();
|
|
|
|
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
|
BAN::ErrorOr<void> release_block(uint32_t block);
|
|
|
|
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>>& inode_cache() { return m_inode_cache; }
|
|
|
|
const Ext2::Superblock& superblock() const { return m_superblock; }
|
|
|
|
struct BlockLocation
|
|
{
|
|
uint32_t block;
|
|
uint32_t offset;
|
|
};
|
|
BAN::ErrorOr<BlockLocation> locate_inode(uint32_t);
|
|
BlockLocation locate_block_group_descriptior(uint32_t);
|
|
|
|
uint32_t block_size() const { return 1024 << superblock().log_block_size; }
|
|
|
|
class BlockBufferManager
|
|
{
|
|
public:
|
|
BlockBufferManager() = default;
|
|
BlockBufferWrapper get_buffer();
|
|
|
|
BAN::ErrorOr<void> initialize(size_t block_size);
|
|
|
|
private:
|
|
struct BlockBuffer
|
|
{
|
|
BAN::Vector<uint8_t> buffer;
|
|
bool used { false };
|
|
};
|
|
|
|
private:
|
|
BAN::Array<BlockBuffer, 10> m_buffers;
|
|
};
|
|
|
|
private:
|
|
Mutex m_mutex;
|
|
|
|
BAN::RefPtr<BlockDevice> m_block_device;
|
|
|
|
BAN::RefPtr<Inode> m_root_inode;
|
|
BAN::Vector<uint32_t> m_superblock_backups;
|
|
|
|
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache;
|
|
|
|
BlockBufferManager m_buffer_manager;
|
|
|
|
Ext2::Superblock m_superblock;
|
|
|
|
friend class Ext2Inode;
|
|
friend class BAN::RefPtr<Ext2FS>;
|
|
};
|
|
|
|
}
|