forked from Bananymous/banan-os
Kernel: Add comparison operator for inodes
This commit is contained in:
parent
5224df321e
commit
76d5364a55
|
@ -135,26 +135,34 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes() override;
|
virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes() override;
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView) override;
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView) override;
|
||||||
|
|
||||||
|
virtual Type type() const override { return Type::Ext2; }
|
||||||
|
virtual bool operator==(const Inode& other) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::ErrorOr<uint32_t> data_block_index(uint32_t);
|
BAN::ErrorOr<uint32_t> data_block_index(uint32_t);
|
||||||
|
|
||||||
using block_callback_t = BAN::ErrorOr<bool>(*)(const BAN::Vector<uint8_t>&, void*);
|
using block_callback_t = BAN::ErrorOr<bool>(*)(const BAN::Vector<uint8_t>&, void*);
|
||||||
BAN::ErrorOr<void> for_each_block(block_callback_t, void*);
|
BAN::ErrorOr<void> for_each_block(block_callback_t, void*);
|
||||||
|
|
||||||
|
uint32_t index() const { return m_index; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ext2Inode() {}
|
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, BAN::StringView name, uint32_t index)
|
||||||
Ext2Inode(Ext2FS* fs, Ext2::Inode inode, BAN::StringView name)
|
|
||||||
: m_fs(fs)
|
: m_fs(fs)
|
||||||
, m_inode(inode)
|
, m_inode(inode)
|
||||||
, m_name(name)
|
, m_name(name)
|
||||||
|
, m_index(index)
|
||||||
{}
|
{}
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(Ext2FS&, uint32_t, BAN::StringView);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ext2FS* m_fs = nullptr;
|
Ext2FS& m_fs;
|
||||||
Ext2::Inode m_inode;
|
Ext2::Inode m_inode;
|
||||||
BAN::String m_name;
|
BAN::String m_name;
|
||||||
|
uint32_t m_index;
|
||||||
|
|
||||||
friend class Ext2FS;
|
friend class Ext2FS;
|
||||||
|
friend class BAN::RefPtr<Ext2Inode>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Ext2FS : public FileSystem
|
class Ext2FS : public FileSystem
|
||||||
|
|
|
@ -35,6 +35,12 @@ namespace Kernel
|
||||||
uint16_t mode;
|
uint16_t mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
General,
|
||||||
|
Ext2,
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Inode() {}
|
virtual ~Inode() {}
|
||||||
|
|
||||||
|
@ -52,6 +58,9 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) = 0;
|
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) = 0;
|
||||||
virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes() = 0;
|
virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes() = 0;
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView) = 0;
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView) = 0;
|
||||||
|
|
||||||
|
virtual Type type() const { return Type::General; }
|
||||||
|
virtual bool operator==(const Inode&) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,8 +2,6 @@
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <kernel/FS/Ext2.h>
|
#include <kernel/FS/Ext2.h>
|
||||||
|
|
||||||
#include <kernel/kprint.h>
|
|
||||||
|
|
||||||
#define EXT2_DEBUG_PRINT 0
|
#define EXT2_DEBUG_PRINT 0
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -138,10 +136,19 @@ namespace Kernel
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode, BAN::StringView name)
|
||||||
|
{
|
||||||
|
Ext2::Inode ext2_inode = TRY(fs.read_inode(inode));
|
||||||
|
Ext2Inode* result = new Ext2Inode(fs, ext2_inode, name, inode);
|
||||||
|
if (result == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
return BAN::RefPtr<Inode>::adopt(result);
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> Ext2Inode::data_block_index(uint32_t asked_data_block)
|
BAN::ErrorOr<uint32_t> Ext2Inode::data_block_index(uint32_t asked_data_block)
|
||||||
{
|
{
|
||||||
uint32_t data_blocks_count = m_inode.blocks / (2 << m_fs->superblock().log_block_size);
|
uint32_t data_blocks_count = m_inode.blocks / (2 << m_fs.superblock().log_block_size);
|
||||||
uint32_t blocks_per_array = (1024 << m_fs->superblock().log_block_size) / sizeof(uint32_t);
|
uint32_t blocks_per_array = (1024 << m_fs.superblock().log_block_size) / sizeof(uint32_t);
|
||||||
|
|
||||||
if (asked_data_block >= data_blocks_count)
|
if (asked_data_block >= data_blocks_count)
|
||||||
return BAN::Error::from_c_string("Ext2: no such block");
|
return BAN::Error::from_c_string("Ext2: no such block");
|
||||||
|
@ -162,7 +169,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (m_inode.block[12] == 0)
|
if (m_inode.block[12] == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
auto block_array = TRY(m_fs->read_block(m_inode.block[12]));
|
auto block_array = TRY(m_fs.read_block(m_inode.block[12]));
|
||||||
uint32_t block = ((uint32_t*)block_array.data())[asked_data_block];
|
uint32_t block = ((uint32_t*)block_array.data())[asked_data_block];
|
||||||
if (block == 0)
|
if (block == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
|
@ -174,11 +181,11 @@ namespace Kernel
|
||||||
// Doubly indirect blocks
|
// Doubly indirect blocks
|
||||||
if (asked_data_block < blocks_per_array * blocks_per_array)
|
if (asked_data_block < blocks_per_array * blocks_per_array)
|
||||||
{
|
{
|
||||||
auto singly_indirect_array = TRY(m_fs->read_block(m_inode.block[13]));
|
auto singly_indirect_array = TRY(m_fs.read_block(m_inode.block[13]));
|
||||||
uint32_t direct_block = ((uint32_t*)singly_indirect_array.data())[asked_data_block / blocks_per_array];
|
uint32_t direct_block = ((uint32_t*)singly_indirect_array.data())[asked_data_block / blocks_per_array];
|
||||||
if (direct_block == 0)
|
if (direct_block == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
auto block_array = TRY(m_fs->read_block(direct_block));
|
auto block_array = TRY(m_fs.read_block(direct_block));
|
||||||
uint32_t block = ((uint32_t*)block_array.data())[asked_data_block % blocks_per_array];
|
uint32_t block = ((uint32_t*)block_array.data())[asked_data_block % blocks_per_array];
|
||||||
if (block == 0)
|
if (block == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
|
@ -190,15 +197,15 @@ namespace Kernel
|
||||||
// Triply indirect blocks
|
// Triply indirect blocks
|
||||||
if (asked_data_block < blocks_per_array * blocks_per_array * blocks_per_array)
|
if (asked_data_block < blocks_per_array * blocks_per_array * blocks_per_array)
|
||||||
{
|
{
|
||||||
auto doubly_indirect_array = TRY(m_fs->read_block(m_inode.block[14]));
|
auto doubly_indirect_array = TRY(m_fs.read_block(m_inode.block[14]));
|
||||||
uint32_t singly_indirect_block = ((uint32_t*)doubly_indirect_array.data())[asked_data_block / (blocks_per_array * blocks_per_array)];
|
uint32_t singly_indirect_block = ((uint32_t*)doubly_indirect_array.data())[asked_data_block / (blocks_per_array * blocks_per_array)];
|
||||||
if (singly_indirect_block == 0)
|
if (singly_indirect_block == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
auto singly_indirect_array = TRY(m_fs->read_block(singly_indirect_block));
|
auto singly_indirect_array = TRY(m_fs.read_block(singly_indirect_block));
|
||||||
uint32_t direct_block = ((uint32_t*)singly_indirect_array.data())[(asked_data_block / blocks_per_array) % blocks_per_array];
|
uint32_t direct_block = ((uint32_t*)singly_indirect_array.data())[(asked_data_block / blocks_per_array) % blocks_per_array];
|
||||||
if (direct_block == 0)
|
if (direct_block == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
auto block_array = TRY(m_fs->read_block(direct_block));
|
auto block_array = TRY(m_fs.read_block(direct_block));
|
||||||
uint32_t block = ((uint32_t*)block_array.data())[asked_data_block % blocks_per_array];
|
uint32_t block = ((uint32_t*)block_array.data())[asked_data_block % blocks_per_array];
|
||||||
if (block == 0)
|
if (block == 0)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
|
@ -210,12 +217,12 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::for_each_block(block_callback_t callback, void* callback_data)
|
BAN::ErrorOr<void> Ext2Inode::for_each_block(block_callback_t callback, void* callback_data)
|
||||||
{
|
{
|
||||||
uint32_t data_block_count = m_inode.blocks / (2 << m_fs->superblock().log_block_size);
|
uint32_t data_block_count = m_inode.blocks / (2 << m_fs.superblock().log_block_size);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < data_block_count; i++)
|
for (uint32_t i = 0; i < data_block_count; i++)
|
||||||
{
|
{
|
||||||
uint32_t data_block_index = TRY(this->data_block_index(i));
|
uint32_t data_block_index = TRY(this->data_block_index(i));
|
||||||
auto block_data = TRY(m_fs->read_block(data_block_index));
|
auto block_data = TRY(m_fs.read_block(data_block_index));
|
||||||
if (!TRY(callback(block_data, callback_data)))
|
if (!TRY(callback(block_data, callback_data)))
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -233,7 +240,7 @@ namespace Kernel
|
||||||
if (offset + count > m_inode.size)
|
if (offset + count > m_inode.size)
|
||||||
count = m_inode.size - offset;
|
count = m_inode.size - offset;
|
||||||
|
|
||||||
const uint32_t block_size = 1024 << m_fs->superblock().log_block_size;
|
const uint32_t block_size = 1024 << m_fs.superblock().log_block_size;
|
||||||
|
|
||||||
ASSERT(offset % block_size == 0);
|
ASSERT(offset % block_size == 0);
|
||||||
|
|
||||||
|
@ -245,7 +252,7 @@ namespace Kernel
|
||||||
for (uint32_t block = first_block; block < last_block; block++)
|
for (uint32_t block = first_block; block < last_block; block++)
|
||||||
{
|
{
|
||||||
uint32_t data_block = TRY(data_block_index(block));
|
uint32_t data_block = TRY(data_block_index(block));
|
||||||
auto block_data = TRY(m_fs->read_block(data_block));
|
auto block_data = TRY(m_fs.read_block(data_block));
|
||||||
|
|
||||||
uint32_t to_copy = BAN::Math::min<uint32_t>(block_data.size(), count - n_read);
|
uint32_t to_copy = BAN::Math::min<uint32_t>(block_data.size(), count - n_read);
|
||||||
|
|
||||||
|
@ -271,7 +278,7 @@ namespace Kernel
|
||||||
search_info info;
|
search_info info;
|
||||||
info.file_name = file_name;
|
info.file_name = file_name;
|
||||||
info.result = {};
|
info.result = {};
|
||||||
info.fs = m_fs;
|
info.fs = &m_fs;
|
||||||
|
|
||||||
block_callback_t function =
|
block_callback_t function =
|
||||||
[](const BAN::Vector<uint8_t>& block_data, void* info_) -> BAN::ErrorOr<bool>
|
[](const BAN::Vector<uint8_t>& block_data, void* info_) -> BAN::ErrorOr<bool>
|
||||||
|
@ -286,10 +293,7 @@ namespace Kernel
|
||||||
BAN::StringView entry_name = BAN::StringView(entry->name, entry->name_len);
|
BAN::StringView entry_name = BAN::StringView(entry->name, entry->name_len);
|
||||||
if (entry->inode && info.file_name == entry_name)
|
if (entry->inode && info.file_name == entry_name)
|
||||||
{
|
{
|
||||||
Ext2Inode* inode = new Ext2Inode(info.fs, TRY(info.fs->read_inode(entry->inode)), entry_name);
|
info.result = TRY(Ext2Inode::create(*info.fs, entry->inode, entry_name));
|
||||||
if (inode == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
info.result = BAN::RefPtr<Inode>::adopt(inode);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
entry_addr += entry->rec_len;
|
entry_addr += entry->rec_len;
|
||||||
|
@ -316,7 +320,7 @@ namespace Kernel
|
||||||
|
|
||||||
directory_info info;
|
directory_info info;
|
||||||
info.inodes = {};
|
info.inodes = {};
|
||||||
info.fs = m_fs;
|
info.fs = &m_fs;
|
||||||
|
|
||||||
block_callback_t function =
|
block_callback_t function =
|
||||||
[](const BAN::Vector<uint8_t>& block_data, void* info_) -> BAN::ErrorOr<bool>
|
[](const BAN::Vector<uint8_t>& block_data, void* info_) -> BAN::ErrorOr<bool>
|
||||||
|
@ -330,13 +334,9 @@ namespace Kernel
|
||||||
Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr;
|
Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr;
|
||||||
if (entry->inode)
|
if (entry->inode)
|
||||||
{
|
{
|
||||||
BAN::StringView entry_name = BAN::StringView(entry->name, entry->name_len);
|
auto entry_name = BAN::StringView(entry->name, entry->name_len);
|
||||||
Ext2::Inode current_inode = TRY(info.fs->read_inode(entry->inode));
|
auto inode = TRY(Ext2Inode::create(*info.fs, entry->inode, entry_name));
|
||||||
|
TRY(info.inodes.push_back(inode));
|
||||||
Ext2Inode* inode = new Ext2Inode(info.fs, BAN::move(current_inode), entry_name);
|
|
||||||
if (inode == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
TRY(info.inodes.push_back(BAN::RefPtr<Inode>::adopt(inode)));
|
|
||||||
}
|
}
|
||||||
entry_addr += entry->rec_len;
|
entry_addr += entry->rec_len;
|
||||||
}
|
}
|
||||||
|
@ -348,6 +348,17 @@ namespace Kernel
|
||||||
return info.inodes;
|
return info.inodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Ext2Inode::operator==(const Inode& other) const
|
||||||
|
{
|
||||||
|
if (type() != other.type())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Ext2Inode& ext2_other = (Ext2Inode&)other;
|
||||||
|
if (&m_fs != &ext2_other.m_fs)
|
||||||
|
return false;
|
||||||
|
return index() == ext2_other.index();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<Ext2FS*> Ext2FS::create(StorageDevice::Partition& partition)
|
BAN::ErrorOr<Ext2FS*> Ext2FS::create(StorageDevice::Partition& partition)
|
||||||
{
|
{
|
||||||
Ext2FS* ext2fs = new Ext2FS(partition);
|
Ext2FS* ext2fs = new Ext2FS(partition);
|
||||||
|
@ -453,10 +464,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2FS::initialize_root_inode()
|
BAN::ErrorOr<void> Ext2FS::initialize_root_inode()
|
||||||
{
|
{
|
||||||
Ext2Inode* root_inode = new Ext2Inode(this, TRY(read_inode(Ext2::Enum::ROOT_INO)), "");
|
m_root_inode = TRY(Ext2Inode::create(*this, Ext2::Enum::ROOT_INO, ""));
|
||||||
if (root_inode == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
m_root_inode = BAN::RefPtr<Inode>::adopt(root_inode);
|
|
||||||
|
|
||||||
#if EXT2_DEBUG_PRINT
|
#if EXT2_DEBUG_PRINT
|
||||||
dprintln("root inode:");
|
dprintln("root inode:");
|
||||||
|
|
Loading…
Reference in New Issue