vmmcache: redo how vnode locking is expected

This commit is contained in:
Matheus
2024-09-18 18:03:07 -03:00
parent 216a2e8d01
commit d5a4f2a4ad
6 changed files with 44 additions and 25 deletions
+22 -6
View File
@@ -228,7 +228,6 @@ 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 (vfs_iscacheable(node)) {
*written = 0;
@@ -242,8 +241,12 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
goto leave;
}
MUTEX_ACQUIRE(&node->size_lock, false);
vattr_t attr;
VOP_LOCK(node);
err = VOP_GETATTR(node, &attr, getcred());
VOP_UNLOCK(node);
if (err)
goto leave;
@@ -251,14 +254,18 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
if (node->type == V_TYPE_REGULAR && newsize) {
// do resize stuff if regular and applicable
VOP_LOCK(node);
err = VOP_RESIZE(node, newsize, &current_thread()->proc->cred);
VOP_UNLOCK(node);
if (err)
goto leave;
} else if (node->type == V_TYPE_BLKDEV) {
// else just get the disk size and limit the read size
blockdesc_t blockdesc;
int r;
VOP_LOCK(node);
err = VOP_IOCTL(node, BLOCK_IOCTL_GETDESC, &blockdesc, &r, NULL);
VOP_UNLOCK(node);
__assert(err == 0);
size_t bytesize = blockdesc.blockcapacity * blockdesc.blocksize;
@@ -315,18 +322,20 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
if (err)
goto leave;
}
leave:
MUTEX_RELEASE(&node->size_lock);
} else {
// special file, just write as its not being cached
VOP_LOCK(node);
err = VOP_WRITE(node, buffer, size, offset, flags, written, getcred());
VOP_UNLOCK(node);
}
leave:
VOP_UNLOCK(node);
return err;
}
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 (vfs_iscacheable(node)) {
*bytesread = 0;
@@ -342,9 +351,12 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
size_t nodesize = 0;
MUTEX_ACQUIRE(&node->size_lock, false);
if (node->type == V_TYPE_REGULAR) {
vattr_t attr;
VOP_LOCK(node);
err = VOP_GETATTR(node, &attr, getcred());
VOP_UNLOCK(node);
if (err)
goto leave;
@@ -352,7 +364,9 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
} else {
blockdesc_t blockdesc;
int r;
VOP_LOCK(node);
err = VOP_IOCTL(node, BLOCK_IOCTL_GETDESC, &blockdesc, &r, NULL);
VOP_UNLOCK(node);
__assert(err == 0);
nodesize = blockdesc.blockcapacity * blockdesc.blocksize;
@@ -404,12 +418,14 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t
}
pmm_release(FROM_HHDM(address));
}
leave:
MUTEX_RELEASE(&node->size_lock);
} else {
// special file, just read as size doesn't matter
VOP_LOCK(node);
err = VOP_READ(node, buffer, size, offset, flags, bytesread, getcred());
VOP_UNLOCK(node);
}
leave:
VOP_UNLOCK(node);
return err;
}
+2 -2
View File
@@ -92,7 +92,7 @@ typedef struct vfs_t {
typedef struct vnode_t {
struct vops_t *ops;
mutex_t lock;
mutex_t sizelock;
mutex_t size_lock;
int refcount;
int flags;
int type;
@@ -161,7 +161,7 @@ typedef struct vops_t {
#define VOP_INIT(vn, o, f, t, v) \
(vn)->ops = o; \
MUTEX_INIT(&(vn)->lock); \
MUTEX_INIT(&(vn)->sizelock); \
MUTEX_INIT(&(vn)->size_lock); \
(vn)->refcount = 1; \
(vn)->flags = f; \
(vn)->type = t; \
+1 -2
View File
@@ -581,9 +581,8 @@ bool vmm_pagefault(void *addr, bool user, int actions) {
} else {
// cacheable vnode
page_t *res = NULL;
VOP_LOCK(range->vnode);
int error = vmmcache_getpage(range->vnode, range->offset + mapoffset, &res);
VOP_UNLOCK(range->vnode);
if (error == ENXIO || error == ENOMEM) {
if (error == ENOMEM)
printf("vmm: out of memory to handle getpage (sending SIGBUS)\n");
+2 -1
View File
@@ -102,7 +102,6 @@ static void removepage(page_t *page) {
--vmmcache_cachedpages;
}
// vnode expected locked
int vmmcache_getpage(vnode_t *vnode, uintmax_t offset, page_t **res) {
__assert(vnode->type == V_TYPE_REGULAR || vnode->type == V_TYPE_BLKDEV);
__assert((offset % PAGE_SIZE) == 0);
@@ -164,7 +163,9 @@ int vmmcache_getpage(vnode_t *vnode, uintmax_t offset, page_t **res) {
RELEASE_LOCK();
VOP_LOCK(vnode);
int error = VOP_GETPAGE(vnode, offset, newpage);
VOP_UNLOCK(vnode);
if (error) {
// an error happened with GETPAGE, remove the page from the cache,
+13 -14
View File
@@ -43,14 +43,14 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
int newfd;
ret.errno = fd_new(flags & O_CLOEXEC, &newfile, &newfd);
if (ret.errno)
goto cleanup_nounlock;
goto cleanup;
vnode_t *vnode = NULL;
ret.errno = vfs_open(dirnode, pathbuf, fileflagstovnodeflags(flags), &vnode);
if (ret.errno == 0 && (flags & O_CREAT) && (flags & O_EXCL)) {
// exclusive and file already exists
ret.errno = EEXIST;
goto cleanup_nounlock;
goto cleanup;
} else if (ret.errno == ENOENT && (flags & O_CREAT)) {
// create file
vattr_t attr = {
@@ -62,12 +62,7 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
ret.errno = vfs_create(dirnode, pathbuf, &attr, V_TYPE_REGULAR, &vnode);
if (ret.errno == EEXIST && (flags & O_EXCL) == 0)
goto retry_open;
} else if (ret.errno) {
// any other error
goto cleanup_nounlock;
} else {
// success, lock file
VOP_LOCK(vnode);
VOP_UNLOCK(vnode);
}
if (ret.errno)
@@ -79,12 +74,22 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
}
vattr_t attr;
VOP_LOCK(vnode);
ret.errno = VOP_GETATTR(vnode, &attr, &current_thread()->proc->cred);
VOP_UNLOCK(vnode);
if (ret.errno)
goto cleanup;
if (vnode->type == V_TYPE_REGULAR && (flags & O_TRUNC) && (flags & FILE_WRITE)) {
MUTEX_ACQUIRE(&vnode->size_lock, false);
VOP_LOCK(vnode);
ret.errno = VOP_RESIZE(vnode, 0, &current_thread()->proc->cred);
VOP_UNLOCK(vnode);
MUTEX_RELEASE(&vnode->size_lock);
if (ret.errno)
goto cleanup;
}
@@ -99,11 +104,6 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
ret.ret = newfd;
cleanup:
if (vnode)
VOP_UNLOCK(vnode);
cleanup_nounlock:
if (vnode && ret.errno) {
vfs_close(vnode, fileflagstovnodeflags(flags));
VOP_RELEASE(vnode);
@@ -112,7 +112,6 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
if (newfile && ret.errno)
__assert(fd_close(newfd) == 0);
if (pathbuf)
free(pathbuf);
+4
View File
@@ -17,9 +17,13 @@ syscallret_t syscall_ftruncate(int fd, size_t size) {
goto cleanup;
}
MUTEX_ACQUIRE(&file->vnode->size_lock, false);
VOP_LOCK(file->vnode);
ret.errno = VOP_RESIZE(file->vnode, size, &current_thread()->proc->cred);
VOP_UNLOCK(file->vnode);
MUTEX_RELEASE(&file->vnode->size_lock);
ret.ret = ret.errno ? -1 : 0;