mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
vmmcache: redo how vnode locking is expected
This commit is contained in:
+22
-6
@@ -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, ¤t_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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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, ¤t_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, ¤t_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);
|
||||
|
||||
|
||||
@@ -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, ¤t_thread()->proc->cred);
|
||||
|
||||
VOP_UNLOCK(file->vnode);
|
||||
MUTEX_RELEASE(&file->vnode->size_lock);
|
||||
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user