syscalls: fsync

This commit is contained in:
Matheus
2024-05-25 12:04:29 -03:00
parent abb2fb9b26
commit b9071fe59e
11 changed files with 131 additions and 38 deletions
+3 -1
View File
@@ -65,6 +65,7 @@ extern syscall_sigreturn
extern syscall_uname
extern syscall_hostname
extern syscall_sync
extern syscall_fsync
syscalltab:
dq syscall_print
dq syscall_mmap
@@ -132,7 +133,8 @@ dq syscall_sigreturn
dq syscall_uname
dq syscall_hostname
dq syscall_sync
syscallcount equ 66
dq syscall_fsync
syscallcount equ 67
section .text
global arch_syscall_entry
; on entry:
+5 -3
View File
@@ -4,7 +4,7 @@
#ifdef SYSCALL_LOGGING
#define SYSCALL_COUNT 66
#define SYSCALL_COUNT 67
#define LOGSTR(x) arch_e9_puts(x)
static char *name[] = {
@@ -73,7 +73,8 @@ static char *name[] = {
"sigreturn",
"uname",
"hostname",
"sync"
"sync",
"fsync"
};
static char *args[] = {
@@ -142,7 +143,8 @@ static char *args[] = {
"N/A", // sigreturn
"utsname %p", // uname
"new %p newsize %lu old %p oldsize %lu", // hostname
"N/A" // sync
"N/A", // sync
"fd %d" // fsync
};
#endif
+11 -1
View File
@@ -1654,6 +1654,15 @@ static int ext2_rename(vnode_t *sourcedir, char *oldname, vnode_t *targetdir, ch
return err;
}
static int ext2_sync(vnode_t *vnode) {
int e = vmmcache_sync(vnode);
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
// TODO don't sync the entire disk but rather only the inodes and blocks
int e2 = vmmcache_sync(fs->backing);
// only the first errors are reported
return e ? e : e2;
}
static int ext2_inactive(vnode_t *vnode) {
ext2node_t *node = (ext2node_t *)vnode;
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
@@ -1829,7 +1838,8 @@ static vops_t vnops = {
.inactive = ext2_inactive,
.rename = ext2_rename,
.getpage = ext2_getpage,
.putpage = ext2_putpage
.putpage = ext2_putpage,
.sync = ext2_sync
};
void ext2_init() {
+2 -1
View File
@@ -260,7 +260,8 @@ static vops_t vnops = {
.resize = pipefs_enodev,
.rename = pipefs_enodev,
.putpage = pipefs_enodev,
.getpage = pipefs_enodev
.getpage = pipefs_enodev,
.sync = pipefs_enodev
};
static void ctor(scache_t *cache, void *obj) {
+2 -1
View File
@@ -186,7 +186,8 @@ static vops_t vnops = {
.rename = sockfs_enodev,
.ioctl = sockfs_ioctl,
.putpage = sockfs_enodev,
.getpage = sockfs_enodev
.getpage = sockfs_enodev,
.sync = sockfs_enodev
};
static void ctor(scache_t *cache, void *obj) {
+7 -1
View File
@@ -493,6 +493,11 @@ static int tmpfs_putpage(vnode_t *node, uintmax_t offset, struct page_t *page) {
return 0;
}
static int tmpfs_sync(vnode_t *node) {
// sync is a no-op on tmpfs
return 0;
}
static vfsops_t vfsops = {
.mount = tmpfs_mount,
.root = tmpfs_root
@@ -520,7 +525,8 @@ static vops_t vnops = {
.resize = tmpfs_resize,
.rename = tmpfs_rename,
.getpage = tmpfs_getpage,
.putpage = tmpfs_putpage
.putpage = tmpfs_putpage,
.sync = tmpfs_sync
};
static tmpfsnode_t *newnode(vfs_t *vfs, int type) {
+2
View File
@@ -105,6 +105,7 @@ typedef struct vops_t {
int (*rename)(vnode_t *source, char *oldname, vnode_t *target, char *newname, int flags);
int (*getpage)(vnode_t *node, uintmax_t offset, struct page_t *page);
int (*putpage)(vnode_t *node, uintmax_t offset, struct page_t *page);
int (*sync)(vnode_t *node);
} vops_t;
#define VFS_INIT(v, o, f) \
@@ -156,6 +157,7 @@ typedef struct vops_t {
#define VOP_RENAME(s, o, t, n, f) (s)->ops->rename(s, o, t, n, f)
#define VOP_GETPAGE(v, o, p) (v)->ops->getpage(v, o, p)
#define VOP_PUTPAGE(v, o, p) (v)->ops->putpage(v, o, p)
#define VOP_SYNC(v) (v)->ops->sync(v)
#define VOP_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST)
#define VOP_RELEASE(v) {\
if (__atomic_sub_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\
+1 -1
View File
@@ -9,7 +9,7 @@ int vmmcache_getpage(vnode_t *vnode, uintmax_t offset, page_t **res);
int vmmcache_takepage(page_t *page);
int vmmcache_makedirty(page_t *page);
int vmmcache_truncate(vnode_t *vnode, uintmax_t offset);
int vmmcache_syncvnode(vnode_t *vnode);
int vmmcache_syncvnode(vnode_t *vnode, uintmax_t startoffset, size_t size);
int vmmcache_sync();
#endif
+65 -13
View File
@@ -232,12 +232,73 @@ int vmmcache_truncate(vnode_t *vnode, uintmax_t offset) {
return 0;
}
int vmmcache_syncvnode(vnode_t *vnode) {
__assert(!"unimplemented");
// called with lock held
// returns with lock released
static int syncpage(page_t *page) {
__assert(page->flags & PAGE_FLAGS_DIRTY);
page->flags &= ~PAGE_FLAGS_DIRTY;
RELEASE_LOCK();
int e = 0;
if ((page->flags & PAGE_FLAGS_TRUNCATED) == 0) {
e = VOP_PUTPAGE(page->backing, page->offset, (page_t *)page);
VOP_RELEASE(page->backing);
}
pmm_release(pmm_getpageaddress((page_t *)page));
return e;
}
static page_t *dirtylist;
int vmmcache_syncvnode(vnode_t *vnode, uintmax_t offset, size_t size) {
offset = ROUND_DOWN(offset, PAGE_SIZE);
uintmax_t top = offset + size;
// overflow check
__assert(top > offset);
HOLD_LOCK();
// loop through all vnode pages in memory and check which ones are in the range and are dirty
// TODO create a proper vnode dirty list as to not have to loop through the ENTIRE thing in memory
page_t *page = vnode->pages;
page_t *vnodedirtylist = NULL;
for (; page; page = page->vnodenext) {
if (page->offset < offset || page->offset >= top)
continue;
// remove from write list and add to an internal list using the write pointers
// in a singly linked list way
if (page->writenext)
page->writenext->writeprev = page->writeprev;
if (page->writeprev)
page->writeprev->writenext = page->writenext;
else
dirtylist = page->writenext;
page->writenext = vnodedirtylist;
page->writeprev = NULL;
vnodedirtylist = page;
}
RELEASE_LOCK();
int e = 0;
while (vnodedirtylist) {
// in the case of failure, only the first error to occur will be reported and we will not
// retry the write and keep on syncing the pages to disk
HOLD_LOCK();
page_t *page = vnodedirtylist;
vnodedirtylist = vnodedirtylist->writenext;
page->writenext = NULL;
int error = syncpage(page);
if (e == 0)
e = error;
// syncpage returns with lock released
}
return e;
}
int vmmcache_sync() {
polldesc_t polldesc = {0};
int e = poll_initdesc(&polldesc, 1);
@@ -313,22 +374,13 @@ static void writer() {
continue;
}
__assert(page->flags & PAGE_FLAGS_DIRTY);
page->flags &= ~PAGE_FLAGS_DIRTY;
dirtylist = page->writenext;
if (dirtylist)
dirtylist->writeprev = NULL;
page->writenext = NULL;
RELEASE_LOCK();
if ((page->flags & PAGE_FLAGS_TRUNCATED) == 0) {
VOP_PUTPAGE(page->backing, page->offset, (page_t *)page);
VOP_RELEASE(page->backing);
}
pmm_release(pmm_getpageaddress((page_t *)page));
// TODO notify error on vmmcache_syncvnode
syncpage((page_t *)page);
}
}
+17
View File
@@ -6,3 +6,20 @@ syscallret_t syscall_sync(context_t *) {
vmmcache_sync();
return ret;
}
syscallret_t syscall_fsync(context_t *context, int fd) {
syscallret_t ret = {
.ret = -1
};
file_t *file = fd_get(fd);
if (file == NULL) {
ret.errno = EBADF;
return ret;
}
ret.errno = VOP_SYNC(file->vnode);
fd_release(file);
return ret;
}