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_uname
extern syscall_hostname extern syscall_hostname
extern syscall_sync extern syscall_sync
extern syscall_fsync
syscalltab: syscalltab:
dq syscall_print dq syscall_print
dq syscall_mmap dq syscall_mmap
@@ -132,7 +133,8 @@ dq syscall_sigreturn
dq syscall_uname dq syscall_uname
dq syscall_hostname dq syscall_hostname
dq syscall_sync dq syscall_sync
syscallcount equ 66 dq syscall_fsync
syscallcount equ 67
section .text section .text
global arch_syscall_entry global arch_syscall_entry
; on entry: ; on entry:
+5 -3
View File
@@ -4,7 +4,7 @@
#ifdef SYSCALL_LOGGING #ifdef SYSCALL_LOGGING
#define SYSCALL_COUNT 66 #define SYSCALL_COUNT 67
#define LOGSTR(x) arch_e9_puts(x) #define LOGSTR(x) arch_e9_puts(x)
static char *name[] = { static char *name[] = {
@@ -73,7 +73,8 @@ static char *name[] = {
"sigreturn", "sigreturn",
"uname", "uname",
"hostname", "hostname",
"sync" "sync",
"fsync"
}; };
static char *args[] = { static char *args[] = {
@@ -142,7 +143,8 @@ static char *args[] = {
"N/A", // sigreturn "N/A", // sigreturn
"utsname %p", // uname "utsname %p", // uname
"new %p newsize %lu old %p oldsize %lu", // hostname "new %p newsize %lu old %p oldsize %lu", // hostname
"N/A" // sync "N/A", // sync
"fd %d" // fsync
}; };
#endif #endif
+11 -1
View File
@@ -1654,6 +1654,15 @@ static int ext2_rename(vnode_t *sourcedir, char *oldname, vnode_t *targetdir, ch
return err; 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) { static int ext2_inactive(vnode_t *vnode) {
ext2node_t *node = (ext2node_t *)vnode; ext2node_t *node = (ext2node_t *)vnode;
ext2fs_t *fs = (ext2fs_t *)vnode->vfs; ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
@@ -1829,7 +1838,8 @@ static vops_t vnops = {
.inactive = ext2_inactive, .inactive = ext2_inactive,
.rename = ext2_rename, .rename = ext2_rename,
.getpage = ext2_getpage, .getpage = ext2_getpage,
.putpage = ext2_putpage .putpage = ext2_putpage,
.sync = ext2_sync
}; };
void ext2_init() { void ext2_init() {
+2 -1
View File
@@ -260,7 +260,8 @@ static vops_t vnops = {
.resize = pipefs_enodev, .resize = pipefs_enodev,
.rename = pipefs_enodev, .rename = pipefs_enodev,
.putpage = pipefs_enodev, .putpage = pipefs_enodev,
.getpage = pipefs_enodev .getpage = pipefs_enodev,
.sync = pipefs_enodev
}; };
static void ctor(scache_t *cache, void *obj) { static void ctor(scache_t *cache, void *obj) {
+2 -1
View File
@@ -186,7 +186,8 @@ static vops_t vnops = {
.rename = sockfs_enodev, .rename = sockfs_enodev,
.ioctl = sockfs_ioctl, .ioctl = sockfs_ioctl,
.putpage = sockfs_enodev, .putpage = sockfs_enodev,
.getpage = sockfs_enodev .getpage = sockfs_enodev,
.sync = sockfs_enodev
}; };
static void ctor(scache_t *cache, void *obj) { 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; return 0;
} }
static int tmpfs_sync(vnode_t *node) {
// sync is a no-op on tmpfs
return 0;
}
static vfsops_t vfsops = { static vfsops_t vfsops = {
.mount = tmpfs_mount, .mount = tmpfs_mount,
.root = tmpfs_root .root = tmpfs_root
@@ -520,7 +525,8 @@ static vops_t vnops = {
.resize = tmpfs_resize, .resize = tmpfs_resize,
.rename = tmpfs_rename, .rename = tmpfs_rename,
.getpage = tmpfs_getpage, .getpage = tmpfs_getpage,
.putpage = tmpfs_putpage .putpage = tmpfs_putpage,
.sync = tmpfs_sync
}; };
static tmpfsnode_t *newnode(vfs_t *vfs, int type) { 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 (*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 (*getpage)(vnode_t *node, uintmax_t offset, struct page_t *page);
int (*putpage)(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; } vops_t;
#define VFS_INIT(v, o, f) \ #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_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_GETPAGE(v, o, p) (v)->ops->getpage(v, o, p)
#define VOP_PUTPAGE(v, o, p) (v)->ops->putpage(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_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST)
#define VOP_RELEASE(v) {\ #define VOP_RELEASE(v) {\
if (__atomic_sub_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\ 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_takepage(page_t *page);
int vmmcache_makedirty(page_t *page); int vmmcache_makedirty(page_t *page);
int vmmcache_truncate(vnode_t *vnode, uintmax_t offset); 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(); int vmmcache_sync();
#endif #endif
+65 -13
View File
@@ -232,12 +232,73 @@ int vmmcache_truncate(vnode_t *vnode, uintmax_t offset) {
return 0; return 0;
} }
int vmmcache_syncvnode(vnode_t *vnode) { // called with lock held
__assert(!"unimplemented"); // 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; 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() { int vmmcache_sync() {
polldesc_t polldesc = {0}; polldesc_t polldesc = {0};
int e = poll_initdesc(&polldesc, 1); int e = poll_initdesc(&polldesc, 1);
@@ -313,22 +374,13 @@ static void writer() {
continue; continue;
} }
__assert(page->flags & PAGE_FLAGS_DIRTY);
page->flags &= ~PAGE_FLAGS_DIRTY;
dirtylist = page->writenext; dirtylist = page->writenext;
if (dirtylist) if (dirtylist)
dirtylist->writeprev = NULL; dirtylist->writeprev = NULL;
page->writenext = NULL; page->writenext = NULL;
// TODO notify error on vmmcache_syncvnode
RELEASE_LOCK(); syncpage((page_t *)page);
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));
} }
} }
+17
View File
@@ -6,3 +6,20 @@ syscallret_t syscall_sync(context_t *) {
vmmcache_sync(); vmmcache_sync();
return ret; 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;
}
+16 -16
View File
@@ -192,10 +192,10 @@ index 0000000..e5b087a
+ +
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
new file mode 100644 new file mode 100644
index 0000000..12da52c index 0000000..e94f84f
--- /dev/null --- /dev/null
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
@@ -0,0 +1,695 @@ @@ -0,0 +1,694 @@
+#include <bits/ensure.h> +#include <bits/ensure.h>
+#include <mlibc/debug.hpp> +#include <mlibc/debug.hpp>
+#include <mlibc/all-sysdeps.hpp> +#include <mlibc/all-sysdeps.hpp>
@@ -248,8 +248,7 @@ index 0000000..12da52c
+} +}
+#endif +#endif
+ +
+namespace mlibc { +namespace mlibc {
+
+ int sys_setuid(uid_t id) { + int sys_setuid(uid_t id) {
+ // TODO UNSTUB + // TODO UNSTUB
+ return 0; + return 0;
@@ -279,6 +278,16 @@ index 0000000..12da52c
+ // TODO UNSTUB + // TODO UNSTUB
+ return 0; + return 0;
+ } + }
+
+ int sys_setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) {
+ // TODO unstub
+ return ENOSYS;
+ }
+
+ int sys_fsync(int fd) {
+ long ret;
+ return syscall(SYSCALL_FSYNC, &ret, fd);
+ }
+ +
+ pid_t sys_getppid() { + pid_t sys_getppid() {
+ long ret; + long ret;
@@ -320,16 +329,6 @@ index 0000000..12da52c
+ syscall(SYSCALL_SYNC, &ret); + syscall(SYSCALL_SYNC, &ret);
+ } + }
+ +
+ int sys_fsync(int fd) {
+ // TODO as the VFS does not do caching as of yet, this system call is stubbed and should be implemented once caching is done
+ return 0;
+ }
+
+ int sys_setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) {
+ // TODO unstub
+ return ENOSYS;
+ }
+
+ #ifndef MLIBC_BUILDING_RTLD + #ifndef MLIBC_BUILDING_RTLD
+ int sys_getentropy(void *buffer, size_t length) { + int sys_getentropy(void *buffer, size_t length) {
+ int fd; + int fd;
@@ -910,10 +909,10 @@ index 0000000..990eca0
+#endif +#endif
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
new file mode 100644 new file mode 100644
index 0000000..7daaf11 index 0000000..5148ce4
--- /dev/null --- /dev/null
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
@@ -0,0 +1,89 @@ @@ -0,0 +1,90 @@
+#ifndef _SYSCALL_H_INCLUDE +#ifndef _SYSCALL_H_INCLUDE
+#define _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE
+ +
@@ -983,6 +982,7 @@ index 0000000..7daaf11
+#define SYSCALL_UNAME 63 +#define SYSCALL_UNAME 63
+#define SYSCALL_HOSTNAME 64 +#define SYSCALL_HOSTNAME 64
+#define SYSCALL_SYNC 65 +#define SYSCALL_SYNC 65
+#define SYSCALL_FSYNC 66
+ +
+#include <stddef.h> +#include <stddef.h>
+#include <stdint.h> +#include <stdint.h>