Changeset 657 for trunk/kernel/fs


Ignore:
Timestamp:
Mar 18, 2020, 11:16:59 PM (5 years ago)
Author:
alain
Message:

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

Location:
trunk/kernel/fs
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/fs/devfs.c

    r637 r657  
    33 *
    44 * Author   Mohamed Lamine Karaoui (2014,2015)
    5  *          Alain Greiner (2016,2017,2018,2019)
     5 *          Alain Greiner (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) Sorbonne Universites
     
    5353#endif
    5454
    55 /////////////////////////////////////
    56 devfs_ctx_t * devfs_ctx_alloc( void )
     55///////////////////////////////////
     56xptr_t devfs_ctx_alloc( cxy_t cxy )
    5757{
    5858    kmem_req_t    req;
     
    6262    req.flags   = AF_KERNEL | AF_ZERO;
    6363
    64         return kmem_alloc( &req );
     64    // allocates devfs context from target cluster
     65        return XPTR( cxy , kmem_remote_alloc( cxy , &req ) );
    6566}
    6667
    6768/////////////////////////////////////////////
    68 void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
    69                      xptr_t        devfs_dev_inode_xp,
    70                      xptr_t        devfs_external_inode_xp )
     69void devfs_ctx_init( xptr_t     devfs_ctx_xp,
     70                     xptr_t     devfs_dev_inode_xp,
     71                     xptr_t     devfs_external_inode_xp )
    7172{
    72     devfs_ctx->dev_inode_xp      = devfs_dev_inode_xp;
    73     devfs_ctx->external_inode_xp = devfs_external_inode_xp;
    74 
    75     fs_context[FS_TYPE_DEVFS].extend = devfs_ctx;
     73    // get cluster and local pointer on remote devfs context
     74    devfs_ctx_t * devfs_ctx_ptr = GET_PTR( devfs_ctx_xp );
     75    cxy_t         devfs_ctx_cxy = GET_CXY( devfs_ctx_xp );
     76
     77    // set values in remote devfs context
     78    hal_remote_s64( XPTR( devfs_ctx_cxy  , &devfs_ctx_ptr->dev_inode_xp ),
     79                    devfs_dev_inode_xp );
     80
     81    hal_remote_s64( XPTR( devfs_ctx_cxy  , &devfs_ctx_ptr->external_inode_xp ),
     82                    devfs_external_inode_xp );
     83
     84    // register devfs context in the remote fs_context array[]
     85    hal_remote_spt( XPTR( devfs_ctx_cxy , &fs_context[FS_TYPE_DEVFS].extend ),
     86                          devfs_ctx_ptr );
    7687}
    7788
    78 /////////////////////////////////////////////////
    79 void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx )
     89//////////////////////////////////////////////
     90void devfs_ctx_destroy( xptr_t  devfs_ctx_xp )
    8091{
    8192    kmem_req_t    req;
    8293
     94    // get cluster and local pointer on devfs context
     95    devfs_ctx_t * devfs_ctx_ptr = GET_PTR( devfs_ctx_xp );
     96    cxy_t         devfs_ctx_cxy = GET_CXY( devfs_ctx_xp );
     97
    8398    req.type = KMEM_KCM;
    84     req.ptr  = devfs_ctx;
    85     kmem_free( &req );
     99    req.ptr  = devfs_ctx_ptr;
     100
     101    // release devfs context descriptor to remote cluster
     102    kmem_remote_free( devfs_ctx_cxy , &req );
    86103}
    87104
     
    95112    vfs_inode_t * inode;
    96113
     114    // get
     115
    97116    // create DEVFS "dev" inode in cluster 0
    98117    error = vfs_add_child_in_parent( 0,                // cxy
     
    158177///////////////////////////////////////////////////
    159178void devfs_local_init( xptr_t   devfs_dev_inode_xp,
    160                        xptr_t   devfs_external_inode_xp,
    161                        xptr_t * devfs_internal_inode_xp )
     179                       xptr_t   devfs_external_inode_xp )
    162180{
     181    xptr_t        internal_inode_xp;   // extended pointer on <internal> inode
     182    vfs_inode_t * internal_inode_ptr;  // local pointer on <internal> inode
    163183    char          node_name[16];
    164184    xptr_t        chdev_xp;
     
    168188    vfs_inode_t * inode_ptr;
    169189    uint32_t      channel;
    170     xptr_t        unused_xp;    // required by add_child_in_parent()
     190    xptr_t        unused_xp;           // required by add_child_in_parent()
    171191    error_t       error;
     192   
    172193
    173194#if DEBUG_DEVFS_LOCAL_INIT
     
    179200#endif
    180201
    181     // create "internal" directory
     202    // create <internal> directory
    182203    snprintf( node_name , 16 , "internal_%x" , local_cxy );
    183204
    184     error = vfs_add_child_in_parent( local_cxy,
    185                                      FS_TYPE_DEVFS,
    186                                      devfs_dev_inode_xp,
    187                                      node_name,
     205    error = vfs_add_child_in_parent( local_cxy,              // target cluster
     206                                     FS_TYPE_DEVFS,          // FS type
     207                                     devfs_dev_inode_xp,     // parent inode
     208                                     node_name,              // child name
    188209                                     &unused_xp,
    189                                      devfs_internal_inode_xp );
    190 
    191     // set inode "type" field
    192     inode_ptr = GET_PTR( *devfs_internal_inode_xp );
    193     inode_ptr->type = INODE_TYPE_DEV;
     210                                     &internal_inode_xp );   // child inode
     211
     212    // set <internal> inode "type" field
     213    internal_inode_ptr       = GET_PTR( internal_inode_xp );
     214    internal_inode_ptr->type = INODE_TYPE_DEV;
    194215 
    195216    // create dentries <.> and <..> in <internal>
    196     error |= vfs_add_special_dentries( *devfs_internal_inode_xp,
     217    error |= vfs_add_special_dentries( internal_inode_xp,
    197218                                       devfs_dev_inode_xp );
    198219
     
    226247        error = vfs_add_child_in_parent( local_cxy,
    227248                                         FS_TYPE_DEVFS,
    228                                          *devfs_internal_inode_xp,
     249                                         internal_inode_xp,
    229250                                         chdev_ptr->name,
    230251                                         &unused_xp,
     
    270291            error = vfs_add_child_in_parent( local_cxy,
    271292                                             FS_TYPE_DEVFS,
    272                                              *devfs_internal_inode_xp,
     293                                             internal_inode_xp,
    273294                                             chdev_ptr->name,
    274295                                             &unused_xp,
  • trunk/kernel/fs/devfs.h

    r612 r657  
    33 *
    44 * Authors       Mohamed Lamine Karaoui (2014,2015)
    5  *               Alain Greiner (2016,2017)
     5 *               Alain Greiner (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
     
    2626#define _DEVFS_H_
    2727
     28
    2829//////////////////////////////////////////////////////////////////////////////////////////
    29 // The DEVFS File System contains inodes and dentries associated to all chdev descriptors
    30 // availables in the architecture.
     30// The DEVFS File System contains the inodes and dentries associated to the chdev
     31// descriptors available in the architecture.
    3132//
    3233// It is structured as a three levels tree structure :
     
    4142//
    4243// The DEVFS extensions to the generic VFS are the following:
    43 // 1) The vfs_ctx_t "extend" void* field is pointing on the devfs_ctx_t structure.
    44 //    This structure contains two extended pointers on the DEVFS "dev" directory inode,
    45 //    and on the "external" directory inode.
    46 // 2) The vfs_inode_t "extend" void* field is pointing on the chdev descriptor.
     44// 1) The vfs_ctx_t "extend" field is pointing on the devfs_ctx_t structure.
     45// 2) The vfs_inode_t "extend" field is pointing on the chdev descriptor.
    4746//////////////////////////////////////////////////////////////////////////////////////////
    4847
     
    5756}
    5857devfs_ctx_t;
    59 
    60 
    6158/*****************************************************************************************
    62  * This fuction allocates memory from local cluster for a DEVFS context descriptor.
     59 * This fuction allocates memory for a DEVFS context descriptor in cluster identified
     60 * by the <cxy> argument.
    6361 *****************************************************************************************
    64  * @ return a pointer on the created context / return NULL if failure.
     62 * @ cxy     : [in] target cluster identifier.
     63 * @ return an extended pointer on the created context / return NULL if failure.
    6564 ****************************************************************************************/
    66 devfs_ctx_t * devfs_ctx_alloc( void );
     65xptr_t  devfs_ctx_alloc( cxy_t cxy );
    6766
    6867/*****************************************************************************************
     
    7069 * to the relevant VFS context in the local cluster.
    7170 *****************************************************************************************
    72  * @ devfs_ctx               : local pointer on DEVFS context.
     71 * @ devfs_ctx               : [in]  extended pointer on DEVFS context.
    7372 * @ devfs_dev_inode_xp      : [out] extended pointer on  <dev> inode.
    7473 * @ devfs_external_inode_xp : [out] extended pointer on  <external> inode.
    7574 ****************************************************************************************/
    76 void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
    77                      xptr_t        devfs_dev_inode_xp,
    78                      xptr_t        devfs_external_inode_xp );
     75void devfs_ctx_init( xptr_t    devfs_ctx_xp,
     76                     xptr_t    devfs_dev_inode_xp,
     77                     xptr_t    devfs_external_inode_xp );
    7978
    8079/*****************************************************************************************
     
    8382 * @ devfs_ctx   : local pointer on DEVFS context.
    8483 ****************************************************************************************/
    85 void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx );
     84void devfs_ctx_destroy( xptr_t  devfs_ctx_xp );
    8685
    8786/*****************************************************************************************
    88  * This function start to create the DEVFS subtree.
    89  * This function should be called once in the cluster containing the VFS parent inode.
    90  * More precisely, it creates in cluster 0 the "dev" and "external" DEVFS directories.
    91  * For each one, it creates the inode and link the associated dentry to parent inode.
    92  * The DEVFS root inode is linked to the VFS parent inode identified by <parent_inode_xp>.
     87 * This function starts to create the DEVFS subtree.
     88 * This function creates in cluster 0 the "dev" and "external" DEVFS directories.
     89 * For each one, it creates the inode and the associated dentry. The DEVFS root inode
     90 * <dev is linked to the VFS parent inode identified by <parent_inode_xp>.
    9391 *****************************************************************************************
    94  * @ parent_inode_xp         : extended pointer on the parent VFS inode.
     92 * @ parent_inode_xp         : [in]  extended pointer on the parent VFS inode.
    9593 * @ devfs_dev_inode_xp      : [out] extended pointer on created <dev> inode.
    9694 * @ devfs_external_inode_xp : [out] extended pointer on created <external> inode.
     
    105103 * 1. In each cluster (i), it creates the "internal" directory,
    106104 *    linked to the DEVFS "dev" parent directory.
    107  * 2. In each cluster (i), it creates - for each external chdev in cluster (i) -
     105 * 2. In each cluster (i), it creates, for each external chdev in cluster (i),
    108106 *    a pseudo-file, linked to the DEVFS "external" parent directory.
    109  * 3. In each cluster (i), it creates - for each internal chdev in cluster (i) -
     107 * 3. In each cluster (i), it creates, for each internal chdev in cluster (i),
    110108 *    a pseudo-file, linked to the DEVFS "internal" parent directory.
    111109 *****************************************************************************************
    112  * @ devfs_dev_inode_xp      : extended pointer on DEVFS root inode.
    113  * @ devfs_external_inode_xp : extended pointer on DEVFS external inode.
    114  * @ devfs_internal_inode_xp : [out] extended pointer on created <internal> inode.
     110 * @ devfs_dev_inode_xp      : [in]  extended pointer on DEVFS root inode.
     111 * @ devfs_external_inode_xp : [in]  extended pointer on DEVFS external inode.
    115112 ****************************************************************************************/
    116113void devfs_local_init( xptr_t   devfs_dev_inode_xp,
    117                        xptr_t   devfs_external_inode_xp,
    118                        xptr_t * devfs_internal_inode_xp );
     114                       xptr_t   devfs_external_inode_xp );
    119115                       
    120116/******************************************************************************************
  • trunk/kernel/fs/fatfs.c

    r656 r657  
    22 * fatfs.c - FATFS file system API implementation.
    33 *
    4  * Author    Alain Greiner (2016,2017,2018,2019)
     4 * Author    Alain Greiner (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    122122        for( i = nbytes ; i > 0 ; i-- )
    123123        {
    124             res = (res<<8) | hal_remote_lb( buffer_xp+offset+i-1 );
     124            res = (res<<8) | hal_remote_lb( buffer_xp + offset + i-1 );
    125125        }
    126126    }
     
    129129        for( i = 0 ; i < nbytes ; i++ )
    130130        {
    131             res = (res<<8) | hal_remote_lb( buffer_xp+offset+i );
     131            res = (res<<8) | hal_remote_lb( buffer_xp + offset + i );
    132132        }
    133133    }
     
    135135
    136136}  // end fatfs_get_remote_record()
     137
     138/*
    137139
    138140//////////////////////////////////////////////////////////////////////////////////////////
     
    164166}  // end fatfs_set_record()
    165167
     168*/
     169
    166170//////////////////////////////////////////////////////////////////////////////////////////
    167171// This function writes one, two, or four bytes from a 32 bits integer to a remote
     
    185189        for( i = nbytes ; i > 0 ; i-- )
    186190        {
    187             hal_remote_sb( (buffer_xp+offset+i-1) , (uint8_t)(value>>((i-1)<<3)) );
     191            hal_remote_sb( (buffer_xp + offset + i-1 ) , (uint8_t)(value>>((i-1)<<3)) );
    188192        }
    189193    }
     
    192196        for( i = 0 ; i < nbytes ; i++ )
    193197        {
    194             hal_remote_sb( (buffer_xp+offset+i) , (uint8_t)(value>>((nbytes-1-i)<<3)) );
     198            hal_remote_sb( (buffer_xp + offset + i) , (uint8_t)(value>>((nbytes-1-i)<<3)) );
    195199        }
    196200    }
     
    470474    cxy_t         fat_cxy;         // FAT cluster identifier
    471475    fatfs_ctx_t * fatfs_ctx;       // local pointer on FATFS context in FAT cluster
    472     xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
    473476    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
    474477    uint32_t      page_id;         // current page index in FAT mapper
     
    482485    fatfs_ctx = GET_PTR( fatfs_ctx_xp );
    483486 
    484     // get FAT mapper pointers from FATFS context
    485     fat_mapper_xp  = hal_remote_l64( XPTR( fat_cxy , &fatfs_ctx->fat_mapper_xp ) );
    486     fat_mapper_ptr = GET_PTR( fat_mapper_xp );
    487 
    488 // check FAT cluster
    489 assert( (fat_cxy == GET_CXY( fat_mapper_xp )) , "unconsistent FAT cluster" );
     487    // get FAT mapper pointer from FATFS context
     488    fat_mapper_ptr  = hal_remote_lpt( XPTR( fat_cxy , &fatfs_ctx->fat_mapper ) );
    490489
    491490    // build extended pointer on FAT mapper radix tree
     
    575574   
    576575    // update the FS_INFO sector on IOC device
    577     return dev_ioc_move_data( IOC_SYNC_WRITE , fs_info_buffer_xp , fs_info_lba , 1 );
     576    return dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
    578577 
    579578}  // end fatfs_update_ioc_fsinfo()
     
    581580//////////////////////////////////////////////////////////////////////////////////////////
    582581// This static function decrements the  "free_clusters" variable, and updates the
    583 // "free_cluster_hint" variable in the FATFS context in FAT cluster, identified
    584 // by the <fat_ctx_xp> argument, when a new <cluster> has been allocated from FAT.
     582// "free_cluster_hint" variable in the FATFS context in FAT cluster,  when a new
     583// <cluster_id> has been allocated from the FAT.
     584// It synchronously updates the FS_INFO sector on the IOC device.
     585// The FATFS context in FAT cluster is identified by the <fat_ctx_xp> argument.
     586// It can be called by a thead running in any cluster.
    585587// It scan all slots in the FAT mapper seen as an array of 32 bits words, looking for the
    586 // first free slot larger than the <cluster> argument, to update "free_cluster_hint".
    587 // It synchronously updates the FS_INFO sector on the IOC device.
    588 // It can be called by a thead running in any cluster.
     588// first free slot larger than the <cluster_id>.
    589589// The lock protecting exclusive access to the FAT must be taken by the calling function.
    590590//////////////////////////////////////////////////////////////////////////////////////////
    591591// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
    592 // @ cluster       : recently allocated cluster index in FAT.
     592// @ cluster_id    : recently allocated cluster index in FAT.
    593593// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
    594594//////////////////////////////////////////////////////////////////////////////////////////
    595595static error_t fatfs_free_clusters_decrement( xptr_t    fatfs_ctx_xp,
    596                                               uint32_t  cluster )
     596                                              uint32_t  cluster_id )
    597597{
    598598    error_t       error;
    599     cxy_t         fat_cxy;        // FAT cluster identifier
    600     fatfs_ctx_t * fat_ctx_ptr;    // local pointer on fatfs context in FAT cluster
    601     xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    602     xptr_t        hint_xp;        // extended pointer on "free_cluster_hint" shared variable
    603     xptr_t        numb_xp;        // extended pointer on "free_clusters" shared variable
    604     uint32_t      numb;           // "free_clusters" variable current value
    605     uint32_t      hint;           // "free_cluster_hint" variable current value
    606     uint32_t      page_id;        // page index in FAT mapper
    607     uint32_t      slot_id;        // slot index in one page of FAT (1024 slots per page)
    608     uint32_t      page_max;       // max number of pages in FAT mapper
    609     xptr_t        page_xp;        // extended pointer on current page in FAT mapper
    610     xptr_t        base_xp;        // extended pointer on current page base
    611     xptr_t        slot_xp;        // extended pointer on current slot in FAT mapper
     599    cxy_t         fat_cxy;         // FAT cluster identifier
     600    fatfs_ctx_t * fat_ctx_ptr;     // local pointer on fatfs context in FAT cluster
     601    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
     602    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     603    xptr_t        hint_xp;         // extended pointer on "free_cluster_hint" shared variable
     604    xptr_t        numb_xp;         // extended pointer on "free_clusters" shared variable
     605    uint32_t      page_id;         // page index in FAT mapper
     606    uint32_t      slot_id;         // slot index in one page of FAT (1024 slots per page)
     607    uint32_t      page_max;        // max number of pages in FAT mapper
     608    xptr_t        page_xp;         // extended pointer on current page in FAT mapper
     609    xptr_t        base_xp;         // extended pointer on current page base
     610    xptr_t        slot_xp;         // extended pointer on current slot in FAT mapper
     611    uint32_t      found;           // free slot found when non zero
    612612
    613613#if DEBUG_FATFS_FREE_CLUSTERS
     
    615615thread_t * this  = CURRENT_THREAD;
    616616if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
    617 printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n",
    618 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
     617printk("\n[%s] thread[%x,%x] enter for allocated cluster_id %x / cycle %d\n",
     618__FUNCTION__, this->process->pid, this->trdid, cluster_id , cycle );
    619619#endif
    620620
     
    627627    numb_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_clusters );
    628628
    629     // update "free_clusters" value
    630     numb = hal_remote_l32( numb_xp ) - 1;
    631     hal_remote_s32( numb_xp , numb );
    632 
    633     // get extended pointer on FAT mapper
    634     fat_mapper_xp = hal_remote_l64( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper_xp ) );
    635 
    636     // initialise variables to scan the FAT mapper
    637     // and find the first free slot > cluster
    638     page_id  = (cluster + 1) >> 10;
    639     slot_id  = (cluster + 1) & 0x3FF;
     629    // get pointers on FAT mapper from FATFS context
     630    fat_mapper_ptr = hal_remote_lpt( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper ) );
     631    fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
     632
     633    // initialise the loop variables to scan the FAT mapper
     634    page_id  = (cluster_id + 1) >> 10;
     635    slot_id  = (cluster_id + 1) & 0x3FF;
    640636    page_max = hal_remote_l32( XPTR( fat_cxy, &fat_ctx_ptr->fat_sectors_count ) ) >> 3;
    641 
    642     // scan FAT mapper / loop on pages
    643     while ( page_id < page_max )           
     637    found    = 0;
     638
     639    // scan FAT mapper : first loop on pages
     640    while ( (page_id < page_max) && (found == 0) )           
    644641    {
    645642        // get current page from mapper
    646         page_xp = mapper_remote_get_page( fat_mapper_xp , page_id );
     643        page_xp = mapper_get_fat_page( fat_mapper_xp , page_id );
    647644
    648645        if( page_xp == XPTR_NULL )
     
    655652        base_xp = ppm_page2base( page_xp );
    656653
    657         // scan FAT mapper / loop on slots
    658         while ( slot_id < 1024 )
     654        // scan the FAT mapper : second loop on slots
     655        while ( (slot_id < 1024) && (found == 0) )
    659656        {
    660657            // get extended pointer on current slot
     
    664661            if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER )
    665662            {
    666                 // update "free_cluster_hint" value
    667                 hint = (page_id << 10) + slot_id - 1;
    668                 hal_remote_s32( hint_xp , hint );
    669 
    670                 // update FS_INFO sector on IOC device
    671                 error = fatfs_update_ioc_fat( fatfs_ctx_xp,
    672                                               page_id,
    673                                               page_id );
    674 
    675                 if( error )
    676                 {
    677                     printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
    678                     return -1;
    679                 }
     663                // exit both loops
     664                found = 1;
     665            }
     666            else
     667            {
     668                // update slot_id if not found
     669                slot_id++;
     670            }
     671        }  // end loop on slots
     672
     673        // update page_id & slot_id variables if not found
     674        if( found == 0 )
     675        {
     676            page_id++;
     677            slot_id = 0;
     678        }
     679    }  // end loop on pages
     680
     681    if( found )  // free cluster found
     682    {
     683        // update "free_clusters" and "free_cluster_hint" value in FATFS context
     684        hal_remote_atomic_add( numb_xp , -1 );
     685        hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 );
     686
     687        // update FS_INFO sector on IOC device
     688        error = fatfs_update_ioc_fsinfo( fatfs_ctx_xp );
     689
     690        if( error )
     691        {
     692            printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
     693            return -1;
     694        }
    680695
    681696#if DEBUG_FATFS_FREE_CLUSTERS
    682 cycle = (uint32_t)hal_get_cycles();
    683 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
    684 printk("\n[%s] thread[%x,%x] exit / hint %x / free %x / cycle %d\n",
     697if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
     698printk("\n[%s] thread[%x,%x] exit / hint %x / free %x\n",
    685699__FUNCTION__, this->process->pid, this->trdid,
    686 hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle );
    687 #endif
    688                 return 0;
    689             }
    690 
    691             // update slot_id
    692             slot_id = 0;
    693 
    694         }  // end loop on slots
    695 
    696         // update page_id & slot_id variables
    697         page_id++;
    698         slot_id = 0;
    699 
    700     }  // end loop on pages
    701 
    702     // return error if no free cluster found
    703     printk("\n[ERROR] in %s : No free cluster found\n", __FUNCTION__ );
    704     return -1;
     700hal_remote_l32(hint_xp), hal_remote_l32(numb_xp) );
     701#endif
     702        return 0;
     703    }
     704    else  // free cluster not found
     705    {
     706        printk("\n[ERROR] in %s : No free cluster_id found\n", __FUNCTION__ );
     707        return -1;
     708    }
    705709   
    706710}  // end fatfs_free_clusters_decrement()
     
    709713// This static function increments the "free_clusters" variable, and updates the
    710714// "free_cluster_hint" variables in the FATFS context in FAT cluster, identified
    711 // by the <fat_ctx_xp> argument, when a FATFS cluster is released.
     715// by the <fat_ctx_xp> argument, when a FATFS <cluster_id> has been released.
    712716// If the released cluster index is smaller than the current (hint) value,
    713717// it set "free_cluster_hint" <= cluster.
    714 // It does NOT update the  FS_INFO sector on the IOC device.
     718// It does NOT update the  FS_INFO sector on the IOC device, as this is done by the
     719// calling fatfs_release_inode() function.
    715720// It can be called by a thead running in any cluster.
    716721// The lock protecting exclusive access to the FAT must be taken by the calling function.
    717722//////////////////////////////////////////////////////////////////////////////////////////
    718723// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
    719 // @ cluster       : recently released cluster index in FAT.
     724// @ cluster_id    : recently released cluster index in FAT.
    720725// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
    721726//////////////////////////////////////////////////////////////////////////////////////////
    722727static error_t fatfs_free_clusters_increment( xptr_t   fatfs_ctx_xp,
    723                                               uint32_t cluster )
    724 {
    725     error_t       error;
     728                                              uint32_t cluster_id )
     729{
    726730    cxy_t         fat_cxy;      // FAT cluster identifier
    727731    fatfs_ctx_t * fat_ctx_ptr;  // local pointer on fatfs context in FAT cluster
     
    735739thread_t * this  = CURRENT_THREAD;
    736740if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
    737 printk("\n[%s] thread[%x,%x] enter for released cluster %x / cycle %d\n",
    738 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
     741printk("\n[%s] thread[%x,%x] enter for released cluster_id %x / cycle %d\n",
     742__FUNCTION__, this->process->pid, this->trdid, cluster_id , cycle );
    739743#endif
    740744
     
    753757    // update "numb" and "hint" variables as required
    754758    numb++;
    755     if ( (cluster - 1) < hint ) hint = cluster - 1;
     759    if ( (cluster_id - 1) < hint ) hint = cluster_id - 1;
    756760
    757761    // update free_clusters
     
    759763    hal_remote_s32( hint_xp , hint );
    760764
    761     // update FS_INFO sector on IOC device
    762     error = fatfs_update_ioc_fsinfo( fatfs_ctx_xp );
    763 
    764     if( error )
    765     {
    766         printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
    767         return -1;
    768     }
    769 
    770765#if DEBUG_FATFS_FREE_CLUSTERS
    771 cycle = (uint32_t)hal_get_cycles();
    772 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
    773 printk("\n[%s] thread[%x,%x] exit / hint %x / free %x / cycle %d\n",
     766if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
     767printk("\n[%s] thread[%x,%x] exit / hint %x / free %x\n",
    774768__FUNCTION__, this->process->pid, this->trdid,
    775 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ), cycle );
     769hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) );
    776770#endif
    777771
     
    853847
    854848//////////////////////////////////////////////////////////////////////////////////////////
     849// This static function access the FAT mapper to allocate a new cluster in the FATFS,
     850// and returns in <searched_cluster_id> the FATFS cluster index of a free cluster.
     851// It updates the FAT mapper (handling miss from IOC device if required) :
     852// - if the <last_cluster_id> is zero, the new cluster is the first allocated cluster,
     853//   and the <searched_cluster_id> FAT slot is set to END_OF_CHAIN_CLUSTER.
     854// - if the <last_cluster_id> argument is not zero, the new cluster is not the first,
     855//   the <last_cluster_id> FAT slot is set to <searched_cluster_id>,
     856//   the <searched_cluster_id> FAT slot is set to END_OF_CHAIN_CLUSTER.
     857// This function also updates the  two "free_cluster_hint" and "free_clusters" variables
     858// stored in the FATFS context. It takes the rwlock stored in the FATFS context in the
     859// FAT cluster to get exclusive access to the FAT.
     860// This function synchronously updates the FAT region on IOC device.
     861// It can be called by a thread running in any cluster as it uses remote accesses.
     862//////////////////////////////////////////////////////////////////////////////////////////
     863// @ last_cluster_id      : [in]  previous last cluster index.
     864// @ searched_cluster_id  : [out] allocated cluster index.
     865// @ return 0 if success / return -1 if no more free clusters on IOC device.
     866//////////////////////////////////////////////////////////////////////////////////////////
     867static error_t fatfs_cluster_alloc( uint32_t   last_cluster_id,
     868                                    uint32_t * searched_cluster_id )
     869{
     870    error_t       error;
     871    uint32_t      free_clusters;   // total number of free clusters
     872    uint32_t      hint;            // hint + 1 is the first free cluster
     873    uint32_t      new_cluster_id;  // allocated cluster index in FAT
     874    uint32_t      new_page_id;     // allocated cluster page index in FAT mapper
     875    uint32_t      new_slot_id;     // allocated cluster slot index in page (1024 slots per page)
     876    xptr_t        new_page_xp;     // extended pointer on FAT page for allocated cluster
     877    xptr_t        new_slot_xp;     // extended pointer on allocated cluster slot in FAT
     878    uint32_t      last_page_id;    // last cluster page index in FAT mapper
     879    uint32_t      last_slot_id;    // last cluster slot index in page (1024 slots per page)
     880    xptr_t        last_slot_xp;    // extended pointer on last cluster slot in FAT
     881    xptr_t        last_page_xp;    // extended pointer on FAT page for last cluster
     882    vfs_ctx_t   * vfs_ctx;         // local pointer on VFS context (same in all clusters)
     883    fatfs_ctx_t * loc_fatfs_ctx;   // local pointer on local FATFS context
     884    fatfs_ctx_t * fat_fatfs_ctx;   // local pointer on FATFS context in FAT cluster
     885    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
     886    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     887    cxy_t         fat_cxy;         // FAT mapper cluster identifier
     888    xptr_t        lock_xp;         // extended pointer on lock protecting free clusters info
     889    xptr_t        hint_xp;         // extended pointer on free_cluster_hint in FAT cluster
     890    xptr_t        free_xp;         // extended pointer on free_clusters_number in FAT cluster
     891   
     892#if DEBUG_FATFS_CLUSTER_ALLOC
     893uint32_t   cycle = (uint32_t)hal_get_cycles();
     894thread_t * this  = CURRENT_THREAD;
     895if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     896printk("\n[%s] thread[%x,%x] enter / lats_cluster_id %x / cycle = %d\n",
     897__FUNCTION__, this->process->pid, this->trdid, last_cluster_id, cycle );
     898#endif
     899
     900    // get local pointer on VFS context (same in all clusters)
     901    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     902
     903    // get local pointer on local FATFS context
     904    loc_fatfs_ctx = vfs_ctx->extend;
     905
     906    // get FAT cluster
     907    fat_cxy = CONFIG_VFS_ROOT_CXY;
     908
     909    // get pointers on FAT mapper
     910    fat_mapper_ptr = loc_fatfs_ctx->fat_mapper;
     911    fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
     912
     913    // get local pointer on FATFS context in FAT cluster
     914    fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     915
     916    // build relevant extended pointers on free clusters info in FAT cluster
     917    lock_xp = XPTR( fat_cxy , &fat_fatfs_ctx->lock );
     918    hint_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint );
     919    free_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters );
     920
     921    // take the FAT lock in write mode
     922    remote_rwlock_wr_acquire( lock_xp );
     923
     924    // get hint and free_clusters values from FATFS context in FAT cluster
     925    hint          = hal_remote_l32( hint_xp );
     926    free_clusters = hal_remote_l32( free_xp );
     927       
     928#if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
     929if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     930printk("\n[%s] thread[%x,%x] get free info : hint %x / free_clusters %x\n",
     931__FUNCTION__, this->process->pid, this->trdid, hint, free_clusters );
     932#endif
     933
     934    // check "free_clusters"
     935    if ( free_clusters == 0 )
     936    {
     937        printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ );
     938        remote_rwlock_wr_release( lock_xp );
     939        return -1;
     940    }
     941    else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN )
     942    {
     943        printk("\n[WARNING] in %s : only %d free FATFS clusters\n",
     944        __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN );
     945    }
     946
     947    // get new cluster, page & slot indexes in FAT
     948    new_cluster_id = hint + 1;
     949    new_page_id    = new_cluster_id >> 10;
     950    new_slot_id    = new_cluster_id & 0x3FF;
     951
     952    // get relevant FAT page descriptor from FAT mapper
     953    new_page_xp = mapper_get_fat_page( fat_mapper_xp , new_page_id );
     954
     955    if( new_page_xp == XPTR_NULL )
     956    {
     957        printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
     958        remote_rwlock_wr_release( lock_xp );
     959        return -1;
     960    }
     961
     962    // build extended pointer on new cluster slot in FAT mapper
     963    new_slot_xp = ppm_page2base( new_page_xp ) + (new_slot_id << 2);
     964         
     965    // check selected cluster actually free
     966    if( hal_remote_l32( new_slot_xp ) != FREE_CLUSTER )
     967    {
     968        printk("\n[ERROR] in %s : selected cluster_id %x not free\n",
     969        __FUNCTION__, new_cluster_id );
     970        remote_rwlock_wr_release( lock_xp );
     971        return -1;
     972    }
     973
     974    // update new_cluster slot in FAT mapper
     975    hal_remote_s32( new_slot_xp  , END_OF_CHAIN_CLUSTER_MIN );
     976
     977    // handle last_cluster_id argument if non zero
     978    if( last_cluster_id )
     979    {
     980        // get last cluster page & slot indexes in FAT
     981        last_page_id    = last_cluster_id >> 10;
     982        last_slot_id    = last_cluster_id & 0x3FF;
     983
     984        // get relevant FAT page descriptor from FAT mapper
     985        last_page_xp = mapper_get_fat_page( fat_mapper_xp , last_page_id );
     986
     987        if( last_page_xp == XPTR_NULL )
     988        {
     989            printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
     990            remote_rwlock_wr_release( lock_xp );
     991            return -1;
     992        }
     993
     994        // build extended pointer on new cluster slot in FAT mapper
     995        last_slot_xp = ppm_page2base( last_page_xp ) + (last_slot_id << 2);
     996         
     997        // check last cluster actually end of chain
     998        if( hal_remote_l32( last_slot_xp ) != END_OF_CHAIN_CLUSTER_MIN )
     999        {
     1000            printk("\n[ERROR] in %s : last_cluster_id %x not END_OF_CHAIN\n",
     1001            __FUNCTION__, last_cluster_id );
     1002            remote_rwlock_wr_release( lock_xp );
     1003            return -1;
     1004        }
     1005
     1006        // update last_cluster slot in FAT mapper
     1007        hal_remote_s32( last_slot_xp , new_cluster_id );
     1008    }
     1009    else
     1010    {
     1011        last_page_xp = XPTR_NULL;
     1012    }
     1013
     1014    // update the FAT new_page on device
     1015    error = fatfs_move_page( new_page_xp , IOC_SYNC_WRITE );
     1016
     1017    if( error )
     1018    {
     1019        printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
     1020        remote_rwlock_wr_release( lock_xp );
     1021        return -1;
     1022    }
     1023
     1024    // update the FAT last_page on device when required
     1025    if( (last_page_xp != XPTR_NULL) && (last_page_xp != new_page_xp) )
     1026    {
     1027        error = fatfs_move_page( last_page_xp , IOC_SYNC_WRITE );
     1028
     1029        if( error )
     1030        {
     1031            printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
     1032            remote_rwlock_wr_release( lock_xp );
     1033            return -1;
     1034        }
     1035    }
     1036
     1037    // update free cluster info in FATFS context and in FS_INFO sector
     1038    error = fatfs_free_clusters_decrement( XPTR( fat_cxy , fat_fatfs_ctx ) , new_cluster_id );
     1039
     1040    if( error )
     1041    {
     1042        printk("\n[ERROR] in %s : cannot update free cluster info\n", __FUNCTION__ );
     1043        remote_rwlock_wr_release( lock_xp );
     1044        return -1;
     1045    }
     1046
     1047    // release FAT lock
     1048    remote_rwlock_wr_release( lock_xp );
     1049
     1050#if DEBUG_FATFS_CLUSTER_ALLOC
     1051cycle = (uint32_t)hal_get_cycles();
     1052if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1053printk("\n[%s] thread[%x,%x] exit / allocated cluster_id %x in FAT / cycle %d\n",
     1054__FUNCTION__, this->process->pid, this->trdid, new_cluster_id, cycle );
     1055#endif
     1056
     1057    *searched_cluster_id = new_cluster_id;
     1058    return 0;
     1059
     1060}  // end fatfs_cluster_alloc()
     1061
     1062
     1063//////////////////////////////////////////////////////////////////////////////////////////
    8551064// This static function access the FAT (File Allocation Table), stored in the FAT mapper,
    8561065// and returns in <searched_cluster_id> the FATFS cluster_id for a given page of a given
    857 // inode, identified by the <searched_page_id> argument, that is the page index in file
     1066// inode, identified by the <searched_page_id> argument that is the page index in file
    8581067// (i.e. the page index in file mapper). The entry point in the FAT is defined by the
    8591068// <first_cluster_id> argument, that is the cluster_id of an already allocated cluster.
     
    8611070// fatfs_inode extension), or any page of the file whose <first_page_id> argument
    8621071// is smaller than the searched <first_page_id> argument.
    863 // This function can be called by a thread running in any cluster, as it uses remote
    864 // access primitives when the FAT mapper is remote.
     1072// This function can be called by a thread running in any cluster.
    8651073// The FAT mapper being a WRITE-THROUGH cache, this function updates the FAT mapper
    8661074// from informations stored on IOC device in case of miss when scanning the FAT mapper.
     
    8851093    uint32_t   current_cluster_id;     // index of cluster in FATFS
    8861094    xptr_t     lock_xp;                // extended pointer on FAT lock
     1095    xptr_t     fat_mapper_xp;          // extended pointer on FAT mapper
     1096    mapper_t * fat_mapper_ptr;         // local pointer on FAT mapper
     1097    cxy_t      fat_cxy;                // FAT cluster
     1098    error_t    error;
    8871099
    8881100assert( (searched_page_id > first_page_id) ,
     
    8931105thread_t * this  = CURRENT_THREAD;
    8941106if( DEBUG_FATFS_GET_CLUSTER < cycle )
    895 printk("\n[%s] thread[%x,%x] enter / first_cluster_id %x / searched_page_id %d / cycle %d\n",
    896 __FUNCTION__, this->process->pid, this->trdid, first_cluster_id, searched_page_id, cycle );
     1107printk("\n[%s] thread[%x,%x] enter / frst_pid %x / frst_cid %x / srch_pid %d / cycle %d\n",
     1108__FUNCTION__, this->process->pid, this->trdid,
     1109first_page_id, first_cluster_id, searched_page_id, cycle );
    8971110#endif
    8981111
     
    9031116    fatfs_ctx_t * loc_fatfs_ctx = vfs_ctx->extend;
    9041117
    905     // get extended pointer and cluster on FAT mapper
    906     xptr_t fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    907     cxy_t  fat_cxy        = GET_CXY( fat_mapper_xp );
     1118    // get FAT cluster
     1119    fat_cxy = CONFIG_VFS_ROOT_CXY;
     1120   
     1121    // get pointers on FAT mapper
     1122    fat_mapper_ptr = loc_fatfs_ctx->fat_mapper;
     1123    fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
    9081124
    9091125    // get local pointer on FATFS context in FAT cluster
     
    9311147
    9321148        // get pointer on current page descriptor in FAT mapper
    933         xptr_t current_page_xp = mapper_remote_get_page( fat_mapper_xp , fat_page_index );
     1149        xptr_t current_page_xp = mapper_get_fat_page( fat_mapper_xp , fat_page_index );
    9341150
    9351151        if( current_page_xp == XPTR_NULL )
     
    9421158
    9431159        // get pointer on buffer containing the FAT mapper page
    944         xptr_t base_xp = ppm_page2base( current_page_xp );
    945         uint32_t * buffer = (uint32_t *)GET_PTR( base_xp );
     1160        xptr_t     base_xp = ppm_page2base( current_page_xp );
     1161        uint32_t * buffer  = (uint32_t *)GET_PTR( base_xp );
    9461162
    9471163        // get next_cluster_id from FAT slot 
    9481164        uint32_t next_cluster_id = hal_remote_l32( XPTR( fat_cxy, &buffer[fat_slot_index] ) );
    9491165
    950         // allocate a new FAT cluster when there is no cluster
    951         // allocated on device for the current page
     1166        // allocate a new FAT cluster when END_OF_CHAIN found
    9521167        if( next_cluster_id >= END_OF_CHAIN_CLUSTER_MIN )
    9531168        {
     
    9561171
    9571172            // allocate a new cluster_id (and update both FAT mapper and FAT on device).
    958             error_t error = fatfs_cluster_alloc( &next_cluster_id );
    959 
     1173            error = fatfs_cluster_alloc( current_cluster_id,
     1174                                         &next_cluster_id );
    9601175            if( error )
    9611176            {
     
    9681183#if (DEBUG_FATFS_GET_CLUSTER & 1)
    9691184if( DEBUG_FATFS_GET_CLUSTER < cycle )
    970 printk("\n[%s] allocated a new cluster_id %d in FATFS\n",
     1185printk("\n[%s] allocated a new cluster_id %x in FATFS\n",
    9711186__FUNCTION__, next_cluster_id );
    9721187#endif
     
    9771192#if (DEBUG_FATFS_GET_CLUSTER & 1)
    9781193if( DEBUG_FATFS_GET_CLUSTER < cycle )
    979 printk("\n[%s] traverse FAT / fat_page_index %d / fat_slot_index %d / next_cluster_id %x\n",
    980 __FUNCTION__, fat_page_index, fat_slot_index , next_cluster_id );
     1194printk("\n[%s] traverse FAT / current_cluster_id %x / next_cluster_id %x\n",
     1195__FUNCTION__, current_cluster_id , next_cluster_id );
    9811196#endif
    9821197
     
    9911206#if DEBUG_FATFS_GET_CLUSTER
    9921207if( DEBUG_FATFS_GET_CLUSTER < cycle )
    993 printk("\n[%s] thread[%x,%x] exit / searched_cluster_id = %d\n",
    994 __FUNCTION__, this->process->pid, this->trdid, current_cluster_id );
     1208printk("\n[%s] thread[%x,%x] exit / frst_pid %d / frst_cid %x / srch_pid %d / srch_cid %x\n",
     1209__FUNCTION__, this->process->pid, this->trdid,
     1210first_page_id, first_cluster_id, searched_page_id, current_cluster_id );
    9951211#endif
    9961212
     
    10001216}  // end fatfs_get_cluster()
    10011217
    1002 
    1003 
    1004 
    1005 
    1006 //////////////////////////////////////////////////////////////////////////////////////////
    1007 //              FATFS specific extern functions
    1008 //////////////////////////////////////////////////////////////////////////////////////////
    1009 
    1010 ///////////////////////////////////
    1011 void fatfs_display_ctx( cxy_t cxy )
    1012 {
    1013     // get pointer on local FATFS context
    1014     vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
    1015         fatfs_ctx_t * ctx     = hal_remote_lpt( XPTR( cxy , &vfs_ctx->extend ) );
    1016 
    1017     uint32_t fat_sectors       = hal_remote_l32( XPTR( cxy , &ctx->fat_sectors_count ) );
    1018     uint32_t sector_size       = hal_remote_l32( XPTR( cxy , &ctx->bytes_per_sector ) );
    1019     uint32_t sec_per_clus      = hal_remote_l32( XPTR( cxy , &ctx->sectors_per_cluster ) );
    1020     uint32_t fat_lba           = hal_remote_l32( XPTR( cxy , &ctx->fat_begin_lba ) );
    1021     uint32_t data_lba          = hal_remote_l32( XPTR( cxy , &ctx->cluster_begin_lba ) );
    1022     uint32_t fsinfo_lba        = hal_remote_l32( XPTR( cxy , &ctx->fs_info_lba ) );
    1023     uint32_t root_dir_clus     = hal_remote_l32( XPTR( cxy , &ctx->root_dir_cluster ) );
    1024     uint32_t free_clusters     = hal_remote_l32( XPTR( cxy , &ctx->free_clusters ) );
    1025     uint32_t free_cluster_hint = hal_remote_l32( XPTR( cxy , &ctx->free_cluster_hint ) );
    1026     xptr_t   mapper_xp         = hal_remote_l64( XPTR( cxy , &ctx->fat_mapper_xp ) );
    1027     void   * fs_info_buffer    = hal_remote_lpt( XPTR( cxy , &ctx->fs_info_buffer ) );
    1028 
    1029     printk("\n*** FAT context in cluster %x\n"
    1030            "- fat_sectors       = %d\n"
    1031            "- sector size       = %d\n"
    1032            "- cluster size      = %d\n"
    1033            "- fat_lba           = %x\n"
    1034            "- data_lba          = %x\n"
    1035            "- fsinfo_lba        = %x\n"
    1036            "- root_dir_cluster  = %x\n"
    1037            "- free_clusters     = %x\n"
    1038            "- free_cluster_hint = %x\n"
    1039            "- fat_mapper_ptr    = %x\n"
    1040            "- fs_info_buffer    = %x\n",
    1041            cxy,
    1042            fat_sectors,
    1043            sector_size,
    1044            sector_size * sec_per_clus,
    1045            fat_lba,
    1046            data_lba,
    1047            fsinfo_lba,
    1048            root_dir_clus,
    1049            free_clusters,
    1050            free_cluster_hint,
    1051            GET_PTR( mapper_xp ),
    1052            fs_info_buffer );
    1053 
    1054 }  // end fatfs_ctx_display()
    1055 
    1056 //////////////////////////////////////////
    1057 void fatfs_display_fat( uint32_t  page_id,
    1058                         uint32_t  min_slot,
    1059                         uint32_t  nb_slots )
    1060 {
    1061     uint32_t line;
    1062 
    1063     // compute number of lines to display
    1064     uint32_t min_line = min_slot >> 3;
    1065     uint32_t max_line = (min_slot + nb_slots - 1) >> 3;
    1066 
    1067     // get pointer on local FATFS context
    1068     vfs_ctx_t   * vfs_ctx       = &fs_context[FS_TYPE_FATFS];
    1069     fatfs_ctx_t * loc_fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
    1070 
    1071     // get pointers on FAT mapper (in FAT cluster)
    1072     xptr_t     mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    1073     cxy_t      mapper_cxy = GET_CXY( mapper_xp );
    1074 
    1075     // get pointer on FATFS context in FAT cluster
    1076     fatfs_ctx_t * fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
    1077  
    1078     // get current value of hint and free_clusters
    1079     uint32_t hint = hal_remote_l32( XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint ) );
    1080     uint32_t free = hal_remote_l32( XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters ) );
    1081 
    1082     // get extended pointer on requested page descriptor in FAT mapper
    1083     xptr_t page_xp = mapper_remote_get_page( mapper_xp , page_id );
    1084 
    1085     // get pointers on requested page base
    1086     xptr_t     base_xp  = ppm_page2base( page_xp );
    1087     void     * base     = GET_PTR( base_xp );
    1088 
    1089     printk("\n***** FAT mapper / cxy %x / page_id %d / base %x / free_clusters %x / hint %x\n",
    1090     mapper_cxy, page_id, base, free, hint );
    1091 
    1092     for( line = min_line ; line <= max_line ; line++ )
    1093     {
    1094         printk("%d : %X | %X | %X | %X | %X | %X | %X | %X\n", (line<<3),
    1095         hal_remote_l32( base_xp + ((line<<5)      ) ),
    1096         hal_remote_l32( base_xp + ((line<<5) + 4  ) ),
    1097         hal_remote_l32( base_xp + ((line<<5) + 8  ) ),
    1098         hal_remote_l32( base_xp + ((line<<5) + 12 ) ),
    1099         hal_remote_l32( base_xp + ((line<<5) + 16 ) ),
    1100         hal_remote_l32( base_xp + ((line<<5) + 20 ) ),
    1101         hal_remote_l32( base_xp + ((line<<5) + 24 ) ),
    1102         hal_remote_l32( base_xp + ((line<<5) + 28 ) ) );
    1103     }
    1104 
    1105 }  // end fatfs_display_fat()
    1106 
    1107 
    1108 
    1109 ///////////////////////////////////////////////////////////////////////////////////////
    1110 // Generic API : the following functions are called by the kernel VFS
    1111 //               and must be defined by all supported file systems.
    1112 ///////////////////////////////////////////////////////////////////////////////////////
    1113 
    1114 /////////////////////////////////////
    1115 fatfs_ctx_t * fatfs_ctx_alloc( void )
    1116 {
    1117     kmem_req_t    req;
    1118         req.type    = KMEM_KCM;
    1119         req.order   = bits_log2( sizeof(fatfs_ctx_t) );
    1120     req.flags   = AF_KERNEL | AF_ZERO;
    1121 
    1122         return kmem_alloc( &req );
    1123 }
    1124 
    1125 //////////////////////////////////////////////
    1126 void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx )
    1127 {
    1128     error_t       error;
    1129     kmem_req_t    req;
    1130     uint8_t     * buffer;
    1131     xptr_t        buffer_xp;
    1132 
    1133 #if DEBUG_FATFS_CTX_INIT
    1134 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1135 thread_t * this  = CURRENT_THREAD;
    1136 if( DEBUG_FATFS_CTX_INIT < cycle )
    1137 printk("\n[%s] thread[%x,%x] enter for fatfs_ctx = %x / cycle %d\n",
    1138 __FUNCTION__ , this->process->pid, this->trdid, fatfs_ctx , cycle );
    1139 #endif
    1140 
    1141 // check argument
    1142 assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL" );
    1143 
    1144 // check only cluster 0 does FATFS initialization
    1145 assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS");
    1146 
    1147     // allocate a permanent 512 bytes buffer to store
    1148     // - temporarily the BOOT sector
    1149     // - permanently the FS_INFO sector
    1150         req.type    = KMEM_KCM;
    1151     req.order   = 9;                    // 512 bytes
    1152     req.flags   = AF_KERNEL | AF_ZERO;
    1153         buffer      = kmem_alloc( &req );
    1154 
    1155     if( buffer == NULL )
    1156     {
    1157         printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
    1158         hal_core_sleep();
    1159     }
    1160      
    1161     buffer_xp   = XPTR( local_cxy , buffer );
    1162 
    1163     // load the BOOT record from device
    1164     error = dev_ioc_move_data( IOC_SYNC_READ , buffer_xp , 0 , 1 );
    1165 
    1166     if ( error )
    1167     {
    1168         printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ );
    1169         hal_core_sleep();
    1170     }
    1171 
    1172 #if (DEBUG_FATFS_CTX_INIT & 0x1)
    1173 if( DEBUG_FATFS_CTX_INIT < cycle )
    1174 putb( "boot record", buffer , 256 );
    1175 #endif
    1176 
    1177     // get sector size from boot record
    1178     uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer );
    1179     if ( sector_size != 512 )
    1180     {
    1181         printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ );
    1182         hal_core_sleep();
    1183     }
    1184 
    1185     // get cluster size from boot record
    1186     uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer );
    1187     if ( nb_sectors != 8 )
    1188     {
    1189         printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ );
    1190         hal_core_sleep();
    1191     }
    1192 
    1193     // get number of FAT copies from boot record
    1194     uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer );
    1195     if ( nb_fats != 1 )
    1196     {
    1197         printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ );
    1198         hal_core_sleep();
    1199     }
    1200 
    1201     // get number of sectors in FAT from boot record
    1202     uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer );
    1203     if ( (fat_sectors & 0xF) != 0 )
    1204     {
    1205         printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ );
    1206         hal_core_sleep();
    1207     }
    1208 
    1209     // get root cluster from boot record
    1210     uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer );
    1211     if ( root_cluster != 2 )
    1212     {
    1213         printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ );
    1214         hal_core_sleep();
    1215     }
    1216 
    1217     // get FAT lba from boot record
    1218     uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer );
    1219 
    1220     // get FS_INFO sector lba from boot record
    1221     uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer );
    1222 
    1223     // load the FS_INFO record from device
    1224     error = dev_ioc_move_data( IOC_SYNC_READ , buffer_xp , fs_info_lba , 1 );
    1225 
    1226     if ( error )
    1227     {
    1228         printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ );
    1229         hal_core_sleep();
    1230     }
    1231 
    1232     // get free_clusters number from FS_INFO record
    1233     uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer );
    1234     if ( free_clusters >= fat_sectors << 7 )
    1235     {
    1236         printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ );
    1237         hal_core_sleep();
    1238     }
    1239 
    1240     // get free_cluster_hint from FS_INFO record
    1241     uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer );
    1242 
    1243     if ( free_cluster_hint >= fat_sectors << 7 )
    1244     {
    1245         printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ );
    1246         hal_core_sleep();
    1247     }
    1248 
    1249     // allocate a mapper for the FAT itself
    1250     mapper_t * fat_mapper = mapper_create( FS_TYPE_FATFS );
    1251     if ( fat_mapper == NULL )
    1252     {
    1253         printk("\n[PANIC] in %s : no memory for FAT mapper\n", __FUNCTION__ );
    1254         hal_core_sleep();
    1255     }
    1256 
    1257     // the inode field is NULL for the FAT mapper
    1258     fat_mapper->inode = NULL;
    1259 
    1260     // initialize the FATFS context
    1261     fatfs_ctx->fat_begin_lba         = fat_lba;
    1262     fatfs_ctx->fat_sectors_count     = fat_sectors;
    1263     fatfs_ctx->bytes_per_sector      = sector_size;
    1264     fatfs_ctx->sectors_per_cluster   = nb_sectors;
    1265     fatfs_ctx->cluster_begin_lba     = fat_lba + fat_sectors;
    1266     fatfs_ctx->root_dir_cluster      = 2;
    1267     fatfs_ctx->fat_mapper_xp         = XPTR( local_cxy , fat_mapper );
    1268     fatfs_ctx->fs_info_lba           = fs_info_lba;
    1269     fatfs_ctx->free_clusters         = free_clusters;
    1270     fatfs_ctx->free_cluster_hint     = free_cluster_hint;
    1271     fatfs_ctx->fs_info_buffer        = buffer;
    1272 
    1273     remote_rwlock_init( XPTR( local_cxy , &fatfs_ctx->lock ) , LOCK_FATFS_FAT );
    1274 
    1275 #if (DEBUG_FATFS_CTX_INIT & 0x1)
    1276 if( DEBUG_FATFS_CTX_INIT < cycle )
    1277 fatfs_ctx_display( fatfs_ctx );
    1278 #endif
    1279 
    1280 #if DEBUG_FATFS_CTX_INIT
    1281 cycle = (uint32_t)hal_get_cycles();
    1282 if( DEBUG_FATFS_CTX_INIT < cycle )
    1283 printk("\n[%s]  thread[%x,%x] exit for fatfs_ctx = %x / cycle %d\n",
    1284 __FUNCTION__, this->process->pid, this->trdid, fatfs_ctx, cycle );
    1285 #endif
    1286 
    1287 }  // end fatfs_ctx_init()
    1288 
    1289 /////////////////////////////////////////////////
    1290 void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx )
    1291 {
    1292     kmem_req_t    req;
    1293     req.type = KMEM_KCM;
    1294     req.ptr  = fatfs_ctx;
    1295     kmem_free( &req );
    1296 }
    1297 
    1298 ///////////////////////////////////////////////
    1299 error_t fatfs_add_dentry( vfs_inode_t  * inode,
    1300                           vfs_dentry_t * dentry )
    1301 {
    1302     error_t       error;
    1303     uint32_t      length;        // dentry name length
    1304     uint32_t      nb_lfn;        // number or required LFN
    1305     char          sfn[11];       // buffer for SFN name
    1306     uint8_t       checksum;      // name checksum
    1307     mapper_t    * mapper;        // loal pointer on parent inode mapper
    1308     xptr_t        mapper_xp;     // extended pointer on parent inode mapper
    1309     xptr_t        child_xp;      // extended pointer on child inode
    1310     cxy_t         child_cxy;     // child inode cluster
    1311     vfs_inode_t * child_ptr;     // child inode local pointer
    1312     uint32_t      size;          // child inode size
    1313     uint32_t      type;          // child inode type
    1314     uint32_t      cluster;       // child inode cluster index
    1315 
    1316 #if DEBUG_FATFS_ADD_DENTRY
    1317 char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1318 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1319 thread_t * this  = CURRENT_THREAD;
    1320 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    1321 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1322 printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    1323 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1324 #endif
    1325 
    1326 // check arguments
    1327 assert( (inode != NULL) , "inode pointer is NULL\n" );
    1328 assert( (dentry != NULL) , "dentry pointer is NULL\n" );
    1329 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
    1330  
    1331     // get pointers on directory mapper
    1332     mapper    = inode->mapper;
    1333     mapper_xp = XPTR( local_cxy , mapper );
    1334 
    1335     // get extended pointers on remote child inode
    1336     child_xp  = dentry->child_xp;
    1337     child_cxy = GET_CXY( child_xp );
    1338     child_ptr = GET_PTR( child_xp );
    1339 
    1340     // get relevant infos from child inode
    1341     type    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
    1342     size    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->size ) );
    1343     cluster = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( child_cxy , &child_ptr->extend ) );
    1344 
    1345     // analyse dentry name
    1346     error = fatfs_name_format( dentry->name,
    1347                                &length,
    1348                                &nb_lfn,
    1349                                sfn,
    1350                                &checksum );
    1351     if ( error )
    1352     {
    1353         printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ );
    1354         return -1;
    1355     }
    1356                                
    1357     // Search end of directory with two embedded loops:
    1358     // - scan the pages in the mapper
    1359     // - scan the entries in each page to find NO_MORE_ENTRY
    1360 
    1361     xptr_t     page_xp;                 // extended pointer on page descriptor
    1362     xptr_t     base_xp;                 // extended pointer on page base
    1363     uint8_t  * base;                    // local pointer on page base (array of bytes)
    1364     uint32_t   page_id = 0;             // page index in mapper
    1365     uint32_t   offset  = 0;             // position in page
    1366     uint32_t   found   = 0;             // NO_MORE_ENTRY found
    1367 
    1368     // loop on pages in mapper
    1369     while ( found == 0 )
    1370     {
    1371         // get extended pointer on page descriptor in mapper
    1372         page_xp  = mapper_remote_get_page( mapper_xp , page_id );
    1373 
    1374         if ( page_xp == XPTR_NULL )
    1375         {
    1376             printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
    1377             return -1;
    1378         }
    1379        
    1380         // get pointer on page base
    1381         base_xp = ppm_page2base( page_xp );
    1382         base = GET_PTR( base_xp );
    1383 
    1384         // loop on directory entries in this page
    1385         while ( (offset < 4096) && (found == 0) )
    1386         {
    1387             if ( fatfs_get_record( LDIR_ORD, (base + offset) ) == NO_MORE_ENTRY )
    1388             {
    1389                 found = 1;
    1390             } 
    1391             else
    1392             {
    1393                 offset = offset + 32;
    1394             }
    1395         }  // end loop on entries
    1396 
    1397         if ( found == 0 )
    1398         {
    1399             page_id++;
    1400             offset = 0;
    1401         }
    1402     }  // end loop on pages
    1403 
    1404     // Modify the directory mapper: depending on the name length,
    1405     // the new child requires to write (3, 4, or 5) directory entries.
    1406     // To actually register the new child, we use a 5 steps FSM
    1407     // (one state per entry to be written), that is traversed as:
    1408     // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
    1409     // At most two pages are modified:
    1410     // - the page containing the NO_MORE_ENTRY is always modified
    1411     // - the following page can be modified if the name spread on to pages.
    1412 
    1413     char * name = dentry->name;
    1414 
    1415     uint32_t step;          // FSM state
    1416 
    1417     if      ( nb_lfn == 1 ) step = 3;
    1418     else if ( nb_lfn == 2 ) step = 4;
    1419     else if ( nb_lfn == 3 ) step = 5;
    1420    
    1421     uint8_t  * entry;       // pointer on directory entry to be written
    1422     uint32_t   i;           // byte index in one 32 bytes directory
    1423     uint32_t   c;           // character index in name
    1424 
    1425     while ( step )   
    1426     {
    1427         // when the new child is split on two pages,
    1428         // we need to access a new page in mapper
    1429         if ( offset >= 4096 )
    1430         {
    1431             // copy the modified page to IOC device
    1432             fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1433 
    1434             // get the next page in FAT mapper
    1435             page_xp  = mapper_remote_get_page( mapper_xp , page_id + 1 );
    1436 
    1437             if ( page_xp == XPTR_NULL )
    1438             {
    1439                 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
    1440                 return -1;
    1441             }
    1442        
    1443             // get pointer on page base
    1444             base_xp = ppm_page2base( page_xp );
    1445             base = GET_PTR( base_xp );
    1446            
    1447             // update offset
    1448             offset = 0;
    1449         }
    1450 
    1451         // compute directory entry address
    1452         entry = base + offset;
    1453 
    1454 #if (DEBUG_FATFS_ADD_DENTRY & 1)
    1455 cycle = (uint32_t)hal_get_cycles();
    1456 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1457 printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d / cycle %d\n",
    1458 __FUNCTION__, step, offset, nb_lfn, cycle );
    1459 #endif
    1460 
    1461         // write 32 bytes (one directory entry) per iteration
    1462         switch ( step )
    1463         {
    1464             case 5:   // write LFN3 entry
    1465             {
    1466                 c = 26;
    1467                 // scan the 32 bytes in dir_entry
    1468                 for ( i = 0 ; i < 32 ; i++ )
    1469                 {
    1470                     if (i == 0)
    1471                     {
    1472                         if ( nb_lfn == 3) entry[i] = 0x43;
    1473                         else              entry[i] = 0x03;
    1474                     }
    1475                     else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
    1476                                 ((i >= 14) && (i<=25) && ((i&1)==0))   ||
    1477                                 ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
    1478                               ( c < length ) )
    1479                     {
    1480                                           entry[i] = name[c];
    1481                                           c++;
    1482                     }
    1483                     else if (i == 11)     entry[i] = 0x0F;
    1484                     else if (i == 13)     entry[i] = checksum;
    1485                     else                  entry[i] = 0x00;
    1486                 }
    1487                 step--;
    1488                 break;
    1489             }
    1490             case 4:   // write LFN2 entry 
    1491             {
    1492                 c = 13;
    1493                 // scan the 32 bytes in dir_entry
    1494                 for ( i = 0 ; i < 32 ; i++ )
    1495                 {
    1496                     if (i == 0)
    1497                     {
    1498                         if ( nb_lfn == 2) entry[i] = 0x42;
    1499                         else              entry[i] = 0x02;
    1500                     }
    1501                     else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
    1502                                 ((i >= 14) && (i<=25) && ((i&1)==0))   ||
    1503                                 ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
    1504                               ( c < length ) )
    1505                     {
    1506                                           entry[i] = name[c];
    1507                                           c++;
    1508                     }
    1509                     else if (i == 11)     entry[i] = 0x0F;
    1510                     else if (i == 13)     entry[i] = checksum;
    1511                     else                  entry[i] = 0x00;
    1512                 }
    1513                 step--;
    1514                 break;
    1515             }
    1516             case 3:   // Write LFN1 entry   
    1517             {
    1518                 c = 0;
    1519                 // scan the 32 bytes in dir_entry
    1520                 for ( i = 0 ; i < 32 ; i++ )
    1521                 {
    1522                     if (i == 0)
    1523                     {
    1524                         if ( nb_lfn == 1) entry[i] = 0x41;
    1525                         else              entry[i] = 0x01;
    1526                     }
    1527                     else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
    1528                                 ((i >= 14) && (i<=25) && ((i&1)==0))   ||
    1529                                 ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
    1530                               ( c < length ) )
    1531                     {
    1532                                           entry[i] = name[c];
    1533                                           c++;
    1534                     }
    1535                     else if (i == 11)     entry[i] = 0x0F;
    1536                     else if (i == 13)     entry[i] = checksum;
    1537                     else                  entry[i] = 0x00;
    1538                 }
    1539                 step--;
    1540                 break;
    1541             }
    1542             case 2:   // write NORMAL entry     
    1543             {
    1544                 // scan the 32 bytes in dir_entry
    1545                 for ( i = 0 ; i < 32 ; i++ )
    1546                 {
    1547                     if      ( i < 11 )                              // 8.3 SFN
    1548                     {
    1549                                           entry[i] = sfn[i];
    1550                     }
    1551                     else if (i == 11)                               // ATTR
    1552                     {
    1553                         if (type == INODE_TYPE_DIR)  entry[i] = 0x10;
    1554                         else                         entry[i] = 0x20;
    1555                     }
    1556                     else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
    1557                     else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
    1558                     else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
    1559                     else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
    1560                     else if (i == 28)     entry[i] = size>>0;       // size.B0
    1561                     else if (i == 29)     entry[i] = size>>8;       // size.B1
    1562                     else if (i == 30)     entry[i] = size>>16;      // size.B2
    1563                     else if (i == 31)     entry[i] = size>>24;      // size.B3
    1564                     else                  entry[i] = 0x00;
    1565                 }
    1566 
    1567                 // update the "extend" field in dentry descriptor
    1568                 dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5);
    1569 
    1570                 step--;
    1571                 break;
    1572             }
    1573             case 1:   // write NOMORE entry 
    1574             {
    1575                 entry [0] = 0x00;
    1576                 step--;
    1577                 break;
    1578             }
    1579         } // end switch step
    1580 
    1581         offset += 32;
    1582 
    1583     } // exit while     
    1584 
    1585 #if (DEBUG_FATFS_ADD_DENTRY & 1)
    1586 cycle = (uint32_t)hal_get_cycles();
    1587 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1588 printk("\n[%s]  thread[%x,%x] before IOC access / cycle %d\n",
    1589 __FUNCTION__, this->process->pid, this->trdid, cycle );
    1590 #endif
    1591 
    1592     // copy the modified page to the IOC device
    1593     fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1594 
    1595 #if DEBUG_FATFS_ADD_DENTRY
    1596 cycle = (uint32_t)hal_get_cycles();
    1597 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1598 printk("\n[%s]  thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n",
    1599 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1600 #endif
    1601 
    1602     return 0;
    1603 
    1604 }  // end fatfs_add_dentry()
    1605 
    1606 //////////////////////////////////////////////////
    1607 error_t fatfs_remove_dentry( vfs_inode_t  * inode,
    1608                              vfs_dentry_t * dentry )
    1609 {
    1610     xptr_t     mapper_xp;  // extended pointer on mapper
    1611     mapper_t * mapper;     // local pointer on mapper
    1612     xptr_t     page_xp;    // extended pointer on mapper page descriptor
    1613     xptr_t     base_xp;    // extended pointer on mapper page base
    1614     uint8_t  * base;       // local pointer on mapper page base
    1615 
    1616 #if DEBUG_FATFS_REMOVE_DENTRY
    1617 char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1618 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1619 thread_t * this  = CURRENT_THREAD;
    1620 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    1621 if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1622 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    1623 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1624 #endif
    1625 
    1626 // check arguments
    1627 assert( (inode != NULL) , "inode pointer is NULL\n" );
    1628 assert( (dentry != NULL) , "dentry pointer is NULL\n" );
    1629 assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" );
    1630 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
    1631 
    1632     // get pointers on directory mapper
    1633     mapper    = inode->mapper;
    1634     mapper_xp = XPTR( local_cxy , mapper );
    1635 
    1636     // compute number of LFN entries
    1637     uint32_t nb_lfn;
    1638     uint32_t name_length = strlen( dentry->name );
    1639 
    1640     if      ( name_length <= 13 ) nb_lfn  = 1;
    1641     else if ( name_length <= 26 ) nb_lfn  = 2;
    1642     else                          nb_lfn  = 3;
    1643 
    1644     // we must invalidate (2, 3 or 4) 32 bytes entries:
    1645     // the NORMAL entry (registered in dentry->extend) and all preceding LFN entries
    1646     // At most two pages are modified:
    1647     // - the page containing the NORMAL entry is always modified.
    1648     // - the preceding page is modified when the name spread on two pages.
    1649 
    1650     // get 32 bytes directory entry index from dentry->extend
    1651     uint32_t  dentry_id  = (uint32_t)(intptr_t)dentry->extend;
    1652 
    1653     // get page index and offset in parent directory mapper
    1654     uint32_t  page_id    = dentry_id >> 7;
    1655     uint32_t  offset     = (dentry_id & 0x7F)<<5;
    1656 
    1657 #if DEBUG_FATFS_REMOVE_DENTRY & 1
    1658 if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1659 printk("\n[%s] dentry_id %x / page_id %x / offset %x\n",
    1660 __FUNCTION__, dentry_id, page_id, offset );
    1661 #endif
    1662 
    1663     // get extended pointer on page descriptor from parent directory mapper
    1664     page_xp  = mapper_remote_get_page( mapper_xp , page_id );
    1665 
    1666     if ( page_xp == XPTR_NULL )
    1667     {
    1668         printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
    1669         return -1;
    1670     }
    1671        
    1672     // get pointers on page base
    1673     base_xp = ppm_page2base( page_xp );
    1674     base    = GET_PTR( base_xp );
    1675 
    1676     // invalidate NORMAL entry in directory cache
    1677     base[offset] = 0xE5;
    1678 
    1679     // invalidate LFN entries
    1680     while ( nb_lfn )
    1681     {
    1682         if (offset == 0)  // we must load page (page_id - 1)
    1683         {
    1684 
    1685 // check page_id
    1686 assert( (page_id > 0), "page_id and offset cannot be both 0\n" );
    1687 
    1688             // copy the modified page to the IOC device
    1689             fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1690 
    1691             // get extended pointer on page descriptor from parent directory mapper
    1692             page_xp  = mapper_remote_get_page( mapper_xp , page_id );
    1693 
    1694             if ( page_xp == XPTR_NULL )
    1695             {
    1696                 printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
    1697                 return -1;
    1698             }
    1699        
    1700             // get pointers on page base
    1701             base_xp = ppm_page2base( page_xp );
    1702             base    = GET_PTR( base_xp );
    1703 
    1704             // update offset
    1705             offset = 4096;
    1706         }
    1707 
    1708         offset = offset - 32;
    1709 
    1710 // check for LFN entry
    1711 assert( (fatfs_get_record( DIR_ATTR, base + offset ) == ATTR_LONG_NAME_MASK ),
    1712 "this directory entry must be a LFN\n");
    1713 
    1714         // invalidate LFN entry
    1715         base[offset] = 0xE5;
    1716 
    1717         nb_lfn--;
    1718     }     
    1719 
    1720     // copy the modified page to the IOC device
    1721     fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1722    
    1723 
    1724 #if DEBUG_FATFS_REMOVE_DENTRY
    1725 cycle = (uint32_t)hal_get_cycles();
    1726 if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1727 printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
    1728 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1729 #endif
    1730 
    1731     return 0;
    1732 
    1733 }  // end fatfs_remove_dentry
    1734 
    1735 
    17361218//////////////////////////////////////////////////////////////////////////////////////////////
    1737 // This static function scan the pages of a mapper containing a FAT32 directory, identified
    1738 // by the <mapper> argument, to find the directory entry identified by the <name> argument,
    1739 // and return a pointer on the directory entry, described as and array of 32 bytes, and the
    1740 // index of this entry in the FAT32 mapper, seen as an array of 32 bytes entries.
    1741 // It is called by the fatfs_new_dentry() and fatfs_update_dentry() functions.
    1742 // It must be called by a thread running in the cluster containing the mapper.
     1219// This static function scan the pages of a directory mapper, identified by the <mapper_xp>
     1220// argument, to find the directory entry identified by the <name> argument, and returns
     1221// a pointer on the directory entry, described as an array of 32 bytes, and the index of
     1222// this entry in the FAT32 mapper, seen as an array of 32 bytes entries.
     1223// It makes a local copy of each directory entry to reduce the number of remote accesses.
     1224// It is called by the fatfs_new_dentry_from_mapper() function.
     1225// It can be called by a thread running in any cluster.
    17431226//////////////////////////////////////////////////////////////////////////////////////////////
    1744 // @ mapper    : [in]  local pointer on directory mapper.
     1227// @ mapper_xp : [in]  extended pointer on directory mapper.
    17451228// @ name      : [in]  searched directory entry name.
    17461229// @ entry     : [out] buffer for the pointer on the 32 bytes directory entry (when found).
     
    17481231// @ return 0 if found / return 1 if not found / return -1 if mapper access error.
    17491232//////////////////////////////////////////////////////////////////////////////////////////////
    1750 static error_t fatfs_scan_directory( mapper_t *  mapper,
     1233static error_t fatfs_scan_directory( xptr_t      mapper_xp,
    17511234                                     char     *  name,
    17521235                                     uint8_t  ** entry,
    17531236                                     uint32_t *  index )
    17541237{
    1755     // Two embedded loops to scan the directory mapper:
    1756     // - scan the parent directory mapper pages
    1757     // - scan the directory entries in each 4 Kbytes page
    1758 
    1759 // check parent_inode and child_inode
    1760 assert( (mapper != NULL) , "mapper pointer is NULL\n" );
    1761 assert( (name   != NULL ), "child name is undefined\n" );
    1762 assert( (entry  != NULL ), "entry buffer undefined\n" );
     1238    uint8_t  buf[32];   // local buffer for one FAT32 directory entry
     1239
     1240// check arguments
     1241assert( (mapper_xp != XPTR_NULL) , "mapper pointer is NULL\n" );
     1242assert( (name      != NULL     ) , "child name is undefined\n" );
    17631243
    17641244#if DEBUG_FATFS_SCAN_DIRECTORY
    1765 char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1766 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1767 thread_t * this  = CURRENT_THREAD;
    1768 vfs_inode_get_name( XPTR( local_cxy , mapper->inode ) , parent_name );
     1245char          parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1246uint32_t      cycle      = (uint32_t)hal_get_cycles();
     1247thread_t    * this       = CURRENT_THREAD;
     1248mapper_t    * mapper_ptr = GET_PTR( mapper_xp );
     1249cxy_t         mapper_cxy = GET_CXY( mapper_xp );
     1250vfs_inode_t * inode_ptr  = hal_remote_lpt( XPTR( mapper_cxy , &mapper_ptr->inode ) );
     1251vfs_inode_get_name( XPTR( mapper_cxy , inode_ptr ) , parent_name );
    17691252if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    17701253printk("\n[%s]  thread[%x,%x] enter to search child <%s> in parent <%s> / cycle %d\n",
     
    17771260    char       lfn2[16];         // buffer for one partial cname
    17781261    char       lfn3[16];         // buffer for one partial cname
    1779     xptr_t     mapper_xp;        // extended pointer on mapper descriptor
    1780     xptr_t     page_xp;          // extended pointer on page descriptor
    1781     xptr_t     base_xp;          // extended pointer on page base
    1782     uint8_t  * base;             // local pointer on page base
     1262    xptr_t     page_xp;          // extended pointer on one page descriptor
     1263    xptr_t     base_xp;          // extended pointer on one page base
    17831264    uint8_t    attr;             // directory entry ATTR field
    17841265    uint8_t    ord;              // directory entry ORD field
     
    17891270    uint32_t   offset    = 0;    // byte offset in page
    17901271
    1791     mapper_xp = XPTR( local_cxy , mapper );
     1272    // Two embedded loops to scan the directory mapper:
     1273    // - scan the parent directory mapper pages
     1274    // - scan the directory entries in each 4 Kbytes page
    17921275
    17931276    // scan the mapper pages
     
    17951278    {
    17961279        // get one page
    1797         page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1280        page_xp = mapper_get_page( mapper_xp , page_id );
    17981281
    17991282        if( page_xp == XPTR_NULL)
     
    18041287        // get page base
    18051288        base_xp = ppm_page2base( page_xp );
    1806         base    = (uint8_t *)GET_PTR( base_xp );
    1807 
    1808 #if (DEBUG_FATFS_SCAN_DIRECTORY & 0x1)
     1289
     1290#if (DEBUG_FATFS_SCAN_DIRECTORY & 1)
    18091291if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    18101292mapper_display_page( mapper_xp , page_xp , 256 );
     
    18131295        while( (offset < 4096) && (found == 0) )
    18141296        {
    1815             attr = fatfs_get_record( DIR_ATTR , base + offset );   
    1816             ord  = fatfs_get_record( LDIR_ORD , base + offset );   
     1297            // makes a local copy of current directory entry  (32 bytes)
     1298            hal_remote_memcpy( XPTR( local_cxy , buf ) , base_xp + offset , 32 );
     1299
     1300            // get attr and ord from local buffer
     1301            attr = fatfs_get_record( DIR_ATTR , buf );   
     1302            ord  = fatfs_get_record( LDIR_ORD , buf );   
    18171303
    18181304            if (ord == NO_MORE_ENTRY)                 // no more entry => break
     
    18321318                seq = ord & 0x3;
    18331319                lfn = (seq > lfn) ? seq : lfn;   
    1834                 if      ( seq == 1 ) fatfs_get_name_from_long( base + offset, lfn1 );
    1835                 else if ( seq == 2 ) fatfs_get_name_from_long( base + offset, lfn2 );
    1836                 else if ( seq == 3 ) fatfs_get_name_from_long( base + offset, lfn3 );
     1320                if      ( seq == 1 ) fatfs_get_name_from_long( buf , lfn1 );
     1321                else if ( seq == 2 ) fatfs_get_name_from_long( buf , lfn2 );
     1322                else if ( seq == 3 ) fatfs_get_name_from_long( buf , lfn3 );
    18371323                offset = offset + 32;
    18381324            }
     
    18421328                if      ( lfn == 0 )
    18431329                {
    1844                     fatfs_get_name_from_short( base + offset , cname );
     1330                    fatfs_get_name_from_short( buf , cname );
    18451331                }
    18461332                else if ( lfn == 1 )
     
    18631349                if ( strcmp( name , cname ) == 0 )
    18641350                {
     1351                    uint8_t * base = GET_PTR( base_xp );
    18651352                    *entry = base + offset;
    1866                     *index = ((page_id<<12) + offset)>>5;
    1867                     found     = 1;
     1353                    *index = ( (page_id << 12) + offset ) >> 5;
     1354                    found  = 1;
    18681355                }
    18691356                offset = offset + 32;
    18701357                lfn    = 0;
    18711358            }
     1359
    18721360        }  // end loop on directory entries in page
    18731361
     
    18811369
    18821370#if DEBUG_FATFS_SCAN_DIRECTORY
    1883 cycle = (uint32_t)hal_get_cycles();
    18841371if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    18851372printk("\n[%s]  thread[%x,%x] exit / found child <%s> in <%s>\n",
     
    18921379
    18931380#if DEBUG_FATFS_SCAN_DIRECTORY
    1894 cycle = (uint32_t)hal_get_cycles();
    18951381if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    18961382printk("\n[%s]  thread[%x,%x] exit / child <%s> in <%s> not found\n",
     
    19091395
    19101396
    1911 
    1912 /////////////////////////////////////////////////////
    1913 error_t fatfs_new_dentry( vfs_inode_t * parent_inode,
    1914                           char        * name,
    1915                           xptr_t        child_inode_xp )
    1916 {
    1917     uint8_t      * entry;            // pointer on FAT32 directory entry (array of 32 bytes)
    1918     uint32_t       index;            // index of FAT32 directory entry in mapper
    1919     mapper_t     * mapper;           // pointer on directory mapper
    1920     uint32_t       cluster;          // directory entry cluster
    1921     uint32_t       size;             // directory entry size
    1922     bool_t         is_dir;           // directory entry type (file/dir)
    1923     xptr_t         root_xp;          // extended pointer on root of parent dentries
    1924     xptr_t         iter_xp;          // iterator for this list
    1925     cxy_t          child_inode_cxy;  // child inode cluster 
    1926     vfs_inode_t  * child_inode_ptr;  // child inode local pointer
    1927     xptr_t         dentry_xp;        // extended pointer on searched dentry descriptor
    1928     cxy_t          dentry_cxy;       // cluster identifier of dentry (must be local_cxy)
    1929     vfs_dentry_t * dentry_ptr;       // local pointer
    1930     error_t        error;
    1931 
    1932     char           parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1933 
    1934 // check arguments
    1935 assert( (parent_inode   != NULL)       , "parent_inode is NULL\n" );
    1936 assert( (name           != NULL)       , "name is NULL\n" );
    1937 assert( (child_inode_xp != XPTR_NULL ) , "child_inode is NULL\n" );
    1938 
    1939     // get child inode cluster and local pointer
    1940     child_inode_cxy = GET_CXY( child_inode_xp );
    1941     child_inode_ptr = GET_PTR( child_inode_xp );
    1942 
    1943     // build extended pointer on root of list of parent dentries
    1944     root_xp = XPTR( child_inode_cxy , &child_inode_ptr->parents );
    1945 
    1946 // check child inode has at least one parent
    1947 assert( (xlist_is_empty( root_xp ) == false ), "child inode must have one parent\n");
    1948 
    1949 #if DEBUG_FATFS_NEW_DENTRY
     1397//////////////////////////////////////////////////////////////////////////////////////////
     1398//              FATFS debug functions
     1399//////////////////////////////////////////////////////////////////////////////////////////
     1400
     1401///////////////////////////////////
     1402void fatfs_display_ctx( cxy_t cxy )
     1403{
     1404    // get pointer on local FATFS context
     1405    vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
     1406        fatfs_ctx_t * ctx     = hal_remote_lpt( XPTR( cxy , &vfs_ctx->extend ) );
     1407
     1408    uint32_t fat_sectors       = hal_remote_l32( XPTR( cxy , &ctx->fat_sectors_count ) );
     1409    uint32_t sector_size       = hal_remote_l32( XPTR( cxy , &ctx->bytes_per_sector ) );
     1410    uint32_t sec_per_clus      = hal_remote_l32( XPTR( cxy , &ctx->sectors_per_cluster ) );
     1411    uint32_t fat_lba           = hal_remote_l32( XPTR( cxy , &ctx->fat_begin_lba ) );
     1412    uint32_t data_lba          = hal_remote_l32( XPTR( cxy , &ctx->cluster_begin_lba ) );
     1413    uint32_t fsinfo_lba        = hal_remote_l32( XPTR( cxy , &ctx->fs_info_lba ) );
     1414    uint32_t root_dir_clus     = hal_remote_l32( XPTR( cxy , &ctx->root_dir_cluster ) );
     1415    uint32_t free_clusters     = hal_remote_l32( XPTR( cxy , &ctx->free_clusters ) );
     1416    uint32_t free_cluster_hint = hal_remote_l32( XPTR( cxy , &ctx->free_cluster_hint ) );
     1417    void   * fat_mapper        = hal_remote_lpt( XPTR( cxy , &ctx->fat_mapper ) );
     1418    void   * fs_info_buffer    = hal_remote_lpt( XPTR( cxy , &ctx->fs_info_buffer ) );
     1419
     1420    printk("\n*** FAT context in cluster %x\n"
     1421           "- fat_sectors       = %d\n"
     1422           "- sector size       = %d\n"
     1423           "- cluster size      = %d\n"
     1424           "- fat_lba           = %x\n"
     1425           "- data_lba          = %x\n"
     1426           "- fsinfo_lba        = %x\n"
     1427           "- root_dir_cluster  = %x\n"
     1428           "- free_clusters     = %x\n"
     1429           "- free_cluster_hint = %x\n"
     1430           "- fat_mapper        = %x\n"
     1431           "- fs_info_buffer    = %x\n",
     1432           cxy,
     1433           fat_sectors,
     1434           sector_size,
     1435           sector_size * sec_per_clus,
     1436           fat_lba,
     1437           data_lba,
     1438           fsinfo_lba,
     1439           root_dir_clus,
     1440           free_clusters,
     1441           free_cluster_hint,
     1442           fat_mapper,
     1443           fs_info_buffer );
     1444
     1445}  // end fatfs_display_ctx()
     1446
     1447//////////////////////////////////////////
     1448void fatfs_display_fat( uint32_t  min_slot,
     1449                        uint32_t  nb_slots )
     1450{
     1451    // one FAT mapper page contains 1024 slots = 128 lines of 8 slots
     1452
     1453    uint32_t   page_id;
     1454    uint32_t   line;
     1455    cxy_t      fat_cxy;         // FAT cluster
     1456    mapper_t * mapper;          // local pointer on FAT mapper
     1457    xptr_t     mapper_xp;       // extended pointer on fat_mapper
     1458    uint32_t   min_cluster_id;  // index of min slot to be displayed
     1459    uint32_t   min_page_id;     // index of min page to be displayed
     1460    uint32_t   min_line_id;     // index of min line in min page ( < 128 )
     1461    uint32_t   max_cluster_id;  // index of max slot to be displayed
     1462    uint32_t   max_page_id;     // index of max page to be displayed
     1463    uint32_t   max_line_id;     // index of max line in max page ( < 128 )
     1464
     1465    // compute min values
     1466    min_cluster_id = min_slot & 0xFFFFFFF8;
     1467    min_line_id    = (min_cluster_id & 0x3FF) >> 3;
     1468    min_page_id    = min_cluster_id >> 10;
     1469
     1470    // compute max values
     1471    max_cluster_id = min_slot + nb_slots - 1;
     1472    max_line_id    = (max_cluster_id & 0x3FF) >> 3;
     1473    max_page_id    = max_cluster_id >> 10;
     1474
     1475    // get pointer on local FATFS context
     1476    vfs_ctx_t   * vfs_ctx       = &fs_context[FS_TYPE_FATFS];
     1477    fatfs_ctx_t * loc_fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
     1478
     1479    // get FAT cluster
     1480    fat_cxy = CONFIG_VFS_ROOT_CXY;
     1481
     1482    // get pointers on FAT mapper (in FAT cluster)
     1483    mapper    = loc_fatfs_ctx->fat_mapper;
     1484    mapper_xp = XPTR( fat_cxy , mapper );
     1485
     1486    // get pointer on FATFS context in FAT cluster
     1487    fatfs_ctx_t * fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     1488 
     1489    // get current value of hint and free_clusters
     1490    uint32_t hint = hal_remote_l32( XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint ) );
     1491    uint32_t free = hal_remote_l32( XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters ) );
     1492
     1493    printk("\n***** FAT mapper / cxy %x / free_clusters %x / hint %x\n", fat_cxy, free, hint );
     1494
     1495    // scan all pages as required by min_page_id and max_page_id
     1496    for( page_id = min_page_id ; page_id <= max_page_id ; page_id++ )
     1497    {
     1498        // get extended pointer on requested page descriptor in FAT mapper
     1499        xptr_t page_xp = mapper_get_fat_page( mapper_xp , page_id );
     1500
     1501        // get extended pointer on requested page base
     1502        xptr_t     base_xp  = ppm_page2base( page_xp );
     1503
     1504        // compute min_line & max_line in current page
     1505        uint32_t min_line = (page_id == min_page_id) ? min_line_id : 0;
     1506        uint32_t max_line = (page_id == max_page_id) ? max_line_id : 127;
     1507
     1508        // loop on lines in current page
     1509        for( line = min_line ; line <= max_line ; line++ )
     1510        {
     1511            printk("%x : %X | %X | %X | %X | %X | %X | %X | %X\n",
     1512            (page_id << 10) + (line <<3 ),
     1513            hal_remote_l32( base_xp + ((line<<5)      ) ),
     1514            hal_remote_l32( base_xp + ((line<<5) + 4  ) ),
     1515            hal_remote_l32( base_xp + ((line<<5) + 8  ) ),
     1516            hal_remote_l32( base_xp + ((line<<5) + 12 ) ),
     1517            hal_remote_l32( base_xp + ((line<<5) + 16 ) ),
     1518            hal_remote_l32( base_xp + ((line<<5) + 20 ) ),
     1519            hal_remote_l32( base_xp + ((line<<5) + 24 ) ),
     1520            hal_remote_l32( base_xp + ((line<<5) + 28 ) ) );
     1521        }
     1522    }
     1523}  // end fatfs_display_fat()
     1524
     1525/////////////////////////////////////
     1526error_t fatfs_check_free_info( void )
     1527{
     1528    error_t       error;
     1529    fatfs_ctx_t * fatfs_ctx_ptr;              // local pointer on fatfs context in cluster 0
     1530    uint32_t      ctx_free_clusters;          // number of free clusters from fatfs context
     1531    uint32_t      ctx_free_cluster_hint;      // free cluster hint from fatfs context
     1532    uint32_t      ioc_free_clusters;          // number of free clusters from fatfs context
     1533    uint32_t      ioc_free_cluster_hint;      // free cluster hint from fatfs context
     1534    uint32_t      fs_info_lba;                // lba of FS_INFO sector on IOC device
     1535    uint8_t     * fs_info_buffer;             // local pointer on FS_INFO buffer in cluster 0
     1536    xptr_t        fs_info_buffer_xp;          // extended pointer on FS_INFO buffer in cluster 0
     1537    uint8_t       tmp_buf[512];               // 512 bytes temporary buffer
     1538    xptr_t        tmp_buf_xp;                 // extended pointer on temporary buffer
     1539
     1540#if DEBUG_FATFS_SYNC_FSINFO
    19501541uint32_t   cycle = (uint32_t)hal_get_cycles();
    19511542thread_t * this  = CURRENT_THREAD;
    1952 vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    1953 if( DEBUG_FATFS_NEW_DENTRY < cycle )
     1543if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1544printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1545__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1546#endif
     1547
     1548    // get pointer on fatfs context in cluster 0
     1549    fatfs_ctx_ptr = hal_remote_lpt( XPTR( 0 , &fs_context[FS_TYPE_FATFS].extend ) );
     1550
     1551    // get "free_clusters" and "free_cluster_hint" from fatfs context in cluster 0
     1552    ctx_free_clusters     = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_clusters ) );
     1553    ctx_free_cluster_hint = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_cluster_hint ) );
     1554
     1555    // get fs_info_lba
     1556    fs_info_lba = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->fs_info_lba ) );
     1557
     1558    // build extended pointer on temporary buffer
     1559    tmp_buf_xp = XPTR( local_cxy , tmp_buf );
     1560
     1561    // copy FS_INFO sector from IOC to local buffer
     1562    error = dev_ioc_sync_read( tmp_buf_xp , fs_info_lba , 1 );
     1563
     1564    if ( error )
     1565    {
     1566        printk("\n[ERROR] in %s : cannot access FS_INFO on IOC device\n", __FUNCTION__ );
     1567        return -1;
     1568    }
     1569
     1570    // get current values of "free_clusters" and "free_cluster_hint" from FS_INFO on IOC
     1571    ioc_free_clusters     = fatfs_get_remote_record( FS_FREE_CLUSTERS     , tmp_buf_xp );
     1572    ioc_free_cluster_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , tmp_buf_xp );
     1573
     1574#if DEBUG_FATFS_SYNC_FSINFO
     1575if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1576printk("\n[%s] thread[%x,%x] / ctx_free %x / ioc_free %x / ctx_hint %x / ioc_hint %x\n",
     1577__FUNCTION__ , this->process->pid, this->trdid,
     1578ctx_free_clusters, ioc_free_clusters, ctx_free_cluster_hint, ioc_free_cluster_hint );
     1579#endif
     1580
     1581    // check values
     1582    if( (ioc_free_clusters     != ctx_free_clusters) ||
     1583        (ioc_free_cluster_hint != ctx_free_cluster_hint) )
     1584    {
     1585        printk("\n[WARNING] in %s : unconsistent free clusters info\n"
     1586        " ioc_free %x / ctx_free %x / ioc_hint %x / ctx_hint %x\n",
     1587        __FUNCTION__, ioc_free_clusters, ctx_free_clusters,
     1588        ioc_free_cluster_hint, ctx_free_cluster_hint );
     1589
     1590        // get pointers on FS_INFO buffer in cluster 0
     1591        fs_info_buffer    = hal_remote_lpt( XPTR( 0 , &fatfs_ctx_ptr->fs_info_buffer ) );
     1592        fs_info_buffer_xp = XPTR( 0 , fs_info_buffer );
     1593
     1594        // update FS_INFO buffer in cluster 0
     1595        fatfs_set_remote_record(FS_FREE_CLUSTERS    ,fs_info_buffer_xp,ctx_free_clusters );
     1596        fatfs_set_remote_record(FS_FREE_CLUSTER_HINT,fs_info_buffer_xp,ctx_free_cluster_hint);
     1597
     1598        // update the FS_INFO sector on IOC device
     1599        error = dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
     1600
     1601        if ( error )
     1602        {
     1603            printk("\n[ERROR] in %s : cannot update FS_INFO on IOC device\n", __FUNCTION__ );
     1604            return -1;
     1605        }
     1606    }
     1607
     1608#if DEBUG_FATFS_SYNC_FSINFO
     1609cycle = (uint32_t)hal_get_cycles();
     1610if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1611printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1612__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1613#endif
     1614
     1615    return 0;
     1616
     1617}  // end fatfs_check_free_info()
     1618
     1619
     1620
     1621
     1622
     1623///////////////////////////////////////////////////////////////////////////////////////
     1624// Generic API : the following functions are called by the kernel VFS
     1625//               and must be defined by all supported file systems.
     1626///////////////////////////////////////////////////////////////////////////////////////
     1627
     1628
     1629/////////////////////////////////////
     1630xptr_t  fatfs_ctx_alloc( cxy_t  cxy )
     1631{
     1632    kmem_req_t    req;
     1633
     1634    // allocate memory from remote cluster
     1635        req.type     = KMEM_KCM;
     1636        req.order    = bits_log2( sizeof(fatfs_ctx_t) );
     1637    req.flags    = AF_KERNEL | AF_ZERO;
     1638 
     1639    return XPTR( cxy , kmem_remote_alloc( cxy , &req ) );
     1640
     1641}  //end faffs_ctx_alloc()
     1642
     1643///////////////////////////////////////////////
     1644error_t  fatfs_ctx_init( xptr_t  fatfs_ctx_xp )
     1645{
     1646    error_t       error;
     1647    kmem_req_t    req;
     1648    cxy_t         cxy;             // FATFS context cluster identifier
     1649    fatfs_ctx_t * fatfs_ctx_ptr;   // local pointer on FATFS context
     1650    uint8_t     * buffer;          // local pointer on 512 bytes buffer
     1651    xptr_t        buffer_xp;       // extended pointer on 512 bytes buffer
     1652    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     1653    mapper_t    * fat_mapper;      // local pointer on FAT mapper
     1654
     1655    // get FATFS context cluster and local pointer
     1656    cxy           = GET_CXY( fatfs_ctx_xp );       
     1657    fatfs_ctx_ptr = GET_PTR( fatfs_ctx_xp );
     1658   
     1659#if DEBUG_FATFS_CTX_INIT
     1660uint32_t   cycle = (uint32_t)hal_get_cycles();
     1661thread_t * this  = CURRENT_THREAD;
     1662if( DEBUG_FATFS_CTX_INIT < cycle )
     1663printk("\n[%s] thread[%x,%x] enter for fatfs_ctx (%x,%x) / cycle %d\n",
     1664__FUNCTION__ , this->process->pid, this->trdid, cxy, fatfs_ctx_ptr , cycle );
     1665#endif
     1666
     1667    // allocate a 512 bytes buffer in remote cluster, used to store
     1668    // temporarily the BOOT sector, and permanently the FS_INFO sector
     1669        req.type    = KMEM_KCM;
     1670    req.order   = 9;                    // 512 bytes
     1671    req.flags   = AF_KERNEL | AF_ZERO;
     1672        buffer      = kmem_remote_alloc( cxy , &req );
     1673
     1674    if( buffer == NULL )
     1675    {
     1676        printk("\n[PANIC] in %s : cannot allocate buffer in cluster %x\n",
     1677        __FUNCTION__ , cxy );
     1678        return -1;
     1679    }
     1680     
     1681    // build extended pointer on buffer
     1682    buffer_xp = XPTR( cxy , buffer );
     1683
     1684    // load the BOOT record from device
     1685    error = dev_ioc_sync_read( buffer_xp , 0 , 1 );
     1686
     1687    if ( error )
     1688    {
     1689        printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ );
     1690        return -1;
     1691    }
     1692
     1693#if (DEBUG_FATFS_CTX_INIT & 0x1)
     1694uint8_t bs[256];
     1695hal_remote_memcpy( XPTR( local_cxy , bs ) , buffer_xp , 256 );
     1696if( DEBUG_FATFS_CTX_INIT < cycle )
     1697putb( "boot record", bs , 256 );
     1698#endif
     1699
     1700    // get sector size from boot record
     1701    uint32_t sector_size = fatfs_get_remote_record( BPB_BYTSPERSEC , buffer_xp );
     1702
     1703    if ( sector_size != 512 )
     1704    {
     1705        printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ );
     1706        return -1;
     1707    }
     1708
     1709    // get cluster size from boot record
     1710    uint32_t nb_sectors = fatfs_get_remote_record( BPB_SECPERCLUS , buffer_xp );
     1711
     1712    if ( nb_sectors != 8 )
     1713    {
     1714        printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ );
     1715        return -1;
     1716    }
     1717
     1718    // get number of FAT copies from boot record
     1719    uint32_t nb_fats = fatfs_get_remote_record( BPB_NUMFATS , buffer_xp );
     1720
     1721    if ( nb_fats != 1 )
     1722    {
     1723        printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ );
     1724        return -1;
     1725    }
     1726
     1727    // get number of sectors in FAT from boot record
     1728    uint32_t fat_sectors = fatfs_get_remote_record( BPB_FAT32_FATSZ32 , buffer_xp );
     1729
     1730    if ( (fat_sectors & 0xF) != 0 )
     1731    {
     1732        printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ );
     1733        return -1;
     1734    }
     1735
     1736    // get root cluster from boot record
     1737    uint32_t root_cluster = fatfs_get_remote_record( BPB_FAT32_ROOTCLUS , buffer_xp );
     1738
     1739    if ( root_cluster != 2 )
     1740    {
     1741        printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ );
     1742        return -1;
     1743    }
     1744
     1745    // get FAT lba from boot record
     1746    uint32_t fat_lba = fatfs_get_remote_record( BPB_RSVDSECCNT , buffer_xp );
     1747
     1748    // get FS_INFO sector lba from boot record
     1749    uint32_t fs_info_lba = fatfs_get_remote_record( BPB_FAT32_FSINFO , buffer_xp );
     1750
     1751    // load the FS_INFO record from device
     1752    error = dev_ioc_sync_read( buffer_xp , fs_info_lba , 1 );
     1753
     1754    if ( error )
     1755    {
     1756        printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ );
     1757        return -1;
     1758    }
     1759
     1760    // get free_clusters number from FS_INFO record
     1761    uint32_t free_clusters = fatfs_get_remote_record( FS_FREE_CLUSTERS , buffer_xp );
     1762
     1763    if ( free_clusters >= fat_sectors << 7 )
     1764    {
     1765        printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ );
     1766        return -1;
     1767    }
     1768
     1769    // get free_cluster_hint from FS_INFO record
     1770    uint32_t free_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , buffer_xp );
     1771
     1772    if ( free_hint >= fat_sectors << 7 )
     1773    {
     1774        printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ );
     1775        return -1;
     1776    }
     1777
     1778    // allocate a mapper for the FAT in remote cluster
     1779    fat_mapper_xp  = mapper_create( cxy , FS_TYPE_FATFS );
     1780
     1781    // get local pointer on FAT mapper
     1782    fat_mapper = GET_PTR( fat_mapper_xp );
     1783
     1784    if ( fat_mapper == NULL )
     1785    {
     1786        printk("\n[PANIC] in %s : no memory for FAT mapper in cluster %x\n",
     1787        __FUNCTION__ , cxy );
     1788        return -1;
     1789    }
     1790
     1791#if (DEBUG_FATFS_CTX_INIT & 0x1)
     1792if( DEBUG_FATFS_CTX_INIT < cycle )
     1793printk("\n[%s] sector_size %d / nb_sectors %d / fat_sectors %x / hint %x\n",
     1794__FUNCTION__, sector_size, nb_sectors, fat_sectors, free_hint );
     1795#endif
     1796
     1797    // the inode field is NULL for the FAT mapper
     1798    hal_remote_spt( XPTR( cxy , &fat_mapper->inode ) , NULL );
     1799
     1800    // initialize the FATFS context
     1801    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->fat_begin_lba       ), fat_lba );
     1802    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->fat_sectors_count   ), fat_sectors );
     1803    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->bytes_per_sector    ), sector_size );
     1804    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->sectors_per_cluster ), nb_sectors );
     1805    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->cluster_begin_lba   ), fat_lba + fat_sectors );
     1806    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->root_dir_cluster    ), 2 );
     1807    hal_remote_spt( XPTR( cxy , &fatfs_ctx_ptr->fat_mapper          ), fat_mapper );
     1808    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->fs_info_lba         ), fs_info_lba );
     1809    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->free_clusters       ), free_clusters );
     1810    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->free_cluster_hint   ), free_hint );
     1811    hal_remote_spt( XPTR( cxy , &fatfs_ctx_ptr->fs_info_buffer      ), buffer );
     1812
     1813    // initialize FATFS lock
     1814    remote_rwlock_init( XPTR( cxy , &fatfs_ctx_ptr->lock ) , LOCK_FATFS_FAT );
     1815
     1816#if DEBUG_FATFS_CTX_INIT
     1817if( DEBUG_FATFS_CTX_INIT < cycle )
     1818printk("\n[%s]  thread[%x,%x] exit for fatfs_ctx (%x,%x)\n",
     1819__FUNCTION__, this->process->pid, this->trdid, cxy, fatfs_ctx_ptr );
     1820#endif
     1821
     1822        return 0;
     1823
     1824}  // end fatfs_ctx_init()
     1825
     1826//////////////////////////////////////////////
     1827void fatfs_ctx_destroy( xptr_t  fatfs_ctx_xp )
     1828{
     1829    kmem_req_t   req;
     1830    mapper_t   * fat_mapper;
     1831    uint8_t    * fs_info_buffer;
     1832
     1833    // get FATFS context cluster and local pointer
     1834    fatfs_ctx_t * fatfs_ctx_ptr = GET_PTR( fatfs_ctx_xp );
     1835    cxy_t         fatfs_ctx_cxy = GET_CXY( fatfs_ctx_xp );
     1836
     1837    // get pointer on FAT mapper
     1838    fat_mapper = hal_remote_lpt( XPTR( fatfs_ctx_cxy , &fatfs_ctx_ptr->fat_mapper ) );
     1839
     1840    // release FAT mapper
     1841    mapper_destroy( XPTR( fatfs_ctx_cxy , fat_mapper ) );
     1842
     1843    // get pointer on FS_INFO buffer
     1844    fs_info_buffer = hal_remote_lpt( XPTR( fatfs_ctx_cxy , &fatfs_ctx_ptr->fs_info_buffer ) );
     1845
     1846    // release FS_INFO buffer
     1847    req.type = KMEM_KCM;
     1848    req.ptr  = fs_info_buffer;
     1849    kmem_remote_free( fatfs_ctx_cxy , &req );
     1850
     1851    // release FATFS context descriptor
     1852    req.type = KMEM_KCM;
     1853    req.ptr  = fatfs_ctx_ptr;
     1854    kmem_remote_free( fatfs_ctx_cxy , &req );
     1855
     1856}  // end fatfs_ctx_destroy()
     1857
     1858/////////////////////////////////////////////////////////
     1859error_t fatfs_add_dentry( xptr_t         parent_inode_xp,
     1860                          vfs_dentry_t * dentry_ptr )
     1861{
     1862    error_t       error;
     1863    vfs_inode_t * parent_inode_ptr;   // parent inode local pointer
     1864    cxy_t         parent_cxy;         // pparent inode cluster
     1865    xptr_t        child_inode_xp;     // extended pointer on child inode
     1866    cxy_t         child_cxy;          // child inode cluster
     1867    vfs_inode_t * child_inode_ptr;    // child inode local pointer
     1868    uint32_t      length;             // dentry name length
     1869    uint32_t      nb_lfn;             // number or required LFN
     1870    char          sfn[11];            // buffer for SFN name
     1871    uint8_t       checksum;           // name checksum
     1872    mapper_t    * mapper_ptr;         // local pointer on parent directory mapper
     1873    xptr_t        mapper_xp;          // extended pointer on parent directory mapper
     1874    uint32_t      size;               // child inode size
     1875    uint32_t      type;               // child inode type
     1876    void        * extend;             // child inode extension
     1877    uint32_t      cluster_id;         // child inode first cluster_id in FATFS
     1878
     1879    char          child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1880
     1881    uint8_t       buf[32];            // local buffer for one FAT32 directory entry
     1882 
     1883// check arguments
     1884assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     1885assert( (dentry_ptr      != NULL)      , "dentry_ptr argument is NULL\n" );
     1886
     1887    // get directory inode cluster and local pointer
     1888    parent_cxy       = GET_CXY( parent_inode_xp );
     1889    parent_inode_ptr = GET_PTR( parent_inode_xp );
     1890
     1891    // get extended pointers on child inode
     1892    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     1893    child_cxy       = GET_CXY( child_inode_xp );
     1894    child_inode_ptr = GET_PTR( child_inode_xp );
     1895
     1896    // get a local copy of the child name
     1897    vfs_inode_get_name( child_inode_xp  , child_name );
     1898
     1899#if DEBUG_FATFS_ADD_DENTRY
     1900uint32_t   cycle = (uint32_t)hal_get_cycles();
     1901thread_t * this  = CURRENT_THREAD;
     1902char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1903vfs_inode_get_name( parent_inode_xp , parent_name );
     1904if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1905printk("\n[%s]  thread[%x,%x] enter for <%s> in <%s> directory / cycle %d\n",
     1906__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle );
     1907#endif
     1908
     1909    // get pointers on parent directory mapper
     1910    mapper_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     1911    mapper_xp  = XPTR( parent_cxy , mapper_ptr );
     1912
     1913#if (DEBUG_FATFS_ADD_DENTRY & 1)
     1914mapper_display_page( mapper_xp , 0 , 512 );
     1915#endif
     1916
     1917    // get relevant infos from child inode
     1918    type       = hal_remote_l32( XPTR( child_cxy , &child_inode_ptr->type ) );
     1919    size       = hal_remote_l32( XPTR( child_cxy , &child_inode_ptr->size ) );
     1920    extend     = hal_remote_lpt( XPTR( child_cxy , &child_inode_ptr->extend ) );
     1921    cluster_id = (uint32_t)(intptr_t)extend;
     1922
     1923    // analyse child name
     1924    error = fatfs_name_format( child_name,
     1925                               &length,
     1926                               &nb_lfn,
     1927                               sfn,
     1928                               &checksum );
     1929    if ( error )
     1930    {
     1931        printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ );
     1932        return -1;
     1933    }
     1934                               
     1935    // Search end of directory with two embedded loops:
     1936    // - scan the pages in the mapper
     1937    // - scan the entries in each page to find NO_MORE_ENTRY
     1938
     1939    xptr_t     page_xp;                 // extended pointer on page descriptor
     1940    xptr_t     base_xp;                 // extended pointer on page base
     1941
     1942    // initialise loop variables
     1943    uint32_t   page_id = 0;             // page index in mapper
     1944    uint32_t   offset  = 0;             // position in page
     1945    uint32_t   found   = 0;             // NO_MORE_ENTRY found
     1946
     1947    // loop on pages in mapper
     1948    while ( found == 0 )
     1949    {
     1950        // get extended pointer on page descriptor in mapper
     1951        page_xp  = mapper_get_page( mapper_xp , page_id );
     1952
     1953        if ( page_xp == XPTR_NULL )
     1954        {
     1955            printk("\n[ERROR] in %s : cannot extend directory mapper\n",
     1956            __FUNCTION__ );
     1957            return -1;
     1958        }
     1959       
     1960        // get pointer on page base
     1961        base_xp = ppm_page2base( page_xp );
     1962
     1963        // loop on directory entries in this page
     1964        while ( (offset < 4096) && (found == 0) )
     1965        {
     1966            if ( fatfs_get_remote_record( LDIR_ORD, (base_xp + offset) ) == NO_MORE_ENTRY )
     1967            {
     1968                found = 1;
     1969            } 
     1970            else
     1971            {
     1972                offset = offset + 32;
     1973            }
     1974        }  // end loop on entries
     1975
     1976        if ( found == 0 )
     1977        {
     1978            page_id++;
     1979            offset = 0;
     1980        }
     1981    }  // end loop on pages
     1982
     1983#if (DEBUG_FATFS_ADD_DENTRY & 1)
     1984if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1985printk("\n[%s]  thread[%x,%x] found NO_MORE_ENTRY : page_id %d / offset %d\n",
     1986__FUNCTION__, this->process->pid, this->trdid, page_id, offset );
     1987#endif
     1988
     1989    // Modify the directory mapper: depending on the name length,
     1990    // the new child requires to write (3, 4, or 5) directory entries.
     1991    // We build one complete directory entry in a local buffer
     1992    // before copying it the remote mapper. We use use a 5 steps FSM
     1993    // (one state per entry to be written), that is traversed as :
     1994    // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
     1995    // At most two pages are modified:
     1996    // - the page containing the NO_MORE_ENTRY is always modified
     1997    // - the following page can be modified if the name spread on two pages.
     1998
     1999    uint32_t step;          // FSM state
     2000
     2001    if      ( nb_lfn == 1 ) step = 3;
     2002    else if ( nb_lfn == 2 ) step = 4;
     2003    else if ( nb_lfn == 3 ) step = 5;
     2004   
     2005    uint32_t   i;           // byte index in one 32 bytes directory
     2006    uint32_t   c;           // character index in name
     2007
     2008    while ( step )   
     2009    {
     2010        // this block is only executed when the new name spread
     2011        // on two pages, and we need to access a new page in mapper
     2012        if ( offset >= 4096 )
     2013        {
     2014            // copy the modified page to IOC device
     2015            error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2016
     2017            if ( error )
     2018            {
     2019                printk("\n[ERROR] in %s : cannot update directory on device\n",
     2020                __FUNCTION__ );
     2021                return -1;
     2022            }
     2023
     2024            // get the next page in directory mapper
     2025            page_xp  = mapper_get_page( mapper_xp , page_id + 1 );
     2026
     2027            if ( page_xp == XPTR_NULL )
     2028            {
     2029                printk("\n[ERROR] in %s : cannot extend directory mapper\n",
     2030                __FUNCTION__ );
     2031                return -1;
     2032            }
     2033       
     2034            // get pointer on page base
     2035            base_xp = ppm_page2base( page_xp );
     2036           
     2037            // update offset
     2038            offset = 0;
     2039        }
     2040
     2041#if (DEBUG_FATFS_ADD_DENTRY & 1)
     2042cycle = (uint32_t)hal_get_cycles();
     2043if( DEBUG_FATFS_ADD_DENTRY < cycle )
     2044printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d / cycle %d\n",
     2045__FUNCTION__, step, offset, nb_lfn, cycle );
     2046#endif
     2047
     2048        // write one FATFS directory entry (32 bytes) per iteration
     2049        switch ( step )
     2050        {
     2051            case 5:   // write LFN3 entry
     2052            {
     2053                c = 26;
     2054
     2055                // write 32 bytes in local buf
     2056                for ( i = 0 ; i < 32 ; i++ )
     2057                {
     2058                    if (i == 0)
     2059                    {
     2060                        if ( nb_lfn == 3) buf[i] = 0x43;
     2061                        else              buf[i] = 0x03;
     2062                    }
     2063                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     2064                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     2065                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     2066                              ( c < length ) )
     2067                    {
     2068                                          buf[i] = child_name[c];
     2069                                          c++;
     2070                    }
     2071                    else if (i == 11)     buf[i] = 0x0F;
     2072                    else if (i == 13)     buf[i] = checksum;
     2073                    else                  buf[i] = 0x00;
     2074                }
     2075
     2076                // copy 32 bytes from local buffer to remote mapper
     2077                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2078
     2079                step--;
     2080                break;
     2081            }
     2082            case 4:   // write LFN2 entry 
     2083            {
     2084                c = 13;
     2085
     2086                // write 32 bytes in local buf
     2087                for ( i = 0 ; i < 32 ; i++ )
     2088                {
     2089                    if (i == 0)
     2090                    {
     2091                        if ( nb_lfn == 2) buf[i] = 0x42;
     2092                        else              buf[i] = 0x02;
     2093                    }
     2094                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     2095                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     2096                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     2097                              ( c < length ) )
     2098                    {
     2099                                          buf[i] = child_name[c];
     2100                                          c++;
     2101                    }
     2102                    else if (i == 11)     buf[i] = 0x0F;
     2103                    else if (i == 13)     buf[i] = checksum;
     2104                    else                  buf[i] = 0x00;
     2105                }
     2106
     2107                // copy 32 bytes from local buffer to remote mapper
     2108                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2109
     2110                step--;
     2111                break;
     2112            }
     2113            case 3:   // Write LFN1 entry   
     2114            {
     2115                c = 0;
     2116
     2117                // write 32 bytes in local buf
     2118                for ( i = 0 ; i < 32 ; i++ )
     2119                {
     2120                    if (i == 0)
     2121                    {
     2122                        if ( nb_lfn == 1) buf[i] = 0x41;
     2123                        else              buf[i] = 0x01;
     2124                    }
     2125                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     2126                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     2127                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     2128                              ( c < length ) )
     2129                    {
     2130                                          buf[i] = child_name[c];
     2131                                          c++;
     2132                    }
     2133                    else if (i == 11)     buf[i] = 0x0F;
     2134                    else if (i == 13)     buf[i] = checksum;
     2135                    else                  buf[i] = 0x00;
     2136                }
     2137
     2138                // copy 32 bytes from local buffer to remote mapper
     2139                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2140
     2141                step--;
     2142                break;
     2143            }
     2144            case 2:   // write NORMAL entry     
     2145            {
     2146                // write 32 bytes in local buf
     2147                for ( i = 0 ; i < 32 ; i++ )
     2148                {
     2149                    if      ( i < 11 )                               // 8.3 SFN
     2150                    {
     2151                                          buf[i] = sfn[i];
     2152                    }
     2153                    else if (i == 11)                                // ATTR
     2154                    {
     2155                        if (type == INODE_TYPE_DIR)  buf[i] = 0x10;
     2156                        else                         buf[i] = 0x20;
     2157                    }
     2158                    else if (i == 20)     buf[i] = cluster_id>>16;   // cluster.B2
     2159                    else if (i == 21)     buf[i] = cluster_id>>24;   // cluster.B3
     2160                    else if (i == 26)     buf[i] = cluster_id>>0;    // cluster.B0
     2161                    else if (i == 27)     buf[i] = cluster_id>>8;    // cluster.B1
     2162                    else if (i == 28)     buf[i] = size>>0;          // size.B0
     2163                    else if (i == 29)     buf[i] = size>>8;          // size.B1
     2164                    else if (i == 30)     buf[i] = size>>16;         // size.B2
     2165                    else if (i == 31)     buf[i] = size>>24;         // size.B3
     2166                    else                  buf[i] = 0x00;
     2167                }
     2168
     2169                // copy 32 bytes from local buffer to remote mapper
     2170                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2171
     2172                // set the dentry "extend" field
     2173                hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->extend ),
     2174                                (void *)(intptr_t)(((page_id << 12) + offset) >> 5 ) );
     2175                step--;
     2176                break;
     2177            }
     2178            case 1:   // write NOMORE entry 
     2179            {
     2180                hal_remote_s32( base_xp + offset , 0 );
     2181
     2182                step--;
     2183                break;
     2184            }
     2185
     2186        } // end switch step
     2187
     2188        offset += 32;
     2189
     2190    } // end while     
     2191
     2192    // copy the modified page to the IOC device
     2193    error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2194
     2195    if ( error )
     2196    {
     2197        printk("\n[ERROR] in %s : cannot update directory on device\n",
     2198        __FUNCTION__ );
     2199        return -1;
     2200    }
     2201
     2202#if DEBUG_FATFS_ADD_DENTRY
     2203cycle = (uint32_t)hal_get_cycles();
     2204if( DEBUG_FATFS_ADD_DENTRY < cycle )
     2205printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> directory\n",
     2206__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name );
     2207#endif
     2208
     2209#if (DEBUG_FATFS_ADD_DENTRY & 1)
     2210mapper_display_page( mapper_xp , 0 , 512 );
     2211#endif
     2212
     2213    return 0;
     2214
     2215}  // end fatfs_add_dentry()
     2216
     2217////////////////////////////////////////////////////////////
     2218error_t fatfs_remove_dentry( xptr_t         parent_inode_xp,
     2219                             vfs_dentry_t * dentry_ptr )
     2220{
     2221    error_t       error;
     2222    vfs_inode_t * parent_inode_ptr;   // parent inode local pointer
     2223    cxy_t         parent_cxy;         // pparent inode cluster
     2224    xptr_t        child_inode_xp;     // extended pointer on child inode
     2225    cxy_t         child_cxy;          // child inode cluster
     2226    vfs_inode_t * child_inode_ptr;    // child inode local pointer
     2227    xptr_t        mapper_xp;          // extended pointer on mapper
     2228    mapper_t    * mapper_ptr;         // local pointer on mapper
     2229    xptr_t        page_xp;            // extended pointer on mapper page descriptor
     2230    xptr_t        base_xp;            // extended pointer on mapper page base
     2231    uint32_t      dentry_id;          // FAT32 directory entry index
     2232    uint32_t      page_id;            // page index in directory mapper
     2233    uint32_t      offset;             // offset in this mapper page
     2234
     2235    char          child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2236
     2237// check arguments
     2238assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     2239assert( (dentry_ptr      != NULL)      , "dentry_ptr argument is NULL\n" );
     2240
     2241    // get directory inode cluster and local pointer
     2242    parent_cxy       = GET_CXY( parent_inode_xp );
     2243    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2244
     2245    // get extended pointers on child inode
     2246    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2247    child_cxy       = GET_CXY( child_inode_xp );
     2248    child_inode_ptr = GET_PTR( child_inode_xp );
     2249
     2250    // get a local copy of the child name
     2251    vfs_inode_get_name( child_inode_xp  , child_name );
     2252
     2253#if DEBUG_FATFS_REMOVE_DENTRY
     2254uint32_t   cycle = (uint32_t)hal_get_cycles();
     2255thread_t * this  = CURRENT_THREAD;
     2256char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2257vfs_inode_get_name( parent_inode_xp , parent_name );
     2258if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     2259printk("\n[%s]  thread[%x,%x] enter for <%s> in <%s> directory / cycle %d\n",
     2260__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle );
     2261#endif
     2262
     2263    // get pointers on directory mapper
     2264    mapper_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     2265    mapper_xp  = XPTR( parent_cxy , mapper_ptr );
     2266
     2267    // compute number of LFN entries
     2268    uint32_t nb_lfn;
     2269    uint32_t name_length = strlen( child_name );
     2270
     2271    if      ( name_length <= 13 ) nb_lfn  = 1;
     2272    else if ( name_length <= 26 ) nb_lfn  = 2;
     2273    else                          nb_lfn  = 3;
     2274
     2275    // We must invalidate (2,3,4) 32 bytes entries:
     2276    // - the NORMAL entry, registered in dentry->extend.
     2277    // - the (1,2,3) preceding LFN entries.
     2278    // At most two pages are modified:
     2279    // - the page containing the NORMAL entry is always modified.
     2280    // - the preceding page is modified when the name spread on two pages.
     2281
     2282    // get NORMAL entry index from dentry extension
     2283    dentry_id  = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->extend ) );
     2284
     2285    // get page index and offset in parent directory mapper
     2286    page_id  = dentry_id >> 7;
     2287    offset   = (dentry_id & 0x7F)<<5;
     2288
     2289#if DEBUG_FATFS_REMOVE_DENTRY & 1
     2290if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     2291printk("\n[%s] dentry_id %x / page_id %x / offset %x\n",
     2292__FUNCTION__, dentry_id, page_id, offset );
     2293#endif
     2294
     2295    // get extended pointer on page descriptor
     2296    page_xp  = mapper_get_page( mapper_xp , page_id );
     2297
     2298    if ( page_xp == XPTR_NULL )
     2299    {
     2300        printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
     2301        return -1;
     2302    }
     2303       
     2304    // get extended pointer on page base
     2305    base_xp = ppm_page2base( page_xp );
     2306
     2307    // invalidate NORMAL entry in directory cache
     2308    hal_remote_sb( base_xp + offset , 0xE5 );
     2309
     2310    // invalidate LFN entries
     2311    while ( nb_lfn )
     2312    {
     2313        // this block is only executed when the removed name
     2314        // spread on two mapper pages
     2315        if (offset == 0)  // we must load page (page_id - 1)
     2316        {
     2317            // copy the modified page to the IOC device
     2318            error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2319
     2320            if ( error )
     2321            {
     2322                printk("\n[ERROR] in %s : cannot update directory on device\n",
     2323                __FUNCTION__ );
     2324                return -1;
     2325            }
     2326
     2327            // get extended pointer on page descriptor
     2328            page_xp  = mapper_get_page( mapper_xp , page_id );
     2329
     2330            if ( page_xp == XPTR_NULL )
     2331            {
     2332                printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
     2333                return -1;
     2334            }
     2335       
     2336            // get extended pointer on page base
     2337            base_xp = ppm_page2base( page_xp );
     2338
     2339            // update offset
     2340            offset = 4096;
     2341        }
     2342
     2343        offset = offset - 32;
     2344
     2345// check for LFN entry
     2346assert( (fatfs_get_remote_record( DIR_ATTR, base_xp + offset ) == ATTR_LONG_NAME_MASK ),
     2347"this directory entry must be a LFN\n");
     2348
     2349        // invalidate LFN entry
     2350        hal_remote_sb( base_xp + offset , 0xE5 );
     2351
     2352        nb_lfn--;
     2353    }     
     2354
     2355    // copy the modified page to the IOC device
     2356    error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2357   
     2358    if ( error )
     2359    {
     2360        printk("\n[ERROR] in %s : cannot update directory on device\n",
     2361        __FUNCTION__ );
     2362        return -1;
     2363    }
     2364
     2365#if DEBUG_FATFS_REMOVE_DENTRY
     2366cycle = (uint32_t)hal_get_cycles();
     2367if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     2368printk("\n[%s] thread[%x,%x] exit for <%s> in <%s> directory\n",
     2369__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name );
     2370#endif
     2371
     2372    return 0;
     2373
     2374}  // end fatfs_remove_dentry
     2375
     2376/////////////////////////////////////////////////////////////////////
     2377error_t fatfs_new_dentry_from_mapper( xptr_t         parent_inode_xp,
     2378                                      vfs_dentry_t * dentry_ptr )
     2379{
     2380    uint32_t       cluster_id;        // directory entry first FATFS cluster
     2381    uint32_t       size;              // directory entry size
     2382    bool_t         is_dir;            // directory entry type (file/dir)
     2383    cxy_t          parent_cxy;        // parent inode cluster 
     2384    vfs_inode_t  * parent_inode_ptr;  // parent inode local pointer
     2385    mapper_t     * parent_mapper;     // pointer on parent directory mapper
     2386    xptr_t         child_inode_xp;    // extended pointer on child inode
     2387    cxy_t          child_cxy;         // child inode cluster 
     2388    vfs_inode_t  * child_inode_ptr;   // child inode local pointer
     2389    error_t        error;
     2390
     2391    uint8_t        buf[32];           // FAT32 directory entry local copy
     2392
     2393    char           parent_name[CONFIG_VFS_MAX_NAME_LENGTH];     // local parent name copy
     2394    char           child_name[CONFIG_VFS_MAX_NAME_LENGTH];      // local child name copy
     2395
     2396// check arguments
     2397assert( (parent_inode_xp != XPTR_NULL)  , "parent_inode_xp is NULL\n" );
     2398assert( (dentry_ptr      != NULL ) , "dentry_ptr is NULL\n" );
     2399
     2400    // get parent inode cluster and local pointer
     2401    parent_cxy       = GET_CXY( parent_inode_xp );
     2402    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2403
     2404    // get child inode cluster and pointers
     2405    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2406    child_cxy       = GET_CXY( child_inode_xp );
     2407    child_inode_ptr = GET_PTR( child_inode_xp );
     2408
     2409    // get child and parent names
     2410    vfs_inode_get_name( parent_inode_xp , parent_name );
     2411    vfs_inode_get_name( child_inode_xp  , child_name );
     2412
     2413#if DEBUG_FATFS_NEW_DENTRY_FROM
     2414uint32_t   cycle = (uint32_t)hal_get_cycles();
     2415thread_t * this  = CURRENT_THREAD;
     2416if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle )
    19542417printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
    1955 __FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle );
     2418__FUNCTION__, this->process->pid, this->trdid, child_name , parent_name , cycle );
    19562419#endif
    19572420
    19582421    // get local pointer on parent mapper
    1959     mapper = parent_inode->mapper;
    1960 
    1961     // get pointer and index in mapper for searched directory entry
    1962     error  = fatfs_scan_directory( mapper, name , &entry , &index );
    1963 
    1964     // return non fatal error if not found
    1965     if( error )
    1966     {
    1967         vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    1968         printk("\n[ERROR] in %s : cannot find <%s> entry in <%s> directory mapper\n",
    1969         __FUNCTION__, name , parent_name, name );
    1970         return -1;
    1971     }
    1972  
    1973 
    1974     // get relevant infos from FAT32 directory entry
    1975     cluster = (fatfs_get_record( DIR_FST_CLUS_HI , entry ) << 16) |
    1976               (fatfs_get_record( DIR_FST_CLUS_LO , entry )      ) ;
    1977     is_dir  = (fatfs_get_record( DIR_ATTR        , entry ) & ATTR_DIRECTORY);
    1978     size    =  fatfs_get_record( DIR_FILE_SIZE   , entry );
    1979 
    1980     // scan list of parent dentries to search the parent_inode
    1981     bool_t found = false;
    1982     XLIST_FOREACH( root_xp , iter_xp )
    1983     {
    1984         // get pointers on dentry
    1985         dentry_xp  = XLIST_ELEMENT( iter_xp , vfs_dentry_t , parents );
    1986         dentry_cxy = GET_CXY( dentry_xp );
    1987         dentry_ptr = GET_PTR( dentry_xp );
    1988 
    1989         // get local pointer on current parent directory inode
    1990         vfs_inode_t * current = hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) );
    1991 
    1992         // check if current parent is the searched parent
    1993         if( XPTR( dentry_cxy , current ) == XPTR( local_cxy , parent_inode ) )
    1994         {
    1995             found = true;
    1996             break;
    1997         }
    1998     }
    1999 
    2000     if( found == false )
    2001     {
    2002         vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    2003         printk("\n[ERROR] in %s : cannot find <%s> directory in list of parents for <%s>\n",
    2004         __FUNCTION__, parent_name, name );
    2005         return -1;
    2006     }
     2422    parent_mapper = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     2423
     2424    // try to get pointer and index of directory entry in mapper
     2425    uint8_t      * entry = NULL;
     2426    uint32_t       index = 0;
     2427
     2428    error  = fatfs_scan_directory( XPTR( parent_cxy , parent_mapper ),
     2429                                   child_name,
     2430                                   &entry,
     2431                                   &index );
     2432   
     2433    // an error can be non fatal, for a new (created) entry
     2434    if( error )  return -1;
     2435
     2436    // get local copy of found directory entry
     2437    hal_remote_memcpy( XPTR( local_cxy  , buf ),
     2438                       XPTR( parent_cxy , entry ), 32 );
     2439
     2440    // get relevant infos from directory entry
     2441    cluster_id = (fatfs_get_record( DIR_FST_CLUS_HI , buf ) << 16) |
     2442                 (fatfs_get_record( DIR_FST_CLUS_LO , buf )      ) ;
     2443    is_dir     = (fatfs_get_record( DIR_ATTR        , buf ) & ATTR_DIRECTORY );
     2444    size       =  fatfs_get_record( DIR_FILE_SIZE   , buf );
    20072445
    20082446    // update the child inode "type", "size", and "extend" fields
    20092447    vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
    20102448
    2011     hal_remote_s32( XPTR( child_inode_cxy , &child_inode_ptr->type   ) , type );
    2012     hal_remote_s32( XPTR( child_inode_cxy , &child_inode_ptr->size   ) , size );
    2013     hal_remote_s32( XPTR( child_inode_cxy , &child_inode_ptr->extend ) , cluster );
     2449    hal_remote_s32( XPTR( child_cxy , &child_inode_ptr->type   ) , type );
     2450    hal_remote_s32( XPTR( child_cxy , &child_inode_ptr->size   ) , size );
     2451    hal_remote_s32( XPTR( child_cxy , &child_inode_ptr->extend ) , cluster_id );
    20142452
    20152453    // update the dentry "extend" field
    2016     dentry_ptr->extend = (void *)(intptr_t)index;
    2017 
    2018 #if DEBUG_FATFS_NEW_DENTRY
     2454    hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->extend ) , (void *)(intptr_t)index );
     2455
     2456#if DEBUG_FATFS_NEW_DENTRY_FROM
    20192457cycle = (uint32_t)hal_get_cycles();
    2020 if( DEBUG_FATFS_NEW_DENTRY < cycle )
    2021 printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> / cluster_id %x / size %d  / cycle %d\n",
    2022 __FUNCTION__, this->process->pid, this->trdid, name, parent_name, cluster, size,  cycle );
    2023 #endif
    2024 
    2025 
    2026 #if (DEBUG_FATFS_NEW_DENTRY & 1)
    2027 if( DEBUG_FATFS_NEW_DENTRY < cycle )
    2028 {
    2029     fatfs_display_fat( 0 , 0 , 64 );
    2030     fatfs_display_fat( cluster >> 10 ,  (cluster & 0x3FF) , 32 );
    2031 }
     2458if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle )
     2459printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> / cluster_id %x / size %d\n",
     2460__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cluster_id, size );
     2461#endif
     2462
     2463#if (DEBUG_FATFS_NEW_DENTRY_FROM & 1)
     2464if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle )
     2465fatfs_display_fat( cluster_id , 32 );
    20322466#endif
    20332467
    20342468    return 0;
    20352469
    2036 }  // end fatfs_new_dentry()
    2037 
    2038 //////////////////////////////////////////////////
    2039 error_t fatfs_update_dentry( vfs_inode_t  * inode,
    2040                              vfs_dentry_t * dentry,
    2041                              uint32_t       size )
    2042 {
    2043     uint8_t  * entry;    // pointer on FAT32 directory entry (array of 32 bytes)
    2044     uint32_t   index;    // index of FAT32 directory entry in mapper
    2045     mapper_t * mapper;   // pointer on directory mapper
    2046     error_t    error;
    2047 
    2048     char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2470}  // end fatfs_new_dentry_from_mapper()
     2471
     2472///////////////////////////////////////////////////////////////////
     2473error_t fatfs_new_dentry_to_mapper( xptr_t         parent_inode_xp,
     2474                                    vfs_dentry_t * dentry_ptr )
     2475{
     2476    uint32_t       cluster_id;        // directory entry cluster
     2477    cxy_t          parent_cxy;        // parent inode cluster identifier 
     2478    vfs_inode_t  * parent_inode_ptr;  // child inode local pointer
     2479    xptr_t         child_inode_xp;    // extended pointer on child inode
     2480    cxy_t          child_cxy;         // child inode cluster identifier 
     2481    vfs_inode_t  * child_inode_ptr;   // child inode local pointer
     2482    error_t        error;
     2483
     2484    char           parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2485    char           child_name[CONFIG_VFS_MAX_NAME_LENGTH];
    20492486
    20502487// check arguments
    2051 assert( (inode  != NULL) , "inode is NULL\n" );
    2052 assert( (dentry != NULL) , "dentry is NULL\n" );
     2488assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     2489assert( (dentry_ptr      != NULL)      , "dentry_ptr argument NULL\n" );
     2490
     2491    // get child inode cluster and local pointer
     2492    parent_cxy       = GET_CXY( parent_inode_xp );
     2493    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2494
     2495    // get child inode cluster and pointers
     2496    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2497    child_cxy       = GET_CXY( child_inode_xp );
     2498    child_inode_ptr = GET_PTR( child_inode_xp );
     2499
     2500    // get child and parent names
     2501    vfs_inode_get_name( parent_inode_xp , parent_name );
     2502    vfs_inode_get_name( child_inode_xp  , child_name );
     2503
     2504#if DEBUG_FATFS_NEW_DENTRY_TO_MAP
     2505uint32_t   cycle = (uint32_t)hal_get_cycles();
     2506thread_t * this  = CURRENT_THREAD;
     2507if( DEBUG_FATFS_NEW_DENTRY_TO_MAP < cycle )
     2508printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
     2509__FUNCTION__, this->process->pid, this->trdid, child_name , parent_name , cycle );
     2510#endif
     2511
     2512    // 1. allocate one FATFS cluster (update FAT and FSINFO)
     2513    error = fatfs_cluster_alloc( 0 , &cluster_id );
     2514
     2515    if( error )
     2516    {
     2517        printk("\n[ERROR] in %s : cannot find a free cluster_id\n",
     2518        __FUNCTION__ );
     2519        return -1;
     2520    }
     2521       
     2522    // 2. register cluster_id in inode descriptor
     2523    hal_remote_spt( XPTR( child_cxy , &child_inode_ptr->extend ),
     2524                    (void*)(intptr_t)cluster_id );
     2525   
     2526    // 3. introduce dentry in the directory mapper
     2527    error = fatfs_add_dentry( parent_inode_xp , dentry_ptr );
     2528       
     2529    if( error )
     2530    {
     2531        printk("\n[ERROR] in %s : cannot update parent directory mapper\n",
     2532        __FUNCTION__ );
     2533        // TODO release cluster_id [AG]
     2534        return -1;
     2535    }
     2536
     2537#if DEBUG_FATFS_NEW_DENTRY_TO_MAP
     2538if( DEBUG_FATFS_NEW_DENTRY_TO_MAP < cycle )
     2539printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> / cluster_id %x\n",
     2540__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cluster_id );
     2541#endif
     2542
     2543    return 0;
     2544
     2545}  // end fatfs_new_dentry_to mapper()
     2546
     2547
     2548////////////////////////////////////////////////////////////
     2549error_t fatfs_update_dentry( xptr_t         parent_inode_xp,
     2550                             vfs_dentry_t * dentry_ptr )
     2551{
     2552    cxy_t         parent_cxy;        // parent directory cluster identifier
     2553    vfs_inode_t * parent_inode_ptr;  // extended pointer on parent directory inode
     2554    mapper_t    * parent_mapper_ptr; // local pointer on parent directory mapper
     2555    xptr_t        parent_mapper_xp;  // extended pointer on parent directory mapper
     2556    xptr_t        child_inode_xp;    // extended pointer on child inode
     2557    cxy_t         child_cxy;         // child inode cluster identifier
     2558    vfs_inode_t * child_inode_ptr;   // extended pointer on child inode
     2559
     2560    uint32_t      current_size;      // current size in directory mapper
     2561    uint32_t      new_size;          // new size (from child inode)
     2562   
     2563    uint32_t      entry_id;          // directory entry index in parent directory mapper
     2564    uint32_t      page_id;           // page_index in parent directory mapper
     2565    uint32_t      offset;            // directory entry offset in page
     2566    xptr_t        page_xp;           // extended pointer on page descriptor
     2567    xptr_t        base_xp;           // extended pointer on page base
     2568    xptr_t        entry_xp;          // extended pointer on directory entry
     2569
     2570    error_t       error;
     2571
     2572    char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2573    char       child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2574
     2575// check arguments
     2576assert( (parent_inode_xp  != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     2577assert( (dentry_ptr       != NULL)      , "dentry_ptr argument is NULL\n" );
     2578
     2579    // get parent directory cluster ans local pointer
     2580    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2581    parent_cxy       = GET_CXY( parent_inode_xp );
     2582
     2583    // get extended pointer on child inode
     2584    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2585
     2586    // get child and parent names
     2587    vfs_inode_get_name( parent_inode_xp , parent_name );
     2588    vfs_inode_get_name( child_inode_xp  , child_name );
    20532589
    20542590#if DEBUG_FATFS_UPDATE_DENTRY
    20552591uint32_t   cycle = (uint32_t)hal_get_cycles();
    20562592thread_t * this  = CURRENT_THREAD;
    2057 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    20582593if( DEBUG_FATFS_UPDATE_DENTRY < cycle )
    2059 printk("\n[%s]  thread[%x,%x] enter for <%s/%s> / size %d / cycle %d\n",
    2060 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, size, cycle );
    2061 #endif
    2062 
    2063     // get local pointer on mapper
    2064     mapper = inode->mapper;
    2065 
    2066     // get pointer and index in mapper for searched directory entry
    2067     error  = fatfs_scan_directory( mapper, dentry->name , &entry , &index );
    2068 
    2069     if( error )
    2070     {
    2071         vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    2072         printk("\n[ERROR] in %s : cannot find <%s> in parent mapper <%s>\n",
    2073         __FUNCTION__, dentry->name, dir_name );
    2074         return -1;
    2075     }
    2076 
    2077     // get current size value
    2078     uint32_t current_size = fatfs_get_record( DIR_FILE_SIZE , entry );
     2594printk("\n[%s]  thread[%x,%x] enter for <%s> in <%s> / new_size %d / cycle %d\n",
     2595__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, new_size, cycle );
     2596#endif
     2597
     2598    // get child inode cluster and local pointer
     2599    child_cxy       = GET_CXY( child_inode_xp );
     2600    child_inode_ptr = GET_PTR( child_inode_xp );
     2601 
     2602    // get size from child inode
     2603    new_size = hal_remote_l32( XPTR( child_cxy , &child_inode_ptr->size ) );
     2604 
     2605    // get local and extended pointers on parent directory mapper
     2606    parent_mapper_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     2607    parent_mapper_xp  = XPTR( parent_cxy , parent_mapper_ptr );
     2608
     2609    // get directory entry index from dentry extension
     2610    entry_id = (intptr_t)hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->extend ) );
     2611
     2612    // get page index and offset in parent directory mapper
     2613    page_id  = entry_id >> 7;
     2614    offset   = (entry_id & 0x7F) << 5;
     2615
     2616    // get extended pointers on page descriptor and page base
     2617    page_xp = mapper_get_page( parent_mapper_xp , page_id );     
     2618    base_xp = ppm_page2base( page_xp );
     2619
     2620    // build extended pointer on directory entry
     2621    entry_xp = base_xp + offset;
     2622
     2623    // get current size from directory mapper
     2624    current_size = fatfs_get_remote_record( DIR_FILE_SIZE , entry_xp );
    20792625
    20802626    // update dentry in mapper & device only if required
    2081     if( size != current_size )
     2627    if( new_size != current_size )
    20822628    {
    20832629        // set size field in FAT32 directory entry
    2084         fatfs_set_record( DIR_FILE_SIZE , entry , size );
    2085 
    2086         // get pointer on modified page base
    2087         void * base = (void *)((intptr_t)entry & (~CONFIG_PPM_PAGE_MASK));
    2088 
    2089         // get extended pointer on modified page descriptor
    2090         xptr_t page_xp = ppm_base2page( XPTR( local_cxy , base ) );
    2091 
    2092         // synchronously update the modified page on device
     2630        fatfs_set_remote_record( DIR_FILE_SIZE , entry_xp , new_size );
     2631
     2632        // synchronously update the modified mapper page on device
    20932633        error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    20942634
    20952635        if( error )
    20962636        {
    2097             vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    20982637            printk("\n[ERROR] in %s : cannot update parent directory <%s> on device\n",
    2099             __FUNCTION__, dir_name );
     2638            __FUNCTION__, parent_name );
    21002639            return -1;
    21012640        }
     
    21052644cycle = (uint32_t)hal_get_cycles();
    21062645if( DEBUG_FATFS_UPDATE_DENTRY < cycle )
    2107 printk("\n[%s]  thread[%x,%x] exit / updated size for <%s/%s> / cycle %d\n",
    2108 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     2646printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> directory / size %d / cycle %d\n",
     2647__FUNCTION__, this->process->pid, this->trdid, parent_name, child->name, new_size, cycle );
    21092648#endif
    21102649
     
    21682707    {
    21692708        // get one page from mapper
    2170         page_xp = mapper_remote_get_page( mapper_xp , page_id );
     2709        page_xp = mapper_get_page( mapper_xp , page_id );
    21712710
    21722711        if( page_xp == XPTR_NULL) return -1;
     
    22732812}  // end fatfs_get_user_dir()
    22742813
    2275 ///////////////////////////////////////////////
    2276 error_t fatfs_sync_inode( vfs_inode_t * inode )
    2277 {
     2814///////////////////////////////////////////
     2815error_t fatfs_sync_inode( xptr_t inode_xp )
     2816{
     2817    cxy_t         inode_cxy;      // remote inode cluster
     2818    vfs_inode_t * inode_ptr;      // remote inode local pointer
     2819    mapper_t    * mapper;         // remote inode mapper local pointer
     2820    uint32_t      size;           // remote inode size in bytes
     2821    uint32_t      type;           // remote inode type
     2822    xptr_t        rt_xp;          // extended pointer on mapper radix tree
     2823    uint32_t      npages;         // number of pages in mapper
     2824    uint32_t      page_id;        // current page index in mapper
     2825    xptr_t        page_xp;        // extended pointer on current page
     2826    page_t      * page_ptr;       // local pointer on current page
     2827    uint32_t      flags;          // current page flags
     2828    error_t       error;
    22782829
    22792830// check inode pointer and cluster index
    2280 assert( (inode != NULL)                  , "inode pointer undefined\n" );
    2281 assert( (inode->mapper != NULL )         , "mapper pointer undefined\n" );
    2282 assert( (inode->type == INODE_TYPE_FILE) , "inode must be a file\n" );     
     2831assert( (inode_xp != XPTR_NULL)          , "inode pointer undefined\n" );
    22832832
    22842833#if DEBUG_FATFS_SYNC_INODE
     
    22862835uint32_t   cycle = (uint32_t)hal_get_cycles();
    22872836thread_t * this  = CURRENT_THREAD;
    2288 vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     2837vfs_inode_get_name( inode_xp , name );
    22892838if( DEBUG_FATFS_SYNC_INODE < cycle )
    22902839printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
     
    22922841#endif
    22932842
    2294     error_t    error;
    2295     mapper_t * mapper;
    2296     page_t   * page;
    2297     uint32_t   page_id;
    2298 
    2299     // get mapper from inode
    2300     mapper = inode->mapper;
    2301 
    2302     // compute max number of pages in mapper from file size
    2303     uint32_t size  = inode->size;
    2304     uint32_t pages = size >> CONFIG_PPM_PAGE_SHIFT;
    2305     if( size & CONFIG_PPM_PAGE_MASK ) pages++;
     2843    // get inode cluster and local pointer
     2844    inode_cxy = GET_CXY( inode_xp );
     2845    inode_ptr = GET_PTR( inode_xp );
     2846
     2847    //get inode mapper pointer
     2848    mapper    = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     2849
     2850assert( (mapper != NULL) , "mapper pointer is NULL\n" );     
     2851
     2852    // get inode type and size
     2853    size = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size ) );
     2854    type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     2855
     2856assert( (type == INODE_TYPE_FILE) , "inode is not a file\n" );     
     2857
     2858    // compute number of pages
     2859    npages = size >> CONFIG_PPM_PAGE_SHIFT;
     2860    if( size & CONFIG_PPM_PAGE_MASK ) npages++;
    23062861         
    2307     // get pointer on mapper radix tree
    2308     grdxt_t * rt = &mapper->rt;
     2862    // build pointers on mapper radix tree
     2863    rt_xp = XPTR( inode_cxy , &mapper->rt );
    23092864
    23102865    // scan all pages
    2311     for( page_id = 0 ; page_id < pages ; page_id++ )
     2866    for( page_id = 0 ; page_id < npages ; page_id++ )
    23122867    {
    23132868        // get page descriptor from mapper
    2314         page = grdxt_lookup( rt , page_id );
     2869        page_xp = grdxt_remote_lookup( rt_xp , page_id );
    23152870
    23162871        // check all existing pages
    2317         if ( page != NULL )
    2318         {
    2319             if ( page->flags & PG_DIRTY )
     2872        if ( page_xp != XPTR_NULL )
     2873        {
     2874            // get page cluster and local pointer
     2875            page_ptr = GET_PTR( page_xp );
     2876
     2877            // get page flags
     2878            flags = hal_remote_l32( XPTR( inode_cxy , &page_ptr->flags ) );
     2879   
     2880            if ( flags & PG_DIRTY )
    23202881            {
    23212882
    23222883#if (DEBUG_FATFS_SYNC_INODE & 1)
    23232884if( DEBUG_FATFS_SYNC_INODE < cycle )
    2324 printk("\n[%s] thread[%x,%x] synchronizes page %d from <%s> mapper to IOC device\n",
     2885printk("\n[%s] thread[%x,%x] synchronizes page %d of <%s> mapper to IOC device\n",
    23252886__FUNCTION__, page_id, name );
    23262887#endif
    2327                 // build extended pointer on page descriptor
    2328                 xptr_t page_xp = XPTR( local_cxy , page );
    2329 
    23302888                // move page from mapper to device
    23312889                error = fatfs_move_page( page_xp , IOC_WRITE );
     
    23422900cycle = (uint32_t)hal_get_cycles();
    23432901if( DEBUG_FATFS_SYNC_INODE < cycle )
    2344 printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n",
    2345 __FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     2902printk("\n[%s] thread[%x,%x] exit for <%s>\n",
     2903__FUNCTION__ , this->process->pid, this->trdid, name );
    23462904#endif
    23472905
     
    23492907
    23502908}  // end fatfs_sync_inode()
    2351 
    2352 
    2353 
    2354 
    2355 
    23562909
    23572910//////////////////////////////
    23582911error_t fatfs_sync_fat( void )
    23592912{
     2913
     2914    fatfs_ctx_t * fatfs_ctx;
     2915    cxy_t         fat_cxy;
     2916    mapper_t    * mapper_ptr;
     2917    xptr_t        mapper_xp;
     2918    uint32_t      start_page_id;
     2919    uint32_t      found_page_id;
     2920    page_t      * page_ptr;
     2921    xptr_t        page_xp;
     2922    uint32_t      flags;
     2923    error_t       error;
    23602924
    23612925#if DEBUG_FATFS_SYNC_FAT
     
    23662930__FUNCTION__ , this->process->pid, this->trdid, cycle );
    23672931#endif
    2368 
    2369     uint32_t   page_id;
    2370     error_t    error;
    2371 
    2372     // get FAT mapper pointers an cluster
    2373     fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
    2374     xptr_t        mapper_xp  = fatfs_ctx->fat_mapper_xp;
    2375     cxy_t         mapper_cxy = GET_CXY( mapper_xp );
    2376     mapper_t    * mapper_ptr = GET_PTR( mapper_xp );
    2377 
    2378     // compute max number of 4 Kbytes pages in FAT mapper
    2379     // TODO : this could be improved (see fatfs.h) [AG]
    2380     uint32_t   pages = fatfs_ctx->fat_sectors_count >> 3;
    2381          
     2932   
     2933    // get FAT cluster
     2934    fat_cxy = CONFIG_VFS_ROOT_CXY;
     2935   
     2936    // get FAT mapper pointers 
     2937    fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
     2938    mapper_ptr = fatfs_ctx->fat_mapper;
     2939    mapper_xp  = XPTR( fat_cxy , mapper_ptr );
     2940
    23822941    // get pointers on remote FAT mapper radix tree
    23832942    grdxt_t  * rt_ptr = &mapper_ptr->rt;
    2384     xptr_t     rt_xp  = XPTR( mapper_cxy , rt_ptr );
    2385 
    2386     // scan all pages
    2387     for( page_id = 0 ; page_id < pages ; page_id++ )
    2388     {
    2389         // get extended pointer on page descriptor from FAT mapper
    2390         xptr_t page_xp = grdxt_remote_lookup( rt_xp , page_id );
    2391 
    2392         // check all existing pages
    2393         if ( page_xp != XPTR_NULL )
    2394         {
    2395             page_t * page_ptr = GET_PTR( page_xp );
    2396             uint32_t flags    = hal_remote_l32( XPTR( mapper_cxy , &page_ptr->flags ) );
    2397 
    2398             if ( flags & PG_DIRTY )
    2399             {
     2943    xptr_t     rt_xp  = XPTR( fat_cxy , rt_ptr );
     2944
     2945    // initialise page_id
     2946    start_page_id = 0;
     2947
     2948    // scan FAT mapper
     2949    while( 1 )
     2950    {
     2951        // get one page
     2952        page_xp = grdxt_remote_get_first( rt_xp , start_page_id , &found_page_id );
     2953
     2954        // exit loop when no more page found
     2955        if ( page_xp != XPTR_NULL ) break;
     2956
     2957        // get page flags
     2958        page_ptr = GET_PTR( page_xp );
     2959        flags    = hal_remote_l32( XPTR( fat_cxy , &page_ptr->flags ) );
     2960
     2961        if ( flags & PG_DIRTY )
     2962        {
    24002963
    24012964#if (DEBUG_FATFS_SYNC_FAT & 1)
     
    24042967__FUNCTION__, page_id );
    24052968#endif
    2406                 // move page from mapper to device
    2407                 error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    2408 
    2409                 if ( error )  return -1;
    2410 
    2411                 // reset page dirty flag
    2412                 ppm_page_undo_dirty( page_xp );
    2413             }
    2414         }
     2969            // move page from mapper to device
     2970            error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
     2971
     2972            if ( error )  return -1;
     2973
     2974            // reset page dirty flag
     2975            ppm_page_undo_dirty( page_xp );
     2976        }
     2977
     2978        // update loop variable
     2979        start_page_id = found_page_id + 1;
     2980
    24152981    }  // end loop on pages
    24162982
     
    24182984cycle = (uint32_t)hal_get_cycles();
    24192985if( DEBUG_FATFS_SYNC_FAT < cycle )
    2420 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    2421 __FUNCTION__ , this->process->pid, this->trdid, cycle );
     2986printk("\n[%s] thread[%x,%x] exit\n",
     2987__FUNCTION__ , this->process->pid, this->trdid );
    24222988#endif
    24232989
     
    24252991
    24262992}  // end fatfs_sync_fat()
    2427 
    2428 ////////////////////////////////////
    2429 error_t fatfs_sync_free_info( void )
    2430 {
    2431     error_t       error;
    2432     fatfs_ctx_t * fatfs_ctx_ptr;              // local pointer on fatfs context in cluster 0
    2433     uint32_t      ctx_free_clusters;          // number of free clusters from fatfs context
    2434     uint32_t      ctx_free_cluster_hint;      // free cluster hint from fatfs context
    2435     uint32_t      ioc_free_clusters;          // number of free clusters from fatfs context
    2436     uint32_t      ioc_free_cluster_hint;      // free cluster hint from fatfs context
    2437     uint32_t      fs_info_lba;                // lba of FS_INFO sector on IOC device
    2438     uint8_t     * fs_info_buffer;             // local pointer on FS_INFO buffer in cluster 0
    2439     xptr_t        fs_info_buffer_xp;          // extended pointer on FS_INFO buffer in cluster 0
    2440     uint8_t       tmp_buf[512];               // 512 bytes temporary buffer
    2441     xptr_t        tmp_buf_xp;                 // extended pointer on temporary buffer
    2442 
    2443 #if DEBUG_FATFS_SYNC_FSINFO
    2444 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2445 thread_t * this  = CURRENT_THREAD;
    2446 if( DEBUG_FATFS_SYNC_FSINFO < cycle )
    2447 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    2448 __FUNCTION__ , this->process->pid, this->trdid, cycle );
    2449 #endif
    2450 
    2451     // get pointer on fatfs context in cluster 0
    2452     fatfs_ctx_ptr = hal_remote_lpt( XPTR( 0 , &fs_context[FS_TYPE_FATFS].extend ) );
    2453 
    2454     // get "free_clusters" and "free_cluster_hint" from fatfs context in cluster 0
    2455     ctx_free_clusters     = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_clusters ) );
    2456     ctx_free_cluster_hint = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_cluster_hint ) );
    2457 
    2458     // get fs_info_lba
    2459     fs_info_lba = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->fs_info_lba ) );
    2460 
    2461     // build extended pointer on temporary buffer
    2462     tmp_buf_xp = XPTR( local_cxy , tmp_buf );
    2463 
    2464     // copy FS_INFO sector from IOC to local buffer
    2465     error = dev_ioc_move_data( IOC_SYNC_READ , tmp_buf_xp , fs_info_lba , 1 );
    2466 
    2467     if ( error )
    2468     {
    2469         printk("\n[ERROR] in %s : cannot access FS_INFO on IOC device\n", __FUNCTION__ );
    2470         return -1;
    2471     }
    2472 
    2473     // get current values of "free_clusters" and "free_cluster_hint" from FS_INFO on IOC
    2474     ioc_free_clusters     = fatfs_get_remote_record( FS_FREE_CLUSTERS     , tmp_buf_xp );
    2475     ioc_free_cluster_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , tmp_buf_xp );
    2476 
    2477 #if DEBUG_FATFS_SYNC_FSINFO
    2478 if( DEBUG_FATFS_SYNC_FSINFO < cycle )
    2479 printk("\n[%s] thread[%x,%x] / ctx_free %x / ioc_free %x / ctx_hint %x / ioc_hint %x\n",
    2480 __FUNCTION__ , this->process->pid, this->trdid,
    2481 ctx_free_clusters, ioc_free_clusters, ctx_free_cluster_hint, ioc_free_cluster_hint );
    2482 #endif
    2483 
    2484     // check values
    2485     if( (ioc_free_clusters     != ctx_free_clusters) ||
    2486         (ioc_free_cluster_hint != ctx_free_cluster_hint) )
    2487     {
    2488         printk("\n[WARNING] in %s : unconsistent free clusters info\n"
    2489         " ioc_free %x / ctx_free %x / ioc_hint %x / ctx_hint %x\n",
    2490         __FUNCTION__, ioc_free_clusters, ctx_free_clusters,
    2491         ioc_free_cluster_hint, ctx_free_cluster_hint );
    2492 
    2493         // get pointers on FS_INFO buffer in cluster 0
    2494         fs_info_buffer    = hal_remote_lpt( XPTR( 0 , &fatfs_ctx_ptr->fs_info_buffer ) );
    2495         fs_info_buffer_xp = XPTR( 0 , fs_info_buffer );
    2496 
    2497         // update FS_INFO buffer in cluster 0
    2498         fatfs_set_remote_record(FS_FREE_CLUSTERS    ,fs_info_buffer_xp,ctx_free_clusters );
    2499         fatfs_set_remote_record(FS_FREE_CLUSTER_HINT,fs_info_buffer_xp,ctx_free_cluster_hint);
    2500 
    2501         // update the FS_INFO sector on IOC device
    2502         error = dev_ioc_move_data( IOC_SYNC_WRITE , fs_info_buffer_xp , fs_info_lba , 1 );
    2503 
    2504         if ( error )
    2505         {
    2506             printk("\n[ERROR] in %s : cannot update FS_INFO on IOC device\n", __FUNCTION__ );
    2507             return -1;
    2508         }
    2509     }
    2510 
    2511 #if DEBUG_FATFS_SYNC_FSINFO
    2512 cycle = (uint32_t)hal_get_cycles();
    2513 if( DEBUG_FATFS_SYNC_FSINFO < cycle )
    2514 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    2515 __FUNCTION__ , this->process->pid, this->trdid, cycle );
    2516 #endif
    2517 
    2518     return 0;
    2519 
    2520 }  // end fatfs_sync_free_info()
    2521 
    2522 //////////////////////////////////////////////////////////
    2523 error_t fatfs_cluster_alloc( uint32_t * searched_cluster )
    2524 {
    2525     error_t       error;
    2526     uint32_t      page_id;        // page index in FAT mapper
    2527     uint32_t      slot_id;        // slot index in page (1024 slots per page)
    2528     uint32_t      cluster;        // first free cluster index in FAT
    2529     uint32_t      free_clusters;  // total number of free clusters
    2530     vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters)
    2531     fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
    2532     fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
    2533     xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    2534     cxy_t         fat_cxy;        // Fat mapper cluster identifier
    2535     xptr_t        page_xp;        // extended pointer on current page descriptor in mapper
    2536     xptr_t        slot_xp;        // extended pointer on FAT slot defined by hint
    2537     xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info
    2538     xptr_t        hint_xp;        // extended pointer on free_cluster_hint in FAT cluster
    2539     xptr_t        free_xp;        // extended pointer on free_clusters_number in FAT cluster
    2540 
    2541 #if DEBUG_FATFS_CLUSTER_ALLOC
    2542 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2543 thread_t * this  = CURRENT_THREAD;
    2544 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
    2545 printk("\n[%s] thread[%x,%x] enter / cycle = %d\n",
    2546 __FUNCTION__, this->process->pid, this->trdid, cycle );
    2547 #endif
    2548 
    2549     // get local pointer on VFS context (same in all clusters)
    2550     vfs_ctx = &fs_context[FS_TYPE_FATFS];
    2551 
    2552     // get local pointer on local FATFS context
    2553     loc_fatfs_ctx = vfs_ctx->extend;
    2554 
    2555     // get extended pointer on FAT mapper
    2556     fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    2557 
    2558     // get FAT cluster
    2559     fat_cxy = GET_CXY( fat_mapper_xp );
    2560    
    2561     // get local pointer on FATFS context in FAT cluster
    2562     fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
    2563 
    2564     // build relevant extended pointers on free clusters info in mapper cluster
    2565     lock_xp = XPTR( fat_cxy , &fat_fatfs_ctx->lock );
    2566     hint_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint );
    2567     free_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters );
    2568 
    2569     // take the FAT lock in write mode
    2570     remote_rwlock_wr_acquire( lock_xp );
    2571 
    2572     // get hint and free_clusters values from FATFS context in FAT cluster
    2573     cluster       = hal_remote_l32( hint_xp ) + 1;
    2574     free_clusters = hal_remote_l32( free_xp );
    2575        
    2576 #if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
    2577 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
    2578 printk("\n[%s] thread[%x,%x] get free info : hint %x / free_clusters %x\n",
    2579 __FUNCTION__, this->process->pid, this->trdid, (cluster - 1), free_clusters );
    2580 #endif
    2581 
    2582     // check "free_clusters"
    2583     if ( free_clusters == 0 )
    2584     {
    2585         printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ );
    2586         remote_rwlock_wr_release( lock_xp );
    2587         return -1;
    2588     }
    2589     else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN )
    2590     {
    2591         printk("\n[WARNING] in %s : only %n free FATFS clusters\n",
    2592         __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN );
    2593     }
    2594 
    2595     // get page index & slot index for selected cluster
    2596     page_id  = cluster >> 10;
    2597     slot_id  = cluster & 0x3FF;
    2598 
    2599     // get relevant page descriptor from FAT mapper
    2600     page_xp = mapper_remote_get_page( fat_mapper_xp , page_id );
    2601 
    2602     if( page_xp == XPTR_NULL )
    2603     {
    2604         printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
    2605         remote_rwlock_wr_release( lock_xp );
    2606         return -1;
    2607     }
    2608 
    2609     // build extended pointer on selected cluster slot in FAT mapper
    2610     slot_xp = ppm_page2base( page_xp ) + (slot_id << 2);
    2611          
    2612     // check selected cluster actually free
    2613     if( hal_remote_l32( slot_xp ) != FREE_CLUSTER )
    2614     {
    2615         printk("\n[ERROR] in %s : selected cluster %x not free\n", __FUNCTION__, cluster );
    2616         remote_rwlock_wr_release( lock_xp );
    2617         return -1;
    2618     }
    2619 
    2620     // update free cluster info in FATFS context and in FS_INFO sector
    2621     error = fatfs_free_clusters_decrement( XPTR( fat_cxy , fat_fatfs_ctx ) , cluster );
    2622 
    2623     if( error )
    2624     {
    2625         printk("\n[ERROR] in %s : cannot update free cluster info\n", __FUNCTION__ );
    2626         remote_rwlock_wr_release( lock_xp );
    2627         return -1;
    2628     }
    2629 
    2630     // update FAT mapper
    2631     hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
    2632 
    2633     // we don't mark the FAT mapper page as dirty,
    2634     // because we synchronously update FAT on IOC device
    2635     error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    2636 
    2637     if( error )
    2638     {
    2639         printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
    2640         remote_rwlock_wr_release( lock_xp );
    2641         return -1;
    2642     }
    2643 
    2644     // release FAT lock
    2645     remote_rwlock_wr_release( lock_xp );
    2646 
    2647 #if DEBUG_FATFS_CLUSTER_ALLOC
    2648 cycle = (uint32_t)hal_get_cycles();
    2649 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
    2650 printk("\n[%s] thread[%x,%x] exit / allocated cluster %x in FAT / cycle %d\n",
    2651 __FUNCTION__, this->process->pid, this->trdid, cluster, cycle );
    2652 #endif
    2653 
    2654     *searched_cluster = cluster;
    2655     return 0;
    2656 
    2657 }  // end fatfs_cluster_alloc()
    26582993
    26592994//////////////////////////////////////////////
    26602995error_t fatfs_release_inode( xptr_t inode_xp )
    26612996{
    2662     vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters).
    2663     fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
    2664     cxy_t         fat_cxy;        // FAT cluster identifier
    2665     xptr_t        fatfs_ctx_xp;   // extended pointer on FATFS context in FAT cluster
    2666     fatfs_ctx_t * fatfs_ctx_ptr;  // local pointer on FATFS context in FAT cluster
    2667     xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    2668     xptr_t        lock_xp;        // extended pointer on lock protecting FAT.
    2669     xptr_t        first_xp;       // extended pointer on inode extension
    2670     uint32_t      first_cluster;  // first cluster index for released inode
    2671     vfs_inode_t * inode_ptr;      // local pointer on target inode
    2672     cxy_t         inode_cxy;      // target inode cluster identifier
     2997    vfs_ctx_t   * vfs_ctx;           // local pointer on VFS context (same in all clusters)
     2998    cxy_t         fat_cxy;           // FAT cluster identifier
     2999    fatfs_ctx_t * fatfs_ctx_ptr;     // local pointer on FATFS context in FAT cluster
     3000    xptr_t        fatfs_ctx_xp;      // extended pointer on FATFS-context in FAT cluster
     3001    mapper_t    * fat_mapper_ptr;    // local pointer on FAT mapper
     3002    xptr_t        fat_mapper_xp;     // extended pointer on FAT mapper
     3003    xptr_t        lock_xp;           // extended pointer on lock protecting FAT.
     3004    xptr_t        first_xp;          // extended pointer on inode extension
     3005    uint32_t      first_cluster_id;  // first cluster index for released inode
     3006    vfs_inode_t * inode_ptr;         // local pointer on target inode
     3007    cxy_t         inode_cxy;         // target inode cluster identifier
    26733008    error_t       error;
    26743009
     
    26803015    inode_cxy     = GET_CXY( inode_xp );
    26813016
    2682     // get first_cluster from inode extension
    2683     first_xp      = XPTR( inode_cxy , &inode_ptr->extend );
    2684     first_cluster = (uint32_t)(intptr_t)hal_remote_lpt( first_xp );
     3017    // get first_cluster_id from inode extension
     3018    first_xp         = XPTR( inode_cxy , &inode_ptr->extend );
     3019    first_cluster_id = (uint32_t)(intptr_t)hal_remote_lpt( first_xp );
    26853020
    26863021// check first cluster index
    2687 assert( (first_cluster != 0) , "inode extend is NULL\n" );
     3022assert( (first_cluster_id != 0) , "inode extend is NULL\n" );
    26883023
    26893024#if DEBUG_FATFS_RELEASE_INODE
     
    26933028vfs_inode_get_name( inode_xp , name );
    26943029if( DEBUG_FATFS_RELEASE_INODE < cycle )
    2695 printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster %x / cycle %d\n",
    2696 __FUNCTION__ , this->process->pid, this->trdid, name, first_cluster, cycle );
     3030printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster_id %x / cycle %d\n",
     3031__FUNCTION__ , this->process->pid, this->trdid, name, first_cluster_id, cycle );
    26973032#endif
    26983033
     
    27003035    vfs_ctx = &fs_context[FS_TYPE_FATFS];
    27013036
    2702     // get local pointer on local FATFS context
    2703     loc_fatfs_ctx = vfs_ctx->extend;
    2704 
    2705     // get FAT mapper cluster
    2706     fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    2707     fat_cxy        = GET_CXY( fat_mapper_xp );
     3037    // get FAT cluster
     3038    fat_cxy = CONFIG_VFS_ROOT_CXY;
     3039
     3040    // get pointers on FATFS context in FAT cluster
     3041    fatfs_ctx_ptr = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     3042    fatfs_ctx_xp  = XPTR( fat_cxy , fatfs_ctx_ptr );
     3043
     3044    // get FAT mapper pointers
     3045    fat_mapper_ptr = hal_remote_lpt( XPTR( fat_cxy , &fatfs_ctx_ptr->fat_mapper ) );
     3046        fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
    27083047   
    2709     // get pointers on FATFS context in FAT cluster
    2710     fatfs_ctx_ptr  = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
    2711     fatfs_ctx_xp   = XPTR( fat_cxy , fatfs_ctx_ptr );
    2712 
    2713     // get extended pointer on FAT lock in FAT cluster
     3048    // build extended pointer on FAT lock in FAT cluster
    27143049    lock_xp = XPTR( fat_cxy , &fatfs_ctx_ptr->lock );
    27153050
     
    27273062    if ( fatfs_recursive_release( fat_mapper_xp,
    27283063                                  fatfs_ctx_xp,
    2729                                   first_cluster,
     3064                                  first_cluster_id,
    27303065                                  &dirty_page_min,
    27313066                                  &dirty_page_max ) )
     
    27913126}  // end fatfs_release_inode()
    27923127
    2793 ////////////////////////////////////////////
    2794 error_t fatfs_move_page( xptr_t     page_xp,
    2795                          cmd_type_t cmd_type )
    2796 {
    2797     error_t       error;
     3128/////////////////////////////////////////////////
     3129error_t fatfs_move_page( xptr_t          page_xp,
     3130                         ioc_cmd_type_t  cmd_type )
     3131{
     3132    error_t       error = 0;
     3133
    27983134    vfs_inode_t * inode_ptr;
    27993135    mapper_t    * mapper_ptr;     
     
    28293165#if DEBUG_FATFS_MOVE_PAGE
    28303166if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2831 printk("\n[%s] thread[%x,%x] enters for %s /  page %d in FAT mapper / cycle %d\n",
     3167printk("\n[%s] thread[%x,%x] enters %s for  page %d in FAT mapper / cycle %d\n",
    28323168__FUNCTION__, this->process->pid, this->trdid, dev_ioc_cmd_str(cmd_type), page_id, cycle );
    28333169#endif
     
    28363172 
    28373173        // access IOC device
    2838         error = dev_ioc_move_data( cmd_type , buffer_xp , lba , 8 );
     3174        if     (cmd_type == IOC_SYNC_WRITE) error = dev_ioc_sync_write( buffer_xp, lba, 8 );
     3175        else if(cmd_type == IOC_SYNC_READ ) error = dev_ioc_sync_read( buffer_xp, lba, 8 );
     3176        else
     3177        {
     3178            printk("\n[ERROR] in %s : illegal asynchronous FAT access\n", __FUNCTION__ );
     3179        }
    28393180
    28403181        if( error )
    28413182        {
    2842             printk("\n[ERROR] in %s : cannot access device\n", __FUNCTION__ );
     3183            printk("\n[ERROR] in %s : cannot access IOC device\n", __FUNCTION__ );
    28433184            return -1;
    28443185        }
     
    28463187#if DEBUG_FATFS_MOVE_PAGE
    28473188if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2848 printk("\n[%s] thread[%x,%x] exit / page %d in FAT mapper\n",
    2849 __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     3189printk("\n[%s] thread[%x,%x] exit %s for page %d in FAT mapper\n",
     3190__FUNCTION__, this->process->pid, this->trdid, dev_ioc_cmd_str(cmd_type), page_id );
    28503191#endif
    28513192
     
    28563197
    28573198#if DEBUG_FATFS_MOVE_PAGE
    2858 vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );
    28593199if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2860 printk("\n[%s] thread[%x,%x] enters for %s / page %d in <%s> mapper/ cycle %d\n",
    2861 __FUNCTION__, this->process->pid, this->trdid,
    2862 dev_ioc_cmd_str( cmd_type ), page_id, name, cycle );
     3200{
     3201    vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );
     3202    printk("\n[%s] thread[%x,%x] enters %s for page %d in <%s> mapper / cycle %d\n",
     3203    __FUNCTION__, this->process->pid, this->trdid,
     3204    dev_ioc_cmd_str( cmd_type ), page_id, name, cycle );
     3205}
    28633206#endif
    28643207
     
    28933236        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id );
    28943237
    2895         // access IOC device to move 8 blocks
    2896         error = dev_ioc_move_data( cmd_type , buffer_xp , lba , 8 );
     3238        // access IOC device
     3239        if     (cmd_type == IOC_WRITE     ) error = dev_ioc_write( buffer_xp, lba, 8 );
     3240        else if(cmd_type == IOC_READ      ) error = dev_ioc_read( buffer_xp, lba, 8 );
     3241        else if(cmd_type == IOC_SYNC_READ ) error = dev_ioc_sync_read( buffer_xp, lba, 8 );
     3242        else if(cmd_type == IOC_SYNC_WRITE) error = dev_ioc_sync_write( buffer_xp, lba, 8 );
     3243        else
     3244        {
     3245            printk("\n[ERROR] in %s : illegal cmd_type\n", __FUNCTION__ );
     3246        }
    28973247
    28983248        if( error )
     
    29043254#if DEBUG_FATFS_MOVE_PAGE
    29053255if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2906 vfs_inode_get_name( XPTR( page_cxy, inode_ptr ) , name );
    2907 printk("\n[%s] thread[%x,%x] exit / page %d in <%s> mapper / cluster_id %x\n",
    2908 __FUNCTION__, this->process->pid, this->trdid, page_id, name, searched_cluster_id );
     3256{
     3257    printk("\n[%s] thread[%x,%x] exit %s for page %d in <%s> mapper / cluster_id %x\n",
     3258    __FUNCTION__, this->process->pid, this->trdid,
     3259    dev_ioc_cmd_str( cmd_type ), page_id, name, searched_cluster_id );
     3260}
     3261#endif
     3262
     3263#if (DEBUG_FATFS_MOVE_PAGE & 1)
     3264if( DEBUG_FATFS_MOVE_PAGE < cycle )
     3265fatfs_display_fat( searched_cluster_id , 64 );
    29093266#endif
    29103267
  • trunk/kernel/fs/fatfs.h

    r656 r657  
    22 * fatfs.h - FATFS file system API definition.
    33 *
    4  * Author    Mohamed Lamine Karaoui (2014,2015)
    5  *           Alain Greiner (2016,2017,2018)
     4 * Author    Alain Greiner (2016,2017,2018,2019,2020)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    2726
    2827#include <hal_kernel_types.h>
    29 #include <remote_queuelock.h>
     28#include <remote_rwlock.h>
    3029#include <vfs.h>
    3130#include <dev_ioc.h>
     
    3635 *
    3736 * The FATFS specific extensions to the generic VFS are the following:
    38  * 1) The vfs_ctx_t "extend" field is a void* pointing on the fatfs_ctx_t structure.
    39  *    This structure contains various general informations such as the total
    40  *    number of sectors in FAT region, the number of bytes per sector, the number
    41  *    of sectors per cluster, the lba of FAT region, the lba of data region, or the
    42  *    cluster index for the root directory. It contains also an extended pointer
    43  *    on the FAT mapper.
     37 * 1) The vfs_ctx_t "extend" field contains a local pointer on the local
     38 *    fatfs_ctx_t structure.
     39 *
    4440 * 2) The vfs_inode_t "extend" contains, for each inode,
    45  *    the first FAT32 cluster_id (after cast to intptr).
    46  * 3) The vfs_dentry_t "extend" field contains, for each dentry, the entry index
    47  *    in the FATFS directory (32 bytes per FATFS directory entry).
     41 *    the first FATFS cluster_id (after cast to intptr).
     42 *
     43 * 3) The vfs_dentry_t "extend" field contains a local pointer on the local
     44 *    FATFS directory entry (32 bytes) in the directory mapper.
    4845 *
    4946 * In the FAT32 File System, the File Allocation Table is is actually an array
     
    5754 *****************************************************************************************/
    5855 
    59 ///////////////////////////////////////////////////////////////////////////////////////////
    60 
    6156/*************** Partition Boot Sector Format **********************************/
    6257//                                     offset |  length
     
    182177 * This structure defines a FATFS specific context extension to the VFS context.
    183178 * This fatfs context is replicated in all clusters.
     179 * It contains read-only informations such as the total number of sectors in FAT region,
     180 * the number of bytes per sector, the number of sectors per cluster, the lba of FAT,
     181 * the lba of data region, the cluster_id for the root directory, and an extended
     182 * pointer on the FAT mapper.
    184183 *
    185184 * WARNING 1 : All access to the FAT are protected by a remote_rwlock.
     
    189188 *   functions to modify the FAT in both the FAT mapper and on IOC device.
    190189 *
    191  * WARNING 2 : Most fields are constant values, but the <free_cluster_hint>,
    192  * <free_clusters>, <lock>, and the <fs_info_buffer> are shared variables,
    193  * that can be modified by any thread running in any cluster. The <fs_info_buffer>
    194  * contains a copy of the FS_INFO sector, and is only allocated in the FAT cluster
    195  * (cluster 0). It is used to synchronously update the free clusters info on IOC device.
     190 * WARNING 2 : Most fields are constant values, but <free_cluster_hint>, <free_clusters>,
     191 * <lock>, and the buffer pointed by the <fs_info_xp> are shared variables, that can
     192 * modified by any thread running in any cluster. The <fs_info_buffer>  contains
     193 * a copy of the FS_INFO sector, and is only allocated in the FAT cluster.
     194 * It is used to synchronously update the free clusters info on IOC device.
    196195 *  => For all these variables, only the values stored in the FAT cluster must be used.
    197196 ****************************************************************************************/
     
    207206    uint32_t            fs_info_lba;           /*! lba of FS_INFO sector                */
    208207    uint32_t            root_dir_cluster;      /*! cluster index for  root directory    */
    209     xptr_t              fat_mapper_xp;         /*! extended pointer on FAT mapper       */
     208    struct mapper_s   * fat_mapper;            /*! local pointer on FAT mapper          */
    210209
    211210    /* shared variables (only the copy in FAT cluster must be used)                     */
    212     uint32_t            free_cluster_hint;     /*! cluster[hint+1] is the first free    */
    213     uint32_t            free_clusters;         /*! free clusters number                 */
     211    uint32_t            free_cluster_hint;     /*! free_cluster_hint + 1 is first free  */
     212    uint32_t            free_clusters;         /*! number of free clusters              */
    214213    remote_rwlock_t     lock;                  /*! exclusive access to FAT              */
    215214    uint8_t           * fs_info_buffer;        /*! local pointer on FS_INFO buffer      */
     
    224223 * This debug function display the content of the FATFS context copy in cluster
    225224 * identified by the <cxy> argument.
    226  * This function can be called by a thread running in any cluster.
     225 * This function can be called by any thread running in any cluster.
    227226 *****************************************************************************************
    228227 * @ cxy       :  target cluster identifier.
     
    232231/*****************************************************************************************
    233232 * This debug function access the FAT mapper to display the current FAT state,
    234  * as defined by the <page_id>, <min_slot>, and <nb_slots> arguments.
    235  * It loads the missing pages from IOC to mapper if required.
    236  * This function can be called by a thread running in any cluster.
    237  *****************************************************************************************
    238  * @ page_id   : page index in FAT mapper (one page is 4 Kbytes = 1024 slots).
    239  * @ min_slot  : first slot in page
    240  * @ nb_slots  : number of slots (one slot is 4 bytes).
    241  ****************************************************************************************/
    242 void fatfs_display_fat( uint32_t  page_id,
    243                         uint32_t  min_slot,
     233 * as defined by the <min_slot>, and <nb_slots> arguments.
     234 * It display as many lines (8 slots par line) as required to display <nb_slots>,
     235 * starting from the <min_slot>. The displayed slots can spread on several FAT mapper
     236 * pages. It loads the missing pages from IOC to mapper if required.
     237 * This function can be called by any thread running in any cluster.
     238 *****************************************************************************************
     239 * @ min_slot   : first FATFS cluster index.
     240 * @ nb_slots   : number of slots (one slot is 4 bytes.
     241 ****************************************************************************************/
     242void fatfs_display_fat( uint32_t  min_slot,
    244243                        uint32_t  nb_slots );
    245244
     245/*****************************************************************************************
     246 * This function checks the current values of the "free_clusters" and "free_cluster_hint"
     247 * variables in the FS_INFO sector on IOC, versus the values stored in the fatfs context.
     248 * As these values are synchronously updated on IOC device at each modification,
     249 * it does nothing if the values are equal. It updates the FS_INFO sector on IOC device,
     250 * and displays a warning message on TXT0 if they are not equal.
     251 * This function can be called by any thread running in any cluster.
     252 *****************************************************************************************
     253 * @ return 0 if success / return -1 if failure during IOC device access.
     254 ****************************************************************************************/
     255error_t fatfs_check_free_info( void );
    246256
    247257//////////////////////////////////////////////////////////////////////////////////////////
     
    251261
    252262/*****************************************************************************************
    253  * This fuction allocates memory from local cluster for a FATFS context descriptor.
    254  *****************************************************************************************
    255  * @ return a pointer on the created context / return NULL if failure.
    256  ****************************************************************************************/
    257 fatfs_ctx_t * fatfs_ctx_alloc( void );
    258 
    259 /*****************************************************************************************
    260  * This function access the boot device, and initialises the local FATFS context,
    261  * from informations contained in the boot record. This initialisation includes the
    262  * creation of the FAT mapper in cluster 0.
    263  *****************************************************************************************
    264  * @ vfs_ctx   : local pointer on VFS context for FATFS.
    265  ****************************************************************************************/
    266 void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx );
    267 
    268 /*****************************************************************************************
    269  * This function releases memory dynamically allocated for the FATFS context extension.
    270  *****************************************************************************************
    271  * @ vfs_ctx   : local pointer on VFS context.
    272  ****************************************************************************************/
    273 void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx );
     263 * This fuction allocates memory for a FATFS context descriptor in a cluster
     264 * identified by the <cxy> argument.
     265 *****************************************************************************************
     266 * @ cxy   : target cluster identifier.
     267 * @ return an extended pointer on the created context / return XPTR_NULL if failure.
     268 ****************************************************************************************/
     269xptr_t  fatfs_ctx_alloc( cxy_t  cxy );
     270
     271/*****************************************************************************************
     272 * This fuction initialize a fatfs context identified by the <fatfs_ctx_xp> argument
     273 * from informations found in the IOC device boot record. This initialisation includes
     274 * allocation of the FS_INFO buffer and creation of the FAT mapper in the same cluster.
     275 *****************************************************************************************
     276 * @ fatfs_ctx_xp   : extended pointer on fatfs context.
     277 * @ return 0 if success / return -1 if failure.
     278 ****************************************************************************************/
     279error_t  fatfs_ctx_init( xptr_t  fatfs_ctx_xp );
     280
     281/*****************************************************************************************
     282 * This function releases memory dynamically allocated for the FATFS context.
     283 *****************************************************************************************
     284 * @ vfs_ctx_xp   : extended pointer on FATFS context.
     285 ****************************************************************************************/
     286void fatfs_ctx_destroy( xptr_t  fatfs_ctx_xp );
    274287
    275288/*****************************************************************************************
    276289 * This function implements the generic vfs_fs_add_dentry() function for the FATFS.
    277290 *****************************************************************************************
    278  * This function updates a directory mapper identified by the <inode> argument
    279  * to add a new directory entry identified by the <dentry> argument.
     291 * This function introduces in a directory mapper identified by the <parent_inode_xp>
     292 * argument a new directory entry identified by the <dentry_ptr> argument.
     293 * The dentry descriptor and the associated inode descriptor must have been previously
     294 * allocated, initialized, and registered in the Inode Tree.
     295 * The dentry descriptor defines the "name" field.
     296 * The inode descriptor defines the "type", "size", and "cluster_id" fields.
     297 * The "extension field" in dentry descriptor is set : index in the FAT32 directory.
    280298 * All modified pages in the directory mapper are synchronously updated on IOC device.
    281  * It must be called by a thread running in the cluster containing the directory inode.
     299 * This function can be called by any thread running in any cluster.
    282300 *
    283301 * Implementation note : this function works in two steps:
     
    285303 *   to find the end of directory (NO_MORE_ENTRY marker).
    286304 * - Then it writes 3, 4, or 5 directory entries (depending on the name length), using
    287  *   a 5 steps FSM (one state per entry to be written), updates on IOC device the
    288  *   modified pages, and updates the dentry extension field, that must contain
    289  *   the dentry index in FATFS directory.
    290  *****************************************************************************************
    291  * @ inode    : local pointer on directory inode.
    292  * @ dentry   : local pointer on dentry.
    293  * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device.
    294  ****************************************************************************************/
    295 error_t fatfs_add_dentry( struct vfs_inode_s  * inode,
    296                           struct vfs_dentry_s * dentry );
     305 *   a 5 steps FSM (one state per entry to be written), and updates on IOC device the
     306 *   modified pages.
     307 *****************************************************************************************
     308 * @ parent_inode_xp : [in]  extended pointer on parent directory inode.
     309 * @ dentry_ptr      : [in]  local pointer on dentry (in parent directory cluster).
     310 * @ index           : [out] index of the new entry in the FAT32 directory.
     311 * @ return 0 if success / return -1 if failure.
     312 ****************************************************************************************/
     313error_t fatfs_add_dentry( xptr_t                parent_inode_xp,
     314                          struct vfs_dentry_s * dentry_ptr );
    297315
    298316/*****************************************************************************************
    299317 * This function implements the generic vfs_fs_remove_dentry() function for the FATFS.
    300318 *****************************************************************************************
    301  * This function updates a directory identified by the <inode> argument
    302  * to remove a directory entry identified by the <dentry> argument.
     319 * This function updates a directory identified by the <parent_inode_xp> argument
     320 * to remove a directory entry identified by the <dentry_ptr> argument.
    303321 * All modified pages in directory mapper are synchronously updated on IOC device.
    304  * It must be called by a thread running in the cluster containing the inode.
     322 * This function can be called by any thread running in any cluster.
    305323 *
    306324 * Implementation note: this function uses the dentry extension to directly access
     
    308326 * updates the modified pages on IOC device.
    309327 *****************************************************************************************
    310  * @ inode    : local pointer on directory inode.
    311  * @ dentry   : local pointer on dentry.
    312  * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device.
    313  ****************************************************************************************/
    314 error_t fatfs_remove_dentry( struct vfs_inode_s  * inode,
    315                              struct vfs_dentry_s * dentry );
    316 
    317 /*****************************************************************************************
    318  * This function implements the generic vfs_fs_new_dentry() function for the FATFS.
    319  *****************************************************************************************
    320  * It scan a parent directory mapper, identified by the <parent_inode> argument to find
    321  * a directory entry identified by the <name> argument.  In case of success, it completes
    322  * initialization the inode/dentry couple, identified by the  <child_inode_xp> argument.
    323  * The child inode descriptor, and the associated dentry descriptor must have been
    324  * previously allocated by the caller.
     328 * @ parent_inode_xp   : [in] extended pointer on parent directory inode.
     329 * @ dentry_ptr        : [in] local pointer on dentry (in parent directory cluster).
     330 * @ return 0 if success / return -1 if failure.
     331 ****************************************************************************************/
     332error_t fatfs_remove_dentry( xptr_t                parent_inode_xp,
     333                             struct vfs_dentry_s * dentry_ptr );
     334
     335/*****************************************************************************************
     336 * This function implements the generic vfs_fs_new_dentry_from_mapper() for the FATFS.
     337 *****************************************************************************************
     338 * It scan a parent directory mapper, identified by the <parent_inode_xp> argument
     339 * to find a directory entry name defined by the <dentry_ptr> argument, and completes
     340 * the initialization of the dentry and the associated child_inode descriptors,
     341 * from informations found in the parent directory mapper :
    325342 * - It set the "type", "size", and "extend" fields in the child inode descriptor.
    326343 * - It set the " extend" field in the dentry descriptor.
    327  * It must be called by a thread running in the cluster containing the parent inode.
    328  *****************************************************************************************
    329  * @ parent_inode    : local pointer on parent inode (directory).
    330  * @ name            : child name.
    331  * @ child_inode_xp  : extended pointer on remote child inode (file or directory).
     344 * The child inode descriptor, and the dentry descriptor must have been previously
     345 * allocated and introduced in the Inode Tree.
     346 * This function can be called by any thread running in any cluster.
     347 *****************************************************************************************
     348 * @ parent_inode_xp : extended pointer on parent inode (directory).
     349 * @ dentry_ptr      : local pointer on new dentry (in parent inode cluster).
     350 * @ return 0 if success / return -1 if failure.
     351 ****************************************************************************************/
     352error_t fatfs_new_dentry_from_mapper( xptr_t                parent_inode_xp,
     353                                      struct vfs_dentry_s * dentry_ptr );
     354
     355/*****************************************************************************************
     356 * This function implements the generic vfs_fs_new_dentry_to_mapper() for the FATFS.
     357 *****************************************************************************************
     358 * This function  introduces a brand new dentry identified by the <dentry_ptr> argument
     359 * in the mapper of a directory identified by the <parent_inode_xp> argument.
     360 * It is called by the vfs_lookup() function.
     361 * The child inode descriptor, and the dentry descriptor must have been previously
     362 * allocated and introduced in the Inode Tree. The dentry descriptor contains the name.
     363 * 1. It allocates a new FATFS cluster_id,
     364 * 2. It registers the allocated cluster_id in the child inode extension,
     365 * 3. It add a new entry (32 bytes) in the directory mapper,
     366 * This function can be called by any thread running in any cluster.
     367 *****************************************************************************************
     368 * @ parent_inode_xp : [in]  extended pointer on parent inode (directory).
     369 * @ dentry_ptr      : [in]  local pointer on dentry (in parent inode cluster).
     370 * @ return 0 if success / return -1 if failure.
     371 ****************************************************************************************/
     372error_t fatfs_new_dentry_to_mapper( xptr_t                parent_inode_xp,
     373                                    struct vfs_dentry_s * dentry_ptr );
     374
     375/*****************************************************************************************
     376 * This function implements the generic vfs_fs_update_dentry() function for the FATFS.
     377 *****************************************************************************************
     378 * It update the "size" of a directory entry identified by the <dentry_ptr> argument in
     379 * the mapper of a directory identified by the <parent_inode_xp> argument, from the
     380 * value registered in the inode descriptor.
     381 * It scan the directory mapper to find the entry such as name == dentry_ptr->name.
     382 * It set the "size" field in the directory mapper, and updates the modified directory
     383 * page on the IOC device.
     384 * This function can be called by any thread running in any cluster.
     385 *
     386 * TODO the current implementation uses the fatfs_scan_directory to access the
     387 * FAT32 directory by name. We can access directly this directory entry if we use
     388 * the dentry "extend" field...
     389 *****************************************************************************************
     390 * @ parent_inode_xp : extended pointer on inode (directory).
     391 * @ dentry_ptr      : local pointer on dentry (in parent directory cluster).
    332392 * @ return 0 if success / return -1 if child not found.
    333393 ****************************************************************************************/
    334 error_t fatfs_new_dentry( struct vfs_inode_s * parent_inode,
    335                           char               * name,
    336                           xptr_t               child_inode_xp );
    337 
    338 /*****************************************************************************************
    339  * This function implements the generic vfs_fs_update_dentry() function for the FATFS.
    340  *****************************************************************************************
    341  * It update the size of a directory entry identified by the <dentry> argument in
    342  * the mapper of a directory identified by the <inode> argument, as defined by the
    343  * <size> argument.
    344  * It scan the mapper to find the entry identified by the dentry "name" field.
    345  * It set the "size" field in the in the directory mapper AND marks the page as DIRTY.
    346  * It must be called by a thread running in the cluster containing the directory inode.
    347  *****************************************************************************************
    348  * @ inode        : local pointer on inode (directory).
    349  * @ dentry       : local pointer on dentry (for name).
    350  * @ size         : new size value.
    351  * @ return 0 if success / return ENOENT if child not found.
    352  ****************************************************************************************/
    353 error_t fatfs_update_dentry( struct vfs_inode_s  * inode,
    354                              struct vfs_dentry_s * dentry,
    355                              uint32_t              size );
     394error_t fatfs_update_dentry( xptr_t                parent_inode_xp,
     395                             struct vfs_dentry_s * dentry_ptr );
    356396
    357397/*****************************************************************************************
     
    367407 * the Inode Tree is dynamically created, and all dirent fields are documented in the
    368408 * dirent array. Otherwise, only the dentry name is documented.
    369  * It must be called by a thread running in the cluster containing the directory inode.
    370  *****************************************************************************************
    371  * @ inode      : [in]  local pointer on directory inode.
     409 *
     410 * WARNING : It must be called by a thread running in the cluster containing the
     411 * target directory inode.
     412 *****************************************************************************************
     413 * @ parent_inode_xp  : [in]  extended pointer on directory inode.
    372414 * @ array      : [in]  local pointer on array of dirents.
    373415 * @ max_dirent : [in]  max number of slots in dirent array.
     
    390432 *****************************************************************************************
    391433 * It updates the FATFS on the IOC device for a given inode identified by
    392  * the <inode> argument. It scan all pages registered in the associated mapper,
     434 * the <inode_xp> argument. It scan all pages registered in the associated mapper,
    393435 * and copies from mapper to device each page marked as dirty.
    394436 * WARNING : The target <inode> cannot be a directory, because all modifications in a
    395437 * directory are synchronously done on the IOC device by the two fatfs_add_dentry()
    396438 * and fatfs_remove_dentry() functions.
    397  *****************************************************************************************
    398  * @ inode   : local pointer on inode.
    399  * @ return 0 if success / return -1 if failure during IOC device access.
    400  ****************************************************************************************/
    401 error_t fatfs_sync_inode( struct vfs_inode_s * inode );
     439 * This function can be called by any thread running in any cluster.
     440 *****************************************************************************************
     441 * @ inode_xp   : extended pointer on inode.
     442 * @ return 0 if success / return -1 if failure.
     443 ****************************************************************************************/
     444error_t fatfs_sync_inode( xptr_t  inode_xp );
    402445
    403446/*****************************************************************************************
     
    407450 * It scan all clusters registered in the FAT mapper, and copies from mapper to device
    408451 * each page marked as dirty.
    409  *
    410  * TODO : the current implementation check ALL pages in the FAT region, even if most
    411  * pages are empty, and not copied in mapper. It is sub-optimal.
    412  * A solution is to maintain in the FAT context two "dirty_min" and "dirty_max"
    413  * variables defining the smallest/largest dirty page index in FAT mapper...
     452 * This function can be called by any thread running in any cluster.
     453 *
     454 * Implementation note : this function uses the grdxt_remote_get_first() function
     455 * to test only the pages actually registered in the FAT mapper.
    414456 *****************************************************************************************
    415457 * @ return 0 if success / return -1 if failure during IOC device access.
     
    418460
    419461/*****************************************************************************************
    420  * This function implements the generic vfs_fs_sync_fsinfo() function for the FATFS.
    421  *****************************************************************************************
    422  * It checks the current values of the "free_clusters" and "free_cluster_hint" variables
    423  * in the FS_INFO sector on IOC, versus the values stored in the fatfs context.
    424  * As these values are synchronously updated on IOC device at each modification,
    425  * it does nothing if the values are equal. It updates the FS_INFO sector on IOC device,
    426  * and displays a warning message on TXT0 if they are not equal.
    427  * This function can be called by any thread running in any cluster.
    428  *****************************************************************************************
    429  * @ return 0 if success / return -1 if failure during IOC device access.
    430  ****************************************************************************************/
    431 error_t fatfs_sync_free_info( void );
    432 
    433 /*****************************************************************************************
    434  * This function implements the generic vfs_fs_cluster_alloc() function for the FATFS.
    435  *****************************************************************************************
    436  * It access the FAT (File allocation table), stored in the FAT mapper, and returns
    437  * in <searched_cluster> the FATFS cluster index of a free cluster.
    438  * It can be called by a thread running in any cluster, as it uses remote access
    439  * primitives when the FAT mapper is remote. It takes the rwlock stored in the FATFS
    440  * context located in the same cluster as the FAT mapper itself, to get exclusive
    441  * access to the FAT. It uses and updates the <free_cluster_hint> and <free_clusters>
    442  * variables stored in this FATFS context.
    443  * - it updates the <free_cluster_hint> and <free_clusters> variables in FATFS context.
    444  * - it updates the FAT mapper (handling miss from IOC device if required).
    445  * - it synchronously updates the FAT region on IOC device.
    446  * - it returns the allocated cluster index.
    447  *****************************************************************************************
    448  * @ searched_cluster_id  : [out] allocated FATFS cluster index.
    449  * @ return 0 if success / return -1 if no more free clusters on IOC device.
    450  ****************************************************************************************/
    451 error_t fatfs_cluster_alloc( uint32_t * searched_cluster_id );
    452 
    453 /*****************************************************************************************
    454462 * This function implements the generic vfs_fs_release_inode() function for the FATFS.
    455463 *****************************************************************************************
    456  * This function is used to remove a given file or directory from FATFS the file system.
     464 * This function is used to remove a given file or directory from the FATFS file system.
    457465 * It releases all clusters allocated to a file/directory identified by the <inode_xp>
    458466 * argument. All released clusters are marked FREE_CLUSTER in the FAT mapper.
     
    462470 * synchronously update all modified pages in the FAT mapper to the IOC device.
    463471 * Finally the FS-INFO sector on the IOC device is updated.
     472 * This function can be called by any thread running in any cluster.
    464473 *****************************************************************************************
    465474 * @ inode_xp   : extended pointer on inode.
     
    478487 * - For a regular file, it scan the FAT mapper to get the cluster_id on IOC device,
    479488 *   and read/write this cluster.
    480  * It can be called by any thread running in any cluster.
     489 * This function can be called by any thread running in any cluster.
    481490 *
    482491 * WARNING : For the FAT mapper, the inode field in the mapper MUST be NULL, as this
    483492 *           is used to indicate that the corresponding mapper is the FAT mapper.
    484  *
    485  * TODO : In this first implementation, the entry point in the FAT to get the cluster_id
    486  *        is always the cluster_id of the first page, registered in the inode extension.
    487  *        This can introduce a quadratic cost when trying of acessing all pages of a
    488  *        big file. An optimisation would be to introduce in the inode extension two
    489  *        new fields <other_page_id> & <other_cluster_id>, defining a second entry point
    490  *        in the FAT.
    491493 *****************************************************************************************
    492494 * @ page_xp   : extended pointer on page descriptor.
     
    494496 * @ return 0 if success / return EIO if error during device access.
    495497 ****************************************************************************************/
    496 error_t fatfs_move_page( xptr_t      page_xp,
    497                          cmd_type_t  cmd_type );
     498error_t fatfs_move_page( xptr_t          page_xp,
     499                         ioc_cmd_type_t  cmd_type );
    498500
    499501
  • trunk/kernel/fs/ramfs.h

    r188 r657  
    33 *
    44 * Authors   Mohamed Lamine Karaoui (2014,2015)
    5  *           Alain Greiner (2016,2017)
     5 *           Alain Greiner (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    2929// The RAMFS File System does not uses any external device to store data.
    3030// It stores the dynamically created files and directories in the VFS mappers.
    31 // The ramfs_read_page() and ramfs_write_page() functions should never be used.
    3231// The RAMFS cannot be used as the root File System.
    3332//
  • trunk/kernel/fs/vfs.c

    r656 r657  
    33 *
    44 * Author  Mohamed Lamine Karaoui (2015)
    5  *         Alain Greiner (2016,2017,2018,2019)
     5 *         Alain Greiner (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    3333#include <xhtab.h>
    3434#include <string.h>
    35 #include <rpc.h>
    3635#include <errno.h>
    3736#include <kmem.h>
     
    5958//////////////////////////////////////////////////////////////////////////////////////////
    6059
    61 ////////////////////////////////////////
    62 void vfs_ctx_init( vfs_fs_type_t   type,
    63                    uint32_t        attr,
     60///////////////////////////////////////
     61void vfs_ctx_init( cxy_t           cxy,
     62                   vfs_fs_type_t   fs_type,
    6463                       uint32_t        total_clusters,
    6564                       uint32_t        cluster_size,
     
    6766                   void          * extend )
    6867{
    69     vfs_ctx_t * vfs_ctx = &fs_context[type];
    70 
    71     vfs_ctx->type           = type;
    72     vfs_ctx->attr           = attr;
    73     vfs_ctx->total_clusters = total_clusters;
    74     vfs_ctx->cluster_size   = cluster_size;
    75     vfs_ctx->vfs_root_xp    = vfs_root_xp;
    76     vfs_ctx->extend         = extend;
    77 
    78     busylock_init( &vfs_ctx->lock , LOCK_VFS_CTX );
    79 
    80     bitmap_init( vfs_ctx->bitmap , BITMAP_SIZE(CONFIG_VFS_MAX_INODES) );
    81 }
    82 
    83 ////////////////////////////////////////////
    84 error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx,
     68    // get pointer on relevant VFS context (same in all clusters)
     69    vfs_ctx_t * vfs_ctx_ptr = &fs_context[fs_type];
     70
     71    // initialise VFS context fields
     72    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->type           ) , fs_type );
     73    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->total_clusters ) , total_clusters );
     74    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->cluster_size   ) , cluster_size );
     75    hal_remote_s64( XPTR( cxy , &vfs_ctx_ptr->vfs_root_xp    ) , vfs_root_xp );
     76    hal_remote_spt( XPTR( cxy , &vfs_ctx_ptr->extend         ) , extend );
     77
     78    // initialize VFS context lock
     79    remote_busylock_init( XPTR( cxy , &vfs_ctx_ptr->lock ) , LOCK_VFS_CTX );
     80
     81    // initialize inum allocator
     82    bitmap_remote_init( XPTR( cxy , &vfs_ctx_ptr->bitmap ),
     83                        BITMAP_SIZE(CONFIG_VFS_MAX_INODES) );
     84
     85} // end vfs_ctx_init()
     86
     87///////////////////////////////////////////////
     88error_t vfs_ctx_inum_alloc( xptr_t      ctx_xp,
    8589                            uint32_t  * inum )
    8690{
     91    // get context cluster and local pointer
     92    cxy_t       ctx_cxy = GET_CXY( ctx_xp );
     93    vfs_ctx_t * ctx_ptr = GET_PTR( ctx_xp );
     94
     95    // build extended pointer on lock protecting the inum allocator
     96    xptr_t lock_xp = XPTR( ctx_cxy , &ctx_ptr->lock );
     97
     98    // build extended pointer on inum bitmap
     99    xptr_t bitmap_xp = XPTR( ctx_cxy , &ctx_ptr->bitmap );
     100
    87101    // get lock on inum allocator
    88     busylock_acquire( &ctx->lock );
     102    remote_busylock_acquire( lock_xp );
    89103
    90104    // get lid from local inum allocator
    91     uint32_t lid = bitmap_ffc( ctx->bitmap , CONFIG_VFS_MAX_INODES );
     105    uint32_t lid = bitmap_remote_ffc( bitmap_xp , CONFIG_VFS_MAX_INODES );
    92106
    93107    if( lid == 0xFFFFFFFF )   // no more free slot => error
    94108    {
    95109        // release lock
    96         busylock_release( &ctx->lock );
     110        remote_busylock_release( lock_xp );
    97111
    98112        // return error
    99         return 1;
     113        return -1;
    100114    }
    101115    else              // found => return inum
    102116    {
    103117        // set slot allocated
    104         bitmap_set( ctx->bitmap , lid );
     118        bitmap_remote_set( bitmap_xp , lid );
    105119
    106120        // release lock
    107         busylock_release( &ctx->lock );
     121        remote_busylock_release( lock_xp );
    108122
    109123        // return inum
     
    111125        return 0;
    112126    }
    113 }
    114 
    115 ////////////////////////////////////////////
    116 void vfs_ctx_inum_release( vfs_ctx_t * ctx,
    117                            uint32_t    inum )
    118 {
    119     bitmap_clear( ctx->bitmap , inum & 0xFFFF );
    120 }
     127}  // end vfs_ctx_inum_alloc()
     128
     129/////////////////////////////////////////////
     130void vfs_ctx_inum_release( xptr_t     ctx_xp,
     131                           uint32_t   inum )
     132{
     133    // get context cluster and local pointer
     134    cxy_t       ctx_cxy = GET_CXY( ctx_xp );
     135    vfs_ctx_t * ctx_ptr = GET_PTR( ctx_xp );
     136
     137    // build extended pointer on inum bitmap
     138    xptr_t bitmap_xp = XPTR( ctx_cxy , &ctx_ptr->bitmap );
     139
     140    // build extended pointer on lock
     141    xptr_t lock_xp = XPTR( ctx_cxy , &ctx_ptr->lock );
     142
     143    // get lock
     144    remote_busylock_acquire( lock_xp );
     145
     146    bitmap_remote_clear( bitmap_xp , inum & 0xFFFF );
     147
     148    // release lock
     149    remote_busylock_release( lock_xp );
     150
     151}  // end vfs_ctx_inum_release()
    121152
    122153//////////////////////////////////////////////////////////////////////////////////////////
     
    140171}
    141172
    142 ////////////////////////////////////////////////////
    143 error_t vfs_inode_create( vfs_fs_type_t     fs_type,
     173////////////////////////////////////////////////
     174error_t vfs_inode_create( cxy_t             cxy,
     175                          vfs_fs_type_t     fs_type,
    144176                          uint32_t          attr,
    145177                          uint32_t          rights,
     
    148180                          xptr_t          * inode_xp )
    149181{
    150     mapper_t         * mapper;     // associated mapper( to be allocated)
    151     vfs_inode_t      * inode;      // inode descriptor (to be allocated)
    152    
    153     uint32_t           inum;       // inode identifier (to be allocated)
    154     vfs_ctx_t        * ctx;        // file system context
    155         kmem_req_t         req;        // request to kernel memory allocator
     182    xptr_t             mapper_xp;    // extended pointer on associated mapper
     183    mapper_t         * mapper_ptr;   // local pointer on associated mapper
     184    vfs_inode_t      * inode_ptr;    // local pointer on allocated inode
     185    uint32_t           inum;         // inode identifier (to be allocated)
     186    vfs_ctx_t        * ctx;          // file system context
     187        kmem_req_t         req;          // request to kernel memory allocator
    156188    error_t            error;
    157189
     
    166198    }
    167199
    168     // allocate inum
    169     error = vfs_ctx_inum_alloc( ctx , &inum );
    170 
    171     if( error )
    172     {
    173         printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ );
    174         return -1;
    175     }
    176 
    177     // allocate memory for mapper
    178     mapper = mapper_create( fs_type );
    179 
    180     if( mapper == NULL )
    181     {
    182         printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ );
    183         vfs_ctx_inum_release( ctx , inum );
    184         return ENOMEM;
    185     }
    186 
    187200// check inode descriptor contained in one page
    188201assert( (sizeof(vfs_inode_t) <= CONFIG_PPM_PAGE_SIZE),
    189202"inode descriptor must fit in one page" );
    190203
     204    // allocate inum
     205    error = vfs_ctx_inum_alloc( XPTR( cxy , ctx ) , &inum );
     206
     207    if( error )
     208    {
     209        printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ );
     210        return -1;
     211    }
     212
     213    // allocate memory for mapper in cluster cxy
     214    mapper_xp = mapper_create( cxy , fs_type );
     215
     216    if( mapper_xp == XPTR_NULL )
     217    {
     218        printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ );
     219        vfs_ctx_inum_release( XPTR( cxy , ctx ) , inum );
     220        return -1;
     221    }
     222
     223    mapper_ptr = GET_PTR( mapper_xp );
     224
    191225    // allocate one page for VFS inode descriptor
    192     // because the embedded "children xhtab footprint
    193         req.type  = KMEM_PPM;
    194         req.order = 0;
    195     req.flags = AF_KERNEL | AF_ZERO;
    196         inode     = kmem_alloc( &req );
    197 
    198     if( inode == NULL )
     226    // because the embedded "children" xhtab footprint
     227        req.type   = KMEM_PPM;
     228        req.order  = 0;
     229    req.flags  = AF_KERNEL | AF_ZERO;
     230        inode_ptr  = kmem_remote_alloc( cxy , &req );
     231
     232    if( inode_ptr == NULL )
    199233    {
    200234        printk("\n[ERROR] in %s : cannot allocate inode descriptor\n", __FUNCTION__ );
    201         vfs_ctx_inum_release( ctx , inum );
    202         mapper_destroy( mapper );
     235        vfs_ctx_inum_release( XPTR( cxy , ctx ) , inum );
     236        mapper_destroy( mapper_xp );
    203237        return -1;
    204238    }
    205239
     240    // initialise inode field in mapper
     241    hal_remote_spt( XPTR( cxy , &mapper_ptr->inode ) , inode_ptr );
     242 
    206243    // initialize inode descriptor
    207     inode->type       = INODE_TYPE_FILE;     // default value
    208     inode->inum       = inum;
    209     inode->attr       = attr;
    210     inode->rights     = rights;
    211     inode->uid        = uid;
    212     inode->gid        = gid;
    213     inode->ctx        = ctx;
    214     inode->mapper     = mapper;
    215     inode->extend     = NULL;
    216     inode->links      = 0;
    217 
    218     // initialise inode field in mapper
    219     mapper->inode     = inode;
    220  
     244    hal_remote_s32( XPTR( cxy , &inode_ptr->type   ) , INODE_TYPE_FILE );  // default value
     245    hal_remote_s32( XPTR( cxy , &inode_ptr->inum   ) , inum ); 
     246    hal_remote_s32( XPTR( cxy , &inode_ptr->attr   ) , attr ); 
     247    hal_remote_s32( XPTR( cxy , &inode_ptr->rights ) , rights ); 
     248    hal_remote_s32( XPTR( cxy , &inode_ptr->links  ) , 0 );
     249    hal_remote_s32( XPTR( cxy , &inode_ptr->uid    ) , uid ); 
     250    hal_remote_s32( XPTR( cxy , &inode_ptr->gid    ) , gid ); 
     251    hal_remote_spt( XPTR( cxy , &inode_ptr->ctx    ) , ctx ); 
     252    hal_remote_spt( XPTR( cxy , &inode_ptr->mapper ) , mapper_ptr ); 
     253    hal_remote_spt( XPTR( cxy , &inode_ptr->extend ) , NULL ); 
     254
    221255    // initialize chidren dentries xhtab
    222     xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
     256    xhtab_init( XPTR( cxy , &inode_ptr->children ) , XHTAB_DENTRY_TYPE );
    223257
    224258    // initialize parents dentries xlist
    225     xlist_root_init( XPTR( local_cxy , &inode->parents ) );
     259    xlist_root_init( XPTR( cxy , &inode_ptr->parents ) );
    226260 
    227261    // initialize lock protecting size
    228     remote_rwlock_init( XPTR( local_cxy , &inode->size_lock ), LOCK_VFS_SIZE );
     262    remote_rwlock_init( XPTR( cxy , &inode_ptr->size_lock ), LOCK_VFS_SIZE );
    229263
    230264    // initialise lock protecting inode tree traversal
    231     remote_rwlock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN );
     265    remote_rwlock_init( XPTR( cxy , &inode_ptr->main_lock ), LOCK_VFS_MAIN );
    232266
    233267    // return extended pointer on inode
    234     *inode_xp = XPTR( local_cxy , inode );
     268    *inode_xp = XPTR( cxy , inode_ptr );
    235269
    236270#if DEBUG_VFS_INODE_CREATE
     
    238272thread_t *     this       = CURRENT_THREAD;
    239273if( DEBUG_VFS_INODE_CREATE < cycle )
    240 printk("\n[%s] thread[%x,%x] created inode (%x,%x) / cycle %d\n",
    241 __FUNCTION__, this->process->pid, this->trdid, local_cxy, inode, cycle );
     274printk("\n[%s] thread[%x,%x] created inode (%x,%x) / ctx %x / fs_type %d / cycle %d\n",
     275__FUNCTION__, this->process->pid, this->trdid, cxy, inode_ptr, ctx, ctx->type, cycle );
    242276#endif
    243277 
     
    246280}  // end vfs_inode_create() 
    247281
    248 /////////////////////////////////////////////
    249 void vfs_inode_destroy( vfs_inode_t * inode )
    250 {
     282//////////////////////////////////////////
     283void vfs_inode_destroy( xptr_t  inode_xp )
     284{
     285    // get cluster and local pointer
     286    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     287    cxy_t         inode_cxy = GET_CXY( inode_xp );
     288
    251289    // release memory allocated for mapper
    252     mapper_destroy( inode->mapper );
    253 
    254     // release memory allocate for inode descriptor
     290    mapper_destroy( XPTR( inode_cxy , &inode_ptr->mapper ) );
     291
     292    // release memory allocated for inode descriptor
    255293        kmem_req_t req;
    256294        req.type  = KMEM_PPM;
    257         req.ptr   = inode;
    258         kmem_free( &req );
     295        req.ptr   = inode_ptr;
     296        kmem_remote_free( inode_cxy , &req );
    259297
    260298}  // end vfs_inode_destroy()
     
    339377   
    340378    // get inode cluster and local pointer
     379    inode_ptr = GET_PTR( inode_xp );
    341380    inode_cxy = GET_CXY( inode_xp );
    342     inode_ptr = GET_PTR( inode_xp );
    343381
    344382    // build extended pointer on parents dentries root
     
    367405}  // end vfs_inode_get_name()
    368406
    369 ///////////////////////////////////////////////////////
    370 error_t vfs_inode_load_all_pages( vfs_inode_t * inode )
    371 {
    372 
    373 assert( (inode != NULL) , "inode pointer is NULL" );
    374 
     407////////////////////////////////////////////////////
     408error_t vfs_inode_load_all_pages( xptr_t  inode_xp )
     409{
    375410    uint32_t   page_id;
    376411    xptr_t     page_xp;
    377412
    378     mapper_t * mapper = inode->mapper;
    379     uint32_t   size   = inode->size;
    380 
    381 assert( (mapper != NULL) , "mapper pointer is NULL" );
     413
     414    // get inode cluster and local pointer
     415    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     416    cxy_t         inode_cxy = GET_CXY( inode_xp );
     417
     418    // get pointer on mapper and size
     419    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     420    uint32_t   size   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size ) );
    382421
    383422#if DEBUG_VFS_INODE_LOAD_ALL
     423char       name[CONFIG_VFS_MAX_NAME_LENGTH];
    384424uint32_t   cycle = (uint32_t)hal_get_cycles();
    385425thread_t * this  = CURRENT_THREAD;
    386 char       name[CONFIG_VFS_MAX_NAME_LENGTH];
    387 vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     426vfs_inode_get_name( inode_xp , name );
    388427if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
    389428printk("\n[%s] thread[%x,%x] enter for <%s> in cluster %x / cycle %d\n",
    390 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
     429__FUNCTION__, this->process->pid, this->trdid, name, inode_cxy, cycle );
    391430#endif
    392431
     
    400439        // If the mage is missing, this function allocates the missing page,
    401440        // and load the page from IOC device into mapper
    402         page_xp = mapper_remote_get_page( XPTR( local_cxy , mapper ), page_id );
     441        page_xp = mapper_get_page( XPTR( inode_cxy , mapper ), page_id );
    403442
    404443        if( page_xp == XPTR_NULL ) return -1;
     
    408447cycle = (uint32_t)hal_get_cycles();
    409448if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
    410 printk("\n[%s] thread[%x,%x] exit for <%x> in cluster %x / cycle %d\n",
    411 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
     449printk("\n[%s] thread[%x,%x] exit for <%s> in cluster %x\n",
     450__FUNCTION__, this->process->pid, this->trdid, name, inode_cxy );
    412451#endif
    413452
     
    425464    vfs_inode_get_name( inode_xp , name );
    426465
     466    // get inode cluster and local pointer
    427467    cxy_t         inode_cxy = GET_CXY( inode_xp );
    428468    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     
    461501//////////////////////////////////////////////////////////////////////////////////////////
    462502
    463 ///////////////////////////////////////////////////
    464 error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
     503///////////////////////////////////////////////
     504error_t vfs_dentry_create( cxy_t           cxy,
     505                           vfs_fs_type_t   fs_type,
    465506                           char          * name,
    466507                           xptr_t        * dentry_xp )
    467508{
    468     vfs_ctx_t      * ctx;        // context descriptor
    469     vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated)
    470         kmem_req_t       req;        // request to kernel memory allocator
     509        kmem_req_t       req;            // request to kernel memory allocator
     510    vfs_ctx_t      * ctx = NULL;     // context descriptor
     511    vfs_dentry_t   * dentry_ptr;     // dentry descriptor (to be allocated)
     512
     513#if DEBUG_VFS_DENTRY_CREATE
     514thread_t * this  = CURRENT_THREAD;
     515uint32_t   cycle = (uint32_t)hal_get_cycles();
     516if( DEBUG_VFS_DENTRY_CREATE < cycle )
     517printk("\n[%s] thread[%x,%x] enters for <%s> /  fs_type %x / cycle %d\n",
     518__FUNCTION__, this->process->pid, this->trdid, name, fs_type, cycle );
     519#endif
    471520
    472521    // get pointer on context
     
    476525    else
    477526    {
    478         ctx = NULL;
     527        printk("\n[ERROR] in %s undefined fs_type %d\n", __FUNCTION__, fs_type );
    479528        return -1;
    480529    }
     
    483532    uint32_t length = strlen( name );
    484533
    485     if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return EINVAL;
     534    if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return -1;
    486535
    487536    // allocate memory for dentry descriptor
    488         req.type  = KMEM_KCM;
    489         req.order = bits_log2( sizeof(vfs_dentry_t) );
    490     req.flags = AF_KERNEL | AF_ZERO;
    491         dentry    = kmem_alloc( &req );
    492 
    493     if( dentry == NULL )
     537        req.type   = KMEM_KCM;
     538        req.order  = bits_log2( sizeof(vfs_dentry_t) );
     539    req.flags  = AF_KERNEL | AF_ZERO;
     540        dentry_ptr = kmem_remote_alloc( cxy , &req );
     541
     542    if( dentry_ptr == NULL )
    494543    {
    495544        printk("\n[ERROR] in %s : cannot allocate dentry descriptor\n",
     
    499548
    500549    // initialize dentry descriptor
    501     dentry->ctx     = ctx;
    502     dentry->length  = length;
    503     dentry->extend  = NULL;
    504     strcpy( dentry->name , name );
     550    hal_remote_spt( XPTR( cxy , &dentry_ptr->ctx    ) , ctx );
     551    hal_remote_s32( XPTR( cxy , &dentry_ptr->length ) , length );
     552    hal_remote_spt( XPTR( cxy , &dentry_ptr->extend ) , NULL );
     553
     554    // register name
     555    hal_remote_strcpy( XPTR( cxy, dentry_ptr->name ),
     556                       XPTR( local_cxy, name ) );
    505557
    506558    // return extended pointer on dentry
    507     *dentry_xp = XPTR( local_cxy , dentry );
     559    *dentry_xp = XPTR( cxy , dentry_ptr );
    508560
    509561#if DEBUG_VFS_DENTRY_CREATE
    510 thread_t * this  = CURRENT_THREAD;
    511 uint32_t   cycle = (uint32_t)hal_get_cycles();
    512562if( DEBUG_VFS_DENTRY_CREATE < cycle )
    513 printk("\n[%s] thread[%x,%x] created dentry <%s> : (%x,%x) / cycle %d\n",
    514 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, dentry, cycle );
     563printk("\n[%s] thread[%x,%x] exit for <%s> / dentry (%x,%x)\n",
     564__FUNCTION__, this->process->pid, this->trdid, name, cxy, dentry_ptr );
    515565#endif
    516566
     
    519569}  // end vfs_dentry_create()
    520570
    521 ////////////////////////////////////////////////
    522 void vfs_dentry_destroy( vfs_dentry_t * dentry )
    523 {
     571////////////////////////////////////////////
     572void vfs_dentry_destroy( xptr_t  dentry_xp )
     573{
     574    // get cluster and local pointer
     575    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
     576    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
     577 
    524578    // release memory allocated to dentry
    525579        kmem_req_t req;
    526580        req.type  = KMEM_KCM;
    527         req.ptr   = dentry;
    528         kmem_free( &req );
     581        req.ptr   = dentry_ptr;
     582        kmem_remote_free( dentry_cxy , &req );
    529583
    530584}  // end vfs_dentry_destroy()
     
    536590
    537591/////////////////////////////////////////////
    538 error_t vfs_file_create( vfs_inode_t * inode,
    539                          uint32_t      attr,
    540                          xptr_t      * file_xp )
    541 {
    542     vfs_file_t  * file;
     592error_t vfs_file_create( xptr_t     inode_xp,
     593                         uint32_t   attr,
     594                         xptr_t   * file_xp )
     595{
     596    vfs_file_t  * file_ptr;
    543597        kmem_req_t    req;
     598    uint32_t      type;
     599    mapper_t    * mapper;
     600    vfs_ctx_t   * ctx;
     601
     602    // get inode cluster and local pointer
     603    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     604    cxy_t         inode_cxy = GET_CXY( inode_xp );
    544605
    545606#if DEBUG_VFS_FILE_CREATE
     
    547608uint32_t cycle = (uint32_t)hal_get_cycles();
    548609if( DEBUG_VFS_OPEN < cycle )
    549 printk("\n[%s] thread[%x,%x] enter for inode %x in cluster %x / cycle %d\n",
    550 __FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle );
     610printk("\n[%s] thread[%x,%x] enter for inode (%x,%x) / cycle %d\n",
     611__FUNCTION__, this->process->pid, this->trdid, inode_cxy, inode_ptr, cycle );
    551612#endif
    552613
     
    555616        req.order = bits_log2( sizeof(vfs_file_t) );
    556617    req.flags = AF_KERNEL | AF_ZERO;
    557         file      = kmem_alloc( &req );
    558 
    559     if( file == NULL ) return ENOMEM;
     618        file_ptr  = kmem_remote_alloc( inode_cxy , &req );
     619
     620    if( file_ptr == NULL ) return -1;
     621
     622    // get type, ctx and mapper from inode descriptor
     623    type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     624    ctx    = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) );
     625    mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
    560626
    561627    // initializes new file descriptor
    562     file->gc       = 0;
    563     file->type     = inode->type;
    564     file->attr     = attr;
    565     file->offset   = 0;
    566     file->refcount = 1;
    567     file->inode    = inode;
    568     file->ctx      = inode->ctx;
    569     file->mapper   = inode->mapper;
    570 
    571     remote_rwlock_init( XPTR( local_cxy , &file->lock ), LOCK_VFS_FILE );
    572 
    573     *file_xp = XPTR( local_cxy , file );
     628    hal_remote_s32( XPTR( inode_cxy , &file_ptr->type     ) , type );
     629    hal_remote_s32( XPTR( inode_cxy , &file_ptr->attr     ) , attr );
     630    hal_remote_s32( XPTR( inode_cxy , &file_ptr->offset   ) , 0 );
     631    hal_remote_s32( XPTR( inode_cxy , &file_ptr->refcount ) , 1 );
     632    hal_remote_spt( XPTR( inode_cxy , &file_ptr->inode    ) , inode_ptr );
     633    hal_remote_spt( XPTR( inode_cxy , &file_ptr->ctx      ) , ctx );
     634    hal_remote_spt( XPTR( inode_cxy , &file_ptr->mapper   ) , mapper );
     635
     636    remote_rwlock_init( XPTR( inode_cxy , &file_ptr->lock ), LOCK_VFS_FILE );
     637
     638    *file_xp = XPTR( inode_cxy , file_ptr );
    574639
    575640#if DEBUG_VFS_FILE_CREATE
    576641cycle = (uint32_t)hal_get_cycles();
    577642if( DEBUG_VFS_OPEN < cycle )
    578 printk("\n[%s] thread[%x,%x] created file %x in cluster %x / cycle %d\n",
    579 __FUNCTION__, this->process->pid, this->trdid, file, local_cxy, cycle );
     643printk("\n[%s] thread[%x,%x] created file (%x,%x) %x\n",
     644__FUNCTION__, this->process->pid, this->trdid, inode_cxy, file_ptr, cycle );
    580645#endif
    581646
     
    584649}  // end vfs_file_create()
    585650
    586 ///////////////////////////////////////////
    587 void vfs_file_destroy( vfs_file_t *  file )
    588 {
     651////////////////////////////////////////
     652void vfs_file_destroy( xptr_t  file_xp )
     653{
     654    // get file cluster and local pointer
     655    vfs_file_t * file_ptr = GET_PTR( file_xp );
     656    cxy_t        file_cxy = GET_CXY( file_xp );
     657
     658    // release file descriptor
    589659        kmem_req_t req;
    590660        req.type  = KMEM_KCM;
    591         req.ptr   = file;
    592         kmem_free( &req );
     661        req.ptr   = file_ptr;
     662        kmem_remote_free( file_cxy , &req );
    593663
    594664#if DEBUG_VFS_CLOSE
    595665char name[CONFIG_VFS_MAX_NAME_LENGTH];
    596 vfs_file_get_name( XPTR( local_cxy , file ) , name );
     666vfs_file_get_name( file_xp , name );
    597667thread_t * this = CURRENT_THREAD;
    598668uint32_t cycle = (uint32_t)hal_get_cycles();
    599669if( DEBUG_VFS_CLOSE < cycle )
    600670printk("\n[%s] thread[%x,%x] deleted file <%s> in cluster %x / cycle %d\n",
    601 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
     671__FUNCTION__, this->process->pid, this->trdid, name, file_cxy, cycle );
    602672#endif
    603673
     
    738808
    739809    // create a new file descriptor in cluster containing inode
    740     if( inode_cxy == local_cxy )      // target cluster is local
    741     {
    742         error = vfs_file_create( inode_ptr , file_attr , &file_xp );
    743     }
    744     else                              // target cluster is remote
    745     {
    746         rpc_vfs_file_create_client( inode_cxy , inode_ptr , file_attr , &file_xp , &error );
    747     }
     810    error = vfs_file_create( inode_xp , file_attr , &file_xp );
    748811
    749812    if( error )  return error;
     
    764827cycle = (uint32_t)hal_get_cycles();
    765828if( DEBUG_VFS_OPEN < cycle )
    766 printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / cxy %x / cycle %d\n",
    767 __FUNCTION__, process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle );
     829printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / file(%x,%x) / cycle %d\n",
     830__FUNCTION__, process->pid, this->trdid, path, file_id,
     831GET_CXY( file_xp ), GET_PTR( file_xp ), cycle );
    768832#endif
    769833
     
    880944    __FUNCTION__ , this->process->pid, nbytes );
    881945    else           
    882     printk("\n[%s] thread[%x,%x] exit / %d bytes moved from buffer to mapper / size %d\n",
    883     __FUNCTION__ , this->process->pid, nbytes, hal_remote_l32(XPTR(file_cxy,&inode->size)) );
     946    printk("\n[%s] thread[%x,%x] exit / %d bytes moved from buffer to mapper\n",
     947    __FUNCTION__ , this->process->pid, nbytes );
    884948}
    885949#endif
     
    10351099{
    10361100    cxy_t         file_cxy;         // cluster containing the file descriptor.
    1037     vfs_file_t  * file_ptr;         // local ponter on file descriptor
     1101    vfs_file_t  * file_ptr;         // local pointer on file descriptor
    10381102    cxy_t         owner_cxy;        // process owner cluster
    10391103    pid_t         pid;              // process identifier
     
    10761140
    10771141    // copy all dirty pages from mapper to device
    1078     if( file_cxy == local_cxy )
    1079     {
    1080         error = mapper_sync( mapper_ptr );
    1081     }
    1082     else
    1083     {
    1084         rpc_mapper_sync_client( file_cxy,
    1085                                 mapper_ptr,
    1086                                 &error );
    1087     }
     1142    error = mapper_sync( XPTR( file_cxy , mapper_ptr ) );
    10881143
    10891144    if( error )
     
    11281183 
    11291184        // update dentry size in parent directory mapper
    1130         if( parent_cxy == local_cxy )
    1131         {
    1132             error = vfs_fs_update_dentry( parent_inode_ptr,
    1133                                           parent_dentry_ptr,
    1134                                           size );
    1135         }
    1136         else
    1137         {
    1138             rpc_vfs_fs_update_dentry_client( parent_cxy,
    1139                                              parent_inode_ptr,
    1140                                              parent_dentry_ptr,
    1141                                              size,
    1142                                              &error );
    1143         }
     1185        error = vfs_fs_update_dentry( XPTR( parent_cxy , parent_inode_ptr ),
     1186                                      parent_dentry_ptr );
    11441187
    11451188        if( error )
     
    11591202
    11601203        // copy all dirty pages from parent mapper to device
    1161         if( parent_cxy == local_cxy )
    1162         {
    1163             error = mapper_sync( parent_mapper_ptr );
    1164         }
    1165         else
    1166         {
    1167             rpc_mapper_sync_client( parent_cxy,
    1168                                     parent_mapper_ptr,
    1169                                     &error );
    1170         }
     1204        error = mapper_sync( XPTR( parent_cxy , parent_mapper_ptr ) );
    11711205
    11721206        if( error )
     
    12221256    //////// 4) release memory allocated to file descriptor in remote cluster
    12231257
    1224     if( file_cxy == local_cxy )             // file cluster is local
    1225     {
    1226         vfs_file_destroy( file_ptr );
    1227     }
    1228     else                                    // file cluster is local
    1229     {
    1230         rpc_vfs_file_destroy_client( file_cxy , file_ptr );
    1231     }
     1258    vfs_file_destroy( file_xp );
    12321259
    12331260#if DEBUG_VFS_CLOSE
     
    13201347
    13211348    // 2. create one new dentry in parent cluster
    1322     if( parent_cxy == local_cxy ) 
    1323     {
    1324         error = vfs_dentry_create( parent_fs_type,
    1325                                    last_name,
    1326                                    &dentry_xp );
    1327     }
    1328     else
    1329     {
    1330         rpc_vfs_dentry_create_client( parent_cxy,
    1331                                       parent_fs_type,
    1332                                       last_name,
    1333                                       &dentry_xp,
    1334                                       &error );
    1335     }
    1336 
     1349    error = vfs_dentry_create( parent_cxy,
     1350                               parent_fs_type,
     1351                               last_name,
     1352                               &dentry_xp );
    13371353    if( error )
    13381354    {
     
    13611377    inode_cxy = cluster_random_select();
    13621378   
    1363     if( inode_cxy == local_cxy )      // target cluster is local
    1364     {
    1365         error = vfs_inode_create( parent_fs_type,
    1366                                   attr,
    1367                                   rights,
    1368                                   uid,
    1369                                   gid,
    1370                                   &inode_xp );
    1371     }
    1372     else                              // target cluster is remote
    1373     {
    1374         rpc_vfs_inode_create_client( inode_cxy,
    1375                                      parent_fs_type,
    1376                                      attr,
    1377                                      rights,
    1378                                      uid,
    1379                                      gid,
    1380                                      &inode_xp,
    1381                                      &error );
    1382     }
    1383                                      
     1379    // create inode
     1380    error = vfs_inode_create( inode_cxy,
     1381                              parent_fs_type,
     1382                              attr,
     1383                              rights,
     1384                              uid,
     1385                              gid,
     1386                              &inode_xp );
    13841387    if( error )
    13851388    {
    13861389        remote_rwlock_wr_release( lock_xp );
    13871390        printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
    1388                __FUNCTION__ , inode_cxy , path );
    1389         if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr );
    1390         else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr );
     1391         __FUNCTION__ , inode_cxy , path );
     1392        vfs_dentry_destroy( dentry_xp );
    13911393        return -1;
    13921394    }
     
    14341436        remote_rwlock_wr_release( lock_xp );
    14351437        printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
    1436                __FUNCTION__ , inode_cxy , path );
    1437         if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr );
    1438         else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr );
     1438        __FUNCTION__ , inode_cxy , path );
     1439        vfs_dentry_destroy( dentry_xp );
    14391440        return -1;
    14401441    }
     
    14451446    // 8. update parent directory mapper
    14461447    //    and synchronize the parent directory on IOC device
    1447     if (parent_cxy == local_cxy)
    1448     {
    1449         error = vfs_fs_add_dentry( parent_ptr,
    1450                                    dentry_ptr );
    1451     }
    1452     else
    1453     {
    1454         rpc_vfs_fs_add_dentry_client( parent_cxy,
    1455                                       parent_ptr,
    1456                                       dentry_ptr,
    1457                                       &error );
    1458     }
    1459 
     1448    error = vfs_fs_add_dentry( parent_xp,
     1449                               dentry_ptr );
    14601450    if( error )
    14611451    {
     
    15891579    {
    15901580        // 1. create one new dentry
    1591         if( new_parent_cxy == local_cxy ) 
    1592         {
    1593             error = vfs_dentry_create( inode_fs_type,
    1594                                        new_name,
    1595                                        &dentry_xp );
    1596         }
    1597         else
    1598         {
    1599             rpc_vfs_dentry_create_client( new_parent_cxy,
    1600                                           inode_fs_type,
    1601                                           new_name,
    1602                                           &dentry_xp,
    1603                                           &error );
    1604         }
    1605 
     1581        error = vfs_dentry_create( new_parent_cxy,
     1582                                   inode_fs_type,
     1583                                   new_name,
     1584                                   &dentry_xp );
    16061585        if( error )
    16071586        {
     
    16431622        //    and synchronize the parent directory on IOC device
    16441623        if (new_parent_cxy == local_cxy)
    1645         {
    1646             error = vfs_fs_add_dentry( new_parent_ptr,
    1647                                        dentry_ptr );
    1648         }
    1649         else
    1650         {
    1651             rpc_vfs_fs_add_dentry_client( new_parent_cxy,
    1652                                           new_parent_ptr,
    1653                                           dentry_ptr,
    1654                                           &error );
    1655         }
     1624        error = vfs_fs_add_dentry( new_parent_xp,
     1625                                   dentry_ptr );
    16561626        if( error )
    16571627        {
     
    17031673    vfs_fs_type_t     fs_type;            // File system type
    17041674
    1705     char              name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of link to remove
     1675    char              child_name[CONFIG_VFS_MAX_NAME_LENGTH];   // name of link to remove
     1676    char              parent_name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of parent directory
    17061677
    17071678    thread_t  * this    = CURRENT_THREAD;
     
    17311702                        VFS_LOOKUP_PARENT,
    17321703                        &parent_xp,
    1733                         name );
     1704                        child_name );
    17341705    if( error )
    17351706    {
    17361707        remote_rwlock_wr_release( lock_xp );
    17371708        printk("\n[ERROR] in %s : cannot get parent inode for <%s> in <%s>\n",
    1738         __FUNCTION__, name, path );
     1709        __FUNCTION__, child_name, path );
    17391710        return -1;
    17401711    }
    1741 
    1742     // get parent inode cluster and local pointer
     1712   
     1713    // get parent inode name, cluster and local pointer
     1714    vfs_inode_get_name( parent_xp , parent_name );
    17431715    parent_cxy = GET_CXY( parent_xp );
    17441716    parent_ptr = GET_PTR( parent_xp );
    17451717 
    17461718#if( DEBUG_VFS_UNLINK & 1 )
    1747 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1748 vfs_inode_get_name( parent_xp , parent_name );
    17491719if( DEBUG_VFS_UNLINK < cycle )
    17501720printk("\n[%s] thread[%x,%x] : parent inode <%s> is (%x,%x)\n",
     
    17561726
    17571727    // try to get extended pointer on dentry from Inode Tree
    1758     dentry_xp = xhtab_lookup( children_xp , name );
     1728    dentry_xp = xhtab_lookup( children_xp , child_name );
    17591729   
    1760     // when dentry not found in Inode Tree, try to get it from inode tree
     1730    // when dentry not found in Inode Tree, try to get it from mapper
    17611731
    17621732    if( dentry_xp == XPTR_NULL )           // miss target dentry in Inode Tree
     
    17651735#if( DEBUG_VFS_UNLINK & 1 )
    17661736if( DEBUG_VFS_UNLINK < cycle )
    1767 printk("\n[%s] thread[%x,%x] : inode <%s> not found => scan parent mapper\n",
    1768 __FUNCTION__, process->pid, this->trdid, name );
     1737printk("\n[%s] thread[%x,%x] : inode <%s> not found => scan parent mapper <%s>\n",
     1738__FUNCTION__, process->pid, this->trdid, child_name , parent_name );
    17691739#endif
    17701740        // get parent inode FS type
     
    17791749                                         fs_type,
    17801750                                         parent_xp,
    1781                                          name,
     1751                                         child_name,
    17821752                                         &dentry_xp,
    17831753                                         &inode_xp );
    17841754        if( error )
    17851755        {
    1786             printk("\n[ERROR] in %s : cannot create inode <%s> in path <%s>\n",
    1787             __FUNCTION__ , name, path );
    1788 
    1789             vfs_remove_child_from_parent( dentry_xp );
     1756            printk("\n[ERROR] in %s : cannot create inode <%s> in Inode Tree\n",
     1757            __FUNCTION__ , child_name );
    17901758            return -1;
    17911759        }
     
    17971765        // scan parent mapper to find the missing dentry, and complete
    17981766        // initialisation of new dentry and new inode descriptors In Inode Tree
    1799         if( parent_cxy == local_cxy )
     1767        error = vfs_fs_new_dentry_from_mapper( parent_xp,
     1768                                               dentry_ptr );
     1769        if ( error )
    18001770        {
    1801             error = vfs_fs_new_dentry( parent_ptr,
    1802                                        name,
    1803                                        inode_xp );
    1804         }
    1805         else
    1806         {
    1807             rpc_vfs_fs_new_dentry_client( parent_cxy,
    1808                                           parent_ptr,
    1809                                           name,
    1810                                           inode_xp,
    1811                                           &error );
    1812         }
    1813 
    1814         if ( error )   // dentry not found in parent mapper
    1815         {
    1816             printk("\n[ERROR] in %s : cannot get dentry <%s> in path <%s>\n",
    1817             __FUNCTION__ , name, path );
     1771            printk("\n[ERROR] in %s : cannot get entry <%s> in parent <%s> mapper\n",
     1772            __FUNCTION__ , child_name, parent_name );
    18181773            return -1;
    18191774        }
     
    18221777if( DEBUG_VFS_UNLINK < cycle )
    18231778printk("\n[%s] thread[%x,%x] : created missing inode & dentry <%s> in cluster %x\n",
    1824 __FUNCTION__, process->pid, this->trdid, name, inode_cxy );
     1779__FUNCTION__, process->pid, this->trdid, child_name, inode_cxy );
    18251780#endif
    18261781
     
    18561811if( DEBUG_VFS_UNLINK < cycle )
    18571812printk("\n[%s] thread[%x,%x] : unlink inode <%s> / type %s / %d links\n",
    1858 __FUNCTION__, process->pid, this->trdid, name, vfs_inode_type_str(inode_type), inode_links );
     1813__FUNCTION__, process->pid, this->trdid, child_name,
     1814vfs_inode_type_str(inode_type), inode_links );
    18591815#endif
    18601816
     
    18981854        // 2. update parent directory mapper
    18991855        //    and synchronize the parent directory on IOC device
    1900         if (parent_cxy == local_cxy)
    1901         {
    1902             error = vfs_fs_remove_dentry( parent_ptr,
    1903                                           dentry_ptr );
    1904         }
    1905         else           
    1906         {
    1907             rpc_vfs_fs_remove_dentry_client( parent_cxy,
    1908                                              parent_ptr,
    1909                                              dentry_ptr,
    1910                                              &error );
    1911         }
    1912 
     1856        error = vfs_fs_remove_dentry( parent_xp,
     1857                                      dentry_ptr );
    19131858        if( error )
    19141859        {
     
    21722117
    21732118//////////////////////////////////////////////////////////////////////////
    2174 // This static function is called by the vfs_display() function.
     2119// This recursive function is called by the vfs_display() function.
    21752120// that is supposed to take the TXT0 lock.
    21762121//////////////////////////////////////////////////////////////////////////
     
    21842129    uint32_t           inode_size;
    21852130    uint32_t           inode_attr;
    2186     uint32_t           inode_dirty;
    21872131    void             * inode_extd;
    21882132
     
    22342178
    22352179    // compute dirty
    2236     inode_dirty = ((inode_attr & INODE_ATTR_DIRTY) != 0);
     2180    // inode_dirty = ((inode_attr & INODE_ATTR_DIRTY) != 0); unused [AG] dec 2019
    22372181
    22382182    // display inode
    2239     nolock_printk("%s<%s> : %s / extd %x / %d bytes / dirty %d / cxy %x / inode %x / mapper %x\n",
     2183    nolock_printk("%s<%s> : %s / extd %x / %d bytes / cxy %x / inode %x / mapper %x\n",
    22402184    indent_str[indent], name, vfs_inode_type_str( inode_type ), (uint32_t)inode_extd,
    2241     inode_size, inode_dirty, inode_cxy, inode_ptr, mapper_ptr );
     2185    inode_size, inode_cxy, inode_ptr, mapper_ptr );
    22422186
    22432187    // scan directory entries when current inode is a directory
     
    23282272
    23292273    // print header
    2330     nolock_printk("\n***** file system state\n\n");
     2274    nolock_printk("\n***** current VFS state\n\n");
    23312275
    23322276    // call recursive function
     
    24842428    vfs_inode_t      * parent_ptr;   // local pointer on parent inode 
    24852429    xptr_t             dentry_xp;    // extended pointer on dentry       
     2430    vfs_dentry_t     * dentry_ptr;   // local pointer on dentry
    24862431    xptr_t             child_xp;     // extended pointer on child inode
    24872432    cxy_t              child_cxy;    // cluster for child inode
     
    25322477    last      = false;
    25332478    child_xp  = XPTR_NULL;
     2479    child_cxy = 0;
     2480    child_ptr = NULL;
    25342481
    25352482    // loop on nodes in pathname
     
    25702517                               &child_xp );
    25712518
    2572         // get child inode local pointer and cluster
    2573         child_ptr  = GET_PTR( child_xp );
    2574         child_cxy  = GET_CXY( child_xp );
    2575 
    2576         if( found == false )                              // not found in Inode Tree
     2519        if( found == false )                          // child not found in Inode Tree
    25772520        {
    25782521            // when a inode is not found in the Inode Tree:
     
    26062549#endif
    26072550                // get parent inode FS type
    2608                 ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
     2551                ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
    26092552                fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
    26102553
     
    26262569                }
    26272570
    2628                 // get child inode local pointer
    2629                 child_ptr = GET_PTR( child_xp );
     2571                // get child inode and dentry local pointers
     2572                child_ptr  = GET_PTR( child_xp );
     2573                dentry_ptr = GET_PTR( dentry_xp );
    26302574
    26312575#if (DEBUG_VFS_LOOKUP & 1)
     
    26362580                // scan parent mapper to find the missing dentry, and complete
    26372581                // the initialisation of dentry and child inode descriptors
    2638                 if( parent_cxy == local_cxy )
    2639                 {
    2640                     error = vfs_fs_new_dentry( parent_ptr,
    2641                                                name,
    2642                                                child_xp );
    2643                 }
    2644                 else
    2645                 {
    2646                     rpc_vfs_fs_new_dentry_client( parent_cxy,
    2647                                                   parent_ptr,
    2648                                                   name,
    2649                                                   child_xp,
    2650                                                   &error );
    2651                 }
    2652 
    2653                 // when the missing dentry is not in the parent mapper,
    2654                 // a new dentry must be registered in parent directory mapper
    2655                 if ( error )
     2582                error = vfs_fs_new_dentry_from_mapper( parent_xp,
     2583                                                       dentry_ptr );
     2584
     2585                if ( error )  // an error can be fatal or non-fatal :
    26562586                {
    26572587                    if ( last && create )  // add a brand new dentry in parent directory
    26582588                    {
    2659                         error = vfs_new_dentry_init( parent_xp,               
    2660                                                      dentry_xp,
    2661                                                      child_xp );
     2589                        error = vfs_fs_new_dentry_to_mapper( parent_xp,               
     2590                                                             dentry_ptr );
    26622591                        if ( error )
    26632592                        {
    2664                             printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
    2665                             __FUNCTION__, name, pathname );
     2593                            printk("\n[ERROR] in %s : cannot add dentry <%s> in parent dir\n",
     2594                            __FUNCTION__, name );
    26662595                            vfs_remove_child_from_parent( dentry_xp );
    26672596                            return -1;
     
    26742603vfs_inode_display( child_xp );
    26752604#endif
    2676 
    2677 
    26782605                    }
    26792606                    else                   // not last or not create => error
     
    27042631                    if( type == INODE_TYPE_DIR )
    27052632                    {
    2706                         if( child_cxy == local_cxy )
    2707                         {
    2708                             error = vfs_inode_load_all_pages( child_ptr );
    2709                         }
    2710                         else
    2711                         {
    2712                             rpc_vfs_inode_load_all_pages_client( child_cxy,
    2713                                                                  child_ptr,
    2714                                                                  &error );
    2715                         }
     2633                        error = vfs_inode_load_all_pages( child_xp );
     2634
    27162635                        if ( error )
    27172636                        {
     
    27312650            }
    27322651        }
    2733         else                                    // child directly found in inode tree
     2652        else                                    // child found in Inode Tree
    27342653        {
     2654            // get child inode local pointer and cluster
     2655            child_ptr  = GET_PTR( child_xp );
     2656            child_cxy  = GET_CXY( child_xp );
    27352657       
    27362658#if (DEBUG_VFS_LOOKUP & 1)
     
    27592681        // }
    27602682
    2761         // take lock on child inode and release lock on parent
    2762         // vfs_inode_lock( child_xp );
    2763         // vfs_inode_unlock( parent_xp );
    2764 
    27652683        // exit when last
    27662684        if ( last )           // last inode in path  => return relevant info
     
    27922710            }
    27932711        }
    2794         else                     // not the last inode in path => update loop variables
     2712        else                     // not the last node in path => update loop variables
    27952713        {
    27962714            parent_xp = child_xp;
    27972715            current   = next;
    27982716        }
    2799     }
     2717    }  // end while loop on nodes in pathname
     2718
     2719#if ( DEBUG_VFS_LOOKUP & 1 )
     2720if( DEBUG_VFS_LOOKUP < cycle )
     2721vfs_display( root_xp );
     2722#endif
    28002723
    28012724    return 0;
    28022725
    28032726}  // end vfs_lookup()
    2804 
    2805 ////////////////////////////////////////////////
    2806 error_t vfs_new_dentry_init( xptr_t   parent_xp,
    2807                              xptr_t   dentry_xp,
    2808                              xptr_t   child_xp )
    2809 {
    2810     error_t     error;
    2811     uint32_t    cluster_id;
    2812     uint32_t    child_type;
    2813     uint32_t    child_size;
    2814 
    2815 #if DEBUG_VFS_NEW_DENTRY_INIT
    2816 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    2817 char child_name[CONFIG_VFS_MAX_NAME_LENGTH];
    2818 vfs_inode_get_name( parent_xp , parent_name );
    2819 vfs_inode_get_name( child_xp  , child_name );
    2820 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2821 thread_t * this  = CURRENT_THREAD;
    2822 if( DEBUG_VFS_NEW_DENTRY_INIT < cycle )
    2823 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    2824 __FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
    2825 #endif
    2826 
    2827     // get parent inode cluster and local pointer
    2828     cxy_t          parent_cxy = GET_CXY( parent_xp );
    2829     vfs_inode_t  * parent_ptr = GET_PTR( parent_xp );
    2830 
    2831     // get dentry local pointer
    2832     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    2833 
    2834     // get child inode cluster and local pointer
    2835     cxy_t          child_cxy  = GET_CXY( child_xp );
    2836     vfs_inode_t  * child_ptr  = GET_PTR( child_xp );
    2837 
    2838     // 1. allocate one free cluster_id in file system to child inode,
    2839     // and update the File Allocation Table in both the FAT mapper and IOC device.
    2840     // It depends on the child inode FS type.
    2841     vfs_ctx_t * ctx = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) );
    2842 
    2843     error = vfs_fs_cluster_alloc( ctx->type,
    2844                                   &cluster_id );
    2845     if ( error )
    2846     {
    2847         printk("\n[ERROR] in %s : cannot find a free VFS cluster_id\n",
    2848         __FUNCTION__ );
    2849         return -1;
    2850     }
    2851 
    2852 #if( DEBUG_VFS_NEW_DENTRY_INIT & 1)
    2853 if( DEBUG_VFS_NEW_DENTRY_INIT < cycle )
    2854 printk("\n[%s] thread[%x,%x] allocated FS cluster_id %x to <%s>\n",
    2855 __FUNCTION__ , this->process->pid, this->trdid, cluster_id, child_name );
    2856 #endif
    2857 
    2858     // 2. update the child inode descriptor size and extend
    2859     child_type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
    2860     child_size = 0;
    2861    
    2862     hal_remote_s32( XPTR( child_cxy , &child_ptr->size )   , child_size );
    2863     hal_remote_spt( XPTR( child_cxy , &child_ptr->extend ) , (void*)(intptr_t)cluster_id );
    2864 
    2865     // 3. update the parent inode mapper, and
    2866     // update the dentry extension if required
    2867     if( local_cxy == parent_cxy )
    2868     {
    2869         error = vfs_fs_add_dentry( parent_ptr,
    2870                                    dentry_ptr );
    2871     }
    2872     else
    2873     {
    2874         rpc_vfs_fs_add_dentry_client( parent_cxy,
    2875                                       parent_ptr,
    2876                                       dentry_ptr,
    2877                                       &error );
    2878     }
    2879     if ( error )
    2880     {
    2881         printk("\n[ERROR] in %s : cannot register child in parent directory\n",
    2882         __FUNCTION__ );
    2883         return -1;
    2884     }
    2885 
    2886 #if DEBUG_VFS_NEW_DENTRY_INIT
    2887 cycle = (uint32_t)hal_get_cycles();
    2888 if( DEBUG_VFS_NEW_DENTRY_INIT < cycle )
    2889 printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n",
    2890 __FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
    2891 #endif
    2892 
    2893     return 0;
    2894 
    2895 }  // end vfs_new_dentry_init()
    28962727
    28972728///////////////////////////////////////////////////
     
    29062737    xptr_t          dentry_xp;         // extended pointer on dentry (used for . and ..)
    29072738    vfs_dentry_t  * dentry_ptr;        // local pointer on dentry (used for . and ..)
    2908 
    2909     // xptr_t          parents_root_xp;   // extended pointer on inode "parents" field
    2910     // xptr_t          parents_entry_xp;  // extended pointer on dentry "parents" field
    29112739    xptr_t          children_xhtab_xp; // extended pointer on inode "children" field
    29122740    xptr_t          children_entry_xp; // extended pointer on dentry "children" field
     
    29242752#endif
    29252753
    2926     // get new directory cluster and local pointer
     2754    // get child directory cluster and local pointer
    29272755    child_cxy  = GET_CXY( child_xp );
    29282756    child_ptr  = GET_PTR( child_xp );
     
    29332761
    29342762    //////////////////////////// create <.> dentry //////////////////////
    2935     if( child_cxy == local_cxy )     
    2936     {
    2937         error = vfs_dentry_create( fs_type,
    2938                                    ".",
    2939                                    &dentry_xp );
    2940     }
    2941     else
    2942     {
    2943         rpc_vfs_dentry_create_client( child_cxy,
    2944                                       fs_type,
    2945                                       ".",
    2946                                       &dentry_xp,
    2947                                       &error );
    2948     }
     2763    error = vfs_dentry_create( child_cxy,
     2764                               fs_type,
     2765                               ".",
     2766                               &dentry_xp );
    29492767    if( error )
    29502768    {
     
    29672785    children_xhtab_xp = XPTR( child_cxy , &child_ptr->children );
    29682786    children_entry_xp = XPTR( child_cxy , &dentry_ptr->children );
     2787
    29692788    error = xhtab_insert( children_xhtab_xp , "." , children_entry_xp );
     2789
    29702790    if( error )
    29712791    {
     
    29742794        return -1;
    29752795    }
    2976 
    29772796   
    2978     // don't register <.> dentry in child_inode xlist of parents
    2979     // parents_root_xp  = XPTR( child_cxy , &child_ptr->parents );
    2980     // parents_entry_xp = XPTR( child_cxy , &dentry_ptr->parents );
    2981     // xlist_add_first( parents_root_xp , parents_entry_xp );
    2982     // hal_remote_atomic_add( XPTR( child_cxy , &child_ptr->links ) , 1 );
    2983 
    29842797    // update "parent" and "child_xp" fields in <.> dentry
    29852798    hal_remote_s64( XPTR( child_cxy , &dentry_ptr->child_xp ) , child_xp );
     
    29972810    if( child_xp != parent_xp )
    29982811    {
    2999         if( child_cxy == local_cxy )
    3000         {
    3001             error = vfs_fs_add_dentry( child_ptr,
    3002                                        dentry_ptr );
    3003         }
    3004         else
    3005         {
    3006             rpc_vfs_fs_add_dentry_client( child_cxy,
    3007                                           child_ptr,
    3008                                           dentry_ptr,
    3009                                           &error );
    3010         }
     2812        error = vfs_fs_add_dentry( child_xp,
     2813                                   dentry_ptr );
    30112814        if( error )
    30122815        {
     
    30262829
    30272830    ///////////////////////////// create <..> dentry ///////////////////////
    3028     if( child_cxy == local_cxy )     
    3029     {
    3030         error = vfs_dentry_create( fs_type,
    3031                                    "..",
    3032                                    &dentry_xp );
    3033     }
    3034     else
    3035     {
    3036         rpc_vfs_dentry_create_client( child_cxy,
    3037                                       fs_type,
    3038                                       "..",
    3039                                       &dentry_xp,
    3040                                       &error );
    3041     }
     2831    error = vfs_dentry_create( child_cxy,
     2832                               fs_type,
     2833                               "..",
     2834                               &dentry_xp );
    30422835    if( error )
    30432836    {
     
    30852878    if( child_xp != parent_xp )
    30862879    {
    3087         if( child_cxy == local_cxy )
    3088         {
    3089             error = vfs_fs_add_dentry( child_ptr,
    3090                                        dentry_ptr );
    3091         }
    3092         else
    3093         {
    3094             rpc_vfs_fs_add_dentry_client( child_cxy,
    3095                                           child_ptr,
    3096                                           dentry_ptr,
    3097                                           &error );
    3098         }
     2880        error = vfs_fs_add_dentry( child_xp,
     2881                                   dentry_ptr );
    30992882        if( error )
    31002883        {
     
    32593042
    32603043     
    3261 ////////////////////////////////////////////////////////////////////
     3044//////////////////////////////////////////////////////////////
    32623045error_t vfs_add_child_in_parent( cxy_t              child_cxy,
    32633046                                 vfs_fs_type_t      fs_type,
     
    32963079
    32973080    // 1. create dentry in parent cluster
    3298     if( parent_cxy == local_cxy )           // parent cluster is local
    3299     {
    3300         error = vfs_dentry_create( fs_type,
    3301                                    name,
    3302                                    &new_dentry_xp );
    3303     }
    3304     else                                    // parent cluster is remote
    3305     {
    3306         rpc_vfs_dentry_create_client( parent_cxy,
    3307                                       fs_type,
    3308                                       name,
    3309                                       &new_dentry_xp,
    3310                                       &error );
    3311     }
    3312                                      
     3081    error = vfs_dentry_create( parent_cxy,
     3082                               fs_type,
     3083                               name,
     3084                               &new_dentry_xp );
    33133085    if( error )
    33143086    {
     
    33343106    uint32_t gid  = 0;
    33353107   
    3336     if( child_cxy == local_cxy )      // child cluster is local
    3337     {
    3338         error = vfs_inode_create( fs_type,
    3339                                   attr,
    3340                                   mode,
    3341                                   uid,
    3342                                   gid,
    3343                                   &new_inode_xp );
    3344     }
    3345     else                              // child cluster is remote
    3346     {
    3347         rpc_vfs_inode_create_client( child_cxy,
    3348                                      fs_type,
    3349                                      attr,
    3350                                      mode,
    3351                                      uid,
    3352                                      gid,
    3353                                      &new_inode_xp,
    3354                                      &error );
    3355     }
    3356                                      
     3108    error = vfs_inode_create( child_cxy,
     3109                              fs_type,
     3110                              attr,
     3111                              mode,
     3112                              uid,
     3113                              gid,
     3114                              &new_inode_xp );
    33573115    if( error )
    33583116    {
     
    33603118               __FUNCTION__ , child_cxy );
    33613119 
    3362         if( parent_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
    3363         else rpc_vfs_dentry_destroy_client( parent_cxy , new_dentry_ptr );
     3120        vfs_dentry_destroy( new_dentry_xp );
    33643121        return -1;
    33653122    }
     
    33743131#endif
    33753132
    3376 
    33773133    // 3. register new_dentry in new_inode xlist of parents
    33783134    parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents );
     
    34573213
    34583214    // delete dentry descriptor
    3459     if( parent_cxy == local_cxy )
    3460     {
    3461          vfs_dentry_destroy( dentry_ptr );
    3462     }
    3463     else
    3464     {
    3465          rpc_vfs_dentry_destroy_client( parent_cxy,
    3466                                         dentry_ptr );
    3467     }
     3215    vfs_dentry_destroy( dentry_xp );
    34683216
    34693217    // delete child_inode descriptor if last link
    3470     if( links == 1 )
    3471     {
    3472         if( child_cxy == local_cxy )
    3473         {
    3474             vfs_inode_destroy( child_inode_ptr );
    3475         }
    3476         else
    3477         {
    3478             rpc_vfs_inode_destroy_client( child_cxy , child_inode_ptr );
    3479         }
    3480     }
     3218    if( links == 1 )  vfs_inode_destroy( child_inode_xp );
    34813219
    34823220}  // end vfs_remove_child_from_parent()
     
    34893227//////////////////////////////////////////////////////////////////////////////////////////
    34903228
    3491 //////////////////////////////////////////////
    3492 error_t vfs_fs_move_page( xptr_t      page_xp,
    3493                           cmd_type_t  cmd_type )
     3229///////////////////////////////////////////////////
     3230error_t vfs_fs_add_dentry( xptr_t         inode_xp,
     3231                           vfs_dentry_t * dentry_ptr )
    34943232{
    34953233    error_t error = 0;
    34963234
    3497 assert( (page_xp != XPTR_NULL) , "page pointer is NULL" );
    3498 
    3499     page_t * page_ptr = GET_PTR( page_xp );
    3500     cxy_t    page_cxy = GET_CXY( page_xp );
    3501 
    3502     // get local pointer on page mapper
    3503     mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
    3504 
    3505 assert( (mapper != NULL) , "no mapper for page" );
     3235assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
     3236assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
     3237
     3238    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     3239    cxy_t         inode_cxy = GET_CXY( inode_xp );
     3240
     3241    // get inode mapper
     3242    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     3243
     3244assert( (mapper != NULL) , "mapper pointer is NULL")       
    35063245
    35073246    // get FS type
    3508     vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->type ) );
     3247    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    35093248
    35103249    // call relevant FS function
    35113250    if( fs_type == FS_TYPE_FATFS )
    35123251    {
    3513         error = fatfs_move_page( page_xp , cmd_type );
     3252        error = fatfs_add_dentry( inode_xp , dentry_ptr );
    35143253    }
    35153254    else if( fs_type == FS_TYPE_RAMFS )
    35163255    {
    3517         assert( false , "should not be called for RAMFS\n" );
     3256        error = 0;     // does nothing for RAMFS
    35183257    }
    35193258    else if( fs_type == FS_TYPE_DEVFS )
    35203259    {
    3521         assert( false , "should not be called for DEVFS\n" );
     3260        error = 0;     // does nothing for DEVFS
    35223261    }
    35233262    else
     
    35283267    return error;
    35293268
    3530 }  // end vfs_fs_move_page()
    3531 
    3532 ////////////////////////////////////////////////
    3533 error_t vfs_fs_add_dentry( vfs_inode_t  * inode,
    3534                            vfs_dentry_t * dentry )
     3269}  // end vfs_fs_add_dentry()
     3270
     3271//////////////////////////////////////////////////////
     3272error_t vfs_fs_remove_dentry( xptr_t         inode_xp,
     3273                              vfs_dentry_t * dentry_ptr )
    35353274{
    35363275    error_t error = 0;
    35373276
    3538 assert( (inode  != NULL) , "inode  pointer is NULL" );
    3539 assert( (dentry != NULL) , "dentry pointer is NULL" );
    3540 
    3541     mapper_t * mapper = inode->mapper;
    3542 
    3543 assert( (mapper != NULL) , "mapper pointer is NULL" );
     3277assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
     3278assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
     3279
     3280    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     3281    cxy_t         inode_cxy = GET_CXY( inode_xp );
     3282
     3283    // get inode mapper
     3284    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     3285
     3286assert( (mapper != NULL) , "mapper pointer is NULL")       
    35443287
    35453288    // get FS type
    3546     vfs_fs_type_t fs_type = mapper->type;
     3289    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    35473290
    35483291    // call relevant FS function
    35493292    if( fs_type == FS_TYPE_FATFS )
    35503293    {
    3551         error = fatfs_add_dentry( inode , dentry );
     3294        error = fatfs_remove_dentry( inode_xp , dentry_ptr );
     3295
    35523296    }
    35533297    else if( fs_type == FS_TYPE_RAMFS )
     
    35663310    return error;
    35673311
    3568 }  // end vfs_fs_add_dentry()
    3569 
    3570 ///////////////////////////////////////////////////
    3571 error_t vfs_fs_remove_dentry( vfs_inode_t  * inode,
    3572                               vfs_dentry_t * dentry )
     3312}  // end vfs_fs_remove_dentry()
     3313
     3314///////////////////////////////////////////////////////////////
     3315error_t vfs_fs_new_dentry_from_mapper( xptr_t         inode_xp,
     3316                                       vfs_dentry_t * dentry_ptr )
    35733317{
    35743318    error_t error = 0;
    35753319
    3576 assert( (inode  != NULL) , "inode  pointer is NULL" );
    3577 assert( (dentry != NULL) , "dentry pointer is NULL" );
    3578 
    3579     mapper_t * mapper = inode->mapper;
    3580 
    3581 assert( (mapper != NULL) , "mapper pointer is NULL" );
     3320assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
     3321assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
     3322
     3323    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     3324    cxy_t         inode_cxy = GET_CXY( inode_xp );
     3325
     3326    // get inode mapper
     3327    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     3328
     3329assert( (mapper != NULL) , "mapper pointer is NULL")       
    35823330
    35833331    // get FS type
    3584     vfs_fs_type_t fs_type = mapper->type;
     3332    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    35853333
    35863334    // call relevant FS function
    35873335    if( fs_type == FS_TYPE_FATFS )
    35883336    {
    3589         error = fatfs_remove_dentry( inode , dentry );
     3337        error = fatfs_new_dentry_from_mapper( inode_xp , dentry_ptr );
    35903338    }
    35913339    else if( fs_type == FS_TYPE_RAMFS )
    35923340    {
    3593         error = 0;     // does nothing for RAMFS
     3341        assert( false , "should not be called for RAMFS" );
    35943342    }
    35953343    else if( fs_type == FS_TYPE_DEVFS )
    35963344    {
    3597         error = 0;     // does nothing for DEVFS
     3345        assert( false , "should not be called for DEVFS" );
    35983346    }
    35993347    else
     
    36043352    return error;
    36053353
    3606 }  // end vfs_fs_remove_dentry()
    3607 
    3608 ////////////////////////////////////////////////
    3609 error_t vfs_fs_new_dentry( vfs_inode_t * parent,
    3610                            char        * name,
    3611                            xptr_t        child_xp )
     3354} // end vfs_fs_new_dentry_from_mapper()
     3355
     3356///////////////////////////////////////////////////////////////
     3357error_t vfs_fs_new_dentry_to_mapper( xptr_t         inode_xp,
     3358                                     vfs_dentry_t * dentry_ptr )
    36123359{
    36133360    error_t error = 0;
    36143361
    3615 // check arguments
    3616 assert( (parent != NULL) , "parent pointer is NULL");
    3617 assert( (child_xp != XPTR_NULL) , "child pointer is NULL");
    3618 
    3619     // get parent inode FS type
    3620     vfs_fs_type_t fs_type = parent->ctx->type;
     3362assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
     3363assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
     3364
     3365    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     3366    cxy_t         inode_cxy = GET_CXY( inode_xp );
     3367
     3368    // get inode mapper
     3369    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     3370
     3371assert( (mapper != NULL) , "mapper pointer is NULL")       
     3372
     3373    // get FS type
     3374    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    36213375
    36223376    // call relevant FS function
    36233377    if( fs_type == FS_TYPE_FATFS )
    36243378    {
    3625         error = fatfs_new_dentry( parent , name , child_xp );
     3379        error = fatfs_new_dentry_to_mapper( inode_xp , dentry_ptr );
    36263380    }
    36273381    else if( fs_type == FS_TYPE_RAMFS )
     
    36403394    return error;
    36413395
    3642 } // end vfs_fs_new_dentry()
    3643 
    3644 ///////////////////////////////////////////////////
    3645 error_t vfs_fs_update_dentry( vfs_inode_t  * inode,
    3646                               vfs_dentry_t * dentry,
    3647                               uint32_t       size )
     3396} // end vfs_fs_new_dentry_to_mapper()
     3397
     3398//////////////////////////////////////////////////////
     3399error_t vfs_fs_update_dentry( xptr_t         inode_xp,
     3400                              vfs_dentry_t * dentry_ptr )
    36483401{
    36493402    error_t error = 0;
    36503403
    3651 // check arguments
    3652 assert( (inode  != NULL) , "inode  pointer is NULL");
    3653 assert( (dentry != NULL) , "dentry pointer is NULL");
    3654 
    3655     // get parent inode FS type
    3656     vfs_fs_type_t fs_type = inode->ctx->type;
     3404assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
     3405assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
     3406
     3407    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     3408    cxy_t         inode_cxy = GET_CXY( inode_xp );
     3409
     3410    // get inode mapper
     3411    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     3412
     3413assert( (mapper != NULL) , "mapper pointer is NULL")       
     3414
     3415    // get FS type
     3416    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    36573417
    36583418    // call relevant FS function
    36593419    if( fs_type == FS_TYPE_FATFS )
    36603420    {
    3661         error = fatfs_update_dentry( inode , dentry , size );
     3421        error = fatfs_update_dentry( inode_xp , dentry_ptr );
    36623422    }
    36633423    else if( fs_type == FS_TYPE_RAMFS )
     
    37393499}  // end vfs_fs_get_user_dir()
    37403500 
    3741 ////////////////////////////////////////////////
    3742 error_t vfs_fs_sync_inode( vfs_inode_t * inode )
     3501/////////////////////////////////////////////
     3502error_t vfs_fs_sync_inode( xptr_t  inode_xp )
    37433503{
    37443504    error_t error = 0;
    37453505
    3746 // check arguments
    3747 assert( (inode != NULL) , "inode pointer is NULL");
    3748 
    3749     // get inode FS type
    3750     vfs_fs_type_t fs_type = inode->ctx->type;
     3506assert( (inode_xp != XPTR_NULL) , "inode_xp argument is NULL");
     3507
     3508    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     3509    cxy_t         inode_cxy = GET_CXY( inode_xp );
     3510
     3511    // get inode mapper
     3512    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     3513
     3514assert( (mapper != NULL) , "mapper pointer is NULL")       
     3515
     3516    // get FS type
     3517    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    37513518
    37523519    // call relevant FS function
    37533520    if( fs_type == FS_TYPE_FATFS )
    37543521    {
    3755         error = fatfs_sync_inode( inode );
     3522        error = fatfs_sync_inode( inode_xp );
    37563523    }
    37573524    else if( fs_type == FS_TYPE_RAMFS )
     
    37993566}  // end vfs_fs_sync_fat()
    38003567
    3801 //////////////////////////////////////////////////////
    3802 error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type )
    3803 {
    3804     error_t error = 0;
    3805 
    3806     // call relevant FS function
    3807     if( fs_type == FS_TYPE_FATFS )
    3808     {
    3809         error = fatfs_sync_free_info();
    3810     }
    3811     else if( fs_type == FS_TYPE_RAMFS )
    3812     {
    3813         assert( false , "should not be called for RAMFS" );
    3814     }
    3815     else if( fs_type == FS_TYPE_DEVFS )
    3816     {
    3817         assert( false , "should not be called for DEVFS" );
    3818     }
    3819     else
    3820     {
    3821         assert( false , "undefined file system type" );
    3822     }
    3823 
    3824     return error;
    3825 
    3826 }  // end vfs_fs_sync_fat()
    3827 
    3828 /////////////////////////////////////////////////
    3829 error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
    3830                               uint32_t * cluster )
    3831 {
    3832     error_t error = 0;
    3833 
    3834     // call relevant FS function
    3835     if( fs_type == FS_TYPE_FATFS )
    3836     {
    3837         error = fatfs_cluster_alloc( cluster );
    3838     }
    3839     else if( fs_type == FS_TYPE_RAMFS )
    3840     {
    3841         assert( false , "should not be called for RAMFS" );
    3842     }
    3843     else if( fs_type == FS_TYPE_DEVFS )
    3844     {
    3845         assert( false , "should not be called for DEVFS" );
    3846     }
    3847     else
    3848     {
    3849         assert( false , "undefined file system type" );
    3850     }
    3851 
    3852     return error;
    3853 
    3854 } // end vfs_fs_cluster_alloc()
    3855 
    38563568////////////////////////////////////////////////
    38573569error_t vfs_fs_release_inode( xptr_t  inode_xp )
     
    38593571    error_t error = 0;
    38603572
    3861 assert( (inode_xp  != XPTR_NULL) , "inode pointer is NULL")       
     3573assert( (inode_xp  != XPTR_NULL) , "inode_xp argument is NULL")       
    38623574
    38633575    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    38643576    cxy_t         inode_cxy = GET_CXY( inode_xp );
    38653577
    3866     // get local pointer on page mapper
     3578    // get local pointer on mapper
    38673579    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
    38683580
     
    38703582
    38713583    // get FS type from mapper
    3872     vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->type ) );
     3584    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
    38733585
    38743586    // call relevant FS function
     
    38943606}  // end vfs_fs_release_inode()
    38953607
    3896 
     3608//////////////////////////////////////////////////
     3609error_t vfs_fs_move_page( xptr_t          page_xp,
     3610                          ioc_cmd_type_t  cmd_type )
     3611{
     3612    error_t error = 0;
     3613
     3614assert( (page_xp != XPTR_NULL) , "page pointer is NULL" );
     3615
     3616    page_t * page_ptr = GET_PTR( page_xp );
     3617    cxy_t    page_cxy = GET_CXY( page_xp );
     3618
     3619    // get local pointer on  mapper
     3620    mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
     3621
     3622assert( (mapper != NULL) , "no mapper for page" );
     3623
     3624    // get FS type
     3625    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->fs_type ) );
     3626
     3627    // call relevant FS function
     3628    if( fs_type == FS_TYPE_FATFS )
     3629    {
     3630        error = fatfs_move_page( page_xp , cmd_type );
     3631    }
     3632    else if( fs_type == FS_TYPE_RAMFS )
     3633    {
     3634        assert( false , "should not be called for RAMFS\n" );
     3635    }
     3636    else if( fs_type == FS_TYPE_DEVFS )
     3637    {
     3638        assert( false , "should not be called for DEVFS\n" );
     3639    }
     3640    else
     3641    {
     3642        assert( false , "undefined file system type" );
     3643    }
     3644
     3645    return error;
     3646
     3647}  // end vfs_fs_move_page()
     3648
     3649
  • trunk/kernel/fs/vfs.h

    r656 r657  
    33 *
    44 * Author  Mohamed Lamine Karaoui (2014,2015)
    5  *         Alain Greiner (2016,2017,2018)
     5 *         Alain Greiner (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    5555struct vseg_s;
    5656struct page_s;
     57struct ksock_s;
    5758
    5859/******************************************************************************************
     
    7273 * The <extend> field is a pointer on the FS specific context extension.
    7374 * This extension is dynamically allocated by kernel_init in all clusters.
    74  * In each cluster, both this VFS context and the FS specific context are handled as
    75  * private by the local OS intance.
     75 * In each cluster, the inum allocator can be accessed by any thread runing
     76 * in any cluster, and is therefore protected by a remote_busylock.
    7677 *****************************************************************************************/
    7778
    7879typedef enum
    7980{
    80         FS_TYPE_DEVFS = 0,
    81         FS_TYPE_FATFS = 1,
    82         FS_TYPE_RAMFS = 2,
     81        FS_TYPE_RAMFS = 0,
     82        FS_TYPE_DEVFS = 1,
     83        FS_TYPE_FATFS = 2,
    8384 
    8485        FS_TYPES_NR   = 3,
     
    9596typedef struct vfs_ctx_s
    9697{
    97         vfs_fs_type_t  type;                     /*! File System type                        */
    98         uint32_t           attr;                     /*! global attributes for all files in FS   */
    99         uint32_t       total_clusters;           /*! total number of clusters on device      */
    100         uint32_t       cluster_size;             /*! cluster size on device (bytes)          */
    101         xptr_t         vfs_root_xp;              /*! extended pointer on VFS root inode      */
    102     busylock_t     lock;                     /*! lock protecting inum allocator          */
    103     uint32_t       bitmap[BITMAP_SIZE(CONFIG_VFS_MAX_INODES)];  /* inum allocator        */
    104     void         * extend;                   /*! FS specific context extension           */
     98        vfs_fs_type_t      type;                 /*! File System type                        */
     99        uint32_t           total_clusters;       /*! total number of clusters on device      */
     100        uint32_t           cluster_size;         /*! cluster size on device (bytes)          */
     101        xptr_t             vfs_root_xp;          /*! extended pointer on VFS root inode      */
     102    remote_busylock_t  lock;                 /*! lock protecting inum allocator          */
     103    uint32_t           bitmap[BITMAP_SIZE(CONFIG_VFS_MAX_INODES)];  /* inum allocator    */
     104    void               * extend;             /*! FS specific context extension           */
    105105}
    106106vfs_ctx_t;
     
    109109 * This structure define a VFS inode.
    110110 * An inode can have several children dentries (if it is a directory), an can have several
    111  * parents dentries (if it hass several aliases links):
     111 * parents dentries (if it has several aliases links):
    112112 * - The "parents" field is the root of the xlist of parents dentries, and the "links"
    113113 *   fiels define the number of aliases parent dentries. only a FILE inode can have
     
    145145typedef enum
    146146{
    147     INODE_ATTR_DIRTY   =     0x01,       /* modified versus the value on device          */
    148     INODE_ATTR_INLOAD  =     0x04,       /* loading from device in progress              */
    149     INODE_ATTR_NEW     =     0x08,       /* not saved on device yet                      */
     147    INODE_ATTR_DIRTY   =     0x01,       /*! modified versus the value on device         */
     148    INODE_ATTR_INLOAD  =     0x04,       /*! loading from device in progress             */
     149    INODE_ATTR_NEW     =     0x08,       /*! not saved on device yet                     */
    150150}
    151151vfs_inode_attr_t;
     
    193193
    194194/******************************************************************************************
    195  Rpt* This structure defines a directory entry.
     195 * This structure defines a directory entry.
    196196 * A dentry contains the name of a remote file/dir, an extended pointer on the
    197197 * inode representing this file/dir, a local pointer on the inode representing
     
    225225typedef enum
    226226{
    227     FD_ATTR_READ_ENABLE    = 0x01,     /*! read access possible                         */
    228     FD_ATTR_WRITE_ENABLE   = 0x02,     /*! write access possible                        */
    229     FD_ATTR_APPEND         = 0x04,     /*! append on each write                         */
    230     FD_ATTR_CLOSE_EXEC     = 0x08,     /*! close file on exec                           */
    231     FD_ATTR_SYNC           = 0x10,     /*! synchronise FS on each write                 */
    232     FD_ATTR_IS_DIR         = 0x20,     /*! this is a directory                          */
     227    FD_ATTR_READ_ENABLE    = 0x01,     /*! read access possible                          */
     228    FD_ATTR_WRITE_ENABLE   = 0x02,     /*! write access possible                         */
     229    FD_ATTR_APPEND         = 0x04,     /*! append on each write                          */
     230    FD_ATTR_CLOSE_EXEC     = 0x08,     /*! close file on exec                            */
     231    FD_ATTR_SYNC           = 0x10,     /*! synchronise FS on each write                  */
     232    FD_ATTR_IS_DIR         = 0x20,     /*! this is a directory                           */
    233233}
    234234vfs_file_attr_t;
     
    237237{
    238238        struct vfs_ctx_s      * ctx;        /*! local pointer on FS context.                 */
    239         uint32_t                gc;         /*! generation counter                           */
    240239        vfs_file_attr_t         attr;       /*! file attributes bit vector (see above)       */
    241240        vfs_inode_type_t        type;       /*! same type as inode                           */
     
    245244        struct mapper_s       * mapper;     /*! associated file cache                        */
    246245        struct vfs_inode_s    * inode;      /*! local pointer on associated inode            */
     246    struct socket_s       * socket;     /*! local pointer on associated socket           */
    247247        void                  * extend;     /*! FS specific extension                        */
    248248}
     
    255255
    256256/******************************************************************************************
    257  * This function initialise a (statically allocated) VFS context in local cluster.
    258  ******************************************************************************************
     257 * This function initialises a (statically allocated) VFS context in cluster identified
     258 * by the <cxy> argument.
     259 * It is called by the kernel_init() function.
     260 ******************************************************************************************
     261 * @ cxy            : target cluster identifier.
    259262 * @ fs_type        : file system type.
    260  * @ attr           : global attributes (for all files in FS.
    261263 * @ total_clusters : total number of clusters on device.
    262264 * @ cluster_size   : cluster size on device (bytes).
     
    264266 * @ extend         : fs_type_specific extension.
    265267 *****************************************************************************************/
    266 void vfs_ctx_init( vfs_fs_type_t   type,
    267                    uint32_t        attr,
     268void vfs_ctx_init( cxy_t           cxy,
     269                   vfs_fs_type_t   type,
    268270                       uint32_t        total_clusters,
    269271                       uint32_t        cluster_size,
     
    277279 * - the 16 LSB bits contains the local inode identifier  : lid
    278280 ******************************************************************************************
    279  * @ ctx      : local pointer on file system context.
    280  * @ inum     : [ou] buffer for allocated inode identifier.
     281 * @ ctx_xp   : [in]  extended pointer on file system context.
     282 * @ inum     : [out] buffer for allocated inode identifier.
    281283 * @ return 0 if success / return non-zero if error.
    282284 *****************************************************************************************/
    283 error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx,
    284                             uint32_t  * inum );
     285error_t vfs_ctx_inum_alloc( xptr_t     ctx_xp,
     286                            uint32_t * inum );
    285287
    286288/******************************************************************************************
    287289 * This function release an inode identifier.                                 
    288290 ******************************************************************************************
    289  * @ ctx      : local pointer on file system context.
    290  * @ inum     : released inode identifier.
    291  *****************************************************************************************/
    292 void vfs_ctx_inum_release( vfs_ctx_t * ctx,
     291 * @ ctx_xp   : [in] extended pointer on file system context.
     292 * @ inum     : [in] released inode identifier.
     293 *****************************************************************************************/
     294void vfs_ctx_inum_release( xptr_t      ctx_xp,
    293295                           uint32_t    inum );
    294296
     
    305307
    306308/******************************************************************************************
    307  * This function allocates memory from local cluster for an inode descriptor and the
    308  * associated mapper, and partially initialise this inode from arguments values.
     309 * This function allocates memory in cluster identified by the <cxy> argument
     310 * for an inode descriptor and for the associated mapper, and partially initialise
     311 * this inode from arguments values.
    309312 * It does NOT link it to the Inode Tree, as this is done by add_child_in_parent().
    310  * It must called by a local thread. Use the RPC_INODE_CREATE if client thread is remote.
    311  ******************************************************************************************
    312  * @ fs_type    : file system type.
    313  * @ inode_type : inode type.
    314  * @ attr       : inode attributes.
    315  * @ rights     : inode access rights.
    316  * @ uid        : user owner ID.
    317  * @ gid        : group owner ID.
     313 * It can be called by any thread running in any cluster.
     314 ******************************************************************************************
     315 * @ cxy        : [in]  target cluster identifier
     316 * @ fs_type    : [in]  file system type.
     317 * @ attr       : [in]  inode attributes.
     318 * @ rights     : [in]  inode access rights.
     319 * @ uid        : [in]  user owner ID.
     320 * @ gid        : [in]  group owner ID.
    318321 * @ inode_xp   : [out] buffer for extended pointer on created inode.
    319  * @ return 0 if success / return ENOMEM or EINVAL if error.
    320  *****************************************************************************************/
    321 error_t vfs_inode_create( vfs_fs_type_t     fs_type,
     322 * @ return 0 if success / return -1 if error.
     323 *****************************************************************************************/
     324error_t vfs_inode_create( cxy_t             cxy,
     325                          vfs_fs_type_t     fs_type,
    322326                          uint32_t          attr,
    323327                          uint32_t          rights,
     
    330334 * all memory allocated to the mapper (both mapper descriptor and radix tree).
    331335 * The mapper should not contain any dirty page (should be synchronized before deletion).
    332  * It must be executed by a thread running in the cluster containing the inode.
    333  * Use the rpc_vfs_inode_destroy_client() function if required.
     336 * It can be called by any thread running in any cluster.
    334337 ******************************************************************************************
    335  * @ inode  : local pointer on inode descriptor.
    336  *****************************************************************************************/
    337 void vfs_inode_destroy( vfs_inode_t *  inode ); 
     338 * @ inode_xp  : extended pointer on inode descriptor.
     339 *****************************************************************************************/
     340void vfs_inode_destroy( xptr_t  inode_xp ); 
    338341
    339342/******************************************************************************************
    340343 * This function returns the <size> of a file/dir from a remote inode,
    341344 * taking the remote_rwlock protecting <size> in READ_MODE.
     345 * It can be called by any thread running in any cluster.
    342346 *****************************************************************************************
    343347 * @ inode_xp  : extended pointer on the remote inode.
     
    350354 * It takes the rwlock protecting the file size in WRITE_MODE, and set the "size" field
    351355 * when the current size is smaller than the requested <size> argument.
     356 * It can be called by any thread running in any cluster.
    352357 *****************************************************************************************
    353358 * @ inode_xp  : extended pointer on the remote inode.
     
    358363
    359364/******************************************************************************************
    360  * This function takes the main lock of a remote inode.
     365 * This function takes the main lock of a remote inode identified by the <inode_xp>.
    361366 * This lock protect all inode fields, including the children dentries.
     367 * It can be called by any thread running in any cluster.
    362368 *****************************************************************************************
    363369 * @ inode_xp  : extended pointer on the remote inode.
     
    366372
    367373/******************************************************************************************
    368  * This function releases the main lock of a remote inode.
     374 * This function releases the main lock of a remote inode identified by <inode_xp>.
    369375 * This lock protect all inode fiels, including the children dentries.
     376 * It can be called by any thread running in any cluster.
    370377 *****************************************************************************************
    371378 * @ inode_xp  : extended pointer on the remote inode.
     
    377384 * argument to a local buffer identified by the <name> argument.
    378385 * The local buffer size must be at least CONFIG_VFS_MAX_NAME_LENGTH.
     386 * It can be called by any thread running in any cluster.
    379387 ******************************************************************************************
    380388 * @ inode_xp  : extended pointer on the remote inode.
     
    385393
    386394/******************************************************************************************
    387  * This function accesses successively all pages of a file identified by the <inode>,
     395 * This function accesses successively all pages of a file identified by the <inode_xp>,
    388396 * argument, to force misses, and load all pages into mapper.
    389397 * The target inode can be a directory or a file, but this function is mainly used
    390398 * to prefetch a complete directory to the mapper.
    391  * It must be executed by a thread running in the cluster containing the inode.
    392399 * This function does NOT take any lock.
    393  ******************************************************************************************
    394  * @ inode  : local pointer on inode.
     400 * It can be called by any thread running in any cluster.
     401 ******************************************************************************************
     402 * @ inode_xp  : extended pointer on inode.
    395403 * @ return 0 if success / return -1 if device access failure.
    396404 *****************************************************************************************/
    397 error_t vfs_inode_load_all_pages( vfs_inode_t * inode );
    398 
    399 /******************************************************************************************
    400  * This debug function display the curren state of an inode descriptor identified by
    401  * the <inode_xp> argument.
     405error_t vfs_inode_load_all_pages( xptr_t inode_xp );
     406
     407/******************************************************************************************
     408 * This debug function display the curren state of an inode descriptor.
     409 * It can be called by any thread running in any cluster.
    402410 *****************************************************************************************/
    403411void vfs_inode_display( xptr_t inode_xp );
     
    408416
    409417/******************************************************************************************
    410  * This function allocates memory from local cluster for a dentry descriptor,
    411  * initialises it from  arguments values, and returns the extended pointer on dentry.
    412  * It must called by a local thread. Use the RPC_DENTRY_CREATE if client thread is remote.
    413  ******************************************************************************************
     418 * This function allocates memory in cluster identified by the <cxy> argument
     419 * for a dentry descriptor, initialises it from  arguments values, and returns
     420 * in <dentry_xp> the extended pointer on dentry.
     421 * It can be called by any thread running in any cluster.
     422 ******************************************************************************************
     423 * @ cxy        : [in]  target cluster identifier
    414424 * @ fs_type    : [in]  file system type.
    415425 * @ name       : [in]  directory entry file/dir name.
     
    417427 * @ return 0 if success / return ENOMEM or EINVAL if error.
    418428 *****************************************************************************************/
    419 error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
     429error_t vfs_dentry_create( cxy_t           cxy,
     430                           vfs_fs_type_t   fs_type,
    420431                           char          * name,
    421432                           xptr_t        * dentry_xp );
     
    424435 * This function removes the dentry from the parent inode xhtab, and releases the memory
    425436 * allocated to the dentry descriptor.
    426  * It must be executed by a thread running in the cluster containing the dentry.
    427  * Use the RPC_DENTRY_DESTROY if required.
     437 * It can be called by any thread running in any cluster.
    428438 ******************************************************************************************
    429  * @ dentry  : [in] local pointer on dentry descriptor.
    430  *****************************************************************************************/
    431 void vfs_dentry_destroy( vfs_dentry_t *  dentry ); 
     439 * @ dentry_xp  : [in] extended pointer on dentry descriptor.
     440 *****************************************************************************************/
     441void vfs_dentry_destroy( xptr_t  dentry_xp ); 
    432442
    433443
     
    437447
    438448/******************************************************************************************
    439  * This function allocates memory and initializes a new local file descriptor.
    440  * It must be executed in the cluster containing the inode.
    441  * If the client thread is not running in the owner cluster, it must use the
    442  * rpc_vfs_file_create_client() function.
     449 * This function allocates memory and initializes a new file descriptor in the
     450 * cluster defined by the <inode_xp> argument.
     451 * It can be called by any thread running in any cluster.
    443452 ******************************************************************************************
    444  * @ inode    : local pointer on associated inode.
    445  * @ attr     : file descriptor attributes.
    446  * @ file_xp  : [out] buffer for extended pointer on created file descriptor.
     453 * @ inode_xp  : [in]  extended pointer on associated inode.
     454 * @ attr      : [in] file descriptor attributes.
     455 * @ file_xp   : [out] buffer for extended pointer on created file descriptor.
    447456 * @ return 0 if success / return ENOMEM if error.
    448457 *****************************************************************************************/
    449 error_t vfs_file_create( vfs_inode_t * inode,
     458error_t vfs_file_create( xptr_t        inode_xp,
    450459                         uint32_t      attr,
    451460                         xptr_t      * file_xp ); 
    452461
    453462/******************************************************************************************
    454  * This function releases memory allocated to a local file descriptor.
    455  * It must be executed by a thread running in the cluster containing the inode,
    456  * and the file refcount must be zero. Use the RPC_VFS_FILE_DESTROY if required.
     463 * This function releases memory allocated to file descriptor identified
     464 * by the <file_xp> argument.
     465 * It can be called by any thread running in any cluster.
    457466 ******************************************************************************************
    458  * @ file  : local pointer on file descriptor.
    459  *****************************************************************************************/
    460 void vfs_file_destroy( vfs_file_t *  file ); 
     467 * @ file_xp  : [in] extended pointer on file descriptor.
     468 *****************************************************************************************/
     469void vfs_file_destroy( xptr_t  file_xp ); 
    461470
    462471/******************************************************************************************
    463472 * These functions increment (resp. decrement) the count field in a remote file
    464473 * descriptor, using a remote_atomic access.
     474 *****************************************************************************************
     475 * @ file_xp  : extended pointer on file descriptor.
    465476 *****************************************************************************************/
    466477void vfs_file_count_up  ( xptr_t   file_xp );
     
    472483 * The local buffer size must be at least CONFIG_VFS_MAX_NAME_LENGTH.
    473484 *****************************************************************************************
    474  * @ file_xp  : extended pointer on the remote inode.
    475  * @ name     : local buffer pointer.
    476  *****************************************************************************************/
     485 * @ ionde_xp  : [in] extended pointer on the remote inode.
     486 * @ name      : [out] local string.
     487 ***************************************************************************************/
    477488void vfs_file_get_name( xptr_t inode_xp,
    478489                        char * name );
     
    596607
    597608/******************************************************************************************
    598  * This function is called by the vfs_lookup() function when a new (dentry/inode) must
    599  * be created from scratch and introduced in both the parent mapper and the IOC device.
    600  * The dentry and inode descriptors must have been previously created by the caller.
    601  * 1. It allocates one cluster from the relevant FS, updates the FAT mapper,
    602  *    and synchronously update the IOC device).
    603  * 2. It set the "size", and "extend" fields in child inode descriptor.
    604  *    The size is 4096 for a directory, the size is 0 for a file.
    605  * 3. It updates the parent directory mapper to introduce the new child,
    606  *    and synchronously update the IOC device.
    607  * 4. It set the "extend" field in dentry descriptor.
    608  * It can be called by a thread running in any cluster.
    609  ******************************************************************************************
    610  * @ parent_xp   : extended pointer on parent inode descriptor.
    611  * @ dentry_xp   : extended pointer on new dentry descriptor.
    612  * @ child_xp    : extended pointer on child inode descriptor.
    613  * @ return 0 if success / -1 if failure.
    614  *****************************************************************************************/
    615 error_t vfs_new_dentry_init( xptr_t   parent_xp,
    616                              xptr_t   dentry_xp,
    617                              xptr_t   child_xp );
    618 
    619 /******************************************************************************************
    620  * This function creates in the directory identified by the <child_xp> argument,
     609 * This function creates in the directory identified by the <child_inode_xp> argument,
    621610 * the two special dentries <.> and <..>. The parent directory inode is defined
    622  * by the <parent_xp> argument. The two dentries are introduced in the Inode Tree.
     611 * by the <parent_inode_xp> argument. The two dentries are introduced in the Inode Tree.
    623612 * They are also introduced in the child directory mapper, and the IOC device is updated.
    624613 * This function is called by all functions creating a brand new directory : vfs_mkdir(),
     
    629618 * @ return 0 if success / -1 if failure.
    630619 *****************************************************************************************/
    631 error_t vfs_add_special_dentries( xptr_t  child_xp,
    632                                   xptr_t  parent_xp );
     620error_t vfs_add_special_dentries( xptr_t  child_inode_xp,
     621                                  xptr_t  parent_inode_xp );
    633622
    634623/******************************************************************************************
     
    893882
    894883/******************************************************************************************
    895  *        These functions define the VFS "FS" API to a specific File System
    896  *****************************************************************************************/
    897 
    898 /******************************************************************************************
    899  * This function makes the I/O operation to move one page identified by the <page_xp>
    900  * argument to/from the IOC device from/to the mapper, as defined by the <cmd_type>.
     884 *      These functions define the VFS "FS" API to access a specific File System
     885 *****************************************************************************************/
     886
     887/******************************************************************************************
     888 * This function introduces in a directory mapper identified by the <parent_inode_xp>
     889 * argument, a new entry identified by the <dentry_ptr> argument.
    901890 * Depending on the file system type, it calls the proper, FS specific function.
    902  * It is used in case of MISS on the mapper (read), or when a dirty page in the mapper
    903  * must be updated in the File System (write).
    904  * The mapper pointer, and the page index in file are obtained from the page descriptor.
    905  * It can be executed by any thread running in any cluster.
    906  * This function does NOT take any lock.
    907  ******************************************************************************************
    908  * @ page_xp   : extended pointer on page descriptor (for mapper and page_id).
    909  * @ cmd_type  : IOC_READ / IOC_WRITE / IOC_SYNC_READ / IOC_SYNC_WRITE
    910  * @ returns 0 if success / return -1 if device access failure.
    911  *****************************************************************************************/
    912 error_t vfs_fs_move_page( xptr_t      page_xp,
    913                           cmd_type_t  cmd_type );
    914 
    915 /******************************************************************************************
    916  * This function updates the mapper associated to a directory inode identified by the
    917  * <parent> argument, to add a new entry identified by the <dentry> argument.
    918  * The directory inode descriptor and the dentry descriptor are in the same cluster.
    919  * Depending on the file system type, it calls the proper, FS specific function.
    920  * It also updates the dentry descriptor and/or the inode descriptor extensions
    921  * as required by the specific file system type.
     891 * All informations related to the new directory must be contained in the dentry
     892 * descriptor, or in the associated child inode descriptor.
     893 * The dentry descriptor "extend" field is updated as required by the specific FS.
    922894 * Finally, it synchronously updates the parent directory on IOC device.
    923  *
    924  * It must be executed by a thread running in the cluster containing the parent directory.
    925  * It can be the RPC_VFS_FS_ADD_DENTRY. This function does NOT take any lock.
     895 * This function can be called by any thread running in any cluster.
    926896 ******************************************************************************************
    927897 * @ parent  : local pointer on parent (directory) inode.
     
    929899 * @ return 0 if success / return -1 if device access failure.
    930900 *****************************************************************************************/
    931 error_t vfs_fs_add_dentry( vfs_inode_t  * parent,
    932                            vfs_dentry_t * dentry );
    933 
    934 /******************************************************************************************
    935  * This function updates the mapper associated to a directory inode identified by the
    936  * <parent> argument, to remove an entry identified by the <dentry> argument.
    937  * The directory inode descriptor and the dentry descriptor are in the same cluster.
     901error_t vfs_fs_add_dentry( xptr_t         parent_inode_xp,
     902                           vfs_dentry_t * dentry_ptr );
     903
     904/******************************************************************************************
     905 * This function removes from a directory mapper identified by the <parent_inode_xp>
     906 * argument, an entry identified by the <dentry_ptr> argument.
    938907 * Depending on the file system type, it calls the proper, FS specific function.
    939908 * Finally, it synchronously updates the parent directory on IOC device.
    940  *
    941  * Depending on the file system type, it calls the relevant, FS specific function.
    942  * It must be executed by a thread running in the cluster containing the parent directory.
    943  * It can be the RPC_VFS_FS_REMOVE_DENTRY. This function does NOT take any lock.
    944  ******************************************************************************************
    945  * @ parent  : local pointer on parent (directory) inode.
    946  * @ dentry  : local pointer on dentry containing name.
     909 * This function can be called by any thread running in any cluster.
     910 ******************************************************************************************
     911 * @ parent_inode_xp  : extended pointer on parent (directory) inode.
     912 * @ dentry_ptr       : local pointer on dentry containing name.
    947913 * @ return 0 if success / return -1 if device access failure.
    948914 *****************************************************************************************/
    949 error_t vfs_fs_remove_dentry( vfs_inode_t  * parent,
    950                               vfs_dentry_t * dentry );
    951 
    952 /******************************************************************************************
    953  * This function scan the mapper of an an existing parent inode directory, identified by
    954  * the <parent> argument to find a directory entry identified by the <name> argument,
    955  * and updates both the child inode descriptor, identified by the <child_xp> argument,
    956  * and the associated dentry descriptor :
     915error_t vfs_fs_remove_dentry( xptr_t         parent_inode_xp,
     916                              vfs_dentry_t * dentry_ptr );
     917
     918/******************************************************************************************
     919 * This function scan a directory mapper, identified by the <parent_inode_xp> argument
     920 * to find a directory entry identified by the <dentry_ptr> argument,
     921 * and updates both the child inode descriptor, and the associated dentry descriptor:
    957922 * - It set the "size", "type", and "extend" fields in inode descriptor.
    958923 * - It set the "extend" field in dentry descriptor.
    959  * It is called by the vfs_lookup() function in case of miss.
    960  *
     924 * It is called by the vfs_lookup() function in case of miss, and does NOT take any lock.
    961925 * Depending on the file system type, it calls the relevant, FS specific function.
    962  * It must be called by a thread running in the cluster containing the parent inode.
    963  * It can be the RPC_VFS_FS_NEW_DENTRY. This function does NOT take any lock.
    964  ******************************************************************************************
    965  * @ parent    : local pointer on parent inode (directory).
    966  * @ name      : child name.
    967  * @ child_xp  : extended pointer on remote child inode (file or directory)
     926 * This function can be called by any thread running in any cluster.
     927 ******************************************************************************************
     928 * @ parent_inode_xp  : extended pointer on parent inode (directory).
     929 * @ dentry_ptr       : local pointer on new entry (in parent inode cluster).
    968930 * @ return 0 if success / return -1 if dentry not found.
    969931 *****************************************************************************************/
    970 error_t vfs_fs_new_dentry( vfs_inode_t * parent,
    971                            char        * name,
    972                            xptr_t        child_xp );
    973 
    974 /******************************************************************************************
    975  * This function scan the mapper of an an existing inode directory, identified by
    976  * the <inode> argument, to find a directory entry identified by the <dentry> argument,
    977  * and update the size for this directory entry in mapper, as defined by <size>.
     932error_t vfs_fs_new_dentry_from_mapper( xptr_t         parent_inode_xp,
     933                                       vfs_dentry_t * dentry_ptr );
     934
     935/*****************************************************************************************
     936 * This function  introduces a brand new dentry identified by the <dentry_ptr> argument
     937 * in the mapper of a directory identified by the <parent_inode_xp> argument.
     938 * It is called by the vfs_lookup() function, and does NOT take any lock.
     939 * The child inode descriptor, and the dentry descriptor must have been previously
     940 * allocated and introduced in the Inode Tree. The dentry descriptor contains the name.
     941 * Depending on the file system type, it calls the relevant, FS specific function.
     942 * This function can be called by any thread running in any cluster.
     943 *****************************************************************************************
     944 * @ parent_inode_xp : [in]  extended pointer on parent inode (directory).
     945 * @ dentry_ptr      : [in]  local pointer on dentry (in parent inode cluster).
     946 * @ return 0 if success / return -1 if failure.
     947 ****************************************************************************************/
     948error_t vfs_fs_new_dentry_to_mapper( xptr_t         parent_inode_xp,
     949                                     vfs_dentry_t * dentry_ptr );
     950
     951/******************************************************************************************
     952 * This function updates the "size" field of a directory entry identified by the
     953 * <dentry_ptr> argument in a directory mapper identified by the <parent_inode_xp>
     954 * from the value contained in the inode descriptor.
    978955 * The parent directory on device is synchronously updated.
    979956 * It is called by the vfs_close() function.
    980  *
    981957 * Depending on the file system type, it calls the relevant, FS specific function.
    982  * It must be called by a thread running in the cluster containing the parent inode.
    983  * It can be the RPC_VFS_FS_UPDATE_DENTRY. This function does NOT take any lock.
    984  ******************************************************************************************
    985  * @ parent    : local pointer on parent inode (directory).
    986  * @ dentry    : local pointer on dentry.
    987  * @ size      : new size value (bytes).
    988  * @ return 0 if success / return ENOENT if not found.
    989  *****************************************************************************************/
    990 error_t vfs_fs_update_dentry( vfs_inode_t  * inode,
    991                               vfs_dentry_t * dentry,
    992                               uint32_t       size );
     958 * This function can be called by any thread running in any cluster.
     959 ******************************************************************************************
     960 * @ parent_inode_xp  : local pointer on parent inode (directory).
     961 * @ dentry_ptr       : local pointer on dentry (in parent directory cluster).
     962 * @ return 0 if success / return -1 if not found.
     963 *****************************************************************************************/
     964error_t vfs_fs_update_dentry( xptr_t         parent_inode_xp,
     965                              vfs_dentry_t * dentry_ptr );
    993966
    994967/******************************************************************************************
     
    1002975 * the Inode Tree is dynamically created, and all dirent fiels are documented in the
    1003976 * dirent array. Otherwise, only the dentry name is documented.
    1004  *
     977 * This function does NOT take any lock.
    1005978 * Depending on the file system type, it calls the relevant, FS specific function.
    1006  * It must be called by a thread running in the cluster containing the parent inode.
    1007  * This function does NOT take any lock.
     979 *
     980 * WARNING : this function must be called by a thread running in the cluster containing
     981 * the target directory inode.
    1008982 ******************************************************************************************
    1009983 * @ inode      : [in]  local pointer on directory inode.
     
    10311005 * directory are synchronously done on the IOC device by the two vfs_fs_add_dentry()
    10321006 * and vfs_fs_remove_dentry() functions.
    1033  *
    10341007 * Depending on the file system type, it calls the relevant, FS specific function.
    1035  * It must be called by a thread running in the inode cluster.
     1008 * This function can be called by any thread running in any cluster.
    10361009 *****************************************************************************************
    1037  * @ inode   : local pointer on inode.
    1038  * @ return 0 if success / return EIO if failure during device access.
     1010 * @ inode_xp   : remote pointer on inode.
     1011 * @ return 0 if success / return -1 if failure.
    10391012 ****************************************************************************************/
    1040 error_t vfs_fs_sync_inode( struct vfs_inode_s * inode );
     1013error_t vfs_fs_sync_inode( xptr_t inode_xp );
    10411014
    10421015/*****************************************************************************************
     
    10441017 * for the FAT itself. It scan all clusters registered in the FAT mapper, and copies
    10451018 * to device each page marked as dirty.
    1046  *
    10471019 * Depending on the file system type, it calls the relevant, FS specific function.
    10481020 * It can be called by a thread running in any cluster.
     
    10531025error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type );
    10541026
    1055 /*****************************************************************************************
    1056  * This function updates the free clusters info on the IOC device for the FS defined
    1057  * by the <fs_type> argument.
    1058  *
    1059  * Depending on the file system type, it calls the relevant, FS specific function.
    1060  * It can be called by a thread running in any cluster.
    1061  *****************************************************************************************
    1062  * @ fs_type   : specific file system type.
    1063  * @ return 0 if success / return EIO if failure during device access.
    1064  ****************************************************************************************/
    1065 error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type );
    1066 
    1067 /******************************************************************************************
    1068  * This function allocates a free cluster from the FS identified by the <fs_type>
    1069  * argument. It updates the selected FS File Allocation Table.
    1070  *
    1071  * Depending on the file system type, it calls the relevant, FS specific function.
    1072  * It can be called by a thread running in any cluster.
    1073  ******************************************************************************************
    1074  * @ fs_type   : [in]  File System type.
    1075  * @ cluster   : [out] cluster index in File system.
    1076  * @ return 0 if success / return -1 if no free cluster
    1077  *****************************************************************************************/
    1078 error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
    1079                               uint32_t * cluster );
    1080 
    10811027/******************************************************************************************
    10821028 * This function makes all I/O operations required to release all clusters allocated
     
    10841030 * Depending on the file system type, it calls the proper, FS specific function.
    10851031 * It is called by the vfs_unlink() function.
    1086  * It can be executed by a thread running in any cluster.
    10871032 * This function does NOT take any lock.
     1033 * Depending on the file system type, it calls the relevant, FS specific function.
     1034 * This function can be executed by any thread running in any cluster.
    10881035 ******************************************************************************************
    10891036 * @ inode_xp  : extended pointer on inode.
     
    10921039error_t vfs_fs_release_inode( xptr_t  inode_xp );
    10931040
     1041/******************************************************************************************
     1042 * This function makes the I/O operation to move one page identified by the <page_xp>
     1043 * argument to/from the IOC device from/to the mapper, as defined by the <cmd_type>.
     1044 * It is used in case of MISS on the mapper (read), or when a dirty page in the mapper
     1045 * must be updated in the File System (write).
     1046 * The mapper pointer, and the page index in file are obtained from the page descriptor.
     1047 * This function does NOT take any lock.
     1048 * Depending on the file system type, it calls the proper, FS specific function.
     1049 * This function can be executed by any thread running in any cluster.
     1050 ******************************************************************************************
     1051 * @ page_xp   : extended pointer on page descriptor (for mapper and page_id).
     1052 * @ cmd_type  : IOC_READ / IOC_WRITE / IOC_SYNC_READ / IOC_SYNC_WRITE
     1053 * @ returns 0 if success / return -1 if device access failure.
     1054 *****************************************************************************************/
     1055error_t vfs_fs_move_page( xptr_t          page_xp,
     1056                          ioc_cmd_type_t  cmd_type );
     1057
    10941058
    10951059#endif  /* _VFS_H_ */
Note: See TracChangeset for help on using the changeset viewer.