Kernel: Don't msync file backed pages that were never mapped writable

This commit is contained in:
2026-05-17 02:50:32 +03:00
parent 9c79971bdc
commit d7865b2929
2 changed files with 23 additions and 7 deletions

View File

@@ -18,6 +18,7 @@ namespace Kernel
// FIXME: this should probably be ordered tree like map
// for fast lookup and less memory usage
BAN::Vector<paddr_t> pages;
BAN::Vector<uint32_t> writers;
BAN::RefPtr<Inode> inode;
};

View File

@@ -39,7 +39,9 @@ namespace Kernel
if (!(region->m_shared_data = inode->m_shared_region.lock()))
{
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
TRY(shared_data->pages.resize(BAN::Math::div_round_up<size_t>(inode->size(), PAGE_SIZE)));
const size_t page_count = BAN::Math::div_round_up<size_t>(inode->size(), PAGE_SIZE);
TRY(shared_data->pages.resize(page_count, 0));
TRY(shared_data->writers.resize(page_count, 0));
shared_data->inode = inode;
inode->m_shared_region = TRY(shared_data->get_weak_ptr());
region->m_shared_data = BAN::move(shared_data);
@@ -59,9 +61,21 @@ namespace Kernel
{
if (m_vaddr == 0)
return;
switch (m_type)
{
case Type::PRIVATE:
for (paddr_t dirty_page : m_dirty_pages)
if (dirty_page)
Heap::get().release_page(dirty_page);
break;
case Type::SHARED:
const size_t page_count = BAN::Math::div_round_up<size_t>(size(), PAGE_SIZE);
for (size_t i = 0; i < page_count; i++)
if (m_page_table.get_page_flags(m_vaddr + i * PAGE_SIZE) & PageTable::Flags::ReadWrite)
BAN::atomic_sub_fetch(m_shared_data->writers[m_offset / PAGE_SIZE + i], 1);
break;
}
}
SharedFileData::~SharedFileData()
@@ -79,7 +93,7 @@ namespace Kernel
void SharedFileData::sync_no_lock(size_t page_index)
{
if (pages[page_index] == 0)
if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) == 0)
return;
uint8_t page_buffer[PAGE_SIZE];
@@ -179,11 +193,12 @@ namespace Kernel
}
else
{
const paddr_t paddr = m_shared_data->pages[shared_page_index];
auto flags = m_flags;
if (m_type == Type::PRIVATE)
flags &= ~PageTable::Flags::ReadWrite;
m_page_table.map_page_at(paddr, vaddr, flags);
if (flags & PageTable::Flags::ReadWrite)
BAN::atomic_add_fetch(m_shared_data->writers[shared_page_index], 1);
m_page_table.map_page_at(m_shared_data->pages[shared_page_index], vaddr, flags);
}
}
else