forked from Bananymous/banan-os
update main #1
|
@ -9,6 +9,37 @@ namespace Kernel
|
||||||
|
|
||||||
class Ext2FS final : public FileSystem
|
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(); }
|
||||||
|
|
||||||
|
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:
|
public:
|
||||||
static BAN::ErrorOr<Ext2FS*> create(Partition&);
|
static BAN::ErrorOr<Ext2FS*> create(Partition&);
|
||||||
|
|
||||||
|
@ -26,10 +57,12 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> delete_inode(uint32_t);
|
BAN::ErrorOr<void> delete_inode(uint32_t);
|
||||||
BAN::ErrorOr<void> resize_inode(uint32_t, size_t);
|
BAN::ErrorOr<void> resize_inode(uint32_t, size_t);
|
||||||
|
|
||||||
void read_block(uint32_t, BAN::Span<uint8_t>);
|
void read_block(uint32_t, BlockBufferWrapper&);
|
||||||
void write_block(uint32_t, BAN::Span<const uint8_t>);
|
void write_block(uint32_t, const BlockBufferWrapper&);
|
||||||
void sync_superblock();
|
void sync_superblock();
|
||||||
|
|
||||||
|
BlockBufferWrapper get_block_buffer();
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
||||||
|
|
||||||
const Ext2::Superblock& superblock() const { return m_superblock; }
|
const Ext2::Superblock& superblock() const { return m_superblock; }
|
||||||
|
@ -39,11 +72,30 @@ namespace Kernel
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
};
|
};
|
||||||
BAN::ErrorOr<BlockLocation> locate_inode(uint32_t);
|
BlockLocation locate_inode(uint32_t);
|
||||||
BlockLocation locate_block_group_descriptior(uint32_t);
|
BlockLocation locate_block_group_descriptior(uint32_t);
|
||||||
|
|
||||||
uint32_t block_size() const { return 1024 << superblock().log_block_size; }
|
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:
|
private:
|
||||||
RecursiveSpinLock m_lock;
|
RecursiveSpinLock m_lock;
|
||||||
|
|
||||||
|
@ -52,6 +104,8 @@ namespace Kernel
|
||||||
BAN::RefPtr<Inode> m_root_inode;
|
BAN::RefPtr<Inode> m_root_inode;
|
||||||
BAN::Vector<uint32_t> m_superblock_backups;
|
BAN::Vector<uint32_t> m_superblock_backups;
|
||||||
|
|
||||||
|
BlockBufferManager m_buffer_manager;
|
||||||
|
|
||||||
Ext2::Superblock m_superblock;
|
Ext2::Superblock m_superblock;
|
||||||
|
|
||||||
friend class Ext2Inode;
|
friend class Ext2Inode;
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::ErrorOr<uint32_t> fs_block_of_data_block_index(uint32_t data_block_index);
|
uint32_t fs_block_of_data_block_index(uint32_t data_block_index);
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> allocate_new_block();
|
BAN::ErrorOr<uint32_t> allocate_new_block();
|
||||||
BAN::ErrorOr<void> sync();
|
BAN::ErrorOr<void> sync();
|
||||||
|
|
|
@ -90,16 +90,17 @@ namespace Kernel
|
||||||
dprintln(" inodes/group {}", m_superblock.inodes_per_group);
|
dprintln(" inodes/group {}", m_superblock.inodes_per_group);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TRY(m_buffer_manager.initialize(block_size()));
|
||||||
|
|
||||||
{
|
{
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_buffer_manager.get_buffer();
|
||||||
TRY(block_buffer.resize(block_size()));
|
|
||||||
|
|
||||||
if (superblock().rev_level == Ext2::Enum::GOOD_OLD_REV)
|
if (superblock().rev_level == Ext2::Enum::GOOD_OLD_REV)
|
||||||
{
|
{
|
||||||
// In revision 0 all blockgroups contain superblock backup
|
// In revision 0 all blockgroups contain superblock backup
|
||||||
TRY(m_superblock_backups.reserve(number_of_block_groups - 1));
|
TRY(m_superblock_backups.reserve(number_of_block_groups - 1));
|
||||||
for (uint32_t i = 1; i < number_of_block_groups; i++)
|
for (uint32_t i = 1; i < number_of_block_groups; i++)
|
||||||
MUST(block_buffer.push_back(i));
|
MUST(m_superblock_backups.push_back(i));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -118,7 +119,7 @@ namespace Kernel
|
||||||
|
|
||||||
for (uint32_t bg : m_superblock_backups)
|
for (uint32_t bg : m_superblock_backups)
|
||||||
{
|
{
|
||||||
read_block(superblock().first_data_block + superblock().blocks_per_group * bg, block_buffer.span());
|
read_block(superblock().first_data_block + superblock().blocks_per_group * bg, block_buffer);
|
||||||
Ext2::Superblock& superblock_backup = *(Ext2::Superblock*)block_buffer.data();
|
Ext2::Superblock& superblock_backup = *(Ext2::Superblock*)block_buffer.data();
|
||||||
if (superblock_backup.magic != Ext2::Enum::SUPER_MAGIC)
|
if (superblock_backup.magic != Ext2::Enum::SUPER_MAGIC)
|
||||||
derrorln("superblock backup at block {} is invalid ({4H})", bg, superblock_backup.magic);
|
derrorln("superblock backup at block {} is invalid ({4H})", bg, superblock_backup.magic);
|
||||||
|
@ -145,11 +146,8 @@ namespace Kernel
|
||||||
|
|
||||||
const uint32_t block_size = this->block_size();
|
const uint32_t block_size = this->block_size();
|
||||||
|
|
||||||
BAN::Vector<uint8_t> bgd_buffer;
|
auto bgd_buffer = m_buffer_manager.get_buffer();
|
||||||
TRY(bgd_buffer.resize(block_size));
|
auto inode_bitmap = m_buffer_manager.get_buffer();
|
||||||
|
|
||||||
BAN::Vector<uint8_t> inode_bitmap;
|
|
||||||
TRY(inode_bitmap.resize(block_size));
|
|
||||||
|
|
||||||
uint32_t current_group = -1;
|
uint32_t current_group = -1;
|
||||||
BlockLocation bgd_location {};
|
BlockLocation bgd_location {};
|
||||||
|
@ -165,7 +163,7 @@ namespace Kernel
|
||||||
current_group = ino_group;
|
current_group = ino_group;
|
||||||
|
|
||||||
bgd_location = locate_block_group_descriptior(current_group);
|
bgd_location = locate_block_group_descriptior(current_group);
|
||||||
read_block(bgd_location.block, bgd_buffer.span());
|
read_block(bgd_location.block, bgd_buffer);
|
||||||
|
|
||||||
bgd = (Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
bgd = (Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
||||||
if (bgd->free_inodes_count == 0)
|
if (bgd->free_inodes_count == 0)
|
||||||
|
@ -174,7 +172,7 @@ namespace Kernel
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_block(bgd->inode_bitmap, inode_bitmap.span());
|
read_block(bgd->inode_bitmap, inode_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t ino_bitmap_byte = ino_index / 8;
|
const uint32_t ino_bitmap_byte = ino_index / 8;
|
||||||
|
@ -183,10 +181,10 @@ namespace Kernel
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
inode_bitmap[ino_bitmap_byte] |= 1 << ino_bitmap_bit;
|
inode_bitmap[ino_bitmap_byte] |= 1 << ino_bitmap_bit;
|
||||||
write_block(bgd->inode_bitmap, inode_bitmap.span());
|
write_block(bgd->inode_bitmap, inode_bitmap);
|
||||||
|
|
||||||
bgd->free_inodes_count--;
|
bgd->free_inodes_count--;
|
||||||
write_block(bgd_location.block, bgd_buffer.span());
|
write_block(bgd_location.block, bgd_buffer);
|
||||||
|
|
||||||
const uint32_t inode_table_offset = ino_index * superblock().inode_size;
|
const uint32_t inode_table_offset = ino_index * superblock().inode_size;
|
||||||
const BlockLocation inode_location
|
const BlockLocation inode_location
|
||||||
|
@ -198,11 +196,11 @@ namespace Kernel
|
||||||
// NOTE: we don't need inode bitmap anymore, so we can reuse it
|
// NOTE: we don't need inode bitmap anymore, so we can reuse it
|
||||||
auto& inode_buffer = inode_bitmap;
|
auto& inode_buffer = inode_bitmap;
|
||||||
|
|
||||||
read_block(inode_location.block, inode_buffer.span());
|
read_block(inode_location.block, inode_buffer);
|
||||||
memcpy(inode_buffer.data() + inode_location.offset, &ext2_inode, sizeof(Ext2::Inode));
|
memcpy(inode_buffer.data() + inode_location.offset, &ext2_inode, sizeof(Ext2::Inode));
|
||||||
if (superblock().inode_size > sizeof(Ext2::Inode))
|
if (superblock().inode_size > sizeof(Ext2::Inode))
|
||||||
memset(inode_buffer.data() + inode_location.offset + sizeof(Ext2::Inode), 0, superblock().inode_size - sizeof(Ext2::Inode));
|
memset(inode_buffer.data() + inode_location.offset + sizeof(Ext2::Inode), 0, superblock().inode_size - sizeof(Ext2::Inode));
|
||||||
write_block(inode_location.block, inode_buffer.span());
|
write_block(inode_location.block, inode_buffer);
|
||||||
|
|
||||||
m_superblock.free_inodes_count--;
|
m_superblock.free_inodes_count--;
|
||||||
sync_superblock();
|
sync_superblock();
|
||||||
|
@ -214,7 +212,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_error_code(ErrorCode::Ext2_Corrupted);
|
return BAN::Error::from_error_code(ErrorCode::Ext2_Corrupted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FS::read_block(uint32_t block, BAN::Span<uint8_t> buffer)
|
void Ext2FS::read_block(uint32_t block, BlockBufferWrapper& buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
@ -228,7 +226,7 @@ namespace Kernel
|
||||||
MUST(m_partition.read_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.data()));
|
MUST(m_partition.read_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FS::write_block(uint32_t block, BAN::Span<const uint8_t> buffer)
|
void Ext2FS::write_block(uint32_t block, const BlockBufferWrapper& buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
@ -268,6 +266,13 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Ext2FS::BlockBufferWrapper Ext2FS::get_block_buffer()
|
||||||
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
return m_buffer_manager.get_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> Ext2FS::reserve_free_block(uint32_t primary_bgd)
|
BAN::ErrorOr<uint32_t> Ext2FS::reserve_free_block(uint32_t primary_bgd)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
@ -275,25 +280,20 @@ namespace Kernel
|
||||||
if (m_superblock.r_blocks_count >= m_superblock.free_blocks_count)
|
if (m_superblock.r_blocks_count >= m_superblock.free_blocks_count)
|
||||||
return BAN::Error::from_errno(ENOSPC);
|
return BAN::Error::from_errno(ENOSPC);
|
||||||
|
|
||||||
const uint32_t block_size = this->block_size();
|
auto bgd_buffer = m_buffer_manager.get_buffer();
|
||||||
|
auto block_bitmap = m_buffer_manager.get_buffer();
|
||||||
BAN::Vector<uint8_t> bgd_buffer;
|
|
||||||
TRY(bgd_buffer.resize(block_size));
|
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_bitmap;
|
|
||||||
TRY(block_bitmap.resize(block_size));
|
|
||||||
|
|
||||||
auto check_block_group =
|
auto check_block_group =
|
||||||
[&](uint32_t block_group) -> uint32_t
|
[&](uint32_t block_group) -> uint32_t
|
||||||
{
|
{
|
||||||
auto bgd_location = locate_block_group_descriptior(block_group);
|
auto bgd_location = locate_block_group_descriptior(block_group);
|
||||||
read_block(bgd_location.block, bgd_buffer.span());
|
read_block(bgd_location.block, bgd_buffer);
|
||||||
|
|
||||||
auto& bgd = *(Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
auto& bgd = *(Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
||||||
if (bgd.free_blocks_count == 0)
|
if (bgd.free_blocks_count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
read_block(bgd.block_bitmap, block_bitmap.span());
|
read_block(bgd.block_bitmap, block_bitmap);
|
||||||
for (uint32_t block_offset = 0; block_offset < m_superblock.blocks_per_group; block_offset++)
|
for (uint32_t block_offset = 0; block_offset < m_superblock.blocks_per_group; block_offset++)
|
||||||
{
|
{
|
||||||
const uint32_t fs_block_index = m_superblock.first_data_block + m_superblock.blocks_per_group * block_group + block_offset;
|
const uint32_t fs_block_index = m_superblock.first_data_block + m_superblock.blocks_per_group * block_group + block_offset;
|
||||||
|
@ -306,10 +306,10 @@ namespace Kernel
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
block_bitmap[byte] |= 1 << bit;
|
block_bitmap[byte] |= 1 << bit;
|
||||||
write_block(bgd.block_bitmap, block_bitmap.span());
|
write_block(bgd.block_bitmap, block_bitmap);
|
||||||
|
|
||||||
bgd.free_blocks_count--;
|
bgd.free_blocks_count--;
|
||||||
write_block(bgd_location.block, bgd_buffer.span());
|
write_block(bgd_location.block, bgd_buffer);
|
||||||
|
|
||||||
m_superblock.free_blocks_count--;
|
m_superblock.free_blocks_count--;
|
||||||
sync_superblock();
|
sync_superblock();
|
||||||
|
@ -334,7 +334,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_error_code(ErrorCode::Ext2_Corrupted);
|
return BAN::Error::from_error_code(ErrorCode::Ext2_Corrupted);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<Ext2FS::BlockLocation> Ext2FS::locate_inode(uint32_t ino)
|
Ext2FS::BlockLocation Ext2FS::locate_inode(uint32_t ino)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
@ -342,15 +342,14 @@ namespace Kernel
|
||||||
|
|
||||||
const uint32_t block_size = this->block_size();
|
const uint32_t block_size = this->block_size();
|
||||||
|
|
||||||
BAN::Vector<uint8_t> bgd_buffer;
|
auto bgd_buffer = m_buffer_manager.get_buffer();
|
||||||
TRY(bgd_buffer.resize(block_size));
|
|
||||||
|
|
||||||
const uint32_t inode_group = (ino - 1) / superblock().inodes_per_group;
|
const uint32_t inode_group = (ino - 1) / superblock().inodes_per_group;
|
||||||
const uint32_t inode_index = (ino - 1) % superblock().inodes_per_group;
|
const uint32_t inode_index = (ino - 1) % superblock().inodes_per_group;
|
||||||
|
|
||||||
auto bgd_location = locate_block_group_descriptior(inode_group);
|
auto bgd_location = locate_block_group_descriptior(inode_group);
|
||||||
|
|
||||||
read_block(bgd_location.block, bgd_buffer.span());
|
read_block(bgd_location.block, bgd_buffer);
|
||||||
|
|
||||||
auto& bgd = *(Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
auto& bgd = *(Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
||||||
|
|
||||||
|
@ -397,4 +396,26 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ext2FS::BlockBufferWrapper Ext2FS::BlockBufferManager::get_buffer()
|
||||||
|
{
|
||||||
|
for (auto& buffer : m_buffers)
|
||||||
|
{
|
||||||
|
if (buffer.used)
|
||||||
|
continue;
|
||||||
|
buffer.used = true;
|
||||||
|
return Ext2FS::BlockBufferWrapper(buffer.buffer.span(), buffer.used);
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Ext2FS::BlockBufferManager::initialize(size_t block_size)
|
||||||
|
{
|
||||||
|
for (auto& buffer : m_buffers)
|
||||||
|
{
|
||||||
|
TRY(buffer.buffer.resize(block_size));
|
||||||
|
buffer.used = false;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,12 +23,10 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_ino)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_ino)
|
||||||
{
|
{
|
||||||
auto inode_location = TRY(fs.locate_inode(inode_ino));
|
auto inode_location = fs.locate_inode(inode_ino);
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(fs.block_size()));
|
fs.read_block(inode_location.block, block_buffer);
|
||||||
|
|
||||||
fs.read_block(inode_location.block, block_buffer.span());
|
|
||||||
|
|
||||||
auto& inode = *(Ext2::Inode*)(block_buffer.data() + inode_location.offset);
|
auto& inode = *(Ext2::Inode*)(block_buffer.data() + inode_location.offset);
|
||||||
|
|
||||||
|
@ -38,10 +36,10 @@ namespace Kernel
|
||||||
return BAN::RefPtr<Inode>::adopt(result);
|
return BAN::RefPtr<Inode>::adopt(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VERIFY_AND_READ_BLOCK(expr) do { const uint32_t block_index = expr; ASSERT(block_index); m_fs.read_block(block_index, block_buffer.span()); } while (false)
|
#define VERIFY_AND_READ_BLOCK(expr) do { const uint32_t block_index = expr; ASSERT(block_index); m_fs.read_block(block_index, block_buffer); } while (false)
|
||||||
#define VERIFY_AND_RETURN(expr) ({ const uint32_t result = expr; ASSERT(result); return result; })
|
#define VERIFY_AND_RETURN(expr) ({ const uint32_t result = expr; ASSERT(result); return result; })
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> Ext2Inode::fs_block_of_data_block_index(uint32_t data_block_index)
|
uint32_t Ext2Inode::fs_block_of_data_block_index(uint32_t data_block_index)
|
||||||
{
|
{
|
||||||
ASSERT(data_block_index < blocks());
|
ASSERT(data_block_index < blocks());
|
||||||
|
|
||||||
|
@ -53,8 +51,7 @@ namespace Kernel
|
||||||
|
|
||||||
data_block_index -= 12;
|
data_block_index -= 12;
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(blksize()));
|
|
||||||
|
|
||||||
// Singly indirect block
|
// Singly indirect block
|
||||||
if (data_block_index < indices_per_block)
|
if (data_block_index < indices_per_block)
|
||||||
|
@ -115,8 +112,7 @@ namespace Kernel
|
||||||
|
|
||||||
const uint32_t block_size = blksize();
|
const uint32_t block_size = blksize();
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(block_size));
|
|
||||||
|
|
||||||
const uint32_t first_block = offset / block_size;
|
const uint32_t first_block = offset / block_size;
|
||||||
const uint32_t last_block = BAN::Math::div_round_up<uint32_t>(offset + count, block_size);
|
const uint32_t last_block = BAN::Math::div_round_up<uint32_t>(offset + count, block_size);
|
||||||
|
@ -125,8 +121,8 @@ namespace Kernel
|
||||||
|
|
||||||
for (uint32_t data_block_index = first_block; data_block_index < last_block; data_block_index++)
|
for (uint32_t data_block_index = first_block; data_block_index < last_block; data_block_index++)
|
||||||
{
|
{
|
||||||
uint32_t block_index = TRY(fs_block_of_data_block_index(data_block_index));
|
uint32_t block_index = fs_block_of_data_block_index(data_block_index);
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
|
|
||||||
uint32_t copy_offset = (offset + n_read) % block_size;
|
uint32_t copy_offset = (offset + n_read) % block_size;
|
||||||
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - copy_offset, count - n_read);
|
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - copy_offset, count - n_read);
|
||||||
|
@ -153,8 +149,7 @@ namespace Kernel
|
||||||
|
|
||||||
const uint32_t block_size = blksize();
|
const uint32_t block_size = blksize();
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(block_size));
|
|
||||||
|
|
||||||
const uint8_t* u8buffer = (const uint8_t*)buffer;
|
const uint8_t* u8buffer = (const uint8_t*)buffer;
|
||||||
|
|
||||||
|
@ -163,14 +158,14 @@ namespace Kernel
|
||||||
// Write partial block
|
// Write partial block
|
||||||
if (offset % block_size)
|
if (offset % block_size)
|
||||||
{
|
{
|
||||||
uint32_t block_index = TRY(fs_block_of_data_block_index(offset / block_size));
|
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
|
||||||
uint32_t block_offset = offset % block_size;
|
uint32_t block_offset = offset % block_size;
|
||||||
|
|
||||||
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
|
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
|
||||||
|
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
memcpy(block_buffer.data() + block_offset, u8buffer, to_copy);
|
memcpy(block_buffer.data() + block_offset, u8buffer, to_copy);
|
||||||
m_fs.write_block(block_index, block_buffer.span());
|
m_fs.write_block(block_index, block_buffer);
|
||||||
|
|
||||||
u8buffer += to_copy;
|
u8buffer += to_copy;
|
||||||
offset += to_copy;
|
offset += to_copy;
|
||||||
|
@ -179,9 +174,10 @@ namespace Kernel
|
||||||
|
|
||||||
while (to_write >= block_size)
|
while (to_write >= block_size)
|
||||||
{
|
{
|
||||||
uint32_t block_index = TRY(fs_block_of_data_block_index(offset / block_size));
|
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
|
||||||
|
|
||||||
m_fs.write_block(block_index, BAN::Span<const uint8_t>(u8buffer, block_size));
|
memcpy(block_buffer.data(), u8buffer, block_buffer.size());
|
||||||
|
m_fs.write_block(block_index, block_buffer);
|
||||||
|
|
||||||
u8buffer += block_size;
|
u8buffer += block_size;
|
||||||
offset += block_size;
|
offset += block_size;
|
||||||
|
@ -190,11 +186,11 @@ namespace Kernel
|
||||||
|
|
||||||
if (to_write > 0)
|
if (to_write > 0)
|
||||||
{
|
{
|
||||||
uint32_t block_index = TRY(fs_block_of_data_block_index(offset / block_size));
|
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
|
||||||
|
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
memcpy(block_buffer.data(), u8buffer, to_write);
|
memcpy(block_buffer.data(), u8buffer, to_write);
|
||||||
m_fs.write_block(block_index, block_buffer.span());
|
m_fs.write_block(block_index, block_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -216,23 +212,22 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(block_size));
|
|
||||||
|
|
||||||
if (uint32_t rem = m_inode.size % block_size)
|
if (uint32_t rem = m_inode.size % block_size)
|
||||||
{
|
{
|
||||||
uint32_t last_block_index = TRY(fs_block_of_data_block_index(current_data_blocks - 1));
|
uint32_t last_block_index = fs_block_of_data_block_index(current_data_blocks - 1);
|
||||||
|
|
||||||
m_fs.read_block(last_block_index, block_buffer.span());
|
m_fs.read_block(last_block_index, block_buffer);
|
||||||
memset(block_buffer.data() + rem, 0, block_size - rem);
|
memset(block_buffer.data() + rem, 0, block_size - rem);
|
||||||
m_fs.write_block(last_block_index, block_buffer.span());
|
m_fs.write_block(last_block_index, block_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(block_buffer.data(), 0, block_size);
|
memset(block_buffer.data(), 0, block_size);
|
||||||
while (blocks() < needed_data_blocks)
|
while (blocks() < needed_data_blocks)
|
||||||
{
|
{
|
||||||
uint32_t block_index = TRY(allocate_new_block());
|
uint32_t block_index = TRY(allocate_new_block());
|
||||||
m_fs.write_block(block_index, block_buffer.span());
|
m_fs.write_block(block_index, block_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inode.size = new_size;
|
m_inode.size = new_size;
|
||||||
|
@ -254,12 +249,11 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t block_size = blksize();
|
const uint32_t block_size = blksize();
|
||||||
const uint32_t block_index = TRY(fs_block_of_data_block_index(offset));
|
const uint32_t block_index = fs_block_of_data_block_index(offset);
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(block_size));
|
|
||||||
|
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
|
|
||||||
// First determine if we have big enough list
|
// First determine if we have big enough list
|
||||||
{
|
{
|
||||||
|
@ -356,8 +350,8 @@ namespace Kernel
|
||||||
const uint32_t inode_index = TRY(m_fs.create_inode(ext2_inode));
|
const uint32_t inode_index = TRY(m_fs.create_inode(ext2_inode));
|
||||||
|
|
||||||
const uint32_t block_size = m_fs.block_size();
|
const uint32_t block_size = m_fs.block_size();
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
|
||||||
TRY(block_buffer.resize(block_size));
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
|
|
||||||
auto write_inode = [&](uint32_t entry_offset, uint32_t entry_rec_len)
|
auto write_inode = [&](uint32_t entry_offset, uint32_t entry_rec_len)
|
||||||
{
|
{
|
||||||
|
@ -392,8 +386,8 @@ namespace Kernel
|
||||||
goto needs_new_block;
|
goto needs_new_block;
|
||||||
|
|
||||||
// Try to insert inode to last data block
|
// Try to insert inode to last data block
|
||||||
block_index = TRY(fs_block_of_data_block_index(data_block_count - 1));
|
block_index = fs_block_of_data_block_index(data_block_count - 1);
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
|
|
||||||
while (entry_offset < block_size)
|
while (entry_offset < block_size)
|
||||||
{
|
{
|
||||||
|
@ -406,7 +400,7 @@ namespace Kernel
|
||||||
if (entry.inode == 0 && needed_entry_len <= entry.rec_len)
|
if (entry.inode == 0 && needed_entry_len <= entry.rec_len)
|
||||||
{
|
{
|
||||||
write_inode(entry_offset, entry.rec_len);
|
write_inode(entry_offset, entry.rec_len);
|
||||||
m_fs.write_block(block_index, block_buffer.span());
|
m_fs.write_block(block_index, block_buffer);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
else if (needed_entry_len <= entry.rec_len - entry_min_rec_len)
|
else if (needed_entry_len <= entry.rec_len - entry_min_rec_len)
|
||||||
|
@ -415,7 +409,7 @@ namespace Kernel
|
||||||
entry.rec_len = entry_min_rec_len;
|
entry.rec_len = entry_min_rec_len;
|
||||||
|
|
||||||
write_inode(entry_offset + entry.rec_len, new_rec_len);
|
write_inode(entry_offset + entry.rec_len, new_rec_len);
|
||||||
m_fs.write_block(block_index, block_buffer.span());
|
m_fs.write_block(block_index, block_buffer);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,9 +419,9 @@ namespace Kernel
|
||||||
needs_new_block:
|
needs_new_block:
|
||||||
block_index = TRY(allocate_new_block());
|
block_index = TRY(allocate_new_block());
|
||||||
|
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
write_inode(0, block_size);
|
write_inode(0, block_size);
|
||||||
m_fs.write_block(block_index, block_buffer.span());
|
m_fs.write_block(block_index, block_buffer);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -435,7 +429,7 @@ needs_new_block:
|
||||||
#define READ_OR_ALLOCATE_BASE_BLOCK(index_) \
|
#define READ_OR_ALLOCATE_BASE_BLOCK(index_) \
|
||||||
do { \
|
do { \
|
||||||
if (m_inode.block[index_] != 0) \
|
if (m_inode.block[index_] != 0) \
|
||||||
m_fs.read_block(m_inode.block[index_], block_buffer.span()); \
|
m_fs.read_block(m_inode.block[index_], block_buffer); \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
m_inode.block[index_] = TRY(m_fs.reserve_free_block(block_group())); \
|
m_inode.block[index_] = TRY(m_fs.reserve_free_block(block_group())); \
|
||||||
|
@ -446,13 +440,13 @@ needs_new_block:
|
||||||
#define READ_OR_ALLOCATE_INDIRECT_BLOCK(result_, buffer_index_, parent_block_) \
|
#define READ_OR_ALLOCATE_INDIRECT_BLOCK(result_, buffer_index_, parent_block_) \
|
||||||
uint32_t result_ = ((uint32_t*)block_buffer.data())[buffer_index_]; \
|
uint32_t result_ = ((uint32_t*)block_buffer.data())[buffer_index_]; \
|
||||||
if (result_ != 0) \
|
if (result_ != 0) \
|
||||||
m_fs.read_block(result_, block_buffer.span()); \
|
m_fs.read_block(result_, block_buffer); \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
const uint32_t new_block_ = TRY(m_fs.reserve_free_block(block_group())); \
|
const uint32_t new_block_ = TRY(m_fs.reserve_free_block(block_group())); \
|
||||||
\
|
\
|
||||||
((uint32_t*)block_buffer.data())[buffer_index_] = new_block_; \
|
((uint32_t*)block_buffer.data())[buffer_index_] = new_block_; \
|
||||||
m_fs.write_block(parent_block_, block_buffer.span()); \
|
m_fs.write_block(parent_block_, block_buffer); \
|
||||||
\
|
\
|
||||||
result_ = new_block_; \
|
result_ = new_block_; \
|
||||||
memset(block_buffer.data(), 0x00, block_buffer.size()); \
|
memset(block_buffer.data(), 0x00, block_buffer.size()); \
|
||||||
|
@ -465,7 +459,7 @@ needs_new_block:
|
||||||
\
|
\
|
||||||
ASSERT(((uint32_t*)block_buffer.data())[buffer_index_] == 0); \
|
ASSERT(((uint32_t*)block_buffer.data())[buffer_index_] == 0); \
|
||||||
((uint32_t*)block_buffer.data())[buffer_index_] = block_; \
|
((uint32_t*)block_buffer.data())[buffer_index_] = block_; \
|
||||||
m_fs.write_block(parent_block_, block_buffer.span()); \
|
m_fs.write_block(parent_block_, block_buffer); \
|
||||||
\
|
\
|
||||||
m_inode.blocks += blocks_per_fs_block; \
|
m_inode.blocks += blocks_per_fs_block; \
|
||||||
update_and_sync(); \
|
update_and_sync(); \
|
||||||
|
@ -503,8 +497,7 @@ needs_new_block:
|
||||||
|
|
||||||
block_array_index -= 12;
|
block_array_index -= 12;
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(blksize()));
|
|
||||||
|
|
||||||
// singly indirect block
|
// singly indirect block
|
||||||
if (block_array_index < indices_per_fs_block)
|
if (block_array_index < indices_per_fs_block)
|
||||||
|
@ -544,25 +537,14 @@ needs_new_block:
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::sync()
|
BAN::ErrorOr<void> Ext2Inode::sync()
|
||||||
{
|
{
|
||||||
auto inode_location_or_error = m_fs.locate_inode(ino());
|
auto inode_location = m_fs.locate_inode(ino());
|
||||||
if (inode_location_or_error.is_error())
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
{
|
|
||||||
dwarnln("Open inode not found from filesystem");
|
|
||||||
return BAN::Error::from_error_code(ErrorCode::Ext2_Corrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto inode_location = inode_location_or_error.release_value();
|
m_fs.read_block(inode_location.block, block_buffer);
|
||||||
|
|
||||||
const uint32_t block_size = blksize();
|
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
|
||||||
TRY(block_buffer.resize(block_size));
|
|
||||||
|
|
||||||
m_fs.read_block(inode_location.block, block_buffer.span());
|
|
||||||
if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode)))
|
if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode)))
|
||||||
{
|
{
|
||||||
memcpy(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode));
|
memcpy(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode));
|
||||||
m_fs.write_block(inode_location.block, block_buffer.span());
|
m_fs.write_block(inode_location.block, block_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -575,13 +557,12 @@ needs_new_block:
|
||||||
const uint32_t block_size = blksize();
|
const uint32_t block_size = blksize();
|
||||||
const uint32_t data_block_count = blocks();
|
const uint32_t data_block_count = blocks();
|
||||||
|
|
||||||
BAN::Vector<uint8_t> block_buffer;
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
TRY(block_buffer.resize(block_size));
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < data_block_count; i++)
|
for (uint32_t i = 0; i < data_block_count; i++)
|
||||||
{
|
{
|
||||||
const uint32_t block_index = TRY(fs_block_of_data_block_index(i));
|
const uint32_t block_index = fs_block_of_data_block_index(i);
|
||||||
m_fs.read_block(block_index, block_buffer.span());
|
m_fs.read_block(block_index, block_buffer);
|
||||||
|
|
||||||
const uint8_t* block_buffer_end = block_buffer.data() + block_size;
|
const uint8_t* block_buffer_end = block_buffer.data() + block_size;
|
||||||
const uint8_t* entry_addr = block_buffer.data();
|
const uint8_t* entry_addr = block_buffer.data();
|
||||||
|
|
Loading…
Reference in New Issue