= GIET_VM / FAT32 File System = [[PageOutline]] The [source:soft/giet_vm/giet_fat32/fat32.c fat32.c] and [source:soft/giet_vm/giet_fat32/fat32.h fat32.h] files define the GIET_VM File System. == 1) General Principles == This implementation supports only block devices with block_size = 512 bytes. The max size for a single file is 4 Gbytes -1. From the application software point of view, a cluster is the smallest storage allocation unit on the block device : any file (or directory) occupies at least one cluster, and a given cluster cannot be shared by 2 different files. This implementation supports only cluster size = 4 Kbytes (i.e. 8 contiguous blocks on block device). The FAT region on the block device is an array of 32 bits words defining the linked list of clusters allocated to a given file in the DATA region of the block device. The DATA region is actually an array of 4 Kbytes buffers (i.e. an array of clusters). Each slot in the FAT array contains a cluster index, that is the index of the next allocated cluster for a given file. The cluster index in the FAT array is also the cluster index in the DATA region array. The cluster index value cannot be larger than 0x0FFFFFFF (i.e. 256 M). The max addressable storage capacity in the DATA region on the block device is therefore (256 M * 4 Kbytes) = 1 Tbytes. We use the variable ''cluster'' to name the cluster index. This implementation defines four data structures: * The '''File-Cache''' and '''Fat-Cache''' are dynamically allocated memory caches, implemented in the distributed kernel heap. There is actually one independent cache for each file or directory (called File_Cache), and one cache for the FAT itself (called Fat_Cache). The cache size is not fixed: it is dynamically increased from the kernel heap as required by the read / write access to the files, or when new entries are introduced in directories. the directories. Similarly, the Fat-Cache size is dynamically increased as required by the read/write access to the FAT itself. For a file, the memory dynamically allocated to the File-Cache is released when the file is closed by all threads that have a reference on it. For a directory, the memory dynamically allocated to the File-Cache is only released when the directory is removed from the file system. For The Fat-Cache, the memory dynamically allocated is only released at system shut-down. * The '''Inode-Tree''' is an internal representation of the FAT. It is a sub-tree of the File System tree. Each inode define a file or a directory, and contains a pointer on the associated File-Cache. This Inode-Tree is dynamically increased (from the distributed kernel heap) when a new file or a directory is accessed. The memory allocated to the Inode-Tree is only released when the corresponding file or directory is removed from the file system. * The '''File-Descriptor-Array''' is a statically defined array of file descriptors. A private file descriptor is allocated to each thread requiring to open the file, and contains mainly the current file pointer (called ''offset''). The max number of file descriptors is defined by the GIET_OPEN_FILES_MAX global variable (in the ''get_config.h'' file). This array of file descriptors is shared by all applications. * The global '''Fat-Descriptor''' contains general information such as the FAT region lba and size, the DATA region lba and size, pointers on the Fat-Cache and Inode-Tree, the File-Descriptor-Array, and the locks protecting the FAT shared structures. It contains also a single block buffer (512 bytes) used in the initialization phase, and for FS_INFO sector update. To support various block device peripheral, this FAT32 implementation defines a generic function to transparently access various physical block devices, using the driver specified in the ''hard_config.h'' file. Five drivers are presently supported ( IOC_BDV / IOC_HBA / IOC_SDC / IOC_SPI / IOC_RDK ). '''WARNING 1''': A node name (file or directory) cannot be larger than 31 characters. '''WARNING 2''': There is no rescue mechanism (at the moment) in case of kernel heap overflow, when allocating memory for the File-Caches : The system crash with a nice error message on the kernel terminal if the heap defined in the mapping is too small... == 2) Cache Structure & Write Policy == The Fat_Cache and the File_Cache have the same organisation. Each cache contains an integer number of clusters, as the cluster is the smallest unit of data that can be loaded from the block device to a Cache-File. To reduce the access time, this set of clusters is organized as a 64-Tree: each node has one single parent and (up to) 64 children. The leaf nodes are the cluster descriptors. WARNING: To access a given cluster in a given file, we use the ''cluster_id'' variable, that is the index of cluster inside the file. This ''cluster_id'' variable is different from the ''cluster'' variable, that is used to index both the FAT and the DATA region on block device. The cluster_id variable must be split in pieces of 6 bits, that are used to access the proper children at a given level in the 64-Tree. The depth (number of levels) of the 64-Tree depends on the file size : || File Size || levels || || up to 256 Kbytes || 1 || || from 256 Kbytes to 16 Mbytes || 2 || || from 16 Mbytes to 1 Gbytes || 3 || || larger than 1 Gbytes || 4 || For the '''File-Caches''', the GIET_VM implements a '''Write-Back''' policy. In case of write, the data are always modified in the cache. In case of miss, new clusters are allocated to the target file, the cache is updated from the block device if required, and the data are modified in the cache, but not on the block device. The modified clusters are written on the block device only when the last reference is closed, using the dirty flag implemented in each buffer descriptor. For the '''Fat_Cache''', the GIET_VM implements a '''Write-Through''' policy. When the FAT content is modified (i.e. when new clusters are allocated to an existing file, or when a new file (or directory) is created, the modifications are written in the fat_cache (that must be updated in case of miss), and are immediately reported to the block device, for each modified cluster. == 3) Implementation Notes '''File / directory size''' For a file, the number of occupied clusters on the block device can be directly obtained from the attribute, that is a number of bytes stored on block device (in the directory entry), and copied in memory as a specific field in the associated inode. For a directory, the< size> attribute must be set to 0. The number of occupied clusters on block device can be directly obtained from the field in the associated inode: This field is set to 0 for a file, and contain the number of occupied clusters, that cannot be zero, because a directory contains always the '.' and '..' entries. '''File / directory names''' This implementation supports the LFN (long file name) extension, up to 31 characters. Therefore, each file or directory contained in a parent directory occupies several 32 bytes directory entries: * names up to 13 characters occupy 2 entries : one LFN and one NORMAL. * names from 14 to 26 characters occupy 3 entries: two LFN and one NORMAL. * names from 27 to 31 characters occupy 4 entries: three LFN and one NORMAL. When new names are created, a legal 8-3 SFN (Short File Name) alias is generated from the complete new name, and is stored in the NORMAL directory entry, to produce a legal FAT32 image. But this alias SFN is never used by the FAT32 library for file identification. == 4) Extern Functions == === __int '''_fat_init'''( unsigned int kernel_mode )__ === This function initializes the FAT structures. It is called twice, by the boot-loader, and by the kernel_init. The argument defines the initialization mode: * in '''boot mode''' (kernel_mode == 0), it initializes only the statically defined Fat-Descriptor, using informations found in the BOOT sector, that is loaded in the FAT descriptor 512 bytes buffer. In this mode, it is used by the boot code to load the ''kernel.elf'' file, and the various ''application.elf'' files, into memory by accessing directly to the block device. * in '''kernel mode''' (kernel_mode != 0), it uses the distributed kernel heap to initialize the dynamically allocated structures such as the Inode-Tree, the Fat-Cache, and the File-Cache for the root directory. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_open'''( char* pathname , unsigned int flags )__ === This function implements the ''giet_fat_open()'' system call. It allocates a file descriptor to the calling task, for the file identified by the argument. The semantic is similar to the UNIX ''open()'' function, but only the O_CREAT, O_RDONLY and O_TRUNCATE are supported. The UNIX access rights are not supported. If the file does not exist in the specified directory, it is created, and the Inode-Tree, the Fat-Cache and the FAT region on device are updated. If the specified directory does not exist, an error is returned. If several tasks try to open the same file, each task obtains a private file descriptor and the reference count is updated. WARNING : A node name (file or directory) cannot be larger than 31 characters. Returns a file descriptor index on success. Returns a negative value on error. === __int '''_fat_close'''( unsigned int fd_id )__ === This function implements the ''giet_fat_close()'' system call. The semantic is similar to the UNIX ''close()'' function. It decrements the inode reference count for the file identified by the argument. If the reference count is zero, it writes all dirty clusters on block device, and releases the memory allocated to the file_cache: The cache 64-Tree infrastructure (depending on file size) is kept, but all buffers and all buffer descriptors are released. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_file_info'''( unsigned int fd_id , fat_file_info_t* info )__ === This function implements the ''giet_fat_file_info()'' system call. It returns in the argument, the size, offset, and is_dir attributes for a file identified by the argument. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_read'''( unsigned int fd_id , unsigned int vaddr , unsigned int count, unsigned int extend, unsigned int offset , unsigned int modes )__ === This function implements the ''giet_fat_read()'' system call. It accesses the File_Cache associated to the file identified by the argument, and transfers bytes from the cache to the buffer defined by the argument, starting from the current file offset. The argument define the special access modes: If FAT_PADDR_MODE is set, the argument defines the physical address extension. If FAT_FORCED_OFFSET is set, the argument define the actual file offset. In case of miss in the File_Cache, it loads all involved clusters into the cache. Returns the number of bytes actually transferred. Returns a negative value on error. === __int '''_fat_write'''( unsigned int fd_id , unsigned int vaddr , unsigned int count , unsigned int extend , unsigned int modes )__ === This function implements the ''giet_fat_write()'' system call. It accesses the File_Cache associated to the file identified by the argument, and transfers bytes from the buffer defined by the argument to the cache, starting from the current file offset. The argument define the special access modes: If FAT_PADDR_MODE is set, the argument defines the physical address extension. It loads all involved clusters into cache if required. If (offset + count) is larger than the current file size, the file size is increased. It allocates new clusters if required, and updates the Fat-Cache. The FAT region and the FS-INFO sector are updated on block device. As it implements a Write-Back policy, the DATA region on block device is not updated, but the modified clusters are marked dirty. Returns number of bytes actually written on success. Returns a negative value on error. === __int '''_fat_lseek'''( unsigned int fd_id , unsigned int offset , unsigned int whence )__ === This function implements the ''giet_fat_lseek()'' system call. It repositions the offset in the file descriptor defined by the argument, according to the and arguments. The accepted values for the argument are SEEK_SET / SEEK_CUR / SEEK_END : * SEEK_SET => new_offset = offset * SEEK_CUR => new_offset = current_offset + offset * SEEK_END => new_offset = file_size + offset Returns new seek value (in bytes) on success. Returns a negative value on error === __int '''_fat_mkdir'''( char* pathname )__ === This function implements the ''giet_fat_mkdir()'' system call, that has the same semantic as the UNIX ''mkdir()'' function. It creates a new directory in the File System as specified by the argument. The FAT region and the FS_INFO sector on block device are updated. The Inode-Tree is updated. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_remove'''( char* pathname , unsigned int should_be_dir )__ === This function implements the ''giet_fat_unlink()'' system call, that has the same semantic as the UNIX ''unlink()'' function. It removes the file or directory identified by the argument from the File System. An error is returned if the number of references (number of open file descriptors, or number of entries for a directory) is not zero. All clusters allocated to this file in the DATA region are released and the Fat-Cache is updated.. The FAT region and the FS-INFO sector are updated on the block device. The memory allocated to the File_Cache is released. The Inode-Tree is updated. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_rename'''( char* old_path , new_path )__ === This function implements the ''giet_fat_rename()'' system call. It moves an existing file or directory in the FS tree, from one node, defined by the argument to another node, defined by the argument. The type (file/directory) and content are not modified. If the new_path file/dir exist, it is removed from the file system, but only if the remove condition is respected (directory empty / file not referenced). The removed entry is only removed after the new entry is actually created. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_opendir'''( char* pathname )__ === This function implements the ''giet_fat_opendir()'' system call. The semantic is similar to the UNIX ''opendir()'' function. If the directory specified by the argument does not exist, an error is returned. It allocates a file descriptor to the calling task. If several tasks try to open the same directory, each task obtains a private file descriptor. A node name cannot be larger than 31 characters. Returns a file descriptor for the directory index on success. Returns a negative value on error. === __int '''_fat_closedir'''( unsigned int fd_id )__ === This function implements the ''giet_fat_closedir()'' system call. Same behavior as _fat_close(), no check for directory. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_readdir'''( unsigned int fd_id, fat_dirent_t* entry )__ === This function implements the ''giet_fat_readdir()'' system call. It reads one directory entry from the directory identified by the argument provided by ''giet_fat_opendir()''. It returns the following attributes in the argument : cluster , size , is_dir , and name. Returns GIET_FAT32_OK on success. Returns a negative value on error. === __int '''_fat_load_no_cache'''( char* pathname , unsigned int buffer_vbase , unsigned int buffer_size )__ === This function load a file identified by the argument into the memory buffer defined by the and arguments. It is intended to be called by the boot-loader, as it uses neither the dynamically allocated FAT structures (Inode-Tree, Fat_Cache or File-Cache), nor the File-Descriptor-Array. It uses only the 512 bytes buffer defined in the FAT descriptor. Returns GIET_FAT32_OK on success. Returns negative value on error. === __int '''_get_file_cache_buffer'''( fat_node_t* indoor , unsigned int cluster_id , unsigned int writable , fat_cache_desc_t** desc )__ === This function returns in the argument a pointer on a buffer descriptor contained in a File_Cache, handling the possible miss. The searched file or directory is identified by the argument. The argument is the buffer index in the File-Cache. The argument define the behaviour in case of miss in the File-Cache: * if [cluster_id already allocated in FAT] it scan the FAT to find the cluster index on device, and load the missing cluster in the File-Cache, marked as dirty if writable is set. * if [writable and cluster_id not allocated in FAT], it allocates in FAT the required cluster, it updates the size attribute (for a file), or the is_dir attribute (for a directory), and load the missing cluster in the File-Cache, marked as dirty. * if [not writable and cluster_id not allocated in FAT] it returns an error. This function is called by various FAT functions to access a file or a directory, but is also called by the _sys_fat_mmap() function. It does not take the FAT lock, that must be taken by the caller. It returns GIET_FAT32_OK on success, and returns a negative value on error. === __int '''_get_fat_cache_buffer'''( unsigned int cluster_id , fat_cache_desc** desc )__ === This function returns in the argument a pointer on a buffer descriptor contained in the Fat_Cache. The argument is the buffer index in the FAT_Cache. In case of miss, a 4 Kbytes buffer and a buffer descriptor are allocated from the local heap, and the missing cluster is loaded in the Fat_Cache. It returns GIET_FAT32_OK on success, and returns a negative value on error. === __int '''_fat_ioc_access'''( unsigned int use_irq , unsigned int to_mem , unsigned int lba , unsigned int buf_vaddr , unsigned int count )__ === This function transfers one or several blocks between the block device and a memory buffer by calling the relevant driver. The boolean argument forces the descheduling mode if supported by the IOC driver. The boolean argument defines the transfer direction (from block device to memory if non zero). The argument is the first block address on the block device. The argument is the memory buffer virtual address. The argument is the number of blocks to be transferred. It returns 0 on success, or a negative value on failure. == 5) Internal functions == === __void '''_display_cluster_list'''()__ === This debug function displays the list of clusters allocated to one file or directory. === __void '''_display_fat_descriptor'''()__ === This debug function displays the FAT descriptor content. === __void '''_get_name_from_long'''( unsigned char* buffer , char* name )__ === This function extract a (partial) name from a LFN directory entry. === __void '''_get_name_from_short'''( unsigned char* buffer , char* name )__ === This function extract a from a NORMAL directory entry. === __unsigned int '''_get_levels_from_size'''( unsigned int size )__ === This function returns the number of levels of a File-Cache from the of the file. === __unsigned int '''_get_name_from_path'''( char* pathname , char* name , unsigned int* nb_read )__ === This function analyses the argument, from the character defined by the argument. It copies the found name in the buffer (without '/'), and updates the argument. It returns 0 on success. It returns 1 if one name length > NAME_MAX_SIZE characters. === __unsigned int '''_get_last_name'''( char* pathname , char* name )__ === This function scan the argument, and copies in the buffer the last name in the . It returns 0 on success.It returns 1 if one name length > NAME_MAX_SIZE characters. === __unsigned int '''_get_fat_entry'''( unsigned int cluster , unsigned int* value )__ === This function accesses the Fat-Cache and returns in the argument the content of the FAT slot identified by the argument. It loads the missing cluster from block device in the Fat-Cache in case of miss. It returns 0 on success. It returns 1 on error. === __unsigned int '''_set_fat_entry'''( unsigned int cluster , unsigned int value )__ === This function writes a new in the Fat-Cache, in the slot identified by the argument. It loads the missing cluster from block device in the Fat-Cache in case of miss. It returns 0 on success, It returns 1 on error. === __void '''_add_inode_in_tree'''( fat_inode_t* child , fat_inode_t* parent )__ === This function introduces the inode identified by the argument as a new child for the inode in the Inode-Tree. All checking are supposed to be done by the caller. Nor the File-Cache, neither the block device are modified. === __void '''_remove_inode_from_tree'''( fat_inode_t* inode )__ === This function removes one inode identified by the argument from the Inode-Tree. All checking are supposed to be done by the caller. Nor the File-Cache, neither the block device are modified. === __unsigned int '''_update_device_from_cache'''( unsigned int levels , fat_cache_node_t* root , char* string )__ === This recursive function scan one File-Cache (or the Fat-Cache) from root to leaves, to writes all dirty clusters to block device, and reset the dirty bits. The cache is identified by the an arguments. The argument is only used for debug. It returns 0 on success. It returns 1 on error. === __unsigned int '''_update_fs_info()'''__ === This function accesses directly the FS_INFO block on the block device, to update the "first_free_cluster" and "free_clusters_number" values, using only the Fat-Descriptor single block buffer. It return 0 on success. It return 1 on error. === __unsigned int '''_read_entry'''( unsigned int offset , unsigned int size , unsigned char* buffer , unsigned int little_indian )__ === This function read a data field (one to four bytes) from an unsigned char[] , taking endianness into account. The analysed field is defined by the and arguments. === __unsigned int '''_cluster_to_lba'''( unsigned int cluster )__ === This function returns the lba (logic block address in DATA region) from the index. Exit if the cluster value is smaller than 2. === __unsigned int '''_get_nb_entries'''( fat_inode_t* inode , unsigned int* nb_entries )__ === This function returns in the argument the number of entries contained in a directory identified by the pointer. It returns 0 on success. It returns 1 on error. === __unsigned int '''_get_child_from_parent'''( fat_inode_t* parent , char* name , fat_inode_t** inode )__ === This function search in the directory identified by the inode pointer a child (file or directory) identified by its . It returns in the argument the searched child inode pointer. If the searched name is not found in the Inode-Tree, the function accesses the File-cache associated to the parent directory. If the child exists on block device, the Inode-Tree is updated, and a success code is returned. If the file/dir does not exist on block device, a error code is returned. It returns 0 if inode found. It returns 1 if inode not found. It returns 2 in case of error in cache access. === __unsigned int '''_get_inode_from_path'''( char* pathname , fat_inode_t** inode )__ === For a file (or a directory) identified by the argument, this function returns in the argument the inode pointer associated to the searched file (or directory), with code (0). If the searched file (or directory) is not found, but the parent directory is found, it returns in the argument the pointer on the parent inode, with code (1). Code (2) and code (3) are error codes. Both the Inode-Tree and the involved Cache-Files are updated from the block device in case of miss on one inode during the search. Neither the Fat-Cache, nor the block device are updated. It returns 0 if searched inode found It returns 1 if searched inode not found but parent directory found. It returns 2 if searched inode not found and parent directory not found. It returns 3 if one name too long === __unsigned int '''_is_ancestor'''( fat_inode_t* a , fat_inode_t* b )__ === This function checks if inode is an ancestor of inode . It returns 1 if it is true. === __unsigned int '''_get_sfn_name'''( char* name , unsigned int* length , unsigned int* nb_lfn, char* sfn , unsigned char* checksum )__ === This function returns in the and arguments the name length and the number of LFN entries required to store the string. It returns in the argument a legal SFN name extracted from the string (upper case and 8-3 format). It returns in the argument the SFN checksum. * Short name (less than 13 characters) require 1 LFN entry. * Medium names (from 14 to 26 characters require 2 LFN entries. * Large names (up to 31 characters) require 3 LFN entries. It returns 0 on success. It returns 1 if the name length is larger than 31 characters. === __unsigned int '''_update_dir_entry'''( fat_inode_t* inode )__ === For a node identified by the argument, this function updates the "size" and "cluster" fields in the parent directory entry File-Cache, from values defined in the argument. It set the dirty bit in the modified buffer of the parent directory File-Cache. It returns 0 on success. It returns 1 if error. === __unsigned int '''_add_dir_entry'''( fat_inode_t* child , fat_inode_t* parent )__ === This function add a new entry in the Cache-File of the directory. It accesses the File_Cache associated to the parent directory, and scan the clusters allocated to this directory to find the NO_MORE entry, that will be the first modified entry in the directory. Regarding the name storage, it uses LFN entries for all names, but computes a legal (upper case / 8-3) SFN name that will be stored in the NORMAL entry. It writes 1, 2, or 3 LFN entries (depending on the child name actual length), writes one NORMAL entry, and writes the new NO_MORE entry. It updates the dentry field in the child inode. It set the dirty bit for all modified File-Cache buffers. The block device is not modified by this function. It returns 0 on success. It returns 1 in case of error. === __unsigned int '''_remove_dir_entry'''( fat_inode_t* inode )__ === This function invalidates all dir_entries associated to the argument from its parent directory. It set the dirty bit for all modified buffers in parent directory Cache-File. The inode itself is not modified by this function. The block device is not modified by this function. It returns 0 on success. It returns 1 in case of error. === __void '''_add_special_directories'''( fat_inode_t* child , fat_inode_t* parent )__ === This function adds the special entries "." and ".." in the File-Cache of the directory identified by the argument. The parent directory is defined by the argument. The child directory File-Cache is supposed to be empty. We use two NORMAL entries for these "." and ".." entries. The block device is not modified by this function. === __unsigned int '''_one_cluster_allocate'''( fat_inode_t* inode , unsigned int* cluster )__ === This function allocates one cluster in FAT to a file (or directory) identified by the argument. The allocated cluster index is returned in the argument. It allocates also the associated buffers and buffer descriptors in Cache-File. It calls _get_fat_entry() and _set_fat_entry() functions to update the clusters chaining in the Cache-Fat. The FAT region and the FS-INFO sector on block device are also updated. It returns 0 on success. It returns 1 on error. === __unsigned int '''_all_clusters_release'''( fat_node_t* inode )__ === This function releases all clusters allocated to a file or directory identified by the argument, until the end of the FAT linked list. It calls the _cluster release() recursive function to release the clusters in reverse order (from last to first), using the _get_fat_entry() and _set_fat_entry() functions to access the FAT, and update the clusters chaining. The FAT region and the FS-INFO sector on block device are also updated. It returns 0 on success. It returns 1 on error. === __void '''_release_cache_memory'''( fat_cache_node_t* root , unsigned int levels )__ === This recursive function scans one File-Cache (or Fat-Cache) from root to leaves. All memory allocated for 4KB buffers, and buffer descriptors (in leaves) is released, along with the 64-Tree structure (root node is kept). The released cache is identified by the and arguments. It should not contain any dirty clusters. === __fat_cache_node_t* '''_allocate_one_cache_node'''( fat_cache_node_t* first_child )__ === This function allocates and initializes a new cache node. Its first child can be specified (used when adding a cache level). The 63 other children are set to NULL. It returns a pointer to the new Fat-Cache node. === __fat_inode_t* '''_allocate_one_inode'''( char* name , unsigned int is_dir , unsigned int cluster , unsigned int size , unsigned int count , unsigned int dentry , unsigned int cache_allocate )__ === This function allocates and initializes a new inode, using the values defined by the , , , , , and arguments. If the argument is true, an empty cache is allocated. It returns a pointer on the new inode. === __void '''_allocate_one_buffer'''( fat_inode_t* inode , unsigned int cluster_id , unsigned int cluster )__ === This function allocates a 4 Kbytes buffer and the associated cluster descriptor from the heap[x,y] defined by the calling thread, for the file (or directory) identified by the argument. It updates the Cache_File slot identified by the argument. The File-Cache slot must be empty. It updates the buffer descriptor, using the argument, that is the cluster index in FAT. The buffer descriptor dirty bit is set. It traverses the 64-tree Cache-file from top to bottom to find the last level. === __unsigned int '''_get_free_cluster'''( unsigned int* cluster )__ == This function scan the Fat-Cache from the "_free_cluster_hint" global variable to find the first free cluster index, and return this cluster index in the argument. It does not update any data structure: nor the Fat-Cache, neither the FAT descriptor. It returns 0 on success. It returns 1 on error. === __unsigned int '''_remove_node_from_fs'''( fat_inode_t* inode )__ === This function remove from the file system a file or a directory identified by the argument. The remove conditions must be checked by the caller. The relevant lock(s) must have been taken by te caller. It returns 0 on success. It returns 1 on error. === __unsigned int '''_file_info_no_cache'''( char* pathname , unsigned int* file_cluster , unsigned int* file_size )__ === This function returns in the and arguments the cluster index and the size for a file identified by the argument, scanning directly the block device DATA region. It is intended to be called only by the _fat_load_no_cache() function, as it does not use the dynamically allocated File-Caches, but uses only the 4 Kbytes _fat_buffer_data. It returns 0 on success. It returns 1 on error. === __unsigned int '''_next_cluster_no_cache'''( unsigned int cluster , unsigned int* next )__ === This function scan directly the FAT region on the block device, and returns in the argument the value stored in the fat slot identified by the argument. It is intended to be called only by the _fat_load_no_cache() function, as it does not use the dynamically allocated Fat-Cache, but uses only the 4 Kbytes _fat_buffer_fat. It returns 0 on success. It returns 1 on error. === __int '''get_length'''( int offset , int length )__ === This function returns the the size (bytes) of a FAT field, identified by an mnemonic defined in the fat32.h file. === __int '''get_offset'''( int offset , int length )__ === This function returns the the offset (bytes) of a FAT field, identified by an mnemonic defined in the fat32.h file.