Kernel: Avoid a memcpy() of the whole block when paging in from inode

This commit is contained in:
Andreas Kling 2019-08-25 14:34:53 +02:00
parent fa20dcafb5
commit 11896d0e26
Notes: sideshowbarker 2024-07-19 12:32:19 +09:00

View file

@ -342,14 +342,14 @@ bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_re
ASSERT(vmo.is_inode());
auto& inode_vmobject = static_cast<InodeVMObject&>(vmo);
auto& vmo_page = inode_vmobject.physical_pages()[region.first_page_index() + page_index_in_region];
InterruptFlagSaver saver;
sti();
bool interrupts_were_enabled = are_interrupts_enabled();
if (!interrupts_were_enabled)
sti();
LOCKER(vmo.m_paging_lock);
cli();
if (!vmo_page.is_null()) {
#ifdef PAGE_FAULT_DEBUG
@ -362,19 +362,6 @@ bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_re
#ifdef MM_DEBUG
dbgprintf("MM: page_in_from_inode ready to read from inode\n");
#endif
sti();
u8 page_buffer[PAGE_SIZE];
auto& inode = inode_vmobject.inode();
auto nread = inode.read_bytes((region.first_page_index() + page_index_in_region) * PAGE_SIZE, PAGE_SIZE, page_buffer, nullptr);
if (nread < 0) {
kprintf("MM: page_in_from_inode had error (%d) while reading!\n", nread);
return false;
}
if (nread < PAGE_SIZE) {
// If we read less than a page, zero out the rest to avoid leaking uninitialized data.
memset(page_buffer + nread, 0, PAGE_SIZE - nread);
}
cli();
vmo_page = allocate_user_physical_page(ShouldZeroFill::No);
if (vmo_page.is_null()) {
kprintf("MM: page_in_from_inode was unable to allocate a physical page\n");
@ -382,7 +369,17 @@ bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_re
}
remap_region_page(region, page_index_in_region);
u8* dest_ptr = region.vaddr().offset(page_index_in_region * PAGE_SIZE).as_ptr();
memcpy(dest_ptr, page_buffer, PAGE_SIZE);
auto& inode = inode_vmobject.inode();
auto nread = inode.read_bytes((region.first_page_index() + page_index_in_region) * PAGE_SIZE, PAGE_SIZE, dest_ptr, nullptr);
if (nread < 0) {
kprintf("MM: page_in_from_inode had error (%d) while reading!\n", nread);
return false;
}
if (nread < PAGE_SIZE) {
// If we read less than a page, zero out the rest to avoid leaking uninitialized data.
memset(dest_ptr + nread, 0, PAGE_SIZE - nread);
}
return true;
}