/* * vfs.h - Virtual File System definition. * * Author Mohamed Lamine Karaoui (2014,2015) * Alain Greiner (2016,2017,2018) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH 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; version 2.0 of the License. * * ALMOS-MKH 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 ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _VFS_H_ #define _VFS_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /**** Forward declarations ***/ struct vfs_inode_s; struct vfs_dentry_s; struct vfs_ctx_s; struct vfs_file_s; struct mapper_s; struct process_s; struct device_s; struct vseg_s; struct page_s; /****************************************************************************************** * These flags are used to define the working mode of the vfs_lookup() function. *****************************************************************************************/ #define VFS_LOOKUP_DIR 0x01 /* the searched inode must be a directory */ #define VFS_LOOKUP_OPEN 0x02 /* the search is for an open/opendir */ #define VFS_LOOKUP_PARENT 0x04 /* return the parent inode (not the inode itself) */ #define VFS_LOOKUP_CREATE 0x10 /* file must be created if missing */ #define VFS_LOOKUP_EXCL 0x20 /* file cannot previously exist */ /****************************************************************************************** * This structure defines a VFS context, that contains informations common to all inodes * and dentries for a given file system. As it is declared as a global variable in the * kdata segment (fs_context[] array), it is replicated in all clusters. * The field is a pointer on the FS specific context extension. * This extension is dynamically allocated by kernel_init in all clusters. * In each cluster, both this VFS context and the FS specific context are handled as * private by the local OS intance. *****************************************************************************************/ typedef enum { FS_TYPE_DEVFS = 0, FS_TYPE_FATFS = 1, FS_TYPE_RAMFS = 2, FS_TYPES_NR = 3, } vfs_fs_type_t; typedef enum { CTX_ATTR_READ_ONLY = 0x01, /*! write access prohibited */ CTX_ATTR_SYNC = 0x10, /*! synchronise FS on each write */ } vfs_ctx_attr_t; typedef struct vfs_ctx_s { vfs_fs_type_t type; /*! File System type */ uint32_t attr; /*! global attributes for all files in FS */ uint32_t total_clusters; /*! total number of clusters on device */ uint32_t cluster_size; /*! cluster size on device (bytes) */ xptr_t vfs_root_xp; /*! extended pointer on VFS root inode */ busylock_t lock; /*! lock protecting inum allocator */ uint32_t bitmap[BITMAP_SIZE(CONFIG_VFS_MAX_INODES)]; /* inum allocator */ void * extend; /*! FS specific context extension */ } vfs_ctx_t; /****************************************************************************************** * This structure define a VFS inode. * An inode can have several children dentries (if it is a directory), an can have several * parents dentries (if it hass several aliases links): * - The "parents" field is the root of the xlist of parents dentries, and the "links" * fiels define the number of aliases parent dentries. only a FILE inode can have * several parents (no hard links for directories). * - The "children" field is an embedded xhtab containing pointers on all local children * dentries. This set of children is empty for a FILE inode. * Synchronisation: * - the main_lock (remote_rwlock) is used during the inode tree traversal, * or for inode modification (add/remove children in xhtab). * - the size_lock (remote_rwlock) is used during read/write accesses to the size * field in the mapper. * - access to the data stored in the associated mapper use the mapper remote_rwlock * protecting radix tree traversal and modifications. *****************************************************************************************/ /* this enum define the VFS inode types values */ /* WARNING : this enum must be kept consistent with macros in file */ /* and with types in file. */ typedef enum { INODE_TYPE_FILE = 0, /*! regular file */ INODE_TYPE_DIR = 1, /*! directory */ INODE_TYPE_FIFO = 2, /*! POSIX named pipe */ INODE_TYPE_PIPE = 3, /*! POSIX anonymous pipe */ INODE_TYPE_SOCK = 4, /*! POSIX socket */ INODE_TYPE_DEV = 5, /*! character device */ INODE_TYPE_BLK = 6, /*! block device */ INODE_TYPE_SYML = 7, /*! symbolic link */ } vfs_inode_type_t; /* this enum define the VFS inode attributes values */ typedef enum { INODE_ATTR_DIRTY = 0x01, /* modified versus the value on device */ INODE_ATTR_INLOAD = 0x04, /* loading from device in progress */ INODE_ATTR_NEW = 0x08, /* not saved on device yet */ } vfs_inode_attr_t; typedef struct vfs_inode_s { struct vfs_ctx_s * ctx; /*! local pointer on FS context */ uint32_t inum; /*! inode identifier (unique in file system) */ uint32_t attr; /*! inode attributes (see above) */ vfs_inode_type_t type; /*! inode type (see above) */ uint32_t size; /*! number of bytes */ uint32_t uid; /*! user owner identifier */ uint32_t gid; /*! group owner identifier */ uint32_t rights; /*! access rights */ xlist_entry_t parents; /*! root of list of parents dentries */ uint32_t links; /*! number of parent dentries (hard links) */ xhtab_t children; /*! embedded xhtab of children dentries */ remote_rwlock_t size_lock; /*! protect read/write to size */ remote_rwlock_t main_lock; /*! protect inode tree traversal and modifs */ struct mapper_s * mapper; /*! associated file cache */ void * extend; /*! fs_type_specific inode extension */ } vfs_inode_t; /* This define the masks for the inode field */ #define VFS_ISUID 0x0004000 #define VFS_ISGID 0x0002000 #define VFS_ISVTX 0x0001000 #define VFS_IRWXU 0x0000700 #define VFS_IRUSR 0x0000400 #define VFS_IWUSR 0x0000200 #define VFS_IXUSR 0x0000100 #define VFS_IRWXG 0x0000070 #define VFS_IRGRP 0x0000040 #define VFS_IWGRP 0x0000020 #define VFS_IXGRP 0x0000010 #define VFS_IRWXO 0x0000007 #define VFS_IROTH 0x0000004 #define VFS_IWOTH 0x0000002 #define VFS_IXOTH 0x0000001 /****************************************************************************************** Rpt* This structure defines a directory entry. * A dentry contains the name of a remote file/dir, an extended pointer on the * inode representing this file/dir, a local pointer on the inode representing * the parent directory. * A dentry can be member of the set of children of a given directory inode (xhtab). * A dentry can be member of the set of parents of a given inode (xlist). *****************************************************************************************/ typedef struct vfs_dentry_s { struct vfs_ctx_s * ctx; /*! local pointer on FS context */ char name[CONFIG_VFS_MAX_NAME_LENGTH]; uint32_t length; /*! name length (bytes) */ struct vfs_inode_s * parent; /*! local pointer on parent inode */ xptr_t child_xp; /*! extended pointer on child inode */ xlist_entry_t children; /*! member of set of children dentries */ xlist_entry_t parents; /*! member of set of parent dentries */ void * extend; /*! FS specific extension */ } vfs_dentry_t; /****************************************************************************************** * This file structure describes an open file/directory for a given process. * It is not replicated, and is dynamically allocated in the cluster that contains * the inode, when a thread makes an open() or opendir() system call. * It cannot exist a file structure without an inode structure in same cluster. * As the fd_array (containing extended pointers on the open file descriptors) * is replicated in all process descriptors, we need a references counter. *****************************************************************************************/ typedef enum { FD_ATTR_READ_ENABLE = 0x01, /*! read access possible */ FD_ATTR_WRITE_ENABLE = 0x02, /*! write access possible */ FD_ATTR_APPEND = 0x04, /*! append on each write */ FD_ATTR_CLOSE_EXEC = 0x08, /*! close file on exec */ FD_ATTR_SYNC = 0x10, /*! synchronise FS on each write */ FD_ATTR_IS_DIR = 0x20, /*! this is a directory */ } vfs_file_attr_t; typedef struct vfs_file_s { struct vfs_ctx_s * ctx; /*! local pointer on FS context. */ uint32_t gc; /*! generation counter */ vfs_file_attr_t attr; /*! file attributes bit vector (see above) */ vfs_inode_type_t type; /*! same type as inode */ uint32_t offset; /*! seek position in file */ uint32_t refcount; /*! all pointers on this file descriptor */ remote_rwlock_t lock; /*! protect offset modifications */ struct mapper_s * mapper; /*! associated file cache */ struct vfs_inode_s * inode; /*! local pointer on associated inode */ void * extend; /*! FS specific extension */ } vfs_file_t; /****************************************************************************************** * These functions access / modify a VFS context. *****************************************************************************************/ /****************************************************************************************** * This function initialise a (statically allocated) VFS context in local cluster. ****************************************************************************************** * @ fs_type : file system type. * @ attr : global attributes (for all files in FS. * @ total_clusters : total number of clusters on device. * @ cluster_size : cluster size on device (bytes). * @ vfs_root_xp : extended pointer on VFS root inode. * @ extend : fs_type_specific extension. *****************************************************************************************/ void vfs_ctx_init( vfs_fs_type_t type, uint32_t attr, uint32_t total_clusters, uint32_t cluster_size, xptr_t vfs_root_xp, void * extend ); /****************************************************************************************** * This function allocates an inode identifier from the local cluster inum allocator. * The inum respects a fixed format: * - the 16 MSB bits contain the cluster identifier : cxy * - the 16 LSB bits contains the local inode identifier : lid ****************************************************************************************** * @ ctx : local pointer on file system context. * @ inum : [ou] buffer for allocated inode identifier. * @ return 0 if success / return non-zero if error. *****************************************************************************************/ error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx, uint32_t * inum ); /****************************************************************************************** * This function release an inode identifier. ****************************************************************************************** * @ ctx : local pointer on file system context. * @ inum : released inode identifier. *****************************************************************************************/ void vfs_ctx_inum_release( vfs_ctx_t * ctx, uint32_t inum ); /****************************************************************************************** * These low-level functions access / modify a VFS inode descriptor *****************************************************************************************/ /****************************************************************************************** * This function returns a printable string for the inode type. *****************************************************************************************/ const char * vfs_inode_type_str( vfs_inode_type_t type ); /****************************************************************************************** * This function allocates memory from local cluster for an inode descriptor and the * associated mapper, and partially initialise this inode from arguments values. * It does NOT link it to the Inode Tree, as this is done by add_child_in_parent(). * It must called by a local thread. Use the RPC_INODE_CREATE if client thread is remote. ****************************************************************************************** * @ fs_type : file system type. * @ inode_type : inode type. * @ attr : inode attributes. * @ rights : inode access rights. * @ uid : user owner ID. * @ gid : group owner ID. * @ inode_xp : [out] buffer for extended pointer on created inode. * @ return 0 if success / return ENOMEM or EINVAL if error. *****************************************************************************************/ error_t vfs_inode_create( vfs_fs_type_t fs_type, uint32_t attr, uint32_t rights, uid_t uid, gid_t gid, xptr_t * inode_xp ); /****************************************************************************************** * This function releases memory allocated to an inode descriptor, including * all memory allocated to the mapper (both mapper descriptor and radix tree). * The mapper should not contain any dirty page (should be synchronized before deletion). * It must be executed by a thread running in the cluster containing the inode. * Use the rpc_vfs_inode_destroy_client() function if required. ****************************************************************************************** * @ inode : local pointer on inode descriptor. *****************************************************************************************/ void vfs_inode_destroy( vfs_inode_t * inode ); /****************************************************************************************** * This function returns the of a file/dir from a remote inode, * taking the remote_rwlock protecting in READ_MODE. ***************************************************************************************** * @ inode_xp : extended pointer on the remote inode. * @ return the current size. *****************************************************************************************/ uint32_t vfs_inode_get_size( xptr_t inode_xp ); /****************************************************************************************** * This function updates the "size" field of a remote inode identified by . * It takes the rwlock protecting the file size in WRITE_MODE, and set the "size" field * when the current size is smaller than the requested argument. ***************************************************************************************** * @ inode_xp : extended pointer on the remote inode. * @ size : requested size value. *****************************************************************************************/ void vfs_inode_update_size( xptr_t inode_xp, uint32_t size ); /****************************************************************************************** * This function takes the main lock of a remote inode. * This lock protect all inode fields, including the children dentries. ***************************************************************************************** * @ inode_xp : extended pointer on the remote inode. *****************************************************************************************/ void vfs_inode_lock( xptr_t inode_xp ); /****************************************************************************************** * This function releases the main lock of a remote inode. * This lock protect all inode fiels, including the children dentries. ***************************************************************************************** * @ inode_xp : extended pointer on the remote inode. *****************************************************************************************/ void vfs_inode_unlock( xptr_t inode_xp ); /****************************************************************************************** * This debug function copies the name of a remote inode identified by the * argument to a local buffer identified by the argument. * The local buffer size must be at least CONFIG_VFS_MAX_NAME_LENGTH. ****************************************************************************************** * @ inode_xp : extended pointer on the remote inode. * @ name : local buffer pointer. *****************************************************************************************/ void vfs_inode_get_name( xptr_t inode_xp, char * name ); /****************************************************************************************** * This function accesses successively all pages of a file identified by the , * argument, to force misses, and load all pages into mapper. * The target inode can be a directory or a file, but this function is mainly used * to prefetch a complete directory to the mapper. * It must be executed by a thread running in the cluster containing the inode. * This function does NOT take any lock. ****************************************************************************************** * @ inode : local pointer on inode. * @ return 0 if success / return -1 if device access failure. *****************************************************************************************/ error_t vfs_inode_load_all_pages( vfs_inode_t * inode ); /****************************************************************************************** * This debug function display the curren state of an inode descriptor identified by * the argument. *****************************************************************************************/ void vfs_inode_display( xptr_t inode_xp ); /****************************************************************************************** * These low-level functions access / modify a VFS dentry descriptor *****************************************************************************************/ /****************************************************************************************** * This function allocates memory from local cluster for a dentry descriptor, * initialises it from arguments values, and returns the extended pointer on dentry. * It must called by a local thread. Use the RPC_DENTRY_CREATE if client thread is remote. ****************************************************************************************** * @ fs_type : [in] file system type. * @ name : [in] directory entry file/dir name. * @ dentry_xp : [out] buffer for extended pointer on created dentry. * @ return 0 if success / return ENOMEM or EINVAL if error. *****************************************************************************************/ error_t vfs_dentry_create( vfs_fs_type_t fs_type, char * name, xptr_t * dentry_xp ); /****************************************************************************************** * This function removes the dentry from the parent inode xhtab, and releases the memory * allocated to the dentry descriptor. * It must be executed by a thread running in the cluster containing the dentry. * Use the RPC_DENTRY_DESTROY if required. ****************************************************************************************** * @ dentry : [in] local pointer on dentry descriptor. *****************************************************************************************/ void vfs_dentry_destroy( vfs_dentry_t * dentry ); /****************************************************************************************** * These low-level functions access / modify a VFS file descriptor *****************************************************************************************/ /****************************************************************************************** * This function allocates memory and initializes a new local file descriptor. * It must be executed in the cluster containing the inode. * If the client thread is not running in the owner cluster, it must use the * rpc_vfs_file_create_client() function. ****************************************************************************************** * @ inode : local pointer on associated inode. * @ attr : file descriptor attributes. * @ file_xp : [out] buffer for extended pointer on created file descriptor. * @ return 0 if success / return ENOMEM if error. *****************************************************************************************/ error_t vfs_file_create( vfs_inode_t * inode, uint32_t attr, xptr_t * file_xp ); /****************************************************************************************** * This function releases memory allocated to a local file descriptor. * It must be executed by a thread running in the cluster containing the inode, * and the file refcount must be zero. Use the RPC_VFS_FILE_DESTROY if required. ****************************************************************************************** * @ file : local pointer on file descriptor. *****************************************************************************************/ void vfs_file_destroy( vfs_file_t * file ); /****************************************************************************************** * These functions increment (resp. decrement) the count field in a remote file * descriptor, using a remote_atomic access. *****************************************************************************************/ void vfs_file_count_up ( xptr_t file_xp ); void vfs_file_count_down( xptr_t file_xp ); /****************************************************************************************** * This debug function copies the name of a the file identified by * argument to a local buffer identified by the argument. * The local buffer size must be at least CONFIG_VFS_MAX_NAME_LENGTH. ***************************************************************************************** * @ file_xp : extended pointer on the remote inode. * @ name : local buffer pointer. *****************************************************************************************/ void vfs_file_get_name( xptr_t inode_xp, char * name ); /****************************************************************************************** * These functions access / modify the distributed VFS Inode Tree *****************************************************************************************/ /****************************************************************************************** * This function returns in a kernel allocated by the caller function, * the pathname of a file/dir identified by the argument. * It traverse the Inode Tree from the target node to the root. * It can be called by any thread running in any cluster. * As this buffer if filled in "reverse order" (i.e. from the target inode to the root), * the pathname is stored in the higher part of the buffer. * A pointer on the first character of the pathname is returned in buffer. * * WARNING : This function takes & releases the remote_rwlock protecting the Inode Tree. ****************************************************************************************** * @ inode_xp : [in] extended pointer on target inode descriptor. * @ buffer : [in] kernel buffer for pathname (allocated by caller). * @ first : [out] pointer on first character in buffer. * @ max_size : [in] max number of characters in buffer. * @ return 0 if success / return EINVAL if buffer too small. *****************************************************************************************/ error_t vfs_get_path( xptr_t inode_xp, char * buffer, char ** first, uint32_t max_size ); /****************************************************************************************** * This function traverses the the Inode Tree, from inode identified by the * argument, and returns in the inode identified by the < pathname> argument. * It can be called by a thread running in any cluster. * It supports the following flags that define the lookup modes : * - VFS_LOOKUP_DIR : the searched inode must be a directory * - VFS_LOOKUP_OPEN : the search is for an open/opendir * - VFS_LOOKUP_PARENT : return the parent inode (not the inode itself) * - VFS_LOOKUP_CREATE : file/directory must be created if missing on IOC * - VFS_LOOKUP_EXCL : file cannot previously exist * As the inode Tree is a cache, the search policy is the following : * - If a given directory name in the path is not found in the inode tree, it try to load * the missing dentry/inode couple, from informations found in the parent directory. * - If this directory entry does not exist on IOC, it returns an error. * - If the the file identified by the pathname does not exist on IOC but the * flag CREATE is set, the inode is created. It returns an error otherwise. * - If the the file identified by the pathname exist on device, but both flags EXCL * and CREATE are set, an error is returned. * - If the PARENT flag is set, it returns in an extended pointer on the parent * inode, and copies in buffer a string containing the last name in path. * * WARNING : The remote_rwlock protecting the Inode Tree must be taken by the caller. * * TODO the access rights are not checked yet. ****************************************************************************************** * @ root_xp : [in] extended pointer on root inode (can be root of a subtree). * @ pathname : [in] path (can be relative or absolute). * @ lookup_mode : [in] flags defining the searching mode. * @ inode_xp : [out] buffer for extended pointer on searched inode. * @ last_name : [out] pointer on buffer for last name in path. * @ return 0 if success / ENOENT if inode not found , EACCES if permisson denied, *****************************************************************************************/ error_t vfs_lookup( xptr_t root_xp, char * pathname, uint32_t lookup_mode, xptr_t * inode_xp, char * last_name ); /****************************************************************************************** * This function creates a new couple dentry/inode, and insert it in the Inode-Tree. * Only the distributed Inode Tree is modified: it does NOT modify the parent mapper, * and does NOT update the FS on IOC device. * It set the inode type to the default INODE_TYPE_FILE value * It can be executed by any thread running in any cluster (can be different from both * the child cluster and the parent cluster). * The new child inode and the parent inode can have different FS types. * [Implementation note] * As there are cross-references between inode and dentry, this function implements * a five steps scenario : * 1) The dentry descriptor is created in the cluster containing the existing * inode, and partially initialized, using the RPC_VFS_CREATE DENTRY if required. * 2) The inode and its associated mapper are created in cluster identified by , * and partially initialised, using the RPC_VFS_CREATE_INODE if required. * 3) The pointers on dentry in parent inode are updated, using remote access. * 4) The pointers on dentry in child inode are updated, using remotes access. * 5) The pointers on parent and child inode in dentry are updated, using remotes access. ***************************************************************************************** * @ child_inode_cxy : [in] target cluster for child inode. * @ fs_type : [in] child inode FS type. * @ parent_inode_xp : [in] extended pointer on parent inode. * @ name : [in] new directory entry name. * @ dentry_xp : [out] buffer for extended pointer on dentry * @ child_inode_xp : [out] buffer for extended pointer on child inode. * @ return 0 if success / -1 if dentry or inode cannot be created. *****************************************************************************************/ error_t vfs_add_child_in_parent( cxy_t child_inode_cxy, vfs_fs_type_t fs_type, xptr_t parent_inode_xp, char * name, xptr_t * dentry_xp, xptr_t * child_inode_xp ); /****************************************************************************************** * This function removes a remote dentry from the Inode-Tree. * - It removes the dentry from the parent inode xhtab ("children" field), and from the * child inode xlist ("parents" field). * - It releases the memory allocated to the dentry descriptor. * - If the number of parents of the child inode is one, it also releases the memory * allocated to the child inode. * Only the Inode Tree is modified: it does NOT modify the parent mapper, * and does NOT update the FS on IOC device. * It can be executed by any thread running in any cluster (can be different from both * the inode cluster and the dentry cluster). ****************************************************************************************** * @ dentry_xp : extended pointer on removed dentry. *****************************************************************************************/ void vfs_remove_child_from_parent( xptr_t dentry_xp ); /****************************************************************************************** * This function is called by the vfs_lookup() function when a new (dentry/inode) must * be created from scratch and introduced in both the parent mapper and the IOC device. * The dentry and inode descriptors must have been previously created by the caller. * 1. It allocates one cluster from the relevant FS, updates the FAT mapper, * and synchronously update the IOC device). * 2. It set the "size", and "extend" fields in child inode descriptor. * 3. It updates the parent directory mapper to introduce the new child, * and synchronously update the IOC device. * 4. It set the "extend" field in dentry descriptor. * It can be called by a thread running in any cluster. ****************************************************************************************** * @ parent_xp : extended pointer on parent inode descriptor. * @ dentry_xp : extended pointer on new dentry descriptor. * @ child_xp : extended pointer on child inode descriptor. * @ return 0 if success / -1 if failure. *****************************************************************************************/ error_t vfs_new_dentry_init( xptr_t parent_xp, xptr_t dentry_xp, xptr_t child_xp ); /****************************************************************************************** * This function creates in the directory identified by the argument, * the two special dentries <.> and <..>. The parent directory inode is defined * by the argument. The two dentries are introduced in the Inode Tree. * They are also introduced in the child directory mapper, and the IOC device is updated. * This function is called by all functions creating a brand new directory : vfs_mkdir(), * devfs_global_init(), and devfs_local_init(). ****************************************************************************************** * @ child_xp : extended pointer on new directory inode. * @ parent_xp : extended pointer on parent directory inode. * @ return 0 if success / -1 if failure. *****************************************************************************************/ error_t vfs_add_special_dentries( xptr_t child_xp, xptr_t parent_xp ); /****************************************************************************************** * This recursive function diplays a complete inode/dentry sub-tree. * Any inode can be selected as the sub-tree root. * WARNING : this function is not protected against a concurrent inode/dentry removal... ****************************************************************************************** * @ inode_xp : extended pointer on sub-tree root inode. *****************************************************************************************/ void vfs_display( xptr_t inode_xp ); /****************************************************************************************** * This function mount a given file system type for a given process * TODO non implemented yet [AG]. *****************************************************************************************/ error_t vfs_mount_fs_root( struct device_s * device, uint32_t fs_type, struct process_s * process ); /****************************************************************************************** * These functions define the VFS "syscalls" API (user commands) *****************************************************************************************/ /****************************************************************************************** * This function moves bytes between a remote file mapper, identified by the * argument, and a - possibly distributed - user space , taken into * account the offset in . The transfer direction is defined by . * It is called by the sys_read() and sys_write() functions. ****************************************************************************************** * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false. * @ file_xp : extended pointer on the remote file descriptor. * @ buffer : user space pointer on buffer (can be physically distributed). * @ size : requested number of bytes from offset. * @ returns number of bytes actually moved if success / -1 if error. *****************************************************************************************/ int vfs_user_move( bool_t to_buffer, xptr_t file_xp, void * buffer, uint32_t size ); /****************************************************************************************** * This function moves bytes between a remote file mapper, identified by the * argument, and a - possibly remote - kernel , taken into * account the offset in . The transfer direction is defined by . * It is called by the elf_load_process() function. ****************************************************************************************** * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false. * @ file_xp : extended pointer on the remote file descriptor. * @ buffer_xp : user space pointer on buffer (can be physically distributed). * @ size : requested number of bytes from offset. * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_kernel_move( bool_t to_buffer, xptr_t file_xp, xptr_t buffer_xp, uint32_t size ); /****************************************************************************************** * This function allocates a vfs_file_t structure in the cluster containing the inode * identified by the & arguments. * It initializes it, register it in the reference process fd_array identified by the * argument, and returns both the extended pointer on the file descriptor, * and the allocated index in the and buffers. * The pathname can be relative to current directory or absolute. * If the inode does not exist in the inode cache, it try to find the file on the IOC * device, and creates an inode on a pseudo randomly selected cluster if found. * It the requested file does not exist on device, it creates a new inode if the * O_CREAT flag is set, and return an error otherwise. * * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree. ****************************************************************************************** * @ root_xp : extended pointer on path root inode. * @ path : file pathname (absolute or relative to current directory). * @ process_xp : extended pointer on client reference process. * @ flags : defined in vfs_file_t structure. * @ mode : access rights (as defined by chmod). * @ file_xp : [out] buffer for extended pointer on created remote file descriptor. * @ file_id : [out] buffer for created file descriptor index in reference fd_array. * @ return 0 if success / return non-zero if error. *****************************************************************************************/ error_t vfs_open( xptr_t root_xp, char * path, xptr_t process_xp, uint32_t flags, uint32_t mode, xptr_t * file_xp, uint32_t * file_id ); /****************************************************************************************** * This function set a new value in the offset of the open file descriptor . * This value depends on the argument: * - if VFS_SEEK_SET, new value is * - if VFS_SEEK_CUR, new value is current_offset + * - if VFS_SEEK_END, new value is file_size + ****************************************************************************************** * @ file_xp : extended pointer on the remote open file descriptor. * @ offset : local pointer on source kernel buffer. * @ whence : VFS_SEEK_SET / VFS_SEEK_CUR / VFS_SEEK_END. * @ new_offset : [out] buffer for new offset value. * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_lseek( xptr_t file_xp, uint32_t offset, uint32_t whence, uint32_t * new_offset ); /****************************************************************************************** * This function close the - non-replicated - file descriptor identified by the * and arguments. The is required to reset the fd_array[] slot. * It can be called by a thread running in any cluster, and executes the following actions: * 1) It access the block device to updates all dirty pages from the mapper associated * to the file, and removes these pages from the dirty list, using an RPC if required. * 2) It updates the file size in all parent directory mapper(s), and update the modified * pages on the block device, using RPCs if required. * 3) All entries in the fd_array copies are directly reset by the calling thread, * using remote accesses. * 4) The memory allocated to file descriptor in cluster containing the inode is released, * using an RPC if cluster containing the file descriptor is remote. ****************************************************************************************** * @ file_xp : extended pointer on the file descriptor. * @ file_id : file descriptor index in fd_array[]. * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_close( xptr_t file_xp, uint32_t file_id ); /****************************************************************************************** * This function is called by the kernel to create in the file system a new directory * identified by the & arguments, with the access permission defined * by the argument. All nodes in the path - but the last - must exist. * * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree. ****************************************************************************************** * @ root_xp : extended pointer on path root inode (any inode in Inode Tree). * @ path : pathname (absolute or relative to current directory). * @ rights : access rights. * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_mkdir( xptr_t root_xp, char * path, uint32_t rights ); /****************************************************************************************** * This function is called by the kernel to create in the file system a new directory * entry identified by the & arguments, to be linked to an * existing inode, identified by the & arguments. * If the link is successful, the link count of the target inode is incremented. * The and share equal access rights to the underlying inode. * Both the IOC device and the Inode Tree are modified. $ * TODO This function should handle any type of node, but the current implementation * handles only the FILE and DIR types. * * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree. ****************************************************************************************** * @ old_root_xp : extended pointer on old path root inode (any inode in Inode Tree). * @ old_path : old pathname (absolute or relative to current directory). * @ nld_root_xp : extended pointer on new path root inode (any inode in Inode Tree). * @ new_path : new pathname (absolute or relative to current directory). * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_link( xptr_t old_root_xp, char * old_path, xptr_t new_root_xp, char * new_path ); /****************************************************************************************** * This function is called by the kernel to remove from the file system a directory entry * identified by the & arguments. * The link count of the target node is decremented. * If the removed link is the last, the target inode is deleted. * Both the IOC device and the Inode Tree are modified. * * TODO This function should handle any type of node, but the current implementation * handles only only the FILE and DIR types. * * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree. ****************************************************************************************** * @ root_xp : extended pointer on root inode (can be any inode in Inode Tree). * @ path : pathname (absolute or relative to current directory). * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_unlink( xptr_t root_xp, char * path ); /****************************************************************************************** * This function returns, in the structure pointed by the pointer, various * informations on the inode identified by the and arguments. * * TODO : only partially implemented yet (only size and inum fields). * * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree. ****************************************************************************************** * @ root_xp : extended pointer on path root inode (any inode in Inode Tree) * @ pathname : pathname to target inode. * @ st : local pointer on the stat structure in kernel space. * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_stat( xptr_t root_xp, char * pathname, struct stat * st ); /****************************************************************************************** * This function creates a new directory as defined by the & arguments. * TODO not implemented yet... ****************************************************************************************** * @ root_xp : extended pointer on the path root directory. * @ path : pathname (absolute or relative to CWD). * @ mode : access rights (as defined by chmod) * @ returns 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_mkdir( xptr_t root_xp, char * path, uint32_t mode ); /****************************************************************************************** * This function makes the directory identified by the arguments * to become the working directory for the calling process. ****************************************************************************************** * @ root_xp : extended pointer on the path root directory. * @ path : pathname (absolute or relative to CWD). * return 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_chdir( xptr_t root_xp, char * path ); /****************************************************************************************** * This function change the access rigths for the file/directory identified by the * and arguments as defined by the argument value. ****************************************************************************************** * @ root_xp : extended pointer on the path root directory. * @ path : pathname (absolute or relative to CWD). * @ mode : access rights * return 0 if success / -1 if error. *****************************************************************************************/ error_t vfs_chmod( xptr_t root_xp, char * path, uint32_t mode ); /****************************************************************************************** * This function creates a named FIFO file. * TODO not implemented yet ****************************************************************************************** * @ root_xp : extended pointer on the path root directory. * @ path : pathname (absolute or relative to CWD). * @ mode : access rights new value. *****************************************************************************************/ error_t vfs_mkfifo( xptr_t root_xp, char * path, uint32_t mode ); /****************************************************************************************** * These functions define the VFS "FS" API to a specific File System *****************************************************************************************/ /****************************************************************************************** * This function makes the I/O operation to move one page identified by the * argument to/from the IOC device from/to the mapper, as defined by the . * Depending on the file system type, it calls the proper, FS specific function. * It is used in case of MISS on the mapper, or when a dirty page in the mapper must * be updated in the File System. * The mapper pointer is obtained from the page descriptor. * It can be executed by any thread running in any cluster. * This function does NOT take any lock. ****************************************************************************************** * @ page_xp : extended pointer on page descriptor (for mapper and page_id). * @ cmd_type : IOC_READ / IOC_WRITE / IOC_SYNC_READ / IOC_SYNC_WRITE * @ returns 0 if success / return -1 if device access failure. *****************************************************************************************/ error_t vfs_fs_move_page( xptr_t page_xp, cmd_type_t cmd_type ); /****************************************************************************************** * This function updates the mapper associated to a directory inode identified by the * argument, to add a new entry identified by the argument. * The directory inode descriptor and the dentry descriptor are in the same cluster. * Depending on the file system type, it calls the proper, FS specific function. * It also updates the dentry descriptor and/or the inode descriptor extensions * as required by the specific file system type. * Finally, it synchronously updates the parent directory on IOC device. * * It must be executed by a thread running in the cluster containing the parent directory. * It can be the RPC_VFS_FS_ADD_DENTRY. This function does NOT take any lock. ****************************************************************************************** * @ parent : local pointer on parent (directory) inode. * @ dentry : local pointer on dentry containing name. * @ return 0 if success / return -1 if device access failure. *****************************************************************************************/ error_t vfs_fs_add_dentry( vfs_inode_t * parent, vfs_dentry_t * dentry ); /****************************************************************************************** * This function updates the mapper associated to a directory inode identified by the * argument, to remove an entry identified by the argument. * The directory inode descriptor and the dentry descriptor are in the same cluster. * Depending on the file system type, it calls the proper, FS specific function. * Finally, it synchronously updates the parent directory on IOC device. * * Depending on the file system type, it calls the relevant, FS specific function. * It must be executed by a thread running in the cluster containing the parent directory. * It can be the RPC_VFS_FS_REMOVE_DENTRY. This function does NOT take any lock. ****************************************************************************************** * @ parent : local pointer on parent (directory) inode. * @ dentry : local pointer on dentry containing name. * @ return 0 if success / return -1 if device access failure. *****************************************************************************************/ error_t vfs_fs_remove_dentry( vfs_inode_t * parent, vfs_dentry_t * dentry ); /****************************************************************************************** * This function scan the mapper of an an existing parent inode directory, identified by * the argument to find a directory entry identified by the argument, * and updates both the child inode descriptor, identified by the argument, * and the associated dentry descriptor : * - It set the "size", "type", and "extend" fields in inode descriptor. * - It set the "extend" field in dentry descriptor. * It is called by the vfs_lookup() function in case of miss. * * Depending on the file system type, it calls the relevant, FS specific function. * It must be called by a thread running in the cluster containing the parent inode. * It can be the RPC_VFS_FS_NEW_DENTRY. This function does NOT take any lock. ****************************************************************************************** * @ parent : local pointer on parent inode (directory). * @ name : child name. * @ child_xp : extended pointer on remote child inode (file or directory) * @ return 0 if success / return -1 if dentry not found. *****************************************************************************************/ error_t vfs_fs_new_dentry( vfs_inode_t * parent, char * name, xptr_t child_xp ); /****************************************************************************************** * This function scan the mapper of an an existing inode directory, identified by * the argument, to find a directory entry identified by the argument, * and update the size for this directory entry in mapper, as defined by . * The parent directory on device is synchronously updated. * It is called by the vfs_close() function. * * Depending on the file system type, it calls the relevant, FS specific function. * It must be called by a thread running in the cluster containing the parent inode. * It can be the RPC_VFS_FS_UPDATE_DENTRY. This function does NOT take any lock. ****************************************************************************************** * @ parent : local pointer on parent inode (directory). * @ dentry : local pointer on dentry. * @ size : new size value (bytes). * @ return 0 if success / return ENOENT if not found. *****************************************************************************************/ error_t vfs_fs_update_dentry( vfs_inode_t * inode, vfs_dentry_t * dentry, uint32_t size ); /****************************************************************************************** * This function scan the mapper of an an existing parent inode directory, identified by * the argument and copy up to valid dentries to a * local dirent array, defined by the argument. The argument defines * the index of the first dentry to copied to the target dirent array. * This function returns in the buffer the number of dentries actually written, * and signals in the buffer when the last valid entry has been found. * If the argument is true, a dentry/inode couple that does not exist in * the Inode Tree is dynamically created, and all dirent fiels are documented in the * dirent array. Otherwise, only the dentry name is documented. * * Depending on the file system type, it calls the relevant, FS specific function. * It must be called by a thread running in the cluster containing the parent inode. * This function does NOT take any lock. ****************************************************************************************** * @ inode : [in] local pointer on directory inode. * @ array : [in] local pointer on array of dirents. * @ max_dirent : [in] max number of slots in dirent array. * @ min_dentry : [in] index of first dentry to be copied into array. * @ detailed : [in] dynamic inode creation if true. * @ entries : [out] number of dentries actually copied into array. * @ done : [out] Boolean true when last entry found. * @ return 0 if success / return -1 if failure. *****************************************************************************************/ error_t vfs_fs_get_user_dir( vfs_inode_t * inode, struct dirent * array, uint32_t max_dirent, uint32_t min_dentry, bool_t detailed, uint32_t * entries, bool_t * done ); /***************************************************************************************** * This function updates the FS on the IOC device for a given inode identified by * the argument. It scan all pages registered in the associated mapper, * and copies from mapper to device each page marked as dirty. * WARNING : The target cannot be a directory, because all modifications in a * directory are synchronously done on the IOC device by the two vfs_fs_add_dentry() * and vfs_fs_remove_dentry() functions. * * Depending on the file system type, it calls the relevant, FS specific function. * It must be called by a thread running in the inode cluster. ***************************************************************************************** * @ inode : local pointer on inode. * @ return 0 if success / return EIO if failure during device access. ****************************************************************************************/ error_t vfs_fs_sync_inode( struct vfs_inode_s * inode ); /***************************************************************************************** * This function updates the FS defined by the argument on the IOC device * for the FAT itself. It scan all clusters registered in the FAT mapper, and copies * to device each page marked as dirty. * * Depending on the file system type, it calls the relevant, FS specific function. * It can be called by a thread running in any cluster. ***************************************************************************************** * @ fs_type : specific file system type. * @ return 0 if success / return EIO if failure during device access. ****************************************************************************************/ error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type ); /***************************************************************************************** * This function updates the free clusters info on the IOC device for the FS defined * by the argument. * * Depending on the file system type, it calls the relevant, FS specific function. * It can be called by a thread running in any cluster. ***************************************************************************************** * @ fs_type : specific file system type. * @ return 0 if success / return EIO if failure during device access. ****************************************************************************************/ error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type ); /****************************************************************************************** * This function allocates a free cluster from the FS identified by the * argument. It updates the selected FS File Allocation Table. * * Depending on the file system type, it calls the relevant, FS specific function. * It can be called by a thread running in any cluster. ****************************************************************************************** * @ fs_type : [in] File System type. * @ cluster : [out] cluster index in File system. * @ return 0 if success / return -1 if no free cluster *****************************************************************************************/ error_t vfs_fs_cluster_alloc( uint32_t fs_type, uint32_t * cluster ); /****************************************************************************************** * This function makes all I/O operations required to release all clusters allocated * on IOC device to a given inode, identified by the argument. * Depending on the file system type, it calls the proper, FS specific function. * It is called by the vfs_unlink() function. * It can be executed by a thread running in any cluster. * This function does NOT take any lock. ****************************************************************************************** * @ inode_xp : extended pointer on inode. * @ return 0 if success / return -1 if device access failure. *****************************************************************************************/ error_t vfs_fs_release_inode( xptr_t inode_xp ); #endif /* _VFS_H_ */