diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-12-29 13:16:53 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-12-29 13:16:53 +0100 |
commit | 1f3115617337bee8fbc63f2247118e89f2803d22 (patch) | |
tree | 52554fc7d20af61f3397f8f08b2e2c7f5f91035f /Kernel | |
parent | c74cde918a5ef031d5f01c663212b1c909564cf4 (diff) | |
download | serenity-1f3115617337bee8fbc63f2247118e89f2803d22.zip |
Kernel: Add a mode flag to sys$purge and allow purging clean inodes
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Process.cpp | 40 | ||||
-rw-r--r-- | Kernel/Process.h | 2 | ||||
-rw-r--r-- | Kernel/UnixTypes.h | 2 | ||||
-rw-r--r-- | Kernel/VM/InodeVMObject.cpp | 25 | ||||
-rw-r--r-- | Kernel/VM/InodeVMObject.h | 4 | ||||
-rw-r--r-- | Kernel/VM/Region.cpp | 4 |
6 files changed, 63 insertions, 14 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 91d870fd6d..4463c481ff 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -404,20 +404,36 @@ int Process::sys$madvise(void* address, size_t size, int advice) return -EINVAL; } -int Process::sys$purge() +int Process::sys$purge(int mode) { - NonnullRefPtrVector<PurgeableVMObject> vmobjects; - { - InterruptDisabler disabler; - MM.for_each_vmobject([&](auto& vmobject) { - if (vmobject.is_purgeable()) - vmobjects.append(static_cast<PurgeableVMObject&>(vmobject)); - return IterationDecision::Continue; - }); - } int purged_page_count = 0; - for (auto& vmobject : vmobjects) { - purged_page_count += vmobject.purge(); + if (mode & PURGE_ALL_VOLATILE) { + NonnullRefPtrVector<PurgeableVMObject> vmobjects; + { + InterruptDisabler disabler; + MM.for_each_vmobject([&](auto& vmobject) { + if (vmobject.is_purgeable()) + vmobjects.append(static_cast<PurgeableVMObject&>(vmobject)); + return IterationDecision::Continue; + }); + } + for (auto& vmobject : vmobjects) { + purged_page_count += vmobject.purge(); + } + } + if (mode & PURGE_ALL_CLEAN_INODE) { + NonnullRefPtrVector<InodeVMObject> vmobjects; + { + InterruptDisabler disabler; + MM.for_each_vmobject([&](auto& vmobject) { + if (vmobject.is_inode()) + vmobjects.append(static_cast<InodeVMObject&>(vmobject)); + return IterationDecision::Continue; + }); + } + for (auto& vmobject : vmobjects) { + purged_page_count += vmobject.release_all_clean_pages(); + } } return purged_page_count; } diff --git a/Kernel/Process.h b/Kernel/Process.h index 40fa865c15..eff6a46674 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -142,7 +142,7 @@ public: int sys$set_mmap_name(void*, size_t, const char*); int sys$mprotect(void*, size_t, int prot); int sys$madvise(void*, size_t, int advice); - int sys$purge(); + int sys$purge(int mode); int sys$select(const Syscall::SC_select_params*); int sys$poll(pollfd*, int nfds, int timeout); ssize_t sys$get_dir_entries(int fd, void*, ssize_t); diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index cf098a6e5e..6ec77943fa 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -467,3 +467,5 @@ struct ifreq { #define AT_FDCWD -100 +#define PURGE_ALL_VOLATILE 0x1 +#define PURGE_ALL_CLEAN_INODE 0x2 diff --git a/Kernel/VM/InodeVMObject.cpp b/Kernel/VM/InodeVMObject.cpp index 65c1177988..6eee62c629 100644 --- a/Kernel/VM/InodeVMObject.cpp +++ b/Kernel/VM/InodeVMObject.cpp @@ -39,7 +39,8 @@ InodeVMObject::~InodeVMObject() size_t InodeVMObject::amount_clean() const { size_t count = 0; - for (int i = 0; i < m_dirty_pages.size(); ++i) { + ASSERT(page_count() == (size_t)m_dirty_pages.size()); + for (size_t i = 0; i < page_count(); ++i) { if (!m_dirty_pages.get(i) && m_physical_pages[i]) ++count; } @@ -125,3 +126,25 @@ void InodeVMObject::inode_contents_changed(Badge<Inode>, off_t offset, ssize_t s region.remap(); }); } + +int InodeVMObject::release_all_clean_pages() +{ + LOCKER(m_paging_lock); + return release_all_clean_pages_impl(); +} + +int InodeVMObject::release_all_clean_pages_impl() +{ + int count = 0; + InterruptDisabler disabler; + for (size_t i = 0; i < page_count(); ++i) { + if (!m_dirty_pages.get(i) && m_physical_pages[i]) { + m_physical_pages[i] = nullptr; + ++count; + } + } + for_each_region([](auto& region) { + region.remap(); + }); + return count; +} diff --git a/Kernel/VM/InodeVMObject.h b/Kernel/VM/InodeVMObject.h index e4e44cff7f..876cdf20ae 100644 --- a/Kernel/VM/InodeVMObject.h +++ b/Kernel/VM/InodeVMObject.h @@ -19,6 +19,8 @@ public: size_t amount_dirty() const; size_t amount_clean() const; + int release_all_clean_pages(); + private: explicit InodeVMObject(Inode&); explicit InodeVMObject(const InodeVMObject&); @@ -29,6 +31,8 @@ private: virtual bool is_inode() const override { return true; } + int release_all_clean_pages_impl(); + NonnullRefPtr<Inode> m_inode; Bitmap m_dirty_pages; }; diff --git a/Kernel/VM/Region.cpp b/Kernel/VM/Region.cpp index 2e905fe7cd..6278d69e75 100644 --- a/Kernel/VM/Region.cpp +++ b/Kernel/VM/Region.cpp @@ -410,6 +410,10 @@ PageFaultResponse Region::handle_inode_fault(size_t page_index_in_region) LOCKER(vmobject().m_paging_lock); cli(); +#ifdef PAGE_FAULT_DEBUG + dbg() << *current << " inode fault in " << name() << " page index: " << page_index_in_region; +#endif + if (!vmobject_physical_page_entry.is_null()) { #ifdef PAGE_FAULT_DEBUG dbgprintf("MM: page_in_from_inode() but page already present. Fine with me!\n"); |