mirror of
https://github.com/RGBCube/serenity
synced 2025-07-02 23:22:07 +00:00
Ext2FS: Fix unpopulated block list cache after mkdir()
When creating a new directory, we set the initial size to 1 block. This meant that we were allocating a block up front, but the Inode's internal block list cache was not populated with this block. This broke write_bytes() on a new directory, since it assumed that the block list cache would be up to date if the call to write_bytes() would not change the directory's size. This patch fixes the issue in two ways: First, we cache the initial block list created for new directories. Second, we now repopulate the block list cache in write_bytes() if it is empty when we get there. This is basically just a safety fallback to avoid having this kind of bug in the future.
This commit is contained in:
parent
3d239be7b4
commit
c1d3ac7108
1 changed files with 14 additions and 6 deletions
|
@ -607,11 +607,8 @@ ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes
|
||||||
|
|
||||||
Locker fs_locker(fs().m_lock);
|
Locker fs_locker(fs().m_lock);
|
||||||
|
|
||||||
if (m_block_list.is_empty()) {
|
if (m_block_list.is_empty())
|
||||||
auto block_list = fs().block_list_for_inode(m_raw_inode);
|
m_block_list = fs().block_list_for_inode(m_raw_inode);
|
||||||
if (m_block_list.size() != block_list.size())
|
|
||||||
m_block_list = move(block_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_block_list.is_empty()) {
|
if (m_block_list.is_empty()) {
|
||||||
kprintf("ext2fs: read_bytes: empty block list for inode %u\n", index());
|
kprintf("ext2fs: read_bytes: empty block list for inode %u\n", index());
|
||||||
|
@ -735,6 +732,14 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
|
||||||
if (resize_result.is_error())
|
if (resize_result.is_error())
|
||||||
return resize_result;
|
return resize_result;
|
||||||
|
|
||||||
|
if (m_block_list.is_empty())
|
||||||
|
m_block_list = fs().block_list_for_inode(m_raw_inode);
|
||||||
|
|
||||||
|
if (m_block_list.is_empty()) {
|
||||||
|
dbg() << "Ext2FSInode::write_bytes(): empty block list for inode " << index();
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
int first_block_logical_index = offset / block_size;
|
int first_block_logical_index = offset / block_size;
|
||||||
int last_block_logical_index = (offset + count) / block_size;
|
int last_block_logical_index = (offset + count) / block_size;
|
||||||
if (last_block_logical_index >= m_block_list.size())
|
if (last_block_logical_index >= m_block_list.size())
|
||||||
|
@ -1391,7 +1396,10 @@ RefPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& name
|
||||||
// We might have cached the fact that this inode didn't exist. Wipe the slate.
|
// We might have cached the fact that this inode didn't exist. Wipe the slate.
|
||||||
m_inode_cache.remove(inode_id);
|
m_inode_cache.remove(inode_id);
|
||||||
|
|
||||||
return get_inode({ fsid(), inode_id });
|
auto inode = get_inode({ fsid(), inode_id });
|
||||||
|
// If we've already computed a block list, no sense in throwing it away.
|
||||||
|
static_cast<Ext2FSInode&>(*inode).m_block_list = move(blocks);
|
||||||
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FSInode::populate_lookup_cache() const
|
void Ext2FSInode::populate_lookup_cache() const
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue