Kernel: Reduce ext2 locking
Replace the mutex with a rwlock and lock when its not necessary
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <kernel/FS/Ext2/Definitions.h>
|
#include <kernel/FS/Ext2/Definitions.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/Lock/Mutex.h>
|
#include <kernel/Lock/RWLock.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -58,25 +58,30 @@ namespace Kernel
|
|||||||
virtual bool has_hungup_impl() const override { return false; }
|
virtual bool has_hungup_impl() const override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32_t block_group() const;
|
||||||
|
|
||||||
// Returns maximum number of data blocks in use
|
// Returns maximum number of data blocks in use
|
||||||
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
|
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
|
||||||
uint32_t max_used_data_block_count() const { return size() / blksize(); }
|
uint32_t max_used_data_block_count() const { return size() / blksize(); }
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
BAN::ErrorOr<void> sync_no_lock();
|
||||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index, bool allocate);
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
|
BAN::ErrorOr<bool> is_directory_empty_no_lock();
|
||||||
BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory);
|
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView);
|
||||||
BAN::ErrorOr<bool> is_directory_empty();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
|
/* needs write end of the lock when allocate is true*/
|
||||||
BAN::ErrorOr<void> cleanup_default_links();
|
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
||||||
BAN::ErrorOr<void> cleanup_data_blocks();
|
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate);
|
||||||
BAN::ErrorOr<void> cleanup_from_fs();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> sync();
|
/* needs write end of the lock */
|
||||||
|
BAN::ErrorOr<void> link_inode_to_directory_no_lock(Ext2Inode&, BAN::StringView name);
|
||||||
|
BAN::ErrorOr<void> remove_inode_from_directory_no_lock(BAN::StringView name, bool cleanup_directory);
|
||||||
|
|
||||||
uint32_t block_group() const;
|
/* needs write end of the lock */
|
||||||
|
BAN::ErrorOr<void> cleanup_indirect_block_no_lock(uint32_t block, uint32_t depth);
|
||||||
|
BAN::ErrorOr<void> cleanup_default_links_no_lock();
|
||||||
|
BAN::ErrorOr<void> cleanup_data_blocks_no_lock();
|
||||||
|
BAN::ErrorOr<void> cleanup_from_fs_no_lock();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino)
|
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino)
|
||||||
@@ -98,7 +103,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (memcmp(&inode.m_inode, &inode_info, sizeof(Ext2::Inode)) == 0)
|
if (memcmp(&inode.m_inode, &inode_info, sizeof(Ext2::Inode)) == 0)
|
||||||
return;
|
return;
|
||||||
if (auto ret = inode.sync(); ret.is_error())
|
if (auto ret = inode.sync_no_lock(); ret.is_error())
|
||||||
dwarnln("failed to sync inode: {}", ret.error());
|
dwarnln("failed to sync inode: {}", ret.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,8 +116,7 @@ namespace Kernel
|
|||||||
Ext2::Inode m_inode;
|
Ext2::Inode m_inode;
|
||||||
const uint32_t m_ino;
|
const uint32_t m_ino;
|
||||||
|
|
||||||
// TODO: try to reduce locking or replace this with rwlock(?)
|
RWLock m_lock;
|
||||||
Mutex m_lock;
|
|
||||||
|
|
||||||
friend class Ext2FS;
|
friend class Ext2FS;
|
||||||
friend class BAN::RefPtr<Ext2Inode>;
|
friend class BAN::RefPtr<Ext2Inode>;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (m_inode.links_count > 0)
|
if (m_inode.links_count > 0)
|
||||||
return;
|
return;
|
||||||
if (auto ret = cleanup_from_fs(); ret.is_error())
|
if (auto ret = cleanup_from_fs_no_lock(); ret.is_error())
|
||||||
dwarnln("Could not cleanup inode from FS: {}", ret.error());
|
dwarnln("Could not cleanup inode from FS: {}", ret.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,13 +56,11 @@ namespace Kernel
|
|||||||
return &m_fs;
|
return &m_fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate)
|
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate)
|
||||||
{
|
{
|
||||||
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
||||||
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (block == 0 && !allocate)
|
if (block == 0 && !allocate)
|
||||||
return BAN::Optional<uint32_t>();
|
return BAN::Optional<uint32_t>();
|
||||||
|
|
||||||
@@ -104,7 +102,7 @@ namespace Kernel
|
|||||||
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block];
|
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block];
|
||||||
const auto old_block = new_block;
|
const auto old_block = new_block;
|
||||||
|
|
||||||
const auto result = TRY(block_from_indirect_block(new_block, index, depth - 1, allocate));
|
const auto result = TRY(block_from_indirect_block_no_lock(new_block, index, depth - 1, allocate));
|
||||||
|
|
||||||
if (needs_write || old_block != new_block)
|
if (needs_write || old_block != new_block)
|
||||||
TRY(m_fs.write_block(block, block_buffer));
|
TRY(m_fs.write_block(block, block_buffer));
|
||||||
@@ -112,13 +110,11 @@ namespace Kernel
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index(uint32_t data_block_index, bool allocate)
|
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate)
|
||||||
{
|
{
|
||||||
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
||||||
const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
|
const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (data_block_index < 12)
|
if (data_block_index < 12)
|
||||||
{
|
{
|
||||||
if (m_inode.block[data_block_index] != 0)
|
if (m_inode.block[data_block_index] != 0)
|
||||||
@@ -140,15 +136,15 @@ namespace Kernel
|
|||||||
data_block_index -= 12;
|
data_block_index -= 12;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block)
|
if (data_block_index < indices_per_block)
|
||||||
return block_from_indirect_block(m_inode.block[12], data_block_index, 1, allocate);
|
return block_from_indirect_block_no_lock(m_inode.block[12], data_block_index, 1, allocate);
|
||||||
data_block_index -= indices_per_block;
|
data_block_index -= indices_per_block;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block * indices_per_block)
|
if (data_block_index < indices_per_block * indices_per_block)
|
||||||
return block_from_indirect_block(m_inode.block[13], data_block_index, 2, allocate);
|
return block_from_indirect_block_no_lock(m_inode.block[13], data_block_index, 2, allocate);
|
||||||
data_block_index -= indices_per_block * indices_per_block;
|
data_block_index -= indices_per_block * indices_per_block;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
||||||
return block_from_indirect_block(m_inode.block[14], data_block_index, 3, allocate);
|
return block_from_indirect_block_no_lock(m_inode.block[14], data_block_index, 3, allocate);
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -157,7 +153,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ASSERT(mode().iflnk());
|
ASSERT(mode().iflnk());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
RWLockRDGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.size < sizeof(m_inode.block))
|
if (m_inode.size < sizeof(m_inode.block))
|
||||||
{
|
{
|
||||||
@@ -176,16 +172,15 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ASSERT(mode().iflnk());
|
ASSERT(mode().iflnk());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
RWLockWRGuard _(m_lock);
|
||||||
|
|
||||||
if (target.size() < sizeof(m_inode.block))
|
if (target.size() < sizeof(m_inode.block))
|
||||||
{
|
{
|
||||||
if (m_inode.size >= sizeof(m_inode.block))
|
if (m_inode.size >= sizeof(m_inode.block))
|
||||||
TRY(cleanup_data_blocks());
|
TRY(cleanup_data_blocks_no_lock());
|
||||||
memset(m_inode.block, 0, sizeof(m_inode.block));
|
memset(m_inode.block, 0, sizeof(m_inode.block));
|
||||||
memcpy(m_inode.block, target.data(), target.size());
|
memcpy(m_inode.block, target.data(), target.size());
|
||||||
m_inode.size = target.size();
|
m_inode.size = target.size();
|
||||||
TRY(sync());
|
TRY(sync_no_lock());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +199,7 @@ namespace Kernel
|
|||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
||||||
return BAN::Error::from_errno(EOVERFLOW);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
LockGuard _0(m_lock);
|
RWLockRDGuard _0(m_lock);
|
||||||
|
|
||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size)
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -226,7 +221,7 @@ 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++)
|
||||||
{
|
{
|
||||||
auto block_index = TRY(fs_block_of_data_block_index(data_block_index, false));
|
auto block_index = TRY(fs_block_of_data_block_index_no_lock(data_block_index, false));
|
||||||
if (block_index.has_value())
|
if (block_index.has_value())
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
else
|
else
|
||||||
@@ -252,7 +247,7 @@ namespace Kernel
|
|||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
||||||
return BAN::Error::from_errno(EOVERFLOW);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
LockGuard _0(m_lock);
|
RWLockWRGuard _0(m_lock);
|
||||||
|
|
||||||
if (m_inode.size < offset + buffer.size())
|
if (m_inode.size < offset + buffer.size())
|
||||||
TRY(truncate_impl(offset + buffer.size()));
|
TRY(truncate_impl(offset + buffer.size()));
|
||||||
@@ -269,7 +264,7 @@ namespace Kernel
|
|||||||
// Write partial block
|
// Write partial block
|
||||||
if (offset % block_size)
|
if (offset % block_size)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(offset / block_size, true));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(offset / block_size, true));
|
||||||
ASSERT(block_index.has_value());
|
ASSERT(block_index.has_value());
|
||||||
|
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
@@ -287,7 +282,7 @@ namespace Kernel
|
|||||||
|
|
||||||
while (to_write >= block_size)
|
while (to_write >= block_size)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(offset / block_size, true));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(offset / block_size, true));
|
||||||
ASSERT(block_index.has_value());
|
ASSERT(block_index.has_value());
|
||||||
|
|
||||||
memcpy(block_buffer.data(), buffer.data() + written, block_buffer.size());
|
memcpy(block_buffer.data(), buffer.data() + written, block_buffer.size());
|
||||||
@@ -300,7 +295,7 @@ namespace Kernel
|
|||||||
|
|
||||||
if (to_write > 0)
|
if (to_write > 0)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(offset / block_size, true));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(offset / block_size, true));
|
||||||
ASSERT(block_index.has_value());
|
ASSERT(block_index.has_value());
|
||||||
|
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
@@ -314,7 +309,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)
|
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
RWLockWRGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.size == new_size)
|
if (m_inode.size == new_size)
|
||||||
return {};
|
return {};
|
||||||
@@ -324,7 +319,7 @@ namespace Kernel
|
|||||||
const auto old_size = m_inode.size;
|
const auto old_size = m_inode.size;
|
||||||
|
|
||||||
m_inode.size = new_size;
|
m_inode.size = new_size;
|
||||||
if (auto ret = sync(); ret.is_error())
|
if (auto ret = sync_no_lock(); ret.is_error())
|
||||||
{
|
{
|
||||||
m_inode.size = old_size;
|
m_inode.size = old_size;
|
||||||
return ret.release_error();
|
return ret.release_error();
|
||||||
@@ -337,8 +332,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
||||||
|
|
||||||
// TODO: this could be atomic
|
RWLockWRGuard _(m_lock);
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (m_inode.mode == mode)
|
if (m_inode.mode == mode)
|
||||||
return {};
|
return {};
|
||||||
@@ -346,7 +340,7 @@ namespace Kernel
|
|||||||
const auto old_mode = m_inode.mode;
|
const auto old_mode = m_inode.mode;
|
||||||
|
|
||||||
m_inode.mode = (m_inode.mode & Inode::Mode::TYPE_MASK) | mode;
|
m_inode.mode = (m_inode.mode & Inode::Mode::TYPE_MASK) | mode;
|
||||||
if (auto ret = sync(); ret.is_error())
|
if (auto ret = sync_no_lock(); ret.is_error())
|
||||||
{
|
{
|
||||||
m_inode.mode = old_mode;
|
m_inode.mode = old_mode;
|
||||||
return ret.release_error();
|
return ret.release_error();
|
||||||
@@ -357,8 +351,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::chown_impl(uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Ext2Inode::chown_impl(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
// TODO: this could be atomic
|
RWLockWRGuard _(m_lock);
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (m_inode.uid == uid && m_inode.gid == gid)
|
if (m_inode.uid == uid && m_inode.gid == gid)
|
||||||
return {};
|
return {};
|
||||||
@@ -368,7 +361,7 @@ namespace Kernel
|
|||||||
|
|
||||||
m_inode.uid = uid;
|
m_inode.uid = uid;
|
||||||
m_inode.gid = gid;
|
m_inode.gid = gid;
|
||||||
if (auto ret = sync(); ret.is_error())
|
if (auto ret = sync_no_lock(); ret.is_error())
|
||||||
{
|
{
|
||||||
m_inode.uid = old_uid;
|
m_inode.uid = old_uid;
|
||||||
m_inode.gid = old_gid;
|
m_inode.gid = old_gid;
|
||||||
@@ -380,8 +373,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::utimens_impl(const timespec times[2])
|
BAN::ErrorOr<void> Ext2Inode::utimens_impl(const timespec times[2])
|
||||||
{
|
{
|
||||||
// TODO: this could be atomic
|
RWLockWRGuard _(m_lock);
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
const uint32_t old_times[2] {
|
const uint32_t old_times[2] {
|
||||||
m_inode.atime,
|
m_inode.atime,
|
||||||
@@ -393,7 +385,7 @@ namespace Kernel
|
|||||||
if (times[1].tv_nsec != UTIME_OMIT)
|
if (times[1].tv_nsec != UTIME_OMIT)
|
||||||
m_inode.mtime = times[1].tv_sec;
|
m_inode.mtime = times[1].tv_sec;
|
||||||
|
|
||||||
if (auto ret = sync(); ret.is_error())
|
if (auto ret = sync_no_lock(); ret.is_error())
|
||||||
{
|
{
|
||||||
m_inode.atime = old_times[0];
|
m_inode.atime = old_times[0];
|
||||||
m_inode.mtime = old_times[1];
|
m_inode.mtime = old_times[1];
|
||||||
@@ -405,19 +397,17 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
|
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
RWLockRDGuard _(m_lock);
|
||||||
for (size_t i = 0; i < max_used_data_block_count(); i++)
|
for (size_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
if (const auto fs_block = TRY(fs_block_of_data_block_index(i, false)); fs_block.has_value())
|
if (const auto fs_block = TRY(fs_block_of_data_block_index_no_lock(i, false)); fs_block.has_value())
|
||||||
TRY(m_fs.sync_block(fs_block.value()));
|
TRY(m_fs.sync_block(fs_block.value()));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::cleanup_indirect_block(uint32_t block, uint32_t depth)
|
BAN::ErrorOr<void> Ext2Inode::cleanup_indirect_block_no_lock(uint32_t block, uint32_t depth)
|
||||||
{
|
{
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
{
|
{
|
||||||
TRY(m_fs.release_block(block));
|
TRY(m_fs.release_block(block));
|
||||||
@@ -433,17 +423,15 @@ namespace Kernel
|
|||||||
const uint32_t next_block = block_buffer.span().as_span<uint32_t>()[i];
|
const uint32_t next_block = block_buffer.span().as_span<uint32_t>()[i];
|
||||||
if (next_block == 0)
|
if (next_block == 0)
|
||||||
continue;
|
continue;
|
||||||
TRY(cleanup_indirect_block(next_block, depth - 1));
|
TRY(cleanup_indirect_block_no_lock(next_block, depth - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(m_fs.release_block(block));
|
TRY(m_fs.release_block(block));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks()
|
BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks_no_lock()
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
|
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@@ -454,25 +442,25 @@ namespace Kernel
|
|||||||
|
|
||||||
// cleanup indirect blocks
|
// cleanup indirect blocks
|
||||||
if (m_inode.block[12])
|
if (m_inode.block[12])
|
||||||
TRY(cleanup_indirect_block(m_inode.block[12], 1));
|
TRY(cleanup_indirect_block_no_lock(m_inode.block[12], 1));
|
||||||
if (m_inode.block[13])
|
if (m_inode.block[13])
|
||||||
TRY(cleanup_indirect_block(m_inode.block[13], 2));
|
TRY(cleanup_indirect_block_no_lock(m_inode.block[13], 2));
|
||||||
if (m_inode.block[14])
|
if (m_inode.block[14])
|
||||||
TRY(cleanup_indirect_block(m_inode.block[14], 3));
|
TRY(cleanup_indirect_block_no_lock(m_inode.block[14], 3));
|
||||||
|
|
||||||
done:
|
done:
|
||||||
// mark blocks as deleted
|
// mark blocks as deleted
|
||||||
memset(m_inode.block, 0x00, sizeof(m_inode.block));
|
memset(m_inode.block, 0x00, sizeof(m_inode.block));
|
||||||
|
|
||||||
TRY(sync());
|
TRY(sync_no_lock());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs()
|
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs_no_lock()
|
||||||
{
|
{
|
||||||
ASSERT(m_inode.links_count == 0);
|
ASSERT(m_inode.links_count == 0);
|
||||||
TRY(cleanup_data_blocks());
|
TRY(cleanup_data_blocks_no_lock());
|
||||||
TRY(m_fs.delete_inode(ino()));
|
TRY(m_fs.delete_inode(ino()));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -482,12 +470,12 @@ done:
|
|||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
ASSERT(offset >= 0);
|
ASSERT(offset >= 0);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
RWLockRDGuard _(m_lock);
|
||||||
|
|
||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= max_used_data_block_count())
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= max_used_data_block_count())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(offset, false));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(offset, false));
|
||||||
if (!block_index.has_value())
|
if (!block_index.has_value())
|
||||||
return BAN::Error::from_errno(ENODATA);
|
return BAN::Error::from_errno(ENODATA);
|
||||||
|
|
||||||
@@ -557,9 +545,8 @@ done:
|
|||||||
{
|
{
|
||||||
ASSERT(mode_has_valid_type(mode));
|
ASSERT(mode_has_valid_type(mode));
|
||||||
|
|
||||||
timespec current_time = SystemTimer::get().real_time();
|
const timespec current_time = SystemTimer::get().real_time();
|
||||||
return Ext2::Inode
|
return Ext2::Inode {
|
||||||
{
|
|
||||||
.mode = (uint16_t)mode,
|
.mode = (uint16_t)mode,
|
||||||
.uid = (uint16_t)uid,
|
.uid = (uint16_t)uid,
|
||||||
.size = 0,
|
.size = 0,
|
||||||
@@ -585,11 +572,6 @@ done:
|
|||||||
{
|
{
|
||||||
ASSERT(this->mode().ifdir());
|
ASSERT(this->mode().ifdir());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
|
||||||
return BAN::Error::from_errno(EEXIST);
|
|
||||||
|
|
||||||
switch (mode & Inode::Mode::TYPE_MASK)
|
switch (mode & Inode::Mode::TYPE_MASK)
|
||||||
{
|
{
|
||||||
case Inode::Mode::IFLNK:
|
case Inode::Mode::IFLNK:
|
||||||
@@ -600,6 +582,11 @@ done:
|
|||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RWLockWRGuard _(m_lock);
|
||||||
|
|
||||||
|
if (!find_inode_no_lock(name).is_error())
|
||||||
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||||
|
|
||||||
auto inode_or_error = Ext2Inode::create(m_fs, new_ino);
|
auto inode_or_error = Ext2Inode::create(m_fs, new_ino);
|
||||||
@@ -611,7 +598,7 @@ done:
|
|||||||
|
|
||||||
auto inode = inode_or_error.release_value();
|
auto inode = inode_or_error.release_value();
|
||||||
|
|
||||||
TRY(link_inode_to_directory(*inode, name));
|
TRY(link_inode_to_directory_no_lock(*inode, name));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -621,9 +608,9 @@ done:
|
|||||||
ASSERT(this->mode().ifdir());
|
ASSERT(this->mode().ifdir());
|
||||||
ASSERT(Mode(mode).ifdir());
|
ASSERT(Mode(mode).ifdir());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
RWLockWRGuard _(m_lock);
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
if (!find_inode_no_lock(name).is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||||
@@ -638,14 +625,14 @@ done:
|
|||||||
auto inode = inode_or_error.release_value();
|
auto inode = inode_or_error.release_value();
|
||||||
|
|
||||||
// link . and ..
|
// link . and ..
|
||||||
if (auto ret = inode->link_inode_to_directory(*inode, "."_sv); ret.is_error())
|
if (auto ret = inode->link_inode_to_directory_no_lock(*inode, "."_sv); ret.is_error())
|
||||||
return ({ TRY(inode->cleanup_from_fs()); ret.release_error(); });
|
return ({ TRY(inode->cleanup_from_fs_no_lock()); ret.release_error(); });
|
||||||
if (auto ret = inode->link_inode_to_directory(*this, ".."_sv); ret.is_error())
|
if (auto ret = inode->link_inode_to_directory_no_lock(*this, ".."_sv); ret.is_error())
|
||||||
return ({ TRY(inode->cleanup_from_fs()); ret.release_error(); });
|
return ({ TRY(inode->cleanup_from_fs_no_lock()); ret.release_error(); });
|
||||||
|
|
||||||
// link to parent
|
// link to parent
|
||||||
if (auto ret = link_inode_to_directory(*inode, name); ret.is_error())
|
if (auto ret = link_inode_to_directory_no_lock(*inode, name); ret.is_error())
|
||||||
return ({ TRY(inode->cleanup_from_fs()); ret.release_error(); });
|
return ({ TRY(inode->cleanup_from_fs_no_lock()); ret.release_error(); });
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -656,13 +643,13 @@ done:
|
|||||||
ASSERT(!inode->mode().ifdir());
|
ASSERT(!inode->mode().ifdir());
|
||||||
ASSERT(&m_fs == inode->filesystem());
|
ASSERT(&m_fs == inode->filesystem());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
RWLockWRGuard _(m_lock);
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
if (!find_inode_no_lock(name).is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
auto ext2_inode = static_cast<Ext2Inode*>(inode.ptr());
|
auto ext2_inode = static_cast<Ext2Inode*>(inode.ptr());
|
||||||
TRY(link_inode_to_directory(*ext2_inode, name));
|
TRY(link_inode_to_directory_no_lock(*ext2_inode, name));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -676,30 +663,30 @@ done:
|
|||||||
auto* ext2_parent = static_cast<Ext2Inode*>(old_parent.ptr());
|
auto* ext2_parent = static_cast<Ext2Inode*>(old_parent.ptr());
|
||||||
|
|
||||||
// FIXME: is this a possible deadlock?
|
// FIXME: is this a possible deadlock?
|
||||||
LockGuard _0(ext2_parent->m_lock);
|
RWLockWRGuard _0(ext2_parent->m_lock);
|
||||||
LockGuard _1(m_lock);
|
RWLockWRGuard _1(m_lock);
|
||||||
|
|
||||||
auto old_inode = TRY(ext2_parent->find_inode_impl(old_name));
|
auto old_inode = TRY(ext2_parent->find_inode_no_lock(old_name));
|
||||||
auto* ext2_inode = static_cast<Ext2Inode*>(old_inode.ptr());
|
auto* ext2_inode = static_cast<Ext2Inode*>(old_inode.ptr());
|
||||||
|
|
||||||
if (auto find_result = find_inode_impl(new_name); find_result.is_error())
|
if (auto find_result = find_inode_no_lock(new_name); find_result.is_error())
|
||||||
{
|
{
|
||||||
if (find_result.error().get_error_code() != ENOENT)
|
if (find_result.error().get_error_code() != ENOENT)
|
||||||
return find_result.release_error();
|
return find_result.release_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRY(unlink_impl(new_name));
|
TRY(remove_inode_from_directory_no_lock(new_name, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(link_inode_to_directory(*ext2_inode, new_name));
|
TRY(link_inode_to_directory_no_lock(*ext2_inode, new_name));
|
||||||
|
|
||||||
TRY(ext2_parent->remove_inode_from_directory(old_name, false));
|
TRY(ext2_parent->remove_inode_from_directory_no_lock(old_name, false));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
|
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory_no_lock(Ext2Inode& inode, BAN::StringView name)
|
||||||
{
|
{
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
@@ -707,15 +694,13 @@ done:
|
|||||||
if (name.size() > 255)
|
if (name.size() > 255)
|
||||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||||
{
|
{
|
||||||
dwarnln("file creation to indexed directory not supported");
|
dwarnln("file creation to indexed directory not supported");
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto error_or = find_inode_impl(name);
|
auto error_or = find_inode_no_lock(name);
|
||||||
if (!error_or.is_error())
|
if (!error_or.is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
if (error_or.error().get_error_code() != ENOENT)
|
if (error_or.error().get_error_code() != ENOENT)
|
||||||
@@ -747,7 +732,7 @@ done:
|
|||||||
memcpy(new_entry.name, name.data(), name.size());
|
memcpy(new_entry.name, name.data(), name.size());
|
||||||
|
|
||||||
inode.m_inode.links_count++;
|
inode.m_inode.links_count++;
|
||||||
TRY(inode.sync());
|
TRY(inode.sync_no_lock());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
@@ -765,7 +750,7 @@ done:
|
|||||||
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, true)).value();
|
block_index = TRY(fs_block_of_data_block_index_no_lock(data_block_count - 1, true)).value();
|
||||||
TRY(m_fs.read_block(block_index, block_buffer));
|
TRY(m_fs.read_block(block_index, block_buffer));
|
||||||
|
|
||||||
while (entry_offset < block_size)
|
while (entry_offset < block_size)
|
||||||
@@ -796,7 +781,7 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
needs_new_block:
|
needs_new_block:
|
||||||
block_index = TRY(fs_block_of_data_block_index(data_block_count, true)).value();
|
block_index = TRY(fs_block_of_data_block_index_no_lock(data_block_count, true)).value();
|
||||||
m_inode.size += blksize();
|
m_inode.size += blksize();
|
||||||
|
|
||||||
memset(block_buffer.data(), 0x00, block_buffer.size());
|
memset(block_buffer.data(), 0x00, block_buffer.size());
|
||||||
@@ -806,18 +791,16 @@ needs_new_block:
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<bool> Ext2Inode::is_directory_empty()
|
BAN::ErrorOr<bool> Ext2Inode::is_directory_empty_no_lock()
|
||||||
{
|
{
|
||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
// Confirm that this doesn't contain anything else than '.' or '..'
|
// Confirm that this doesn't contain anything else than '.' or '..'
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(i, false));
|
||||||
if (!block_index.has_value())
|
if (!block_index.has_value())
|
||||||
continue;
|
continue;
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
@@ -841,14 +824,12 @@ needs_new_block:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::cleanup_default_links()
|
BAN::ErrorOr<void> Ext2Inode::cleanup_default_links_no_lock()
|
||||||
{
|
{
|
||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||||
{
|
{
|
||||||
dwarnln("deletion of indexed directory is not supported");
|
dwarnln("deletion of indexed directory is not supported");
|
||||||
@@ -857,7 +838,7 @@ needs_new_block:
|
|||||||
|
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(i, false));
|
||||||
if (!block_index.has_value())
|
if (!block_index.has_value())
|
||||||
continue;
|
continue;
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
@@ -876,13 +857,13 @@ needs_new_block:
|
|||||||
if (entry_name == "."_sv)
|
if (entry_name == "."_sv)
|
||||||
{
|
{
|
||||||
m_inode.links_count--;
|
m_inode.links_count--;
|
||||||
TRY(sync());
|
TRY(sync_no_lock());
|
||||||
}
|
}
|
||||||
else if (entry_name == ".."_sv)
|
else if (entry_name == ".."_sv)
|
||||||
{
|
{
|
||||||
auto parent = TRY(Ext2Inode::create(m_fs, entry.inode));
|
auto parent = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||||
parent->m_inode.links_count--;
|
parent->m_inode.links_count--;
|
||||||
TRY(parent->sync());
|
TRY(parent->sync_no_lock());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
@@ -901,14 +882,12 @@ needs_new_block:
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::remove_inode_from_directory(BAN::StringView name, bool cleanup_directory)
|
BAN::ErrorOr<void> Ext2Inode::remove_inode_from_directory_no_lock(BAN::StringView name, bool cleanup_directory)
|
||||||
{
|
{
|
||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
|
|
||||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||||
{
|
{
|
||||||
dwarnln("deletion from indexed directory is not supported");
|
dwarnln("deletion from indexed directory is not supported");
|
||||||
@@ -917,7 +896,7 @@ needs_new_block:
|
|||||||
|
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(i, false));
|
||||||
if (!block_index.has_value())
|
if (!block_index.has_value())
|
||||||
continue;
|
continue;
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
@@ -931,9 +910,9 @@ needs_new_block:
|
|||||||
auto inode = TRY(Ext2Inode::create(m_fs, entry.inode));
|
auto inode = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||||
if (cleanup_directory && inode->mode().ifdir())
|
if (cleanup_directory && inode->mode().ifdir())
|
||||||
{
|
{
|
||||||
if (!TRY(inode->is_directory_empty()))
|
if (!TRY(inode->is_directory_empty_no_lock()))
|
||||||
return BAN::Error::from_errno(ENOTEMPTY);
|
return BAN::Error::from_errno(ENOTEMPTY);
|
||||||
TRY(inode->cleanup_default_links());
|
TRY(inode->cleanup_default_links_no_lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inode->nlink() == 0)
|
if (inode->nlink() == 0)
|
||||||
@@ -941,7 +920,7 @@ needs_new_block:
|
|||||||
else
|
else
|
||||||
inode->m_inode.links_count--;
|
inode->m_inode.links_count--;
|
||||||
|
|
||||||
TRY(sync());
|
TRY(sync_no_lock());
|
||||||
|
|
||||||
// NOTE: If this was the last link to inode we must
|
// NOTE: If this was the last link to inode we must
|
||||||
// remove it from inode cache to trigger cleanup
|
// remove it from inode cache to trigger cleanup
|
||||||
@@ -965,18 +944,17 @@ needs_new_block:
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::unlink_impl(BAN::StringView name)
|
BAN::ErrorOr<void> Ext2Inode::unlink_impl(BAN::StringView name)
|
||||||
{
|
{
|
||||||
TRY(remove_inode_from_directory(name, true));
|
RWLockWRGuard _(m_lock);
|
||||||
|
TRY(remove_inode_from_directory_no_lock(name, true));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::sync()
|
BAN::ErrorOr<void> Ext2Inode::sync_no_lock()
|
||||||
{
|
{
|
||||||
auto inode_location = TRY(m_fs.locate_inode(ino()));
|
auto inode_location = TRY(m_fs.locate_inode(ino()));
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
TRY(m_fs.read_block(inode_location.block, block_buffer));
|
TRY(m_fs.read_block(inode_location.block, block_buffer));
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
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));
|
||||||
@@ -987,15 +965,20 @@ needs_new_block:
|
|||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::find_inode_impl(BAN::StringView file_name)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::find_inode_impl(BAN::StringView file_name)
|
||||||
|
{
|
||||||
|
RWLockRDGuard _(m_lock);
|
||||||
|
return find_inode_no_lock(file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::find_inode_no_lock(BAN::StringView file_name)
|
||||||
{
|
{
|
||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index_no_lock(i, false));
|
||||||
if (!block_index.has_value())
|
if (!block_index.has_value())
|
||||||
continue;
|
continue;
|
||||||
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
TRY(m_fs.read_block(block_index.value(), block_buffer));
|
||||||
|
|||||||
Reference in New Issue
Block a user