From b40a6b3fa89a54805299d6c35133f3c975f58514 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Tue, 1 Apr 2025 21:06:55 +0200 Subject: [PATCH] fs: prepare Fygue integration --- include/gint/fs.h | 14 ++++++++++++++ src/fs/close.c | 11 +++++++++-- src/fs/fdopendir.c | 2 +- src/fs/fs.c | 32 ++++++++++++++++++++++++++++++++ src/fs/fugue/fugue.h | 1 - src/fs/fygue/fygue.h | 26 ++++++++++++++++++++++++++ src/fs/lseek.c | 12 ++++++++---- src/fs/mkdir.c | 4 +++- src/fs/open.c | 21 +++++++++++++++++++-- src/fs/read.c | 11 +++++++---- src/fs/rename.c | 5 ++++- src/fs/rmdir.c | 4 +++- src/fs/stat.c | 8 +++++--- src/fs/unlink.c | 5 ++++- src/fs/write.c | 13 ++++++++----- 15 files changed, 143 insertions(+), 26 deletions(-) create mode 100644 src/fs/fygue/fygue.h diff --git a/include/gint/fs.h b/include/gint/fs.h index 6831dd2..b46d447 100644 --- a/include/gint/fs.h +++ b/include/gint/fs.h @@ -9,6 +9,7 @@ extern "C" { #endif +#include #include #include @@ -100,6 +101,19 @@ char *fs_path_normalize(char const *path); calls to BFile. */ uint16_t *fs_path_normalize_fc(char const *path); +/* return True if the provided descriptor is a directory one */ +bool fs_descriptor_is_dir(fs_descriptor_t const *data); + +/* return True if the provided descriptor is a Fugue one */ +bool fs_descriptor_is_fugue(fs_descriptor_t const *data); + +/* return True if the provided descriptor is a Fygue one */ +bool fs_descriptor_is_fygue(fs_descriptor_t const *data); + +/* workaround to keep Fygue filesystem sync */ +//TODO: (re?)move me +void fs_fygue_sync(void); + #ifdef __cplusplus } #endif diff --git a/src/fs/close.c b/src/fs/close.c index 88c96bf..a67293c 100644 --- a/src/fs/close.c +++ b/src/fs/close.c @@ -11,9 +11,16 @@ int close(int fd) } int rc = 0; - if(d->type->close) - rc = d->type->close(d->data); + if(d->type->close == NULL) + goto end; + /* Fugue's close primitive can flush pending IO write operation. So, we + * are in the same situation than the write() primitive: force-sync + * Fygue's descriptor to ensure data intergrity */ + rc = d->type->close(d->data); + if (fs_descriptor_is_fugue(d)) + fs_fygue_sync(); +end: fs_free_descriptor(fd); return rc; } diff --git a/src/fs/fdopendir.c b/src/fs/fdopendir.c index 62e3547..c4360b2 100644 --- a/src/fs/fdopendir.c +++ b/src/fs/fdopendir.c @@ -11,7 +11,7 @@ DIR *fdopendir(int fd) errno = EBADF; return NULL; } - if(desc->type != &fugue_dir_descriptor_type) { + if(!fs_descriptor_is_dir(desc)) { errno = ENOTDIR; return NULL; } diff --git a/src/fs/fs.c b/src/fs/fs.c index 5bea0db..8b96d76 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -3,6 +3,8 @@ #include #include #include +#include "fugue/fugue.h" +#include "fygue/fygue.h" /* File descriptor table */ static fs_descriptor_t *fdtable; @@ -42,6 +44,36 @@ void fs_free_descriptor(int fd) fdtable[fd].data = NULL; } +//--- +// Utils +//--- + +bool fs_descriptor_is_fugue(fs_descriptor_t const *desc) +{ + return ( + (desc->type == &fugue_dir_descriptor_type) || + (desc->type == &fugue_descriptor_type) + ); +} + +bool fs_descriptor_is_fygue(fs_descriptor_t const *desc) +{ + return ( + (desc->type == &fygue_dir_descriptor_type) || + (desc->type == &fygue_descriptor_type) + ); +} + +void fs_fygue_sync(void) +{ + for (int i = 3 ; i < FS_FD_MAX ; i++) { + if (fdtable[i].type == NULL) + continue; + if (fs_descriptor_is_fygue(fdtable[i].data)) + fygue_syncfs(fdtable[i].data); + } +} + int open_generic(fs_descriptor_type_t const *type, void *data, int fd) { if(!fdtable) { diff --git a/src/fs/fugue/fugue.h b/src/fs/fugue/fugue.h index 54e659c..d9f32c3 100644 --- a/src/fs/fugue/fugue.h +++ b/src/fs/fugue/fugue.h @@ -31,7 +31,6 @@ int fugue_mkdir(char const *path, mode_t mode); int fugue_rmdir(char const *path); -int fugue_stat(char const * restrict path, struct stat * restrict statbuf); /* Other functions */ diff --git a/src/fs/fygue/fygue.h b/src/fs/fygue/fygue.h new file mode 100644 index 0000000..bda8de8 --- /dev/null +++ b/src/fs/fygue/fygue.h @@ -0,0 +1,26 @@ +#ifndef FS_FYGUE_H +#define FS_FYGUE_H 1 + +#include +#include +#include +#include +#include + +/* File descriptor type */ +extern const fs_descriptor_type_t fygue_descriptor_type; +/* Directory descriptor type */ +extern const fs_descriptor_type_t fygue_dir_descriptor_type; + +/* Specific implementations of some standard functions */ + +extern int fygue_open(char const *path, int flags, mode_t mode); + +extern int fygue_stat( + char const * restrict path, + struct stat * restrict statbuf +); + +extern int fygue_syncfs(void *desc); + +#endif /* FS_FYGUE_H */ diff --git a/src/fs/lseek.c b/src/fs/lseek.c index c277c8b..efb94fc 100644 --- a/src/fs/lseek.c +++ b/src/fs/lseek.c @@ -15,9 +15,13 @@ off_t lseek(int fd, off_t offset, int whence) return (ssize_t)-1; } - if(d->type->lseek) - return d->type->lseek(d->data, offset, whence); - /* No seek function: cannot seek */ - return 0; + if(d->type->lseek == NULL) + return 0; + /* BFile_Seek() can flush pending IO write operations. Sync Fygue's + * descriptor to avoid data corruption */ + off_t off = d->type->lseek(d->data, offset, whence); + if (fs_descriptor_is_fugue(d)) + fs_fygue_sync(); + return off; } diff --git a/src/fs/mkdir.c b/src/fs/mkdir.c index 08940eb..88c6b18 100644 --- a/src/fs/mkdir.c +++ b/src/fs/mkdir.c @@ -4,5 +4,7 @@ int mkdir(char const *path, mode_t mode) { /* Standard mkdir() is the Fugue filesystem only */ - return fugue_mkdir(path, mode); + int rc = fugue_mkdir(path, mode); + fs_fygue_sync(); + return rc; } diff --git a/src/fs/open.c b/src/fs/open.c index 03b82f9..9a2cbed 100644 --- a/src/fs/open.c +++ b/src/fs/open.c @@ -1,6 +1,7 @@ #include #include #include "fugue/fugue.h" +#include "fygue/fygue.h" int open(char const *path, int flags, ...) { @@ -9,6 +10,22 @@ int open(char const *path, int flags, ...) mode_t mode = va_arg(args, int); va_end(args); - /* Standard open() is the Fugue filesystem only */ - return fugue_open(path, flags, mode); + /* Standard open() use Fugue filesystem if a write operation + * is requested, otherwise use the Fygue filesystem */ + int rc = 0; + if ((flags & O_WRONLY) || (flags & O_RDWR)) { + rc = fugue_open(path, flags, mode); + } else { + rc = fygue_open(path, flags, mode); + } + /* Even with Fygue open primitive, request a sync for all Fygue's + * descriptor because when some flags are set (e.g O_CREATE) Fygue + * invoke BFile_*() syscall that perform IO operation. + * + * Note that Fygue's open() primitive with perform a "lazy" open operation + * by simply ensure that the file exists and mark the file descriptor as + * dirty to force internal data refresh on the next Fygue's IO + * operation */ + fs_fygue_sync(); + return rc; } diff --git a/src/fs/read.c b/src/fs/read.c index e214719..f75b608 100644 --- a/src/fs/read.c +++ b/src/fs/read.c @@ -10,9 +10,12 @@ ssize_t read(int fd, void *buf, size_t size) return (ssize_t)-1; } - if(d->type->read) - return d->type->read(d->data, buf, size); - /* No read function: we can't read anything */ - return 0; + if(d->type->read == NULL) + return 0; + /* BFile_Read() can flush data in some circumstances, force-sync Fygue */ + ssize_t rc = d->type->read(d->data, buf, size); + if (fs_descriptor_is_fugue(d)) + fs_fygue_sync(); + return rc; } diff --git a/src/fs/rename.c b/src/fs/rename.c index 3c20b88..073f720 100644 --- a/src/fs/rename.c +++ b/src/fs/rename.c @@ -1,8 +1,11 @@ #include +#include #include "fugue/fugue.h" int rename(char const *oldpath, char const *newpath) { /* Standard rename() is the Fugue filesystem only */ - return fugue_rename(oldpath, newpath); + int rc = fugue_rename(oldpath, newpath); + fs_fygue_sync(); + return rc; } diff --git a/src/fs/rmdir.c b/src/fs/rmdir.c index ef2c9b7..b99e321 100644 --- a/src/fs/rmdir.c +++ b/src/fs/rmdir.c @@ -4,5 +4,7 @@ int rmdir(char const *path) { /* Standard rmdir() is the Fugue filesystem only */ - return fugue_rmdir(path); + int rc = fugue_rmdir(path); + fs_fygue_sync(); + return rc; } diff --git a/src/fs/stat.c b/src/fs/stat.c index 872e6c1..eb9ad83 100644 --- a/src/fs/stat.c +++ b/src/fs/stat.c @@ -1,8 +1,10 @@ #include -#include "fugue/fugue.h" +#include "fygue/fygue.h" int stat(char const * restrict path, struct stat * restrict statbuf) { - /* Standard stat() is the Fugue filesystem only */ - return fugue_stat(path, statbuf); + /* Standard stat() is also provided by Fugue, but rely on Casio's + * syscall which do not provide all of the information and request + * a world-switch (internally) to works */ + return fygue_stat(path, statbuf); } diff --git a/src/fs/unlink.c b/src/fs/unlink.c index cb43104..9075fed 100644 --- a/src/fs/unlink.c +++ b/src/fs/unlink.c @@ -1,8 +1,11 @@ #include +#include #include "fugue/fugue.h" int unlink(char const *path) { /* Standard unlink() is the Fugue filesystem only */ - return fugue_unlink(path); + int rc = fugue_unlink(path); + fs_fygue_sync(); + return rc; } diff --git a/src/fs/write.c b/src/fs/write.c index 8ce994c..0df7e69 100644 --- a/src/fs/write.c +++ b/src/fs/write.c @@ -9,10 +9,13 @@ ssize_t write(int fd, const void *buf, size_t size) errno = EBADF; return (ssize_t)-1; } - - if(d->type->write) - return d->type->write(d->data, buf, size); - /* No write function: discard the contents but show no error */ - return size; + if(d->type->write == NULL) + return 0; + /* A special synchronisation must be performed to ensure that all + * Fygue's descriptor meta information are valid */ + size = d->type->write(d->data, buf, size); + if (fs_descriptor_is_fugue(d)) + fs_fygue_sync(); + return size; }