vfs: vfs_iscacheable

This commit is contained in:
Matheus
2024-09-04 21:33:59 -03:00
parent be27fb6f3b
commit ee254a81e9
4 changed files with 22 additions and 13 deletions
+2 -2
View File
@@ -230,7 +230,7 @@ static int writenocache(vnode_t *node, page_t *page, uintmax_t pageoffset) {
int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *written, int flags) {
VOP_LOCK(node);
int err = 0;
if (node->type == V_TYPE_REGULAR || node->type == V_TYPE_BLKDEV) {
if (vfs_iscacheable(node)) {
*written = 0;
// can't write a size 0 buffer
if (size == 0)
@@ -328,7 +328,7 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *bytesread, int flags) {
VOP_LOCK(node);
int err = 0;
if (node->type == V_TYPE_REGULAR || node->type == V_TYPE_BLKDEV) {
if (vfs_iscacheable(node)) {
*bytesread = 0;
// can't read 0 bytes from the cache
if (size == 0)
+10
View File
@@ -270,4 +270,14 @@ static inline mode_t vfs_getsystemtype(int type) {
}
}
static inline bool vfs_iscacheable(vnode_t *vnode) {
int type = vnode->type;
// vnodes will be cacheable if:
// - the vnode is a regular or block device
// AND
// - the filesystem implementation exposes the VOP_*PAGE operations.
return (type == V_TYPE_REGULAR || type == V_TYPE_BLKDEV) && vnode->ops->putpage && vnode->ops->getpage;
}
#endif
+8 -8
View File
@@ -227,10 +227,10 @@ static void destroyrange(vmmrange_t *range, uintmax_t _offset, size_t size, int
proc_t *proc = thread ? thread->proc : NULL;
cred_t *cred = proc ? &proc->cred : NULL;
if ((range->flags & VMM_FLAGS_FILE) && ((range->flags & VMM_FLAGS_SHARED) || range->vnode->type == V_TYPE_CHDEV)) {
// shared file mapping or character device mapping
if (range->vnode->type == V_TYPE_CHDEV) {
// character device mapping
if ((range->flags & VMM_FLAGS_FILE) && ((range->flags & VMM_FLAGS_SHARED) || vfs_iscacheable(range->vnode) == false)) {
// shared file mapping or non cacheable mapping
if (vfs_iscacheable(range->vnode) == false) {
// non cacheable mapping
VOP_LOCK(range->vnode);
__assert(VOP_MUNMAP(range->vnode, vaddr, range->offset + offset, mmuflagstovnodeflags(range->mmuflags) | (range->flags & VMM_FLAGS_SHARED ? V_FFLAGS_SHARED : 0), cred) == 0);
VOP_UNLOCK(range->vnode);
@@ -280,7 +280,7 @@ static void changemmurange(vmmrange_t *range, void *base, size_t size, mmuflags_
CHANGE_MASK_CHECK(mask, ARCH_MMU_FLAGS_USER, currentflags, newflags);
CHANGE_MASK_CHECK(mask, ARCH_MMU_FLAGS_NOEXEC, currentflags, newflags);
if ((range->flags & VMM_FLAGS_FILE) && (range->flags & VMM_FLAGS_SHARED) && (mask & ARCH_MMU_FLAGS_WRITE)) {
if ((range->flags & VMM_FLAGS_FILE) && (range->flags & VMM_FLAGS_SHARED) && (mask & ARCH_MMU_FLAGS_WRITE) && vfs_iscacheable(range->vnode)) {
// removing write permissions from a writeable dirty shared mapped page, mark it as dirty, as
// it won't be marked dirty upon a vmm_unmap after this
page_t *page = pmm_getpage(physical);
@@ -568,7 +568,7 @@ bool vmm_pagefault(void *addr, bool user, int actions) {
// page not present in the page tables
if (range->flags & VMM_FLAGS_FILE) {
uintmax_t mapoffset = (uintptr_t)addr - (uintptr_t)range->start;
if (range->vnode->type != V_TYPE_BLKDEV && range->vnode->type != V_TYPE_REGULAR) {
if (vfs_iscacheable(range->vnode) == false) {
// map non cacheable vnodes
VOP_LOCK(range->vnode);
__assert(VOP_MMAP(range->vnode, addr, range->offset + mapoffset, mmuflagstovnodeflags(range->mmuflags) | (range->flags & VMM_FLAGS_SHARED ? V_FFLAGS_SHARED : 0), cred) == 0);
@@ -617,7 +617,7 @@ bool vmm_pagefault(void *addr, bool user, int actions) {
if ((range->flags & VMM_FLAGS_FILE) && (range->flags & VMM_FLAGS_SHARED)) {
// shared file, remap it as writable
arch_mmu_remap(_cpu()->vmmctx->pagetable, oldphys, addr, range->mmuflags);
if (range->vnode->type != V_TYPE_CHDEV) {
if (vfs_iscacheable(range->vnode)) {
// and if its a cache page, mark it as dirty
VOP_LOCK(range->vnode);
vmmcache_makedirty(pmm_getpage(oldphys));
@@ -635,7 +635,7 @@ bool vmm_pagefault(void *addr, bool user, int actions) {
} else {
memcpy(MAKE_HHDM(newphys), MAKE_HHDM(oldphys), PAGE_SIZE);
arch_mmu_remap(_cpu()->vmmctx->pagetable, newphys, addr, range->mmuflags);
if ((range->flags & VMM_FLAGS_FILE) == 0 || range->vnode->type != V_TYPE_CHDEV)
if ((range->flags & VMM_FLAGS_FILE) == 0 || vfs_iscacheable(range->vnode))
pmm_release(oldphys);
status = true;
+2 -3
View File
@@ -78,10 +78,9 @@ syscallret_t syscall_mmap(context_t *context, void *hint, size_t len, int prot,
goto cleanup;
}
// not all charcter devices support mapping, so check if its supported
// (regular files and block devices go through the page cache)
// if the vnode is not cacheable, we need to make sure we can map it
// TODO move this check to vmm_map once the return value of mmap is fixed to return an errno
if (type == V_TYPE_CHDEV) {
if (vfs_iscacheable(file->vnode) == false) {
ret.errno = VOP_MMAP(file->vnode, VOP_MMAP_ADDRESS_MMAP_SUPPORTED, 0, 0, NULL);
if (ret.errno)
goto cleanup;