Skip to content

Commit

Permalink
Kernel: Add a mode flag to sys$purge and allow purging clean inodes
Browse files Browse the repository at this point in the history
  • Loading branch information
awesomekling committed Dec 29, 2019
1 parent c74cde9 commit 1f31156
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 17 deletions.
40 changes: 28 additions & 12 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class Process : public InlineLinkedListNode<Process>
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);
Expand Down
2 changes: 2 additions & 0 deletions Kernel/UnixTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,5 @@ struct ifreq {

#define AT_FDCWD -100

#define PURGE_ALL_VOLATILE 0x1
#define PURGE_ALL_CLEAN_INODE 0x2
25 changes: 24 additions & 1 deletion Kernel/VM/InodeVMObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
4 changes: 4 additions & 0 deletions Kernel/VM/InodeVMObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class InodeVMObject final : public VMObject {
size_t amount_dirty() const;
size_t amount_clean() const;

int release_all_clean_pages();

private:
explicit InodeVMObject(Inode&);
explicit InodeVMObject(const InodeVMObject&);
Expand All @@ -29,6 +31,8 @@ class InodeVMObject final : public VMObject {

virtual bool is_inode() const override { return true; }

int release_all_clean_pages_impl();

NonnullRefPtr<Inode> m_inode;
Bitmap m_dirty_pages;
};
4 changes: 4 additions & 0 deletions Kernel/VM/Region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
23 changes: 20 additions & 3 deletions Userland/purge.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
#include <stdio.h>
#include <Kernel/Syscall.h>
#include <stdio.h>
#include <string.h>

#define PURGE_ALL_VOLATILE 0x1
#define PURGE_ALL_CLEAN_INODE 0x2

int main(int, char**)
int main(int argc, char** argv)
{
int purged_page_count = syscall(SC_purge);
int mode = 0;
if (argc == 1) {
mode = PURGE_ALL_VOLATILE | PURGE_ALL_CLEAN_INODE;
} else {
if (!strcmp(argv[1], "-c")) {
mode = PURGE_ALL_CLEAN_INODE;
} else if (!strcmp(argv[1], "-v")) {
mode = PURGE_ALL_VOLATILE;
} else {
fprintf(stderr, "Unknown option: %s\n", argv[1]);
return 1;
}
}
int purged_page_count = syscall(SC_purge, mode);
printf("Purged page count: %d\n", purged_page_count);
return 0;
}

0 comments on commit 1f31156

Please sign in to comment.