Kernel: Don't msync file backed pages that were never mapped writable
This commit is contained in:
@@ -18,6 +18,7 @@ namespace Kernel
|
|||||||
// FIXME: this should probably be ordered tree like map
|
// FIXME: this should probably be ordered tree like map
|
||||||
// for fast lookup and less memory usage
|
// for fast lookup and less memory usage
|
||||||
BAN::Vector<paddr_t> pages;
|
BAN::Vector<paddr_t> pages;
|
||||||
|
BAN::Vector<uint32_t> writers;
|
||||||
BAN::RefPtr<Inode> inode;
|
BAN::RefPtr<Inode> inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ namespace Kernel
|
|||||||
if (!(region->m_shared_data = inode->m_shared_region.lock()))
|
if (!(region->m_shared_data = inode->m_shared_region.lock()))
|
||||||
{
|
{
|
||||||
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
|
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;
|
shared_data->inode = inode;
|
||||||
inode->m_shared_region = TRY(shared_data->get_weak_ptr());
|
inode->m_shared_region = TRY(shared_data->get_weak_ptr());
|
||||||
region->m_shared_data = BAN::move(shared_data);
|
region->m_shared_data = BAN::move(shared_data);
|
||||||
@@ -59,9 +61,21 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (m_vaddr == 0)
|
if (m_vaddr == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
case Type::PRIVATE:
|
||||||
for (paddr_t dirty_page : m_dirty_pages)
|
for (paddr_t dirty_page : m_dirty_pages)
|
||||||
if (dirty_page)
|
if (dirty_page)
|
||||||
Heap::get().release_page(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()
|
SharedFileData::~SharedFileData()
|
||||||
@@ -79,7 +93,7 @@ namespace Kernel
|
|||||||
|
|
||||||
void SharedFileData::sync_no_lock(size_t page_index)
|
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;
|
return;
|
||||||
|
|
||||||
uint8_t page_buffer[PAGE_SIZE];
|
uint8_t page_buffer[PAGE_SIZE];
|
||||||
@@ -179,11 +193,12 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const paddr_t paddr = m_shared_data->pages[shared_page_index];
|
|
||||||
auto flags = m_flags;
|
auto flags = m_flags;
|
||||||
if (m_type == Type::PRIVATE)
|
if (m_type == Type::PRIVATE)
|
||||||
flags &= ~PageTable::Flags::ReadWrite;
|
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
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user