This is an automated email from the ASF dual-hosted git repository. kasjer pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit a2dbdfdba69159ebe8c02e17ef89a3bde720aae5 Author: Jerzy Kasenberg <[email protected]> AuthorDate: Sat Jun 21 10:50:26 2025 +0200 fs: Introduce file system entity File system was represented by fs_ops that consisted of bunch of file system functions, name, and pointer to link file system ops in chain. Most of the date was constant and there is was no reason to waste RAM for callback pointer. This introduce file_system object that has ops but can be extended to hold file system specific data. Same file system ops can be used for more then one file system. File system can be mounted and that what littlefs and other file systems will. This change mostly changes filesystem_ops to const in most places. Signed-off-by: Jerzy Kasenberg <[email protected]> --- fs/fs/include/fs/fs_if.h | 78 +++++++++++++++++++++++---- fs/fs/pkg.yml | 3 -- fs/fs/src/fs_dirent.c | 19 ++++--- fs/fs/src/fs_file.c | 72 +++++++++++++------------ fs/fs/src/fs_mkdir.c | 25 ++++++--- fs/fs/src/fs_mount.c | 134 +++++++++++++++++++++++++++++++++++------------ fs/fs/src/fs_priv.h | 5 +- fs/fs/syscfg.yml | 7 +++ 8 files changed, 242 insertions(+), 101 deletions(-) diff --git a/fs/fs/include/fs/fs_if.h b/fs/fs/include/fs/fs_if.h index 567561f21..4dfa806de 100644 --- a/fs/fs/include/fs/fs_if.h +++ b/fs/fs/include/fs/fs_if.h @@ -26,6 +26,16 @@ extern "C" { #include "os/mynewt.h" +typedef struct file_system { + const struct fs_ops *ops; + const char *name; +} file_system_t; + +struct mount_point { + const char *mount_point; + const file_system_t *fs; +}; + /* * Common interface filesystem(s) provide. */ @@ -53,10 +63,8 @@ struct fs_ops { int (*f_dirent_name)(const struct fs_dirent *dirent, size_t max_len, char *out_name, uint8_t *out_name_len); int (*f_dirent_is_dir)(const struct fs_dirent *dirent); - - const char *f_name; - - SLIST_ENTRY(fs_ops) sc_next; + int (*f_mount)(const file_system_t *fs); + int (*f_umount)(const file_system_t *fs); }; struct fops_container { @@ -78,18 +86,68 @@ int fs_register(struct fs_ops *fops); * * @return fops if there's only one registered filesystem, NULL otherwise. */ -struct fs_ops *fs_ops_try_unique(void); +const struct fs_ops *fs_ops_try_unique(void); + +const struct fs_ops *fs_ops_from_container(struct fops_container *container); + +/** + * Mount file system + * + * @param fs - file system to mount + * @param path - path to mount i.e. 0:, nffs: + * @return 0 on success + */ +int fs_mount(const file_system_t *fs, const char *path); + +/** + * Unmount file system by mount point + * + * @param mount_point - mount point to unmount i.e. 0:, nffs: + * @return 0 on success + */ +const file_system_t *fs_unmount_mount_point(const char *mount_point); + +/** + * Unmount file system + * + * @param fs - mounted file system to unmount + * @return 0 on success + */ +int fs_unmount_file_system(const file_system_t *fs); /** - * Retrieve a filesystem's operations table + * Get file system mount point path + * + * For given path it will return mount point and file system + * i.e.: + * For 0:/DIREC/FIL.TXT function will return "0:" and fs + * will be filled with pointer to valid file_system_t structure. * - * @param name Name of the filesystem to retrieve fs_ops for + * @param path - file or directory name + * @param fs - on success file system + * @return file system mount point string + */ +const char *file_system_path(const char *path, const file_system_t **fs); + +/** + * Return the only file system mounted * - * @return valid pointer on success, NULL on failure + * It there is only one file system mounted it will be returned by this + * function. If two file system were mounted funciton will return NULL. + * @return non-NULL if exactly one file system is mounted, otherwise NULL */ -struct fs_ops *fs_ops_for(const char *name); +const file_system_t *get_only_file_system(void); -struct fs_ops *fs_ops_from_container(struct fops_container *container); +/** + * Get file system and file system mount point + * + * Usually + * @param path - file system path + * @param fs - file system for path + * @param fs_path - mount point (usually prefix of file path) + */ +void get_file_system_path(const char *path, const file_system_t **fs, + const char **fs_path); #ifdef __cplusplus } diff --git a/fs/fs/pkg.yml b/fs/fs/pkg.yml index 10c68746e..fc3e1eeaa 100644 --- a/fs/fs/pkg.yml +++ b/fs/fs/pkg.yml @@ -26,9 +26,6 @@ pkg.keywords: - filesystem - ffs -pkg.deps: - - "@apache-mynewt-core/fs/disk" - pkg.deps.FS_CLI: - "@apache-mynewt-core/sys/shell" diff --git a/fs/fs/src/fs_dirent.c b/fs/fs/src/fs_dirent.c index c9e46369b..306a82258 100644 --- a/fs/fs/src/fs_dirent.c +++ b/fs/fs/src/fs_dirent.c @@ -22,13 +22,13 @@ struct fs_ops *fops_from_filename(const char *); -static struct fs_ops * +static const struct fs_ops * fops_from_dir(const struct fs_dir *dir) { return fs_ops_from_container((struct fops_container *) dir); } -static inline struct fs_ops * +static inline const struct fs_ops * fops_from_dirent(const struct fs_dirent *dirent) { return fs_ops_from_container((struct fops_container *) dirent); @@ -37,21 +37,24 @@ fops_from_dirent(const struct fs_dirent *dirent) int fs_opendir(const char *path, struct fs_dir **out_dir) { - struct fs_ops *fops = fops_from_filename(path); - return fops->f_opendir(path, out_dir); + const file_system_t *fs; + const char *fs_path; + get_file_system_path(path, &fs, &fs_path); + + return fs->ops->f_opendir(fs_path, out_dir); } int fs_readdir(struct fs_dir *dir, struct fs_dirent **out_dirent) { - struct fs_ops *fops = fops_from_dir(dir); + const struct fs_ops *fops = fops_from_dir(dir); return fops->f_readdir(dir, out_dirent); } int fs_closedir(struct fs_dir *dir) { - struct fs_ops *fops = fops_from_dir(dir); + const struct fs_ops *fops = fops_from_dir(dir); return fops->f_closedir(dir); } @@ -59,13 +62,13 @@ int fs_dirent_name(const struct fs_dirent *dirent, size_t max_len, char *out_name, uint8_t *out_name_len) { - struct fs_ops *fops = fops_from_dirent(dirent); + const struct fs_ops *fops = fops_from_dirent(dirent); return fops->f_dirent_name(dirent, max_len, out_name, out_name_len); } int fs_dirent_is_dir(const struct fs_dirent *dirent) { - struct fs_ops *fops = fops_from_dirent(dirent); + const struct fs_ops *fops = fops_from_dirent(dirent); return fops->f_dirent_is_dir(dirent); } diff --git a/fs/fs/src/fs_file.c b/fs/fs/src/fs_file.c index 320a4eacc..33fee7df4 100644 --- a/fs/fs/src/fs_file.c +++ b/fs/fs/src/fs_file.c @@ -19,7 +19,6 @@ #include <fs/fs.h> #include <fs/fs_if.h> -#include <disk/disk.h> #include <string.h> #include <stdlib.h> @@ -123,7 +122,7 @@ fake_dirent_is_dir(const struct fs_dirent *dirent) return FS_EUNINIT; } -struct fs_ops not_initialized_ops = { +const struct fs_ops not_initialized_ops = { .f_open = &fake_open, .f_close = &fake_close, .f_read = &fake_read, @@ -140,13 +139,17 @@ struct fs_ops not_initialized_ops = { .f_closedir = &fake_closedir, .f_dirent_name = &fake_dirent_name, .f_dirent_is_dir = &fake_dirent_is_dir, - .f_name = "fakefs", }; -struct fs_ops * +const file_system_t fake_fs = { + .ops = ¬_initialized_ops, + .name = "fakefs", +}; + +const struct fs_ops * safe_fs_ops_for(const char *fs_name) { - struct fs_ops *fops; + const struct fs_ops *fops; fops = fs_ops_for(fs_name); if (fops == NULL) { @@ -156,31 +159,20 @@ safe_fs_ops_for(const char *fs_name) return fops; } -struct fs_ops * -fops_from_filename(const char *filename) -{ - char *disk; - char *fs_name = NULL; - struct fs_ops *unique; - - disk = disk_name_from_path(filename); - if (disk) { - fs_name = disk_fs_for(disk); - free(disk); - } else { - /** - * special case: if only one fs was ever registered, - * return that fs' ops. - */ - if ((unique = fs_ops_try_unique()) != NULL) { - return unique; +void +get_file_system_path(const char *path, const file_system_t **fs, const char **fs_path) +{ + *fs_path = file_system_path(path, fs); + if (*fs_path == NULL) { + *fs = get_only_file_system(); + if (*fs == NULL) { + *fs = &fake_fs; } + *fs_path = path; } - - return safe_fs_ops_for(fs_name); } -static inline struct fs_ops * +static inline const struct fs_ops * fops_from_file(const struct fs_file *file) { return fs_ops_from_container((struct fops_container *) file); @@ -189,62 +181,68 @@ fops_from_file(const struct fs_file *file) int fs_open(const char *filename, uint8_t access_flags, struct fs_file **out_file) { - struct fs_ops *fops = fops_from_filename(filename); - return fops->f_open(filename, access_flags, out_file); + const file_system_t *fs; + const char *fs_filename; + + get_file_system_path(filename, &fs, &fs_filename); + return fs->ops->f_open(fs_filename, access_flags, out_file); } int fs_close(struct fs_file *file) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_close(file); } int fs_read(struct fs_file *file, uint32_t len, void *out_data, uint32_t *out_len) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_read(file, len, out_data, out_len); } int fs_write(struct fs_file *file, const void *data, int len) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_write(file, data, len); } int fs_seek(struct fs_file *file, uint32_t offset) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_seek(file, offset); } uint32_t fs_getpos(const struct fs_file *file) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_getpos(file); } int fs_filelen(const struct fs_file *file, uint32_t *out_len) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_filelen(file, out_len); } int fs_unlink(const char *filename) { - struct fs_ops *fops = fops_from_filename(filename); - return fops->f_unlink(filename); + const file_system_t *fs; + const char *fs_filename; + + get_file_system_path(filename, &fs, &fs_filename); + return fs->ops->f_unlink(fs_filename); } int fs_flush(struct fs_file *file) { - struct fs_ops *fops = fops_from_file(file); + const struct fs_ops *fops = fops_from_file(file); return fops->f_flush(file); } diff --git a/fs/fs/src/fs_mkdir.c b/fs/fs/src/fs_mkdir.c index aca27f59f..223b5527b 100644 --- a/fs/fs/src/fs_mkdir.c +++ b/fs/fs/src/fs_mkdir.c @@ -21,18 +21,31 @@ #include "fs_priv.h" -struct fs_ops *fops_from_filename(const char *); - int fs_rename(const char *from, const char *to) { - struct fs_ops *fops = fops_from_filename(from); - return fops->f_rename(from, to); + const file_system_t *fs1; + const file_system_t *fs2; + const char *fs_from; + const char *fs_to; + + get_file_system_path(from, &fs1, &fs_from); + get_file_system_path(to, &fs2, &fs_to); + + if (fs1 == fs2) { + return fs1->ops->f_rename(fs_from, fs_to); + } + + return FS_EINVAL; } int fs_mkdir(const char *path) { - struct fs_ops *fops = fops_from_filename(path); - return fops->f_mkdir(path); + const file_system_t *fs; + const char *fs_path; + + get_file_system_path(path, &fs, &fs_path); + + return fs->ops->f_mkdir(fs_path); } diff --git a/fs/fs/src/fs_mount.c b/fs/fs/src/fs_mount.c index c687cf47c..567c1f469 100644 --- a/fs/fs/src/fs_mount.c +++ b/fs/fs/src/fs_mount.c @@ -26,68 +26,134 @@ #include <fs_mgmt/fs_mgmt.h> #endif -static SLIST_HEAD(, fs_ops) root_fops = SLIST_HEAD_INITIALIZER(); +#define MAX_MOUNT_POINTS MYNEWT_VAL_FS_MAX_MOUNT_POINTS -#if MYNEWT_VAL(FS_MGMT) -static uint8_t g_mgmt_initialized; -#endif +struct mount_point mount_points[MAX_MOUNT_POINTS]; int -fs_register(struct fs_ops *fops) +fs_mount(const file_system_t *fs, const char *mount_point) { - struct fs_ops *sc; + int free_slot = -1; + int rc = FS_EOK; - SLIST_FOREACH(sc, &root_fops, sc_next) { - if (strcmp(sc->f_name, fops->f_name) == 0) { - return FS_EEXIST; + for (int i = 0; i < ARRAY_SIZE(mount_points); ++i) { + if (mount_points[i].mount_point == NULL) { + if (free_slot < 0) { + free_slot = i; + } + } else if (strcmp(mount_point, mount_points[i].mount_point) == 0) { + rc = FS_EEXIST; + goto end; + } + } + if (free_slot >= 0) { + mount_points[free_slot].mount_point = mount_point; + mount_points[free_slot].fs = fs; + rc = fs->ops->f_mount ? fs->ops->f_mount(fs) : 0; + if (rc) { + mount_points[free_slot].mount_point = NULL; + mount_points[free_slot].fs = NULL; } + } else { + rc = FS_ENOMEM; } +end: + return rc; +} - SLIST_INSERT_HEAD(&root_fops, fops, sc_next); +const file_system_t * +fs_unmount_mount_point(const char *mount_point) +{ + const file_system_t *fs = NULL; + + for (int i = 0; i < ARRAY_SIZE(mount_points); ++i) { + if (strcmp(mount_point, mount_points[i].mount_point) == 0) { + fs = mount_points[i].fs; + mount_points[i].mount_point = NULL; + mount_points[i].fs = NULL; + break; + } + } -#if MYNEWT_VAL(FS_MGMT) - if (!g_mgmt_initialized) { - fs_mgmt_register_group(); - g_mgmt_initialized = 1; + return fs; +} + +int +fs_unmount_file_system(const file_system_t *fs) +{ + int rc = FS_EINVAL; + + for (int i = 0; i < ARRAY_SIZE(mount_points); ++i) { + if (mount_points[i].fs == fs) { + mount_points[i].mount_point = NULL; + mount_points[i].fs = NULL; + rc = 0; + break; + } } + + return rc; +} + +#if MYNEWT_VAL(FS_MGMT) +static uint8_t g_mgmt_initialized; #endif - return FS_EOK; +int +fs_register(struct fs_ops *fops) +{ + return FS_EINVAL; } -struct fs_ops * -fs_ops_try_unique(void) +const file_system_t * +get_only_file_system(void) { - struct fs_ops *fops = SLIST_FIRST(&root_fops); + const file_system_t *fs = NULL; - if (fops && !SLIST_NEXT(fops, sc_next)) { - return fops; + for (int i = 0; i < ARRAY_SIZE(mount_points); ++i) { + if (mount_points[i].mount_point == NULL) { + continue; + } + if (fs != NULL) { + fs = NULL; + break; + } + fs = mount_points[i].fs; } - return NULL; + return fs; } -struct fs_ops * -fs_ops_for(const char *fs_name) +const char * +file_system_path(const char *uri, const file_system_t **fs) { - struct fs_ops *fops = NULL; - struct fs_ops *sc; - - if (fs_name) { - SLIST_FOREACH(sc, &root_fops, sc_next) { - if (strcmp(sc->f_name, fs_name) == 0) { - fops = sc; + const char *fs_path = NULL; + const char *m; + + for (int i = 0; i < ARRAY_SIZE(mount_points); ++i) { + if (mount_points[i].mount_point != NULL) { + fs_path = uri; + m = mount_points[i].mount_point; + while (*fs_path == *m) { + ++fs_path; + ++m; + } + /* Reached end of mount point path ? */ + if (*m == '\0') { + if (fs) { + *fs = mount_points[i].fs; + } break; } + fs_path = NULL; } } - - return fops; + return fs_path; } -extern struct fs_ops not_initialized_ops; +extern const struct fs_ops not_initialized_ops; -struct fs_ops * +const struct fs_ops * fs_ops_from_container(struct fops_container *container) { if (!container) { diff --git a/fs/fs/src/fs_priv.h b/fs/fs/src/fs_priv.h index d5138c938..a336e2893 100644 --- a/fs/fs/src/fs_priv.h +++ b/fs/fs/src/fs_priv.h @@ -26,9 +26,8 @@ extern "C" { #endif struct fs_ops; -struct fs_ops *fs_ops_for(const char *fs_name); -struct fs_ops *safe_fs_ops_for(const char *fs_name); - +const struct fs_ops *fs_ops_for(const char *fs_name); +const struct fs_ops *safe_fs_ops_for(const char *fs_name); #ifdef __cplusplus } diff --git a/fs/fs/syscfg.yml b/fs/fs/syscfg.yml index cc676340c..4cf97388f 100644 --- a/fs/fs/syscfg.yml +++ b/fs/fs/syscfg.yml @@ -27,6 +27,13 @@ syscfg.defs: description: 'Enables file system mgmt commands.' value: 0 + FS_MAX_MOUNT_POINTS: + description: > + Number of mount point tha can be used. + There should be one mount point for each file system that + could be mounted. + value: 2 + FS_UPLOAD_MAX_CHUNK_SIZE: description: > The maximum amount of file data that can fit in a
