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