Fork me on GitHub

VFS

The VFS layer implements virtual file system interface, allowing to attach different storage types into a single file system tree.

C API Reference mgos_vfs.h

#include "mgos_vfs.h"

VFS subsystem multiplexes calls to libc file API methods such as open, read, write and close between (potentially) several filesystems attached at different mount points. A filesystem is backed by a device which supports block reads and writes.


struct mgos_vfs_fs {
  int refs;
  const char *type;
  const struct mgos_vfs_fs_ops *ops;
  struct mgos_vfs_dev *dev;
  void *fs_data;
};

extern struct mgos_vfs_mmap_desc *mgos_vfs_mmap_descs;

#define MMAP_DESC_FROM_ADDR(addr)                                 \
  (&mgos_vfs_mmap_descs[(((uintptr_t)(addr)) >> MMAP_ADDR_BITS) & \
                        MMAP_NUM_MASK])
#define MMAP_ADDR_FROM_ADDR(addr) (((uintptr_t)(addr)) & MMAP_ADDR_MASK)

#define MMAP_BASE_FROM_DESC(desc)    \
  ((void *) ((uintptr_t) MMAP_BASE | \
             (((desc) -mgos_vfs_mmap_descs) << MMAP_ADDR_BITS)))

struct mgos_vfs_mmap_desc {
  struct mgos_vfs_fs *fs;
  /* Address at which mmapped data is available */
  void *base;

  /* FS-specific data */
  void *fs_data;
};

We need to declare mgos_vfs_mmap_descs in order for MMAP_DESC_FROM_ADDR() and friends to work. We could use a function instead of that, but it's used on a critical path (reading each mmapped byte), so let it be.

struct mgos_vfs_mmap_desc {
  struct mgos_vfs_fs *fs;
  /* Address at which mmapped data is available */
  void *base;

  /* FS-specific data */
  void *fs_data;
};

void mgos_vfs_mmap_init(void);

int mgos_vfs_mmap_descs_cnt(void);

Returns total number of allocated mmap descriptors (not all of them might be used at the moment)

struct mgos_vfs_mmap_desc *mgos_vfs_mmap_desc_get(int idx);

Returns mmap descriptor at the given index

} DIR;
struct dirent {
  int d_ino;
  char d_name[256];
};

struct dirent {
  int d_ino;
  char d_name[256];
};

DIR *opendir(const char *path);

struct dirent *readdir(DIR *pdir);

int closedir(DIR *pdir);

struct mgos_vfs_fs_ops {
  /* Create a filesystem on the given device. Do not mount. */
  bool (*mkfs)(struct mgos_vfs_fs *fs, const char *opts);

VFS ops table. Filesystem implementation must provide all of these. Operatiosn that are not supported should return false or -1.

bool mgos_vfs_fs_register_type(const char *type,
                               const struct mgos_vfs_fs_ops *ops);

Register fielsystem type and make it available for use in mkfs and mount.

bool mgos_vfs_mkfs(const char *dev_type, const char *dev_opts,
                   const char *fs_type, const char *fs_opts);

Create a filesystem. First a device is opened with given type and options and then filesystem is created on it. Device and filesystem types must've been previosuly registered and options have device and filesystem-specific format and usually are JSON objects.

bool mgos_vfs_mount(const char *path, const char *dev_type,
                    const char *dev_opts, const char *fs_type,
                    const char *fs_opts);

Mount a filesystem. First a device is opened with given type and options and then filesystem is mounted from it and attached to the VFS at a given path. Path must start with a "/" and consist of one component, e.g. "/mnt". Nested mounts are not currently supported, so "/mnt/foo" is not ok. Device and filesystem types must've been previosly registered and options have device and filesystem-specific format and usually are JSON objects.

bool mgos_vfs_umount(const char *path);

Unmount a previously mounted filesystem. Only filesystems with no open files can be unmounted.

void mgos_vfs_umount_all(void);

Unmount all the filesystems, regardless of open files. Done only on reboot.

bool mgos_vfs_gc(const char *path);

Perform GC of a filesystem at the specified mountpoint.

bool mgos_vfs_hal_mount(const char *path, struct mgos_vfs_fs *fs);

Platform implementation must ensure that paths prefixed with "path" are routed to "fs" and file descriptors are translated appropriately.

char *mgos_realpath(const char *path, char *resolved_path);

Clean up path, see realpath(3).

int mgos_vfs_open(const char *filename, int flags, int mode);

libc API

int mgos_vfs_close(int vfd);

ssize_t mgos_vfs_read(int vfd, void *dst, size_t len);

ssize_t mgos_vfs_write(int vfd, const void *src, size_t len);

int mgos_vfs_stat(const char *path, struct stat *st);

int mgos_vfs_fstat(int vfd, struct stat *st);

off_t mgos_vfs_lseek(int vfd, off_t offset, int whence);

int mgos_vfs_unlink(const char *path);

int mgos_vfs_rename(const char *src, const char *dst);

DIR *mgos_vfs_opendir(const char *path);

struct dirent *mgos_vfs_readdir(DIR *pdir);

int mgos_vfs_closedir(DIR *pdir);