/* Copyright (C) 2005,2006 David Decotigny Copyright (C) 2000-2005 The KOS Team (Thomas Petazzoni, David Decotigny, Julien Munier) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SOS_FS_H_ #define _SOS_FS_H_ /** * @file fs.h * * (Virtual) Filesystem management. * * SOS provides a complete Unix-like file system service. Supported * features of this service are: * - mountpoints * - generic file system support (FS) through object-oriented * specialization (so-called VFS) * - hard & symbolic links * - regular files and directories * - block and character device special files (from article 9 onward) * - file mapping * - basic permission management ("rwx" only, no notion of owner) * - chroot * - separation of disk node and namespace notions allowing hard links * and to move/rename/remove files or directories that are in use * - basic FS interface (open/read/seek/creat/mkdir/rename/link * / symlink/chmod/mount/fcntl/ioctl...) * - deferred writes (ie file caching). @see sync(3) * * Among the unsupported features: * - no user-based permission (uid/gid, ACLS) * - no modification / access time accounting * - no Fifo/socket special files (yet) * - no generic support library for common fcntl commands * (F_SETOWN/GETLEASE/NOTIFY, etc.) * - no flock-style functions * * Rationale * ========= * The VFS layer is based on 3 central concepts: * * - The meta-information for each file stored on disk: size, * permissions, ... (struct sos_fs_node for SOS, inode for Unix) * * It is sufficient to know where this meta-information is located * on disk (a simple sector number most of the time) to build the * corresponding struct sos_fs_node into memory and to retrieve the * data of the file from the disk * * For example, consider that we know a sector that holds the meta * information is located at sector 64589 on disk. By retrieving * this meta information directly from disk, we can build the * struct sos_fs_node, which would (for example) tell that the * corresponding file spans (for example) over sectors 4345, 5645, * 4539 and 6575, is 1.7kB long * * Everything is stored this way on the disk, even the * directories. From the disk contents' point of view, a directory * is simply a file whose contents represent a list of mappings * "name" -> meta-information location * * - One or many nodes in the file hierarchy pointing to this data * (struct sos_fs_nscache_node for SOS, struct dentry for Linux). This * tells that the entry "toto" in directory "/home/zorglub" * corresponds to the given struct sos_fs_node * * Actually, with the struct sos_fs_node above, we can reach any * file in the system. However, dealing with mountpoints requires * an intermediary data structure because a directory on a disk * cannot make reference to children struct sos_fs_node on other * disk. This is one of the reasons why there is this struct * sos_fs_nscache_node. Another reason is that we kind-of "cache" the * most used struct sos_fs_node: those that lead from the global * root ("/") to the files and directories currently being used * (hence the name "nscache" for "namespace cache"). This speeds-up * the path-resolving process (aka "lookup"), as the most-used path * are already in-memory and the struct sos_fs_node are already * in-memory too. * * A struct sos_fs_nscache_node can have at most 1 parent (the ".." * entry). It can also have 0 parent in case the node is being used * by a process (file is opened or mapped), but the file is * actually "removed", ie un-reachable from any directory. * * Many such structures can reference the same underlying struct * sos_fs_node, which enables the support of "hard links". * * - The "opened file" strucures. They store the information * pertaining to a particular usage of a file. The most important * thing they store is the "file pointer", which holds the * location in the file where the next read/write operation should * start * * Each process has at least 2 such opened files: its "current * working directory" (RTFM chdir) and its "process root" (RTFM * chroot). Those are heritated across fork() and can be changed by * appropriate syscalls (resp. chdir/chroot). The main "root" of * the system is the process root of the "init" process. The usual * opened files (think of open() and opendir()) are stored in the * file descriptor array (fds[]). This is the index in this array * that is commonly called a "file descriptor". * * * The whole VFS layer comprises a series of objects that can be * specialized to implement different FS support (fat, ext2, ffs, ...): * * - The notion of "file system manager", which basically is a * container to a FS name (eg "FAT", "EXT2", etc...) and a series of * functions responsible for initializing a particular "mounting" of * a FS (the "mount" method). This is SOS's struct sos_fs_manager_type * * - The notion of "file system instance" which contains the data * proper to a particular mounting of an FS. Its most important job * is to allocate new struct sos_fs_node on disk, or to retrieve the * meta-information (ie struct sos_fs_node) located at the given * location on disk. This is roughly THE primary physical interface * between the VFS and the disks. This is SOS's struct * sos_fs_manager_instance, aka the Linux's superblock * * For each struct sos_fs_node that it allocates, or that is loads * from disk into memory, this "instance manager" is responsible * for inidicating the functions that implement the FS-dedicated * routine such as read/write/mmap/ioctl/... for this precise node. * * The nodes (struct sos_fs_node) of a struct * sos_fs_manager_instance that are currently loaded in memory are * stored in a hash-table. The key of this map is the location of the * meta-information on disk. That way, it is very fast to look for * the given meta-information whose location on disk is knows: if * it has already been loaded into memory, its memory address is * quickly resolved thanks to this hash table. */ #include #include #include #include /* Forward declarations (structures defined in this file) */ struct sos_fs_manager_type; struct sos_fs_manager_instance; struct sos_fs_statfs; struct sos_fs_node; struct sos_fs_opened_file; struct sos_fs_stat; #include "fs_nscache.h" #include /** * The type of filesystem object. * * Each struct sos_fs_node has a type. Here are the supported types. */ typedef enum { SOS_FS_NODE_REGULAR_FILE = 0x42, SOS_FS_NODE_DIRECTORY = 0x24, SOS_FS_NODE_SYMLINK = 0x84, SOS_FS_NODE_DEVICE_CHAR = 0x48, SOS_FS_NODE_DEVICE_BLOCK = 0x12 } sos_fs_node_type_t; #define SOS_FS_MANAGER_NAME_MAXLEN 32 /** * Description of a supported Filesystem type. * * These descriptions are listed in an internal list (see * fs.c:fs_list), and each time we want to mount a FS, we precise a * name (eg "FAT", "EXT2", ...). The VFS will look for this name into * the list of supported filesystem types, and, when found, call its * sos_fs_manager_type::mount() method. * * New filesystem types are registered using sos_fs_register_fs_type() */ struct sos_fs_manager_type { char name[SOS_FS_MANAGER_NAME_MAXLEN]; /** * Responsible for making sure the underlying device (if any) really * stores the correct filesystem format, for creating the hash of fs * nodes and for calling sos_fs_register_fs_instance * * @param device May be NULL * * @note mandatory, may block */ sos_ret_t (*mount)(struct sos_fs_manager_type * this, struct sos_fs_node * device, const char * args, struct sos_fs_manager_instance ** mounted_fs); /** * Responsible for de-allocating the hash of fs nodes and for * calling sos_fs_unregister_fs_instance * * @note mandatory, may block */ sos_ret_t (*umount)(struct sos_fs_manager_type * this, struct sos_fs_manager_instance * mounted_fs); /** Free of use */ void * custom_data; /** List of filesystem instances of this type currently mounted somewhere in the system */ struct sos_fs_manager_instance * instances; /** Linkage for the list of filesystem types registered in the system */ struct sos_fs_manager_type *prev, *next; }; /** * Data related to a particular "mounting" of a file system. A * so-called "superblock" under Linux * * This holds the FUNDAMENTAL functions responsible for loading struct * sos_fs_node from disk, or for allocating thom on disk. It also * holds the hash-table of struct sos_fs_node already loaded into * memory. */ struct sos_fs_manager_instance { /** * @note Publicly readable. Written only by sos_fs_manager_type::mount() */ struct sos_fs_manager_type * fs_type; /** * Usually, a filesystem relies on a device (disk, network, ram, * ...) to fetch its data. This is the location of the device. * * @note Publicly readable. Written only by fs.c */ struct sos_fs_node * device; #define SOS_FS_MOUNT_SYNC (1 << 0) #define SOS_FS_MOUNT_READONLY (1 << 1) #define SOS_FS_MOUNT_NOEXEC (1 << 2) /** * Is this FS read-only, without EXEC file permission, write-through * ? Or-red combination of the SOS_FS_MOUNT_ flags * * @note Publicly readable. Written only by fs.c */ sos_ui32_t flags; /** * The namespace node that is the root of THIS file system mounting * * @note Publicly readable. Written only by fs.c */ struct sos_fs_nscache_node * root; /** * List of dirty nodes. These are the nodes that need to be written * back to disk. With FS supporting deferred-writes, the * sos_fs_sync() function will use this list to flush the dirty * nodes back to disk. * * @note Reserved to fs.c */ struct sos_fs_node * dirty_nodes; /** * Build a fresh new FS node at the given location. This implies * the allocation of a new sos_fs_node structure in memory * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*fetch_node_from_disk)(struct sos_fs_manager_instance * this, sos_ui64_t storage_location, struct sos_fs_node ** result); /** * Build a fresh new FS node ON THE DISK of the given type (dir, * plain file, symlink, ...), completely empty ; return a newly * allocated IN-MEMORY node structure representing it * * @param open_creat_flags is the open_flags parameter passed to * sos_fs_open() when O_CREAT is set. 0 when allocated trough * creat/mkdir/mknod/symlink * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*allocate_new_node)(struct sos_fs_manager_instance * this, sos_fs_node_type_t type, const struct sos_process * creator, sos_ui32_t access_rights, sos_ui32_t open_creat_flags, struct sos_fs_node ** result); /** * Return filesystem status (RTFM df) * * @note Optional, may block. Appropriate locking MUST be implemented */ sos_ret_t (*statfs)(struct sos_fs_manager_instance * this, struct sos_fs_statfs * result); /** * Comparison callback called when looking for file/dirs in the * namespace cache. Normally, a usual lexicographical comparison is * done (when this function points to NULL). But for some FS, it * might be useful to use another comparison function (eg for * case-insensitive FS) * * @note Optional (may be NULL), must NOT block */ sos_bool_t (*nsnode_same_name)(const char * name1, sos_ui16_t namelen1, const char * name2, sos_ui16_t namelen2); /** * Hash table of the struct sos_fs_node of this filesystem instance * loaded in memory: key=storage_location, element=sos_fs_node */ struct sos_hash_table * nodecache; /** * Unique identifier of this FS (used in sync method, updated by * fs.c). This enables sync_all_fs to be resilient to mount/umount * and (un)register_fs_type/instance */ sos_ui64_t uid; void * custom_data; /** Linkage for the list of instances for the underlying fs type */ struct sos_fs_manager_instance * prev, * next; }; /** * The CENTRAL data structure of the whole thing. A so-called "inode" * * This represents the meta-information related to a file on disk: its * permission, where its data is located. Actually, in SOS, these * information are not stored in this structure. Instead, we define a * series of methods in this structure that MUST be implemented by the * FS and that realize the higher level operations needed by the * OS. These operations will rely on the meta-information that the FS * code MUST define and manage by itself (hence the * sos_fs_node::custom_data field). */ struct sos_fs_node { /** * An struct sos_fs_node always belong to exactly ONE file system */ struct sos_fs_manager_instance * fs; /** * The so-called "inode": location of this node inside the FS * instance. Updated by struct * sos_fs_manager_instance::fetch_node_from_disk() */ sos_ui64_t storage_location; /** * Number of ON-DISK links to this node. * * - For everything but directories: the number of hard links to the file * - For directories: 1 + the number of children nodes * * @note Publicly readable. Written only by * sos_fs_node_ops_dir::link() and sos_fs_node_ops_dir::unlink() */ sos_count_t ondisk_lnk_cnt; /** * Number of IN-MEMORY nscache_nodes referencing this FS node. * * Corresponds to the number of struct sos_fs_nscache_node pointing * to this node. This could be as much as ondisk_lnk_cnt + 1, but is * usually less * * @note Reserved to fs.c */ sos_count_t inmem_ref_cnt; /** * Directory, symlink, ... * * @see sos_fs_node_type_t * * @note Publicly readable. Written only by fs.c */ sos_fs_node_type_t type; #define SOS_FS_READABLE 00400 #define SOS_FS_WRITABLE 00200 #define SOS_FS_EXECUTABLE 00100 /** * read/write, ... @see the SOS_FS_*ABLE flags * @note Publicly readable. Written only by fs.c */ sos_ui32_t access_rights; /** * @note Reserved to fs.c */ sos_bool_t dirty; /** * Incremented each time one of the opened files for this node is * modified * @note Publicly readable. Written only by fs.c */ sos_lcount_t generation; /** * @note Available only for device files (char/block) * @note Publicly readable. Written only by * sos_fs_manager_instance::fetch_node_from_disk() and mknod() */ struct sos_fs_dev_id_t { sos_ui32_t device_class; /**< aka "major" */ sos_ui32_t device_instance; /**< aka "minor" */ } dev_id; /** Operations common to all node types */ struct sos_fs_node_ops_file *ops_file; /** Operations specific to some node types */ union { /** when type == SOS_FS_NODE_DIRECTORY */ struct sos_fs_node_ops_dir *ops_dir; /** * when type == SOS_FS_NODE_DEVICE_BLOCK * The FS node has a link to some data pertaining to the device, * not to any special operations * @see blkdev.c for a definition of this structure */ struct sos_blockdev_instance *block_device; /** when type == SOS_FS_NODE_SYMLINK */ struct sos_fs_node_ops_symlink *ops_symlink; }; /* Anonymous union (gcc extension) */ /** * Simply free this FS node from the kernel memory: it does NOT * mean that the corresponding on-disk node is free ! Actually, the * corresponding ON-DISK node is free iff ondisk_lnk_cnt == 0. No * need to sync anything to disk, as the VFS will sync the node * before calling this method * * @note Mandatory, may block, no special locking needed */ sos_ret_t (*destructor)(struct sos_fs_node * this); /** * Called when a process opens the node * * @note Mandatory, may block. Appropriate locking MUST be implemented * @note FS-specific EXCEPT for device special files (char & * block) because they are handled in an uniform way by the * chardev/blockdev subsystems * @note As a consequence, FS code can safely assume that "this" is * never a character or block device */ sos_ret_t (*new_opened_file)(struct sos_fs_node * this, const struct sos_process * owner, sos_ui32_t open_flags, struct sos_fs_opened_file ** result_of); /** * Called when a process closes the node * * @note Mandatory, may block. Appropriate locking MUST be implemented * @note FS-specific EXCEPT for device special files (char & * block) because they are handled in an uniform way by the * chardev/blockdev subsystems * @note As a consequence, FS code can safely assume that "this" is * never a character or block device */ sos_ret_t (*close_opened_file)(struct sos_fs_node * this, struct sos_fs_opened_file * of); /** * This should hold the meta information for this node as needed by * the FS instance. */ void * custom_data; /** Hash linkage entry for this FS node in the nodecache dictionary */ struct sos_hash_linkage hlink_nodecache; /** Linkage to list the dirty nodes of the given FS */ struct sos_fs_node *prev_dirty, *next_dirty; }; /** * The list of methods implementing the basic VFS operations on the * given struct sos_fs_node * * @see sos_fs_node::ops_file */ struct sos_fs_node_ops_file { /** * Change size of file * * @note Optional, may block. Appropriate locking MUST be implemented */ sos_ret_t (*truncate)(struct sos_fs_node *this, sos_lsoffset_t length); /** * Retrieve the status (eg size) of the file * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*stat)(struct sos_fs_node * this, struct sos_fs_stat * result); /** * Change the sos_fs_node::access_rights attribute * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*chmod)(struct sos_fs_node * this, sos_ui32_t new_access_rights); /** * Flush any change to the node back to the file system backing store * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*sync)(struct sos_fs_node *this); }; /** * The list of methods implementing the basic VFS symlink operations * * @see sos_fs_node::ops_symlink */ struct sos_fs_node_ops_symlink { /** * Used by the _kernel_ to resolve the symlinks. To change/create a * symlink target, it is needed only from userland: the read/write * methods are made for this * * @param target Pointer to the string representing the target's * path, allocated for the fs_node's lifetime ! * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*expand)(struct sos_fs_node *this, char const ** target, sos_size_t * target_len); }; /** * The list of methods implementing the basic VFS directory operations * * @see sos_fs_node::ops_dir */ struct sos_fs_node_ops_dir { /** * Look for the on-disk location of the sos_fs_node having the given * name * * @note Mandatory, may block. Appropriate locking MUST be implemented */ sos_ret_t (*lookup)(struct sos_fs_node *this, const char * name, sos_ui16_t namelen, sos_ui64_t * result_storage_location); /** * Add a new reference in the current sos_fs_node to the on-disk * location of the given sos_fs_node * * @note Responsible for updating this->ondisk_lnk_cnt * @note Mandatory for writable directories, may block. Appropriate * locking MUST be implemented */ sos_ret_t (*link)(struct sos_fs_node *this, const struct sos_process *actor, const char * entry_name, sos_ui16_t entry_namelen, struct sos_fs_node * node); /** * Remove the entry in the current sos_fs_node for the on-disk * location with the given name * * @note Responsible for updating this->ondisk_lnk_cnt * @note Mandatory for writable directories, may block. Appropriate * locking MUST be implemented */ sos_ret_t (*unlink)(struct sos_fs_node *this, const struct sos_process *actor, const char * entry_name, sos_ui16_t entry_namelen); }; /** * The data structure holding information and method related to a * particular usage of a file. A so-called "struct file" * * This represents the kernel structure behind a "file descriptor" or * behind a chdir/chroot. Among other things, it holds the methods * responsible for reading/writing into the file, and for moving the * file pointer (see @sos_fs_opened_file::position) inside it. */ struct sos_fs_opened_file { /** The process that opened the file/dir */ const struct sos_process * owner; /** * The reference to the sos_fs_nscache_node and, hence, to the underlying sos_fs_node. * * Used to cache the in-memory fs nodes */ struct sos_fs_nscache_node * direntry; /** Use for memory-management */ sos_count_t ref_cnt; /** * Always > 0 (ie max size = 2^63-1 = 9.2 10^18). We make it * "signed" here to limit its range. Because we must be able to * seek to the begining of the file with SEEK_END and a negative * offset, so the max size of the file must be reachable by a lseek * offset * * @note reserved to filesystem instance code. Not modified nor used * by fs.c */ sos_lsoffset_t position; /** * Incremented each time this opened file is modified * * Used to implement a readdir method resilient to * creat/mkdir/rmdir/unlink */ sos_lcount_t generation; /** * @see SOS_FS_OPEN_* flags */ sos_ui32_t open_flags; /** Operations common to all node types */ struct sos_fs_ops_opened_file * ops_file; /** Operations specific to some node types */ union { /** when direntry->fs_node->type == SOS_FS_NODE_DIRECTORY */ struct sos_fs_ops_opened_dir * ops_dir; /** when direntry->fs_node->type == SOS_FS_NODE_DEVICE_CHAR */ struct sos_fs_ops_opened_chardev * ops_chardev; /** when direntry->fs_node->type == SOS_FS_NODE_DEVICE_BLOCK */ struct sos_fs_ops_opened_blockdev * ops_blockdev; }; /* Anonymous union (gcc extension) */ /** * Called upon fork() to duplicate all the opened files * * @note FS-specific EXCEPT for device special files (char & * block) because they are handled in an uniform way by the * chardev/blockdev subsystems * @note As a consequence, FS code can safely assume that "this" is * never a character or block device */ sos_ret_t (*duplicate)(struct sos_fs_opened_file *this, const struct sos_process * for_owner, struct sos_fs_opened_file **result); void * custom_data; }; /** * Reference position for sos_fs_seek */ typedef enum { SOS_SEEK_SET=42, SOS_SEEK_CUR=24, SOS_SEEK_END=84 } sos_seek_whence_t; /** * The list of methods implementing the basic VFS opened file * operations * * See the Unix manual pages, they basically form the interfaces to to * these functions * * @see sos_fs_opened_file::ops_file */ struct sos_fs_ops_opened_file { /** * @note Mandatory, may block. Appropriate locking MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*seek)(struct sos_fs_opened_file *this, sos_lsoffset_t offset, sos_seek_whence_t whence, /* out */ sos_lsoffset_t * result_position); /** * @note Mandatory, may block. Appropriate locking MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*read)(struct sos_fs_opened_file *this, sos_uaddr_t dest_buf, sos_size_t * /* in/out */len); /** * @note Optional (might be NULL), may block. Appropriate locking * MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*write)(struct sos_fs_opened_file *this, sos_uaddr_t src_buf, sos_size_t * /* in/out */len); /** * @note Optional (might be NULL), may block. Appropriate locking * MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*mmap)(struct sos_fs_opened_file *this, sos_uaddr_t *uaddr, sos_size_t size, sos_ui32_t access_rights, sos_ui32_t flags, sos_luoffset_t offset); /** * @note Optional (might be NULL), may block. Appropriate locking * MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*fcntl)(struct sos_fs_opened_file *this, int req_id, sos_ui32_t req_arg /* Usually: sos_uaddr_t */); }; /** * The list of methods implementing the basic VFS opened character device * operations * * @see sos_fs_opened_file::ops_file */ struct sos_fs_ops_opened_chardev { /** * @note Optional (might be NULL), may block. Appropriate locking * MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*ioctl)(struct sos_fs_opened_file *this, int req_id, sos_ui32_t req_arg /* Usually: sos_uaddr_t */); }; /** * The list of methods implementing the basic VFS opened block device * operations * * @see sos_fs_opened_file::ops_file */ struct sos_fs_ops_opened_blockdev { /** * @note Optional (might be NULL), may block. Appropriate locking * MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*ioctl)(struct sos_fs_opened_file *this, int req_id, sos_ui32_t req_arg /* Usually: sos_uaddr_t */); }; /** Data structure that is to be filled by readdir */ struct sos_fs_dirent { sos_ui64_t storage_location; sos_si64_t offset_in_dirfile; sos_ui32_t type; sos_ui16_t namelen; #define SOS_FS_DIRENT_NAME_MAXLEN 128 char name[SOS_FS_DIRENT_NAME_MAXLEN]; }; /** * The list of methods implementing the basic VFS opened directory * operations * * @see sos_fs_opened_file::ops_file */ struct sos_fs_ops_opened_dir { /** * Each time it is called, responsible for filling the sos_fs_dirent * structure, return -SOS_ENOENT when done. * * @note Mandatory, may block. Appropriate locking MUST be implemented * @note Please call sos_fs_mark_dirty() if disk contents is changed */ sos_ret_t (*readdir)(struct sos_fs_opened_file *this, struct sos_fs_dirent * result); }; /** * Used by the stat calls * * @see sos_fs_node_ops_file::stat */ struct sos_fs_stat { struct sos_fs_dev_id_t st_rdev; sos_fs_node_type_t st_type; sos_ui64_t st_storage_location; sos_ui32_t st_access_rights; sos_count_t st_nlink; sos_si64_t st_size; }; /** * Used by the statvfs calls * * @see sos_fs_manager_instance::statfs */ struct sos_fs_statfs { struct sos_fs_dev_id_t f_rdev; sos_size_t f_sz_total; /**< Total size */ sos_size_t f_sz_free; /**< Size left on device */ sos_count_t f_node_total;/**< Total allocatable FS nodes */ sos_count_t f_node_avail;/**< Number of available free FS nodes */ sos_ui32_t f_flags; }; /** * Must be called AFTER the FS manager types needed to mount the root * filesystem have been registered */ sos_ret_t sos_fs_subsystem_setup(const char * root_device, const char * fs_type, const char * mount_args, struct sos_fs_manager_instance ** result_rootfs); /* *************************************************************** * The Following functions are relatively standard * * @see Unix manual pages for details */ /** * mount a file system * * @param actor process calling mount * @param _src_path(len) may be NULL (as for virtfs or /proc) * @fsname the name of the filesystem type to mount * @args any args passed to the sos_fs_manager_type::mount method * @result_fs the resulting filesystem instance */ sos_ret_t sos_fs_mount(struct sos_process * actor, const char * _src_path, sos_size_t _src_pathlen, const char * _dst_path, sos_size_t _dst_pathlen, const char * fsname, sos_ui32_t mountflags, const char * args, struct sos_fs_manager_instance ** /*out*/result_fs); /** * unmount the filesystem at the given location */ sos_ret_t sos_fs_umount(struct sos_process * actor, const char * _mountpoint_path, sos_size_t _mountpoint_pathlen); /** * Flush all the dirty nodes of all the FS to disk */ sos_ret_t sos_fs_sync_all_fs(void); /** * Retrieve filesystem status, or return -SOS_ENOSYS if filesystem * cannot report this */ sos_ret_t sos_fs_vfstat(const struct sos_process * actor, const char * _path, sos_size_t _pathlen, struct sos_fs_statfs * result); /** * Open flags */ #define SOS_FS_OPEN_EXCL (1 << 0) #define SOS_FS_OPEN_CREAT (1 << 1) #define SOS_FS_OPEN_TRUNC (1 << 2) #define SOS_FS_OPEN_NOFOLLOW (1 << 3) #define SOS_FS_OPEN_DIRECTORY (1 << 4) /* Incompatible with CREAT/TRUNC */ #define SOS_FS_OPEN_SYNC (1 << 5) #define SOS_FS_OPEN_CLOSEONEXEC (1 << 6) /* By default, files are kept open upon an exec() */ #define SOS_FS_OPEN_READ (1 << 16) #define SOS_FS_OPEN_WRITE (1 << 17) /** * FS access rights */ #define SOS_FS_S_IRUSR 00400 #define SOS_FS_S_IWUSR 00200 #define SOS_FS_S_IXUSR 00100 #define SOS_FS_S_IRWXALL 07777 /* For symlinks */ sos_ret_t sos_fs_open(const struct sos_process *owner, const char *_path, sos_size_t _pathlen, sos_ui32_t open_flags, sos_ui32_t creat_access_rights, struct sos_fs_opened_file ** of); sos_ret_t sos_fs_close(struct sos_fs_opened_file * of); sos_ret_t sos_fs_read(struct sos_fs_opened_file * of, sos_uaddr_t dest_buf, sos_size_t * /* in/ou */len); sos_ret_t sos_fs_readdir(struct sos_fs_opened_file * of, struct sos_fs_dirent * result); sos_ret_t sos_fs_write(struct sos_fs_opened_file * of, sos_uaddr_t src_buf, sos_size_t * /* in/out */len); sos_ret_t sos_fs_seek(struct sos_fs_opened_file *of, sos_lsoffset_t offset, sos_seek_whence_t whence, sos_lsoffset_t * result_position); sos_ret_t sos_fs_ftruncate(struct sos_fs_opened_file *of, sos_lsoffset_t length); sos_ret_t sos_fs_mmap(struct sos_fs_opened_file *of, sos_uaddr_t *uaddr, sos_size_t size, sos_ui32_t access_rights, sos_ui32_t flags, sos_luoffset_t offset); sos_ret_t sos_fs_fsync(struct sos_fs_opened_file * of); sos_ret_t sos_fs_fcntl(struct sos_fs_opened_file *of, int req_id, sos_ui32_t req_arg /* Usually: sos_uaddr_t */); sos_ret_t sos_fs_ioctl(struct sos_fs_opened_file *of, int req_id, sos_ui32_t req_arg /* Usually: sos_uaddr_t */); sos_ret_t sos_fs_creat(const struct sos_process * creator, const char * _path, sos_size_t _pathlen, sos_ui32_t access_rights); sos_ret_t sos_fs_link(const struct sos_process * creator, const char * _old_path, sos_size_t _old_pathlen, const char * _dest_path, sos_size_t _dest_pathlen); sos_ret_t sos_fs_rename(const struct sos_process * creator, const char * _old_path, sos_size_t _old_pathlen, const char * _dest_path, sos_size_t _dest_pathlen); sos_ret_t sos_fs_unlink(const struct sos_process * actor, const char * _path, sos_size_t _pathlen); sos_ret_t sos_fs_symlink(const struct sos_process * creator, const char * _path, sos_size_t _pathlen, sos_uaddr_t symlink_target, sos_size_t symlink_target_len); sos_ret_t sos_fs_mknod(const struct sos_process * creator, const char * _path, sos_size_t _pathlen, sos_fs_node_type_t type /* only block/char allowed */, sos_ui32_t access_rights, const struct sos_fs_dev_id_t * devid); sos_ret_t sos_fs_mkdir(const struct sos_process * creator, const char * _path, sos_size_t _pathlen, sos_ui32_t access_rights); sos_ret_t sos_fs_rmdir(const struct sos_process * actor, const char * _path, sos_size_t _pathlen); sos_ret_t sos_fs_chmod(const struct sos_process * actor, const char * _path, sos_size_t _pathlen, sos_ui32_t access_rights); sos_ret_t sos_fs_stat(const struct sos_process * actor, const char * _path, sos_size_t _pathlen, int nofollow, struct sos_fs_stat * result); /* *************************************************************** * Restricted functions reserved to FS code and block/char devices */ /** * Function to be called when proposing a new File system type */ sos_ret_t sos_fs_register_fs_type(struct sos_fs_manager_type * fstype); sos_ret_t sos_fs_unregister_fs_type(struct sos_fs_manager_type * fstype); /** * Marthe given file as dirty, for FS supporting deferred write access * mode */ sos_ret_t sos_fs_mark_dirty(struct sos_fs_opened_file * of); /** * Helper function to be called from the mount() method of the FS * instance code. Responsible for creating and updating the "root" * field of the FS instance structure and for connecting this FS in * the nscache * @param root_fsnode The root of the FS being mounted */ sos_ret_t sos_fs_register_fs_instance(struct sos_fs_manager_instance * fs, struct sos_fs_node * root_fsnode); /** * Helper function to be called from the umount() method of the FS * instance code. Responsible for unregistering the instance from the * FS type's instances list and for disconnecting this mountpoint in * the nscache. */ sos_ret_t sos_fs_unregister_fs_instance(struct sos_fs_manager_instance * fs); /* *************************************************************** * Restricted functions reserved to syscall.c */ sos_ret_t sos_fs_ref_opened_file(struct sos_fs_opened_file * of); sos_ret_t _sos_fs_unref_opened_file(struct sos_fs_opened_file ** of); #define sos_fs_unref_opened_file(f) _sos_fs_unref_opened_file(&(f)) /* *************************************************************** * Restricted functions to be used only by fs_nscache.c */ sos_ret_t sos_fs_ref_fsnode(struct sos_fs_node * fsnode); sos_ret_t _sos_fs_unref_fsnode(struct sos_fs_node * fsnode); #define sos_fs_unref_fsnode(n) \ ({ sos_ret_t __retval = _sos_fs_unref_fsnode(n); (n)=NULL; __retval; }) /* *************************************************************** * Restricted functions reserved to process.c and main.c:start_init() */ sos_ret_t sos_fs_new_opened_file(const struct sos_process * proc, struct sos_fs_nscache_node * nsnode, sos_ui32_t open_flags, struct sos_fs_opened_file ** result_of); sos_ret_t sos_fs_duplicate_opened_file(struct sos_fs_opened_file * src_of, const struct sos_process * dst_proc, struct sos_fs_opened_file ** result_of); /** * Generic fcntl function that can be called from inside the FS's * fcntl method. It will handle the following fcntl commands: * - F_DUPFD * - F_GETFD * - F_SETFD * - F_GETFL * - F_SETFL * Any other command will lead to a -SOS_ENOSUP return value. * It will take care not to change anything besides the fs.h structures. */ sos_ret_t sos_fs_basic_fcntl_helper(struct sos_fs_opened_file * src_of, int req_id, sos_ui32_t req_arg); #endif /* _SOS_FS_H_ */