Ignore:
Timestamp:
Dec 3, 2018, 12:15:53 PM (5 years ago)
Author:
alain
Message:

Improve the FAT32 file system to support cat, rm, cp commands.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/fs/fatfs.h

    r484 r602  
    33 *
    44 * Author    Mohamed Lamine Karaoui (2014,2015)
    5  *           Alain Greiner (2016,2017)
     5 *           Alain Greiner (2016,2017,2018)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    2727
    2828#include <hal_kernel_types.h>
    29 #include <rwlock.h>
     29#include <remote_queuelock.h>
    3030#include <vfs.h>
    3131
     
    3535//
    3636// The FATFS extensions to the generic VFS are the following:
     37//
    3738// 1) The vfs_ctx_t "extend" field is a void* pointing on the fatfs_ctx_t structure.
    3839//    This structure contains various general informations such as the total
     
    4142//    cluster index for the root directory. It contains also an extended pointer
    4243//    on the FAT mapper.
    43 // 2) The vfs_inode_t "extend" field is a void*, but contains for each inode,
     44//
     45// 2) The vfs_inode_t "extend" contains, for each inode,
    4446//    the first FAT cluster index (after cast to intptr).
     47//
     48// 3) The vfs_dentry_t "extend" field contains, for each dentry, the entry index
     49//    in the FATFS directory (32 bytes per FATFS entry).
    4550///////////////////////////////////////////////////////////////////////////////////////////
    4651
     
    163168struct vfs_ctx_s;
    164169struct vfs_inode_s;
    165 
    166 /*****************************************************************************************
    167  * This structure defines a FATFS specific context (extension to VFS context).
     170struct vfs_dentry_s;
     171
     172/*****************************************************************************************
     173 * This structure defines a FATFS specific context (extension to VFS context).
     174 * This extension is replicated in all clusters.
     175 *
     176 * WARNING : Almost all fields are constant values, but the <free_cluster_hint> and
     177 * <free_clusters> are shared variables. All kernel instances use the variables
     178 * in cluster 0, using the <free_lock> remote busy_lock for exclusive access.
    168179 ****************************************************************************************/
    169180
    170181typedef struct fatfs_ctx_s
    171182{
    172     uint32_t          fat_sectors_count;     /*! number of sectors in FAT region        */
    173     uint32_t          bytes_per_sector;      /*! number of bytes per sector             */
    174     uint32_t          sectors_per_cluster;   /*! number of sectors per cluster          */
    175     uint32_t          fat_begin_lba;         /*! lba of FAT region                      */
    176     uint32_t          cluster_begin_lba;     /*! lba of data region                     */
    177     uint32_t          root_dir_cluster;      /*! cluster index for the root directory   */
    178     uint32_t          last_allocated_sector; /*! TODO ???                               */
    179     uint32_t          last_allocated_index;  /*! TODO ???                               */
    180     xptr_t            fat_mapper_xp;         /*! FAT mapper (in IO cluster)             */
     183    uint32_t            fat_sectors_count;     /*! number of sectors in FAT region      */
     184    uint32_t            bytes_per_sector;      /*! number of bytes per sector           */
     185    uint32_t            sectors_per_cluster;   /*! number of sectors per cluster        */
     186    uint32_t            fat_begin_lba;         /*! lba of FAT region                    */
     187    uint32_t            cluster_begin_lba;     /*! lba of data region                   */
     188    uint32_t            fs_info_lba;           /*! lba of FS_INFO sector                */
     189    uint32_t            root_dir_cluster;      /*! cluster index for  root directory    */
     190    xptr_t              fat_mapper_xp;         /*! extended pointer on FAT mapper       */
     191    uint32_t            free_cluster_hint;     /*! start point to search free cluster   */
     192    uint32_t            free_clusters;         /*! free clusters number                 */
     193    remote_queuelock_t  free_lock;             /*! exclusive access to hint & number    */
    181194}
    182195fatfs_ctx_t;
     
    186199//////////////////////////////////////////////////////////////////////////////////////////
    187200
    188 /******************************************************************************************
    189  * This function scan the FAT (File Allocation Table), stored in the FAT mapper,
    190  * and returns the FATFS cluster index for a given page of a given file.
    191  * It must be called by a thread running in the cluster containing the FAT mapper.
    192  * We can use a RPC to scan the remote FAT mapper, because the RPC_FIFO will avoid
    193  * contention in the cluster containing the FAT mapper, and the RPC latency is not
    194  * critical compared to the device access latency.
     201/*****************************************************************************************
     202 * This function access the FAT (File Allocation Table), stored in the FAT mapper, and
     203 * returns in <searched_cluster> the FATFS cluster index for a given page of a given
     204 * inode identified by the <first_cluster> and <page_id> arguments.
     205 * It can be called by a thread running in any cluster, as it uses remote access
     206 * primitives when the FAT mapper is remote.
    195207 * The FAT is actually an array of uint32_t slots. Each slot in this array contains the
    196208 * index of another slot in this array, to form one linked list for each file stored on
     
    198210 * FATFS cluster on the device. One FATFS cluster is supposed to contain one PPM page.
    199211 * For a given file, the entry point in the FAT is simply the index of the FATFS cluster
    200  * containing the first page of the file. The mapper being a cache, this function
    201  * automatically updates the FAT mapper from informations stored on device in case of miss.
    202  ******************************************************************************************
    203  * @ mapper                  : local pointer on the FAT mapper.
    204  * @ first_cluster       : index of the first FATFS cluster allocated to the file.
    205  * @ page_index          : index of searched page in file.
    206  * @ searched_cluster_id : [out] found FATFS cluster index.
    207  * @ return 0 if success / return EIO if a FAT mapper miss cannot be solved.
    208  *****************************************************************************************/
    209 error_t fatfs_get_cluster( struct mapper_s * mapper,
    210                            uint32_t          first_cluster,
    211                            uint32_t          page_index,
    212                            uint32_t        * searched_cluster_id );
    213 
    214 /******************************************************************************************
     212 * containing the first page of the file. The FAT mapper being a cache, this function
     213 * updates the FAT mapper from informations stored on IOC device in case of miss.
     214 *****************************************************************************************
     215 * @ first_cluster       : [in]  index of first FATFS cluster allocated to the file.
     216 * @ page_id             : [in]  index of searched page in file.
     217 * @ searched_cluster    : [out] found FATFS cluster index.
     218 * @ return 0 if success / return -1 if a FAT mapper miss cannot be solved.
     219 ****************************************************************************************/
     220error_t fatfs_get_cluster( uint32_t   first_cluster,
     221                           uint32_t   page_id,
     222                           uint32_t * searched_cluster );
     223
     224/*****************************************************************************************
    215225 * This function display the content of the FATFS context.
    216  *****************************************************************************************/
     226 ****************************************************************************************/
    217227void fatfs_ctx_display( void );
    218228
     229/*****************************************************************************************
     230 * This function displays the content of a part of the File Allocation Table.
     231 * It loads the requested page fom device to mapper if required.
     232 *****************************************************************************************
     233 * @ page_id   : page index in FAT mapper (one page is 4 Kbytes).
     234 * @ nentries  : number of entries (one entry is 4 bytes).
     235 ****************************************************************************************/
     236void fatfs_display_fat( uint32_t  page_id,
     237                        uint32_t  nentries );
     238
     239
    219240
    220241//////////////////////////////////////////////////////////////////////////////////////////
    221 // Generic API: These functions are called by the kernel,
     242// Generic API: These functions are called by the kernel VFS,
    222243//              and must be implemented by all File Systems.
    223244//////////////////////////////////////////////////////////////////////////////////////////
    224245
    225 /******************************************************************************************
     246/*****************************************************************************************
    226247 * This fuction allocates memory from local cluster for a FATFS context descriptor.
    227  ******************************************************************************************
     248 *****************************************************************************************
    228249 * @ return a pointer on the created context / return NULL if failure.
    229  *****************************************************************************************/
     250 ****************************************************************************************/
    230251fatfs_ctx_t * fatfs_ctx_alloc( void );
    231252
    232253/*****************************************************************************************
    233  * This function access the boot device, and initialises the FATFS context
     254 * This function access the boot device, and initialises the local FATFS context
    234255 * from informations contained in the boot record.
    235256 *****************************************************************************************
     
    246267
    247268/*****************************************************************************************
    248  * This function moves a page from/to the mapper to/from the FATFS file system on device.
    249  * It must be called by a thread running in cluster containing the mapper.
    250  * The pointer on the mapper and the page index in file are found in the page descriptor.
    251  * WARNING : The inode field in the mapper MUST be NULL for the FAT mapper, as this
    252  * is used to implement a specific behaviour to access the FAT zone on device.
    253  *****************************************************************************************
    254  * @ page      : local pointer on page descriptor.
    255  * @ to_mapper : transfer direction
    256  * @ return 0 if success / return EIO if error.
    257  ****************************************************************************************/
    258 error_t fatfs_mapper_move_page( struct page_s * page,
    259                                 bool_t          to_mapper );
    260 
    261 /*****************************************************************************************
    262  * This function scan an existing parent directory, identified by the <parent> argument,
    263  * to find a directory entry identified by the <name> argument and update the remote
    264  * child inode descriptor, identified by the <child_xp> argument.
    265  * It set the "type", "size", and "extend" (FAT cluster index) fields in child inode.
     269 * This function implements the generic vfs_fs_add_dentry() function for the FATFS.
     270 *****************************************************************************************
     271 * This function updates a directory identified by the <inode> argument
     272 * to add a new directory entry identified by the <dentry> argument.
     273 * All modified pages in directory mapper are synchronously updated on IOC device.
     274 * It must be called by a thread running in the cluster containing the inode.
     275 *
     276 * Implementation note : this function works in two steps:
     277 * - It scan the set of 32 bytes FATFS directry entries, using two embedded loops 
     278 *   to find the end of directory (NO_MORE_ENTRY marker).
     279 * - Then it writes 3, 4, or 5 directory entries (depending on the name length), using
     280 *   a 5 steps FSM (one state per entry to be written), updates on IOC device the
     281 *   modified pages, and updates the dentry extension field, that must contain
     282 *   the dentry index in FATFS directory.
     283 *****************************************************************************************
     284 * @ inode    : local pointer on directory inode.
     285 * @ dentry   : local pointer on dentry.
     286 * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device.
     287 ****************************************************************************************/
     288error_t fatfs_add_dentry( struct vfs_inode_s  * inode,
     289                          struct vfs_dentry_s * dentry );
     290
     291/*****************************************************************************************
     292 * This function implements the generic vfs_fs_remove_dentry() function for the FATFS.
     293 *****************************************************************************************
     294 * This function updates a directory identified by the <inode> argument
     295 * to remove a directory entry identified by the <dentry> argument.
     296 * All modified pages in directory mapper are synchronously updated on IOC device.
     297 * It must be called by a thread running in the cluster containing the inode.
     298 *
     299 * Implementation note: this function uses the dentry extension to directly access
     300 * the NORMAL directory entry and invalidate all involved LFN entries. Then it
     301 * updates the modified pages on IOC device.
     302 *****************************************************************************************
     303 * @ inode    : local pointer on directory inode.
     304 * @ dentry   : local pointer on dentry.
     305 * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device.
     306 ****************************************************************************************/
     307error_t fatfs_remove_dentry( struct vfs_inode_s  * inode,
     308                             struct vfs_dentry_s * dentry );
     309
     310/*****************************************************************************************
     311 * This function implements the generic vfs_fs_child_init() function for the FATFS.
     312 *****************************************************************************************
     313 * It scan the mapper of an existing parent directory, identified by the <parent>
     314 * argument, to find a directory entry identified by the <name> argument.
     315 * It updates the existing remote child inode, identified by the <child_xp> argument,
     316 * - it set the "type", "size", and "extend" fields in inode descriptor.
     317 * - it set the " extend" field in dentry descriptor.
    266318 * It must be called by a thread running in the cluster containing the parent inode.
    267319 *****************************************************************************************
     
    271323 * @ return 0 if success / return ENOENT if child not found.
    272324 ****************************************************************************************/
    273 error_t fatfs_inode_load( struct vfs_inode_s * parent_inode,
     325error_t fatfs_child_init( struct vfs_inode_s * parent_inode,
    274326                          char               * name,
    275327                          xptr_t               child_inode_xp );
    276328
     329/*****************************************************************************************
     330 * This function implements the generic vfs_fs_sync_inode() function for the FATFS.
     331 *****************************************************************************************
     332 * It updates the FATFS on the IOC device for a given inode identified by
     333 * the <inode> argument. It scan all pages registered in the associated mapper,
     334 * and copies from mapper to device each page marked as dirty.
     335 * WARNING : The target <inode> cannot be a directory, because all modifications in a
     336 * directory * are synchronously done on the IOC device by the two fatfs_add_dentry()
     337 * and fatfs_remove_dentry() functions.
     338 *****************************************************************************************
     339 * @ inode   : local pointer on inode.
     340 * @ return 0 if success / return EIO if failure during device access.
     341 ****************************************************************************************/
     342error_t fatfs_sync_inode( struct vfs_inode_s * inode );
     343
     344/*****************************************************************************************
     345 * This function implements the generic vfs_fs_sync_fat() function for the FATFS.
     346 *****************************************************************************************
     347 * It updates the FATFS on the IOC device for the FAT itself.
     348 * It scan all clusters registered in the FAT mapper, and copies from mapper to device
     349 * each page marked as dirty.
     350 *
     351 * TODO : the current implementation check ALL pages in the FAT region, even if most
     352 * pages are empty, and not copied in mapper. It is sub-optimal.
     353 * - A first solution is to maintain in the FAT context two "dirty_min" and "dirty_max"
     354 *  variables defining the smallest/largest dirty page index in FAT mapper...
     355 *****************************************************************************************
     356 * @ return 0 if success / return EIO if failure during device access.
     357 ****************************************************************************************/
     358error_t fatfs_sync_fat( void );
     359
     360/*****************************************************************************************
     361 * This function implements the generic vfs_fs_sync_fsinfo() function for the FATFS.
     362 *****************************************************************************************
     363 * It updates the FS_INFO sector on the IOC device.
     364 * It copies the <free_cluster_hint> and <free_clusters> variables from
     365 * the FATFS context in cluster 0 to the FS_INFO sector on device.
     366 *****************************************************************************************
     367 * @ return 0 if success / return EIO if failure during device access.
     368 ****************************************************************************************/
     369error_t fatfs_sync_free_info( void );
     370
     371/*****************************************************************************************
     372 * This function implements the generic vfs_fs_cluster_alloc() function for the FATFS.
     373 *****************************************************************************************
     374 * It access the FAT (File allocation table), stored in the FAT mapper, and returns
     375 * in <searched_cluster> the FATFS cluster index of a free cluster.
     376 * It can be called by a thread running in any cluster, as it uses remote access
     377 * primitives when the FAT mapper is remote. It takes the "free_lock" stored in the
     378 * FATFS context located in the same cluster as the FAT mapper itself, to get exclusive
     379 * access to the FAT. It uses (and updates) the <free_cluster_hint> and <free_clusters>
     380 * shared variables in this FATFS context.
     381 * It updates the FAT mapper, and synchronously updates the FAT region on IOC device.
     382 * The FAT mapper being a cache, this function updates the FAT mapper from informations
     383 * stored on IOC device in case of miss.
     384 *****************************************************************************************
     385 * @ searched_cluster    : [out] found FATFS cluster index.
     386 * @ return 0 if success / return -1 if no more free clusters on IOC device.
     387 ****************************************************************************************/
     388error_t fatfs_cluster_alloc( uint32_t * searched_cluster );
     389
     390/*****************************************************************************************
     391 * This function implements the generic vfs_fs_release_inode() function for the FATFS.
     392 *****************************************************************************************
     393 * It releases all clusters allocated to a file/directory identified by the <inode_xp>
     394 * argument. All released clusters are marked FREE_CLUSTER in the FAT mapper.
     395 * This function calls the recursive function fatfs_cluster_release() to release
     396 * the clusters in reverse order of the linked list (from last to first).
     397 * When the FAT mapper has been updated, it calls the fatfs_sync_fat() function to
     398 * synchronously update all dirty pages in the FAT mapper to the IOC device.
     399 * Finally the FS-INFO sector on the IOC device is updated.
     400 *****************************************************************************************
     401 * @ inode_xp   : extended pointer on inode.
     402 * @ return 0 if success / return EIO if failure during device access.
     403 ****************************************************************************************/
     404error_t fatfs_release_inode( xptr_t inode_xp );
     405
     406/*****************************************************************************************
     407 * This function implements the generic vfs_fs_move_page() function for the FATFS.
     408 *****************************************************************************************
     409 * This function moves a page from/to the mapper to/from the FATFS file system on device.
     410 * The page must have been previously allocated and registered in the mapper, but the 
     411 * page - and the mapper - can be located in another cluster than the calling thread.
     412 * The pointer on the mapper and the page index in file are found in the page descriptor.
     413 * It is used both for the regular file/directory mappers, and for the FAT mapper.
     414 * For the FAT mapper, it access the FATFS to get the location on IOC device.
     415 * For a regular file, it access the FAT mapper to get the cluster index on IOC device.
     416 * It can be called by any thread running in any cluster.
     417 *
     418 * WARNING : For the FAT mapper, the inode field in the mapper MUST be NULL, as this
     419 * is used to indicate that the corresponding mapper is the FAT mapper.
     420 *****************************************************************************************
     421 * @ page_xp   : extended pointer on page descriptor.
     422 * @ to_mapper : true for device->mapper / false for mapper->device
     423 * @ return 0 if success / return EIO if error during device access.
     424 ****************************************************************************************/
     425error_t fatfs_move_page( xptr_t  page_xp,
     426                         bool_t  to_mapper );
     427
     428
     429
     430
     431
     432
    277433#endif  /* _FATFS_H_ */
Note: See TracChangeset for help on using the changeset viewer.