1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:38:11 +00:00

Kernel/Ext2FS: Propagate errors from block list computation functions

This commit is contained in:
Andreas Kling 2021-11-10 15:52:46 +01:00
parent 4661ca5f15
commit f86ee71f65
2 changed files with 48 additions and 44 deletions

View file

@ -518,26 +518,26 @@ ErrorOr<void> Ext2FSInode::flush_block_list()
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list() const ErrorOr<Vector<Ext2FS::BlockIndex>> Ext2FSInode::compute_block_list() const
{ {
return compute_block_list_impl(false); return compute_block_list_impl(false);
} }
Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_with_meta_blocks() const ErrorOr<Vector<Ext2FS::BlockIndex>> Ext2FSInode::compute_block_list_with_meta_blocks() const
{ {
return compute_block_list_impl(true); return compute_block_list_impl(true);
} }
Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_impl(bool include_block_list_blocks) const ErrorOr<Vector<Ext2FS::BlockIndex>> Ext2FSInode::compute_block_list_impl(bool include_block_list_blocks) const
{ {
// FIXME: This is really awkwardly factored.. foo_impl_internal :| // FIXME: This is really awkwardly factored.. foo_impl_internal :|
auto block_list = compute_block_list_impl_internal(m_raw_inode, include_block_list_blocks); auto block_list = TRY(compute_block_list_impl_internal(m_raw_inode, include_block_list_blocks));
while (!block_list.is_empty() && block_list.last() == 0) while (!block_list.is_empty() && block_list.last() == 0)
block_list.take_last(); block_list.take_last();
return block_list; return block_list;
} }
Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_impl_internal(const ext2_inode& e2inode, bool include_block_list_blocks) const ErrorOr<Vector<Ext2FS::BlockIndex>> Ext2FSInode::compute_block_list_impl_internal(ext2_inode const& e2inode, bool include_block_list_blocks) const
{ {
unsigned entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); unsigned entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block());
@ -562,24 +562,25 @@ Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_impl_internal(const e
Vector<Ext2FS::BlockIndex> list; Vector<Ext2FS::BlockIndex> list;
auto add_block = [&](auto bi) { auto add_block = [&](auto bi) -> ErrorOr<void> {
if (blocks_remaining) { if (blocks_remaining) {
list.append(bi); TRY(list.try_append(bi));
--blocks_remaining; --blocks_remaining;
} }
return {};
}; };
if (include_block_list_blocks) { if (include_block_list_blocks) {
// This seems like an excessive over-estimate but w/e. // This seems like an excessive over-estimate but w/e.
list.ensure_capacity(blocks_remaining * 2); TRY(list.try_ensure_capacity(blocks_remaining * 2));
} else { } else {
list.ensure_capacity(blocks_remaining); TRY(list.try_ensure_capacity(blocks_remaining));
} }
unsigned direct_count = min(block_count, (unsigned)EXT2_NDIR_BLOCKS); unsigned direct_count = min(block_count, (unsigned)EXT2_NDIR_BLOCKS);
for (unsigned i = 0; i < direct_count; ++i) { for (unsigned i = 0; i < direct_count; ++i) {
auto block_index = e2inode.i_block[i]; auto block_index = e2inode.i_block[i];
add_block(block_index); TRY(add_block(block_index));
} }
if (!blocks_remaining) if (!blocks_remaining)
@ -587,48 +588,48 @@ Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_impl_internal(const e
// Don't need to make copy of add_block, since this capture will only // Don't need to make copy of add_block, since this capture will only
// be called before compute_block_list_impl_internal finishes. // be called before compute_block_list_impl_internal finishes.
auto process_block_array = [&](auto array_block_index, auto&& callback) { auto process_block_array = [&](auto array_block_index, auto&& callback) -> ErrorOr<void> {
if (include_block_list_blocks) if (include_block_list_blocks)
add_block(array_block_index); TRY(add_block(array_block_index));
auto count = min(blocks_remaining, entries_per_block); auto count = min(blocks_remaining, entries_per_block);
if (!count) if (!count)
return; return {};
size_t read_size = count * sizeof(u32); size_t read_size = count * sizeof(u32);
// FIXME: Handle possible OOM situation. auto maybe_array_storage = ByteBuffer::create_uninitialized(read_size);
auto array_storage = ByteBuffer::create_uninitialized(read_size).release_value(); if (!maybe_array_storage.has_value())
return ENOMEM;
auto array_storage = maybe_array_storage.release_value();
auto* array = (u32*)array_storage.data(); auto* array = (u32*)array_storage.data();
auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)array); auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)array);
if (auto result = fs().read_block(array_block_index, &buffer, read_size, 0); result.is_error()) { TRY(fs().read_block(array_block_index, &buffer, read_size, 0));
// FIXME: Stop here and propagate this error.
dbgln("Ext2FSInode[{}]::compute_block_list_impl_internal(): Error: {}", identifier(), result.error());
}
for (unsigned i = 0; i < count; ++i) for (unsigned i = 0; i < count; ++i)
callback(Ext2FS::BlockIndex(array[i])); TRY(callback(Ext2FS::BlockIndex(array[i])));
return {};
}; };
process_block_array(e2inode.i_block[EXT2_IND_BLOCK], [&](auto block_index) { TRY(process_block_array(e2inode.i_block[EXT2_IND_BLOCK], [&](auto block_index) -> ErrorOr<void> {
add_block(block_index); return add_block(block_index);
}); }));
if (!blocks_remaining) if (!blocks_remaining)
return list; return list;
process_block_array(e2inode.i_block[EXT2_DIND_BLOCK], [&](auto block_index) { TRY(process_block_array(e2inode.i_block[EXT2_DIND_BLOCK], [&](auto block_index) -> ErrorOr<void> {
process_block_array(block_index, [&](auto block_index2) { return process_block_array(block_index, [&](auto block_index2) -> ErrorOr<void> {
add_block(block_index2); return add_block(block_index2);
}); });
}); }));
if (!blocks_remaining) if (!blocks_remaining)
return list; return list;
process_block_array(e2inode.i_block[EXT2_TIND_BLOCK], [&](auto block_index) { TRY(process_block_array(e2inode.i_block[EXT2_TIND_BLOCK], [&](auto block_index) -> ErrorOr<void> {
process_block_array(block_index, [&](auto block_index2) { return process_block_array(block_index, [&](auto block_index2) -> ErrorOr<void> {
process_block_array(block_index2, [&](auto block_index3) { return process_block_array(block_index2, [&](auto block_index3) -> ErrorOr<void> {
add_block(block_index3); return add_block(block_index3);
}); });
}); });
}); }));
return list; return list;
} }
@ -640,10 +641,13 @@ ErrorOr<void> Ext2FS::free_inode(Ext2FSInode& inode)
dbgln_if(EXT2_DEBUG, "Ext2FS[{}]::free_inode(): Inode {} has no more links, time to delete!", fsid(), inode.index()); dbgln_if(EXT2_DEBUG, "Ext2FS[{}]::free_inode(): Inode {} has no more links, time to delete!", fsid(), inode.index());
// Mark all blocks used by this inode as free. // Mark all blocks used by this inode as free.
for (auto block_index : inode.compute_block_list_with_meta_blocks()) { {
VERIFY(block_index <= super_block().s_blocks_count); auto blocks = TRY(inode.compute_block_list_with_meta_blocks());
if (block_index.value()) for (auto block_index : blocks) {
TRY(set_block_allocation_state(block_index, false)); VERIFY(block_index <= super_block().s_blocks_count);
if (block_index.value())
TRY(set_block_allocation_state(block_index, false));
}
} }
// If the inode being freed is a directory, update block group directory counter. // If the inode being freed is a directory, update block group directory counter.
@ -844,7 +848,7 @@ ErrorOr<size_t> Ext2FSInode::read_bytes(off_t offset, size_t count, UserOrKernel
} }
if (m_block_list.is_empty()) if (m_block_list.is_empty())
m_block_list = compute_block_list(); m_block_list = TRY(compute_block_list());
if (m_block_list.is_empty()) { if (m_block_list.is_empty()) {
dmesgln("Ext2FSInode[{}]::read_bytes(): Empty block list", identifier()); dmesgln("Ext2FSInode[{}]::read_bytes(): Empty block list", identifier());
@ -913,7 +917,7 @@ ErrorOr<void> Ext2FSInode::resize(u64 new_size)
} }
if (m_block_list.is_empty()) if (m_block_list.is_empty())
m_block_list = this->compute_block_list(); m_block_list = TRY(compute_block_list());
if (blocks_needed_after > blocks_needed_before) { if (blocks_needed_after > blocks_needed_before) {
auto blocks = TRY(fs().allocate_blocks(fs().group_index_from_inode(index()), blocks_needed_after - blocks_needed_before)); auto blocks = TRY(fs().allocate_blocks(fs().group_index_from_inode(index()), blocks_needed_after - blocks_needed_before));
@ -992,7 +996,7 @@ ErrorOr<size_t> Ext2FSInode::write_bytes(off_t offset, size_t count, const UserO
TRY(resize(new_size)); TRY(resize(new_size));
if (m_block_list.is_empty()) if (m_block_list.is_empty())
m_block_list = compute_block_list(); m_block_list = TRY(compute_block_list());
if (m_block_list.is_empty()) { if (m_block_list.is_empty()) {
dbgln("Ext2FSInode[{}]::write_bytes(): Empty block list", identifier()); dbgln("Ext2FSInode[{}]::write_bytes(): Empty block list", identifier());
@ -1669,7 +1673,7 @@ ErrorOr<int> Ext2FSInode::get_block_address(int index)
MutexLocker locker(m_inode_lock); MutexLocker locker(m_inode_lock);
if (m_block_list.is_empty()) if (m_block_list.is_empty())
m_block_list = compute_block_list(); m_block_list = TRY(compute_block_list());
if (index < 0 || (size_t)index >= m_block_list.size()) if (index < 0 || (size_t)index >= m_block_list.size())
return 0; return 0;

View file

@ -66,10 +66,10 @@ private:
ErrorOr<void> grow_triply_indirect_block(BlockBasedFileSystem::BlockIndex, size_t, Span<BlockBasedFileSystem::BlockIndex>, Vector<BlockBasedFileSystem::BlockIndex>&, unsigned&); ErrorOr<void> grow_triply_indirect_block(BlockBasedFileSystem::BlockIndex, size_t, Span<BlockBasedFileSystem::BlockIndex>, Vector<BlockBasedFileSystem::BlockIndex>&, unsigned&);
ErrorOr<void> shrink_triply_indirect_block(BlockBasedFileSystem::BlockIndex, size_t, size_t, unsigned&); ErrorOr<void> shrink_triply_indirect_block(BlockBasedFileSystem::BlockIndex, size_t, size_t, unsigned&);
ErrorOr<void> flush_block_list(); ErrorOr<void> flush_block_list();
Vector<BlockBasedFileSystem::BlockIndex> compute_block_list() const; ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list() const;
Vector<BlockBasedFileSystem::BlockIndex> compute_block_list_with_meta_blocks() const; ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list_with_meta_blocks() const;
Vector<BlockBasedFileSystem::BlockIndex> compute_block_list_impl(bool include_block_list_blocks) const; ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list_impl(bool include_block_list_blocks) const;
Vector<BlockBasedFileSystem::BlockIndex> compute_block_list_impl_internal(const ext2_inode& e2inode, bool include_block_list_blocks) const; ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list_impl_internal(ext2_inode const&, bool include_block_list_blocks) const;
Ext2FS& fs(); Ext2FS& fs();
const Ext2FS& fs() const; const Ext2FS& fs() const;