summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-12-29 13:16:53 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-12-29 13:16:53 +0100
commit1f3115617337bee8fbc63f2247118e89f2803d22 (patch)
tree52554fc7d20af61f3397f8f08b2e2c7f5f91035f /Kernel
parentc74cde918a5ef031d5f01c663212b1c909564cf4 (diff)
downloadserenity-1f3115617337bee8fbc63f2247118e89f2803d22.zip
Kernel: Add a mode flag to sys$purge and allow purging clean inodes
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Process.cpp40
-rw-r--r--Kernel/Process.h2
-rw-r--r--Kernel/UnixTypes.h2
-rw-r--r--Kernel/VM/InodeVMObject.cpp25
-rw-r--r--Kernel/VM/InodeVMObject.h4
-rw-r--r--Kernel/VM/Region.cpp4
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");