Changeset 602 for trunk


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

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

Location:
trunk/kernel/fs
Files:
6 edited

Legend:

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

    r598 r602  
    8686
    8787/////////////////////////////////////////////////
    88 void devfs_global_init( xptr_t   parent_inode_xp,
     88void devfs_global_init( xptr_t   root_inode_xp,
    8989                        xptr_t * devfs_dev_inode_xp,
    9090                        xptr_t * devfs_external_inode_xp )
    9191{
    9292    error_t  error;
     93    xptr_t   unused_xp;   // required by vfs_add_child_in_parent()
    9394
    9495    // creates DEVFS "dev" inode in cluster 0
     
    9697                                     INODE_TYPE_DIR,
    9798                                     FS_TYPE_DEVFS,
    98                                      parent_inode_xp,
     99                                     root_inode_xp,
    99100                                     "dev",
    100                                      NULL,
    101                                      devfs_dev_inode_xp ); 
     101                                     &unused_xp,
     102                                     devfs_dev_inode_xp );
    102103
    103104    assert( (error == 0) , "cannot create <dev>\n" );
     
    117118                                     *devfs_dev_inode_xp,
    118119                                     "external",
    119                                      NULL,
    120                                      devfs_external_inode_xp ); 
     120                                     &unused_xp,
     121                                     devfs_external_inode_xp );
    121122
    122123    assert( (error == 0) , "cannot create <external>\n" );
     
    129130#endif
    130131
    131 }
     132}  // end devfs_global_init()
    132133
    133134///////////////////////////////////////////////////
     
    141142    chdev_t     * chdev_ptr;
    142143    xptr_t        inode_xp;
     144    cxy_t         inode_cxy;
     145    vfs_inode_t * inode_ptr;
    143146    uint32_t      channel;
     147    xptr_t        unused_xp;    // required by add_child_in_parent()
    144148
    145149    // create "internal" directory
     
    150154                             devfs_dev_inode_xp,
    151155                             node_name,
    152                              NULL,
     156                             &unused_xp,
    153157                             devfs_internal_inode_xp );
    154158#if DEBUG_DEVFS_INIT
     
    164168    if( chdev_xp != XPTR_NULL)
    165169    {
    166         chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     170        chdev_ptr = GET_PTR( chdev_xp );
    167171        vfs_add_child_in_parent( local_cxy,
    168172                                 INODE_TYPE_DEV,
     
    170174                                 *devfs_internal_inode_xp,
    171175                                 chdev_ptr->name,
    172                                  GET_PTR( chdev_xp ),
     176                                 &unused_xp,
    173177                                 &inode_xp );
     178
     179        // update child inode "extend" field
     180        inode_cxy = GET_CXY( inode_xp );
     181        inode_ptr = GET_PTR( inode_xp );
     182        hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     183       
    174184#if DEBUG_DEVFS_INIT
    175185cycle = (uint32_t)hal_get_cycles();
     
    184194    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
    185195    {
    186         chdev_xp = chdev_dir.dma[channel];
     196        chdev_xp  = chdev_dir.dma[channel];
    187197        if( chdev_xp != XPTR_NULL)
    188198        {
    189             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     199            chdev_ptr = GET_PTR( chdev_xp );
    190200            vfs_add_child_in_parent( local_cxy,
    191201                                     INODE_TYPE_DEV,
     
    193203                                     *devfs_internal_inode_xp,
    194204                                     chdev_ptr->name,
    195                                      GET_PTR( chdev_xp ),
     205                                     &unused_xp,
    196206                                     &inode_xp );
     207
     208            // update child inode "extend" field
     209            inode_cxy = GET_CXY( inode_xp );
     210            inode_ptr = GET_PTR( inode_xp );
     211            hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     212       
    197213#if DEBUG_DEVFS_INIT
    198214cycle = (uint32_t)hal_get_cycles();
     
    209225    {
    210226        chdev_cxy = GET_CXY( chdev_xp );
    211         chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     227        chdev_ptr = GET_PTR( chdev_xp );
    212228        if( chdev_cxy == local_cxy )
    213229        {
     
    217233                                     devfs_external_inode_xp,
    218234                                     chdev_ptr->name,
    219                                      GET_PTR( chdev_xp ),
     235                                     &unused_xp,
    220236                                     &inode_xp );
     237
     238            // update child inode "extend" field
     239            inode_cxy = GET_CXY( inode_xp );
     240            inode_ptr = GET_PTR( inode_xp );
     241            hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     242       
    221243#if DEBUG_DEVFS_INIT
    222244cycle = (uint32_t)hal_get_cycles();
     
    233255    {
    234256        chdev_cxy = GET_CXY( chdev_xp );
    235         chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     257        chdev_ptr = GET_PTR( chdev_xp );
    236258        if( chdev_cxy == local_cxy )
    237259        {
     
    241263                                     devfs_external_inode_xp,
    242264                                     chdev_ptr->name,
    243                                      GET_PTR( chdev_xp ),
     265                                     &unused_xp,
    244266                                     &inode_xp );
     267
     268            // update child inode "extend" field
     269            inode_cxy = GET_CXY( inode_xp );
     270            inode_ptr = GET_PTR( inode_xp );
     271            hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     272       
    245273#if DEBUG_DEVFS_INIT
    246274cycle = (uint32_t)hal_get_cycles();
     
    256284    {
    257285        chdev_xp = chdev_dir.txt_rx[channel];
     286        if( chdev_xp != XPTR_NULL )
     287        {
     288            chdev_cxy = GET_CXY( chdev_xp );
     289            chdev_ptr = GET_PTR( chdev_xp );
     290            if( chdev_cxy == local_cxy )
     291            {
     292                vfs_add_child_in_parent( local_cxy,
     293                                         INODE_TYPE_DEV,
     294                                         FS_TYPE_DEVFS,
     295                                         devfs_external_inode_xp,
     296                                         chdev_ptr->name,
     297                                         &unused_xp,
     298                                         &inode_xp );
     299
     300                // update child inode "extend" field
     301                inode_cxy = GET_CXY( inode_xp );
     302                inode_ptr = GET_PTR( inode_xp );
     303                hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     304       
     305#if DEBUG_DEVFS_INIT
     306cycle = (uint32_t)hal_get_cycles();
     307if( DEBUG_DEVFS_INIT < cycle )
     308printk("\n[%s] thread[%x,%x] created <txt_rx[%d]> inode in cluster %x\n",
     309__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
     310#endif
     311            }
     312        }
     313    }
     314
     315    // create a TXT_TX inode in each cluster containing a TXT_TX chdev
     316    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
     317    {
     318        chdev_xp = chdev_dir.txt_tx[channel];
     319        if( chdev_xp != XPTR_NULL )
     320        {
     321            chdev_cxy = GET_CXY( chdev_xp );
     322            chdev_ptr = GET_PTR( chdev_xp );
     323            if( chdev_cxy == local_cxy )
     324            {
     325                vfs_add_child_in_parent( local_cxy,
     326                                         INODE_TYPE_DEV,
     327                                         FS_TYPE_DEVFS,
     328                                         devfs_external_inode_xp,
     329                                         chdev_ptr->name,
     330                                         &unused_xp,
     331                                         &inode_xp );
     332
     333                // update child inode "extend" field
     334                inode_cxy = GET_CXY( inode_xp );
     335                inode_ptr = GET_PTR( inode_xp );
     336                hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     337       
     338#if DEBUG_DEVFS_INIT
     339cycle = (uint32_t)hal_get_cycles();
     340if( DEBUG_DEVFS_INIT < cycle )
     341printk("\n[%s] thread[%x,%x] created <txt_tx[%d]> inode in cluster %x\n",
     342__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
     343#endif
     344            }
     345        }
     346    }
     347
     348    // create an IOC inode in each cluster containing an IOC chdev
     349    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
     350    {
     351        chdev_xp = chdev_dir.ioc[channel];
     352        if( chdev_xp != XPTR_NULL )
     353        {
     354            chdev_cxy = GET_CXY( chdev_xp );
     355            chdev_ptr = GET_PTR( chdev_xp );
     356            if( chdev_cxy == local_cxy )
     357            {
     358                vfs_add_child_in_parent( local_cxy,
     359                                         INODE_TYPE_DEV,
     360                                         FS_TYPE_DEVFS,
     361                                         devfs_external_inode_xp,
     362                                         chdev_ptr->name,
     363                                         &unused_xp,
     364                                         &inode_xp );
     365
     366                // update child inode "extend" field
     367                inode_cxy = GET_CXY( inode_xp );
     368                inode_ptr = GET_PTR( inode_xp );
     369                hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     370       
     371#if DEBUG_DEVFS_INIT
     372cycle = (uint32_t)hal_get_cycles();
     373if( DEBUG_DEVFS_INIT < cycle )
     374printk("\n[%s] thread[%x,%x] created <ioc[%d]> inode in cluster %x\n",
     375__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
     376#endif
     377            }
     378        }
     379    }
     380
     381    // create a FBF inode in each cluster containing a FBF chdev
     382    for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ )
     383    {
     384        chdev_xp = chdev_dir.fbf[channel];
     385        if( chdev_xp != XPTR_NULL )
     386        {
     387            chdev_cxy = GET_CXY( chdev_xp );
     388            chdev_ptr = GET_PTR( chdev_xp );
     389            if( chdev_cxy == local_cxy )
     390            {
     391                vfs_add_child_in_parent( local_cxy,
     392                                         INODE_TYPE_DEV,
     393                                         FS_TYPE_DEVFS,
     394                                         devfs_external_inode_xp,
     395                                         chdev_ptr->name,
     396                                         &unused_xp,
     397                                         &inode_xp );
     398
     399                // update child inode "extend" field
     400                inode_cxy = GET_CXY( inode_xp );
     401                inode_ptr = GET_PTR( inode_xp );
     402                hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     403       
     404#if DEBUG_DEVFS_INIT
     405cycle = (uint32_t)hal_get_cycles();
     406if( DEBUG_DEVFS_INIT < cycle )
     407printk("\n[%s] thread[%x,%x] created <fbf[%d]> inode in cluster %x\n",
     408__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
     409#endif
     410            }
     411        }
     412    }
     413
     414    // create a NIC_RX inode in each cluster containing a NIC_RX chdev
     415    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
     416    {
     417        chdev_xp = chdev_dir.nic_rx[channel];
    258418        if( chdev_xp != XPTR_NULL )
    259419        {
     
    267427                                         devfs_external_inode_xp,
    268428                                         chdev_ptr->name,
    269                                          GET_PTR( chdev_xp ),
     429                                         &unused_xp,
    270430                                         &inode_xp );
    271431#if DEBUG_DEVFS_INIT
    272432cycle = (uint32_t)hal_get_cycles();
    273433if( DEBUG_DEVFS_INIT < cycle )
    274 printk("\n[%s] thread[%x,%x] created <txt_rx[%d]> inode in cluster %x\n",
     434printk("\n[%s] thread[%x,%x] created <nic_rx[%d]> inode in cluster %x\n",
    275435__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
    276436#endif
     
    279439    }
    280440
    281     // create a TXT_TX inode in each cluster containing a TXT_TX chdev
    282     for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
    283     {
    284         chdev_xp = chdev_dir.txt_tx[channel];
     441    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
     442    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
     443    {
     444        chdev_xp = chdev_dir.nic_tx[channel];
    285445        if( chdev_xp != XPTR_NULL )
    286446        {
    287447            chdev_cxy = GET_CXY( chdev_xp );
    288             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     448            chdev_ptr = GET_PTR( chdev_xp );
    289449            if( chdev_cxy == local_cxy )
    290450            {
     
    294454                                         devfs_external_inode_xp,
    295455                                         chdev_ptr->name,
    296                                          GET_PTR( chdev_xp ),
     456                                         &unused_xp,
    297457                                         &inode_xp );
    298 #if DEBUG_DEVFS_INIT
    299 cycle = (uint32_t)hal_get_cycles();
    300 if( DEBUG_DEVFS_INIT < cycle )
    301 printk("\n[%s] thread[%x,%x] created <txt_tx[%d]> inode in cluster %x\n",
    302 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
    303 #endif
    304             }
    305         }
    306     }
    307 
    308     // create an IOC inode in each cluster containing an IOC chdev
    309     for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
    310     {
    311         chdev_xp = chdev_dir.ioc[channel];
    312         if( chdev_xp != XPTR_NULL )
    313         {
    314             chdev_cxy = GET_CXY( chdev_xp );
    315             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
    316             if( chdev_cxy == local_cxy )
    317             {
    318                 vfs_add_child_in_parent( local_cxy,
    319                                          INODE_TYPE_DEV,
    320                                          FS_TYPE_DEVFS,
    321                                          devfs_external_inode_xp,
    322                                          chdev_ptr->name,
    323                                          GET_PTR( chdev_xp ),
    324                                          &inode_xp );
    325 #if DEBUG_DEVFS_INIT
    326 cycle = (uint32_t)hal_get_cycles();
    327 if( DEBUG_DEVFS_INIT < cycle )
    328 printk("\n[%s] thread[%x,%x] created <ioc[%d]> inode in cluster %x\n",
    329 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
    330 #endif
    331             }
    332         }
    333     }
    334 
    335     // create a FBF inode in each cluster containing a FBF chdev
    336     for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ )
    337     {
    338         chdev_xp = chdev_dir.fbf[channel];
    339         if( chdev_xp != XPTR_NULL )
    340         {
    341             chdev_cxy = GET_CXY( chdev_xp );
    342             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
    343             if( chdev_cxy == local_cxy )
    344             {
    345                 vfs_add_child_in_parent( local_cxy,
    346                                          INODE_TYPE_DEV,
    347                                          FS_TYPE_DEVFS,
    348                                          devfs_external_inode_xp,
    349                                          chdev_ptr->name,
    350                                          GET_PTR( chdev_xp ),
    351                                          &inode_xp );
    352 #if DEBUG_DEVFS_INIT
    353 cycle = (uint32_t)hal_get_cycles();
    354 if( DEBUG_DEVFS_INIT < cycle )
    355 printk("\n[%s] thread[%x,%x] created <fbf[%d]> inode in cluster %x\n",
    356 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
    357 #endif
    358             }
    359         }
    360     }
    361 
    362     // create a NIC_RX inode in each cluster containing a NIC_RX chdev
    363     for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
    364     {
    365         chdev_xp = chdev_dir.nic_rx[channel];
    366         if( chdev_xp != XPTR_NULL )
    367         {
    368             chdev_cxy = GET_CXY( chdev_xp );
    369             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
    370             if( chdev_cxy == local_cxy )
    371             {
    372                 vfs_add_child_in_parent( local_cxy,
    373                                          INODE_TYPE_DEV,
    374                                          FS_TYPE_DEVFS,
    375                                          devfs_external_inode_xp,
    376                                          chdev_ptr->name,
    377                                          GET_PTR( chdev_xp ),
    378                                          &inode_xp );
    379 #if DEBUG_DEVFS_INIT
    380 cycle = (uint32_t)hal_get_cycles();
    381 if( DEBUG_DEVFS_INIT < cycle )
    382 printk("\n[%s] thread[%x,%x] created <nic_rx[%d]> inode in cluster %x\n",
    383 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
    384 #endif
    385             }
    386         }
    387     }
    388 
    389     // create a NIC_TX inode in each cluster containing a NIC_TX chdev
    390     for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
    391     {
    392         chdev_xp = chdev_dir.nic_tx[channel];
    393         if( chdev_xp != XPTR_NULL )
    394         {
    395             chdev_cxy = GET_CXY( chdev_xp );
    396             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
    397             if( chdev_cxy == local_cxy )
    398             {
    399                 vfs_add_child_in_parent( local_cxy,
    400                                          INODE_TYPE_DEV,
    401                                          FS_TYPE_DEVFS,
    402                                          devfs_external_inode_xp,
    403                                          chdev_ptr->name,
    404                                          GET_PTR( chdev_xp ),
    405                                          &inode_xp );
     458
     459                // update child inode "extend" field
     460                inode_cxy = GET_CXY( inode_xp );
     461                inode_ptr = GET_PTR( inode_xp );
     462                hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
     463       
    406464#if DEBUG_DEVFS_INIT
    407465cycle = (uint32_t)hal_get_cycles();
     
    462520    channel = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
    463521
     522// Only TXT devices are associated to a pseudo-file
    464523assert( ( func == DEV_FUNC_TXT ) , __FUNCTION__, "illegal device func_type");
    465524
  • trunk/kernel/fs/fatfs.c

    r568 r602  
    22 * fatfs.c - FATFS file system API implementation.
    33 *
    4  * Author    Alain Greiner (2016,2017)
     4 * Author    Alain Greiner (2016,2017,2018)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    4242//////////////////////////////////////////////////////////////////////////////////////////
    4343
    44 extern vfs_ctx_t          fs_context[FS_TYPES_NR];   // allocated in vfs.c file
    45 
    46 //////////////////////////////////////////////////////////////////////////////////////////
    47 //              FATFS specific and static functions
     44extern vfs_ctx_t     fs_context[FS_TYPES_NR];   // allocated in kernel_init.c file
     45
     46//////////////////////////////////////////////////////////////////////////////////////////
     47//              FATFS specific static functions
    4848//////////////////////////////////////////////////////////////////////////////////////////
    4949
     
    8989    uint32_t res  = 0;
    9090
    91     if ( little_endian)
     91    if ( little_endian )
    9292    {
    9393        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
    9494    }
    95     else
     95    else // big_endian
    9696    {
    9797        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
     
    100100
    101101}  // end fatfs_get_record()
     102
     103//////////////////////////////////////////////////////////////////////////////////////////
     104// This function writes one, two, or four bytes from a 32 bits integer to a memory buffer,
     105// taking into account endianness.
     106//////////////////////////////////////////////////////////////////////////////////////////
     107// @ offset        : first byte of record in buffer.
     108// @ size          : record length in bytes (1/2/4).
     109// @ buffer        : pointer on buffer base.
     110// @ little endian : the most significant byte has the highest address when true.
     111// @ return the integer value in a 32 bits word.
     112//////////////////////////////////////////////////////////////////////////////////////////
     113static void fatfs_set_record( uint32_t    offset,
     114                              uint32_t    size,
     115                              uint8_t   * buffer,
     116                              uint32_t    little_endian,
     117                              uint32_t    value )
     118{
     119    uint32_t n;
     120
     121    if ( little_endian )
     122    {
     123        for( n = size ; n > 0 ; n-- ) buffer[offset+n-1] = (uint8_t)(value>>((n-1)<<3));
     124    }
     125    else // big_endian
     126    {
     127        for( n = 0 ; n < size ; n++ ) buffer[offset+n] = (uint8_t)(value>>((size-1-n)<<3));
     128    }
     129
     130}  // end fatfs_set_record()
    102131
    103132//////////////////////////////////////////////////////////////////////////////////////////
     
    136165
    137166    name[j] = '\0';
    138 }
     167
     168}  // fatfs_get_name_from_short()
    139169
    140170//////////////////////////////////////////////////////////////////////////////////////////
     
    213243    name[name_offset] = 0;
    214244
    215 } // end get_name_from_long()
     245} // end fatfs_get_name_from_long()
     246
     247//////////////////////////////////////////////////////////////////////////////////////////
     248// This static function analyse the <name> input argument, and returns in other
     249// output arguments various informations required to store the name in FATFS directory.
     250// The <name> length cannot be larger than 31 characters :
     251// - Short name (less than 13 characters) require 1 LFN entry.
     252// - Medium names (from 14 to 26 characters require 2 LFN entries.
     253// - Large names (up to 31 characters) require 3 LFN entries.
     254//////////////////////////////////////////////////////////////////////////////////////////
     255// @ name     : [in]  complete directory entry name.
     256// @ length   : [out] total number of characters in name.
     257// @ nb_lfn   : [out] number of LFN entries required to store the name.
     258// @ sfn      : [out] a legal SFN name extracted from name / upper case and 8-3 format.
     259// @ checksum : [out] checksum to be stored in SFN.
     260// @ returns 0 on success / returns 1 if the name length is larger than 31 characters.
     261//////////////////////////////////////////////////////////////////////////////////////////
     262static error_t fatfs_name_format( const char  * name,
     263                                  uint32_t    * length,
     264                                  uint32_t    * nb_lfn,
     265                                  char        * sfn,
     266                                  uint8_t     * checksum )
     267{
     268    // compute name length
     269    uint32_t name_length = strlen( name );
     270    *length = name_length;
     271
     272    uint32_t suffix_length = 0;
     273    uint32_t prefix_length = 0;
     274    uint32_t dot_found     = 0;
     275    uint32_t i;
     276
     277    // compute prefix and suffix length
     278    // only the last '.' is taken into account
     279    for ( i=0 ; i<name_length ; i++ )
     280    {
     281        if (name[i] == '.' )
     282        {
     283            if ( dot_found )
     284            {
     285                prefix_length += suffix_length + 1;
     286                suffix_length =  0;
     287            }
     288            else
     289            {
     290                dot_found = 1;
     291            }
     292        }
     293        else
     294        {
     295            if ( dot_found)  suffix_length++;
     296            else             prefix_length++;
     297        }
     298    }
     299
     300    // build SFN prefix (8bits)
     301    if (prefix_length <= 8)
     302    {
     303        for( i=0 ; i<8 ; i++)
     304        {
     305            if ( i<prefix_length ) sfn[i] = to_upper( name[i] );
     306            else                   sfn[i] = 0x20;
     307        }
     308    }
     309    else
     310    {
     311        for( i=0 ; i<6 ; i++)
     312        {
     313            sfn[i] = to_upper( name[i] );
     314        }
     315        sfn[6] = 0x7E;
     316        sfn[7] = 0x31;
     317    }
     318
     319    // build SFN suffix (3 bits)
     320    if ( suffix_length == 0 )
     321    {
     322        sfn[8]  = 0x20;
     323        sfn[9]  = 0x20;
     324        sfn[10] = 0x20;
     325    }
     326    else if ( suffix_length == 1 )
     327    {
     328        sfn[8]  = to_upper( name[name_length-1] );
     329        sfn[9]  = 0x20;
     330        sfn[10] = 0x20;
     331    }
     332    else if ( suffix_length == 2 )
     333    {
     334        sfn[8]  = to_upper( name[name_length-2] );
     335        sfn[9]  = to_upper( name[name_length-1] );
     336        sfn[10] = 0x20;
     337    }
     338    else
     339    {
     340        sfn[8]  = to_upper( name[name_length-suffix_length] );
     341        sfn[9]  = to_upper( name[name_length-suffix_length+1] );
     342        sfn[10] = to_upper( name[name_length-suffix_length+2] );
     343    }
     344
     345    // compute 8 bits checksum
     346    uint8_t sum = 0;
     347    for ( i=0 ; i<11 ; i++ )
     348    {
     349        sum = (((sum & 0x01)<<7) | ((sum & 0xFE)>>1)) + sfn[i];
     350    }
     351    *checksum = sum;
     352
     353    // set nb_lfn and length values
     354    if      ( name_length <= 13 )
     355    {
     356        *nb_lfn  = 1;
     357        return 0;
     358    }
     359    else if ( name_length <= 26 )
     360    {
     361        *nb_lfn  = 2;
     362        return 0;
     363    }
     364    else if ( name_length <= 31 )
     365    {
     366        *nb_lfn  = 3;
     367        return 0;
     368    }
     369    else
     370    {
     371        return 1;
     372    }
     373}   // end fatfs_name_format() 
     374
     375//////////////////////////////////////////////////////////////////////////////////////////
     376// This static function - atomically - decrements "free_clusters", and updates
     377// the "free_cluster_hint" shared variables in the FATFS context in the FAT cluster.
     378// It scan the FAT to find the first free slot larger than the <cluster> argument,
     379// and set "free_cluster_hint" <= (free - 1).
     380//
     381// WARNING : The free_lock protecting exclusive access to these variables
     382//           must be taken by the calling function.
     383//////////////////////////////////////////////////////////////////////////////////////////
     384// @ cluster     : recently allocated cluster index in FAT.
     385//////////////////////////////////////////////////////////////////////////////////////////
     386static error_t fatfs_free_clusters_decrement( uint32_t  cluster )
     387{
     388    fatfs_ctx_t * loc_ctx;      // local pointer on local FATFS context
     389    fatfs_ctx_t * fat_ctx;      // local pointer on FATFS in cluster containing FAT mapper
     390    cxy_t         mapper_cxy;   // cluster identifier for cluster containing FAT mapper
     391    xptr_t        mapper_xp;    // extended pointer on FAT mapper
     392    xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
     393    xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable
     394    uint32_t      numb;         // "free_clusters" variable current value
     395    uint32_t      page_id;      // page index in FAT mapper
     396    uint32_t      slot_id;      // slot index in one page of FAT (1024 slots per page)
     397    uint32_t      page_max;     // max number of pages in FAT mapper
     398    xptr_t        page_xp;      // extended pointer on current page in FAT mapper
     399    xptr_t        slot_xp;      // extended pointer on current slot in FAT mapper
     400
     401#if DEBUG_FATFS_FREE_CLUSTERS
     402uint32_t   cycle = (uint32_t)hal_get_cycles();
     403thread_t * this  = CURRENT_THREAD;
     404if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
     405printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n",
     406__FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
     407#endif
     408
     409    // get local pointer on local FATFS context
     410    loc_ctx = fs_context[FS_TYPE_FATFS].extend;
     411
     412    // get cluster containing FAT mapper
     413    mapper_xp  = loc_ctx->fat_mapper_xp;
     414    mapper_cxy = GET_CXY( mapper_xp );
     415
     416    // get local pointer on FATFS context in FAT cluster
     417    fat_ctx = hal_remote_lpt( XPTR( mapper_cxy , &fs_context[FS_TYPE_FATFS].extend ) );
     418
     419    // build extended pointers on free_clusters, and free_cluster_hint
     420    hint_xp = XPTR( mapper_cxy , &fat_ctx->free_cluster_hint );
     421    numb_xp = XPTR( mapper_cxy , &fat_ctx->free_clusters );
     422
     423    // update "free_clusters"
     424    numb = hal_remote_l32( numb_xp );
     425    hal_remote_s32( numb_xp , numb - 1 );
     426
     427    // scan FAT mapper to find the first free slot > cluster
     428    // and update "free_cluster_hint" as (free - 1)
     429    page_id  = (cluster + 1) >> 10;
     430    slot_id  = (cluster + 1) & 0x3FF;
     431    page_max = (loc_ctx->fat_sectors_count >> 3);
     432
     433    // scan FAT mapper / loop on pages
     434    while ( page_id < page_max )           
     435    {
     436        // get current page from mapper
     437        page_xp = mapper_remote_get_page( mapper_xp , page_id );
     438
     439        if( page_xp == XPTR_NULL )
     440        {
     441            printk("\n[ERROR] in %s : cannot access FAT mapper\n", __FUNCTION__ );
     442            return -1;
     443        }
     444
     445        // scan FAT mapper / loop on slots
     446        while ( slot_id < 1024 )
     447        {
     448            // get extended pointer on current slot
     449            slot_xp = ppm_page2base( page_xp ) + (slot_id << 2);
     450
     451            // test FAT slot value
     452            if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER )
     453            {
     454                // update "free_cluster_hint" <= (free - 1)
     455                hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 );
     456
     457#if DEBUG_FATFS_FREE_CLUSTERS
     458cycle = (uint32_t)hal_get_cycles();
     459if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
     460printk("\n[%s] thread[%x,%x] exit / hint %x / free_clusters %x / cycle %d\n",
     461__FUNCTION__, this->process->pid, this->trdid,
     462hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle );
     463#endif
     464                return 0;
     465            }
     466
     467            // increment  slot_id
     468            slot_id++;
     469
     470        }  // end loop on slots
     471
     472        // update loop variables
     473        page_id++;
     474        slot_id = 0;
     475
     476    }  // end loop on pages
     477
     478    // return error if no free cluster found
     479    printk("\n[ERROR] in %s : No free cluster found\n", __FUNCTION__ );
     480    return -1;
     481   
     482}  // end fatfs_free_clusters_decrement()
     483
     484//////////////////////////////////////////////////////////////////////////////////////////
     485// This static function atomically increments <free_clusters>, and updates
     486// the <free_cluster_hint> shared variables in the FATFS context in the FAT cluster.
     487// If the released cluster index is smaller than the current (hint + 1) value,
     488// it set "free_cluster_hint" <= cluster - 1.
     489//
     490// WARNING : The free_lock protecting exclusive access to these variables
     491//           must be taken by the calling function.
     492//////////////////////////////////////////////////////////////////////////////////////////
     493// @ cluster     : recently released cluster index in FAT.
     494//////////////////////////////////////////////////////////////////////////////////////////
     495static void fatfs_free_clusters_increment( uint32_t  cluster )
     496{
     497    fatfs_ctx_t * loc_ctx;      // local pointer on local FATFS context
     498    fatfs_ctx_t * fat_ctx;      // local pointer on FATFS in cluster containing FAT mapper
     499    cxy_t         fat_cxy;      // cluster identifier for cluster containing FAT mapper
     500    xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
     501    xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable
     502    uint32_t      hint;         // "free_cluster_hint" variable current value
     503    uint32_t      numb;         // "free_clusters" variable current value
     504
     505    // get local pointer on local FATFS context
     506    loc_ctx = fs_context[FS_TYPE_FATFS].extend;
     507
     508    // get cluster containing FAT mapper
     509    fat_cxy = GET_CXY( loc_ctx->fat_mapper_xp );
     510
     511    // get local pointer on FATFS context in FAT cluster
     512    fat_ctx = hal_remote_lpt( XPTR( fat_cxy , &fs_context[FS_TYPE_FATFS].extend ) );
     513
     514    // build extended pointers free_lock, free_clusters, and free_cluster_hint
     515    hint_xp = XPTR( fat_cxy , &fat_ctx->free_cluster_hint );
     516    numb_xp = XPTR( fat_cxy , &fat_ctx->free_clusters );
     517
     518    // get current value of free_cluster_hint and free_clusters
     519    hint = hal_remote_l32( hint_xp );
     520    numb = hal_remote_l32( numb_xp );
     521
     522    // update free_cluster_hint if required
     523    if ( cluster < (hint + 1) ) hal_remote_s32( hint_xp , (cluster - 1) );
     524
     525    // update free_clusters
     526    hal_remote_s32( numb_xp , numb + 1 );
     527
     528#if DEBUG_FATFS_FREE_CLUSTERS
     529thread_t * this = CURRENT_THREAD;
     530if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
     531printk("\n[%s] thread[%x,%x] updates free cluster info : hint %x / number %x\n",
     532__FUNCTION__, this->process->pid, this->trdid,
     533hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) );
     534#endif
     535
     536}  // end fatfs_free_clusters_increment()
     537
     538//////////////////////////////////////////////////////////////////////////////////////////
     539// This recursive function is called by the generic function fatfs_release_all_clusters()
     540// It release all clusters allocated to a given inode in the FAT mapper.
     541// The removal is done in reverse order of the linked list (from last to first).
     542// It does NOT update the FS on the IOC device.
     543//////////////////////////////////////////////////////////////////////////////////////////
     544// @ fat_mapper_xp : extended pointer on FAT mapper.
     545// @ cluster       : cluster index in FAT.
     546// @ return 0 if success / return -1 if error (cannot access FAT)
     547//////////////////////////////////////////////////////////////////////////////////////////
     548static error_t fatfs_recursive_release( xptr_t    fat_mapper_xp,
     549                                        uint32_t  cluster )
     550{
     551    uint32_t next;
     552
     553    // get next cluster from FAT mapper
     554    if ( mapper_remote_get_32( fat_mapper_xp , cluster , &next ) ) return -1;
     555
     556#if (DEBUG_FATFS_RELEASE_INODE & 1)
     557thread_t * this = CURRENT_THREAD;
     558if ( DEBUG_FATFS_RELEASE_INODE < (uint32_t)hal_get_cycles() )
     559printk("\n[%s] thread[%x,%x] access FAT for cluster %x / next %x\n",
     560__FUNCTION__, this->process->pid, this->trdid, cluster, next );
     561#endif
     562
     563    if ( next < END_OF_CHAIN_CLUSTER_MIN )  // non terminal case
     564    {
     565        // call fatfs_recursive_release() on next cluster
     566        if ( fatfs_recursive_release( fat_mapper_xp , next ) ) return -1;
     567    }       
     568
     569    // update current cluster in FAT mapper
     570    if ( mapper_remote_set_32( fat_mapper_xp, cluster , FREE_CLUSTER ) ) return -1;
     571
     572    // Update free_cluster_hint and free_clusters in FAT context
     573    fatfs_free_clusters_increment( cluster );
     574
     575    return 0;
     576
     577}  // end fatfs_recursive_release()
    216578
    217579
     
    220582//////////////////////////////////////////////////////////////////////////////////////////
    221583
    222 //////////////////////////////////////////////////////////////////////////////////////////
     584//////////////////////////////
    223585void fatfs_ctx_display( void )
    224586{
     587    // get pointer on local FATFS context
    225588    vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
    226589    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
    227590
    228591    printk("\n*** FAT context ***\n"
    229            "- fat_sectors      = %d\n"
    230            "- sector size      = %d\n"
    231            "- cluster size     = %d\n"
    232            "- fat_first_lba    = %d\n"
    233            "- data_first_lba   = %d\n"
    234            "- root_dir_cluster = %d\n"
    235            "- mapper_xp        = %l\n",
     592           "- fat_sectors       = %d\n"
     593           "- sector size       = %d\n"
     594           "- cluster size      = %d\n"
     595           "- fat_first_lba     = %d\n"
     596           "- data_first_lba    = %d\n"
     597           "- root_dir_cluster  = %d\n"
     598           "- free_clusters     = %d\n"
     599           "- free_cluster_hint = %d\n"
     600           "- fat_mapper_xp     = %l\n",
    236601           fatfs_ctx->fat_sectors_count,
    237602           fatfs_ctx->bytes_per_sector,
     
    240605           fatfs_ctx->cluster_begin_lba,
    241606           fatfs_ctx->root_dir_cluster,
     607           fatfs_ctx->free_clusters,
     608           fatfs_ctx->free_cluster_hint,
    242609           fatfs_ctx->fat_mapper_xp );
    243 }
    244 
    245 /////////////////////////////////////////////
    246 error_t fatfs_get_cluster( mapper_t * mapper,
    247                            uint32_t   first_cluster_id,
     610
     611}  // end fatfs_ctx_display()
     612
     613//////////////////////////////////////////
     614void fatfs_display_fat( uint32_t  page_id,
     615                        uint32_t  nentries )
     616{
     617    uint32_t line;
     618    uint32_t maxline;
     619
     620    // copute numner of lines to display
     621    maxline = nentries >> 3;
     622    if( nentries & 0x7 ) maxline++;
     623
     624    // get pointer on local FATFS context
     625    vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
     626    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
     627
     628    // get extended pointer on FAT mapper
     629    xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp;
     630
     631    // get extended pointer and cluster of FAT mapper requested page
     632    xptr_t     page_xp  = mapper_remote_get_page( fat_mapper_xp , page_id );
     633
     634    // get extended pointer on requested page base
     635    xptr_t     base_xp  = ppm_page2base( page_xp );
     636
     637    printk("\n***** FAT content / page %d *****\n", page_id );
     638    for( line = 0 ; line < maxline ; line++ )
     639    {
     640        printk("%x : %X | %X | %X | %X | %X | %X | %X | %X\n", (line<<3),
     641        hal_remote_l32( base_xp + ((line<<5)      ) ),
     642        hal_remote_l32( base_xp + ((line<<5) + 4  ) ),
     643        hal_remote_l32( base_xp + ((line<<5) + 8  ) ),
     644        hal_remote_l32( base_xp + ((line<<5) + 12 ) ),
     645        hal_remote_l32( base_xp + ((line<<5) + 16 ) ),
     646        hal_remote_l32( base_xp + ((line<<5) + 20 ) ),
     647        hal_remote_l32( base_xp + ((line<<5) + 24 ) ),
     648        hal_remote_l32( base_xp + ((line<<5) + 28 ) ) );
     649    }
     650
     651}  // end fatfs_display_fat()
     652
     653///////////////////////////////////////////////////////
     654error_t fatfs_get_cluster( uint32_t   first_cluster_id,
    248655                           uint32_t   searched_page_index,
    249656                           uint32_t * searched_cluster_id )
    250657{
    251     page_t   * current_page_desc;      // pointer on current page descriptor
    252     uint32_t * current_page_buffer;    // pointer on current page (array of uint32_t)
     658    xptr_t     current_page_xp;        // pointer on current page descriptor
     659    uint32_t * buffer;                 // pointer on current page (array of uint32_t)
    253660    uint32_t   current_page_index;     // index of current page in FAT
    254661    uint32_t   current_page_offset;    // offset of slot in current page
     
    256663    uint32_t   next_cluster_id;        // content of current FAT slot
    257664
    258     assert( (searched_page_index > 0) ,
    259     "no FAT access required for first page\n");
     665assert( (searched_page_index > 0) ,
     666"no FAT access required for first page\n");
    260667
    261668#if DEBUG_FATFS_GET_CLUSTER
    262 uint32_t cycle = (uint32_t)hal_get_cycles();
     669uint32_t   cycle = (uint32_t)hal_get_cycles();
     670thread_t * this  = CURRENT_THREAD;
    263671if( DEBUG_FATFS_GET_CLUSTER < cycle )
    264 printk("\n[DBG] %s : thread %x enter / first_cluster_id %d / searched_index / cycle %d\n",
    265 __FUNCTION__, CURRENT_THREAD, first_cluster_id, searched_page_index, cycle );
    266 #endif
    267 
    268     // get number of FAT slots per page
    269     uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2;
    270 
    271     // initialize loop variable
    272     current_page_index  = first_cluster_id / slots_per_page;
    273     current_page_offset = first_cluster_id % slots_per_page;
     672printk("\n[%s] thread[%x,%x] enter / first_cluster_id %d / searched_index / cycle %d\n",
     673__FUNCTION__, this->process->pid, this->trdid, first_cluster_id, searched_page_index, cycle );
     674#endif
     675
     676    // get local pointer on local FATFS context
     677    fatfs_ctx_t * ctx = fs_context[FS_TYPE_FATFS].extend;
     678
     679    // get extended pointer and cluster on FAT mapper
     680    xptr_t mapper_xp  = ctx->fat_mapper_xp;
     681    cxy_t  mapper_cxy = GET_CXY( mapper_xp );
     682
     683    // initialize loop variable (1024 slots per page)
     684    current_page_index  = first_cluster_id >> 10;
     685    current_page_offset = first_cluster_id & 0x3FF;
    274686    page_count_in_file  = 0;
    275687    next_cluster_id     = 0xFFFFFFFF;
     
    279691    {
    280692        // get pointer on current page descriptor
    281         current_page_desc = mapper_get_page( mapper , current_page_index );
    282 
    283         if( current_page_desc == NULL ) return EIO;
     693        current_page_xp = mapper_remote_get_page( mapper_xp , current_page_index );
     694
     695        if( current_page_xp == XPTR_NULL )
     696        {
     697            // TODO
     698            return -1;
     699        }
    284700
    285701        // get pointer on buffer for current page
    286         xptr_t base_xp = ppm_page2base( XPTR( local_cxy , current_page_desc ) );
    287         current_page_buffer = (uint32_t *)GET_PTR( base_xp );
     702        xptr_t base_xp = ppm_page2base( current_page_xp );
     703        buffer = (uint32_t *)GET_PTR( base_xp );
    288704
    289705        // get FAT slot content
    290         next_cluster_id = current_page_buffer[current_page_offset];
     706        next_cluster_id = hal_remote_l32( XPTR( mapper_cxy , &buffer[current_page_offset] ) );
    291707
    292708#if (DEBUG_FATFS_GET_CLUSTER & 1)
    293709if( DEBUG_FATFS_GET_CLUSTER < cycle )
    294 printk("\n[DBG] %s : traverse FAT / current_page_index = %d\n"
     710printk("\n[%s] traverse FAT / current_page_index = %d\n"
    295711"current_page_offset = %d / next_cluster_id = %d\n",
    296712__FUNCTION__, current_page_index, current_page_offset , next_cluster_id );
     
    298714
    299715        // update loop variables
    300         current_page_index  = next_cluster_id / slots_per_page;
    301         current_page_offset = next_cluster_id % slots_per_page;
     716        current_page_index  = next_cluster_id >> 10;
     717        current_page_offset = next_cluster_id & 0x3FF;
    302718        page_count_in_file++;
    303719    }
    304720
    305     if( next_cluster_id == 0xFFFFFFFF ) return EIO;
     721    if( next_cluster_id == 0xFFFFFFFF ) return -1;
    306722   
    307723#if DEBUG_FATFS_GET_CLUSTER
    308724cycle = (uint32_t)hal_get_cycles();
    309725if( DEBUG_FATFS_GET_CLUSTER < cycle )
    310 printk("\n[DBG] %s : thread %x exit / searched_cluster_id = %d / cycle %d\n",
    311 __FUNCTION__, CURRENT_THREAD, next_cluster_id / cycle );
     726printk("\n[%s] thread[%x,%x] exit / searched_cluster_id = %d / cycle %d\n",
     727__FUNCTION__, this->process->pid, this->trdid, next_cluster_id / cycle );
    312728#endif
    313729
     
    320736
    321737///////////////////////////////////////////////////////////////////////////////////////
    322 // Generic API : the following functions are called by the kernel (VFS)
     738// Generic API : the following functions are called by the kernel VFS
    323739//               and must be defined by all supported file systems.
    324740///////////////////////////////////////////////////////////////////////////////////////
     
    342758    uint8_t     * buffer;
    343759
    344 #if DEBUG_FATFS_INIT
     760#if DEBUG_FATFS_CTX_INIT
    345761uint32_t cycle = (uint32_t)hal_get_cycles();
    346 if( DEBUG_FATFS_INIT < cycle )
    347 printk("\n[DBG] %s : thread %x enter for fatfs_ctx = %x / cycle %d\n",
    348 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx , cycle );
    349 #endif
    350 
    351     assert( (fatfs_ctx != NULL) ,
    352     "cannot allocate memory for FATFS context\n" );
     762if( DEBUG_FATFS_CTX_INIT < cycle )
     763printk("\n[%s] thread[%x,%x] enter for fatfs_ctx = %x / cycle %d\n",
     764__FUNCTION__ , this->process->pid, this->trdid, fatfs_ctx , cycle );
     765#endif
     766
     767// check argument
     768assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL\n" );
     769
     770// check only cluster 0 does FATFS init
     771assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS\n");
    353772
    354773    // allocate a 512 bytes buffer to store the boot record
     
    357776        buffer      = (uint8_t *)kmem_alloc( &req );
    358777
    359     assert( (buffer != NULL) ,
    360     "cannot allocate memory for 512 bytes buffer\n" );
     778    if( buffer == NULL )
     779    {
     780        printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
     781        hal_core_sleep();
     782    }
    361783     
    362     // load the boot record from device
    363     // using a synchronous access to IOC device 
     784    // load the BOOT record from device
    364785    error = dev_ioc_sync_read( buffer , 0 , 1 );
    365786
    366     assert( (error == 0) ,
    367     "cannot access boot record\n" );
    368 
    369 #if (DEBUG_FATFS_INIT & 0x1)
    370 if( DEBUG_FATFS_INIT < cycle )
     787    if ( error )
     788    {
     789        printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ );
     790        hal_core_sleep();
     791    }
     792
     793#if (DEBUG_FATFS_CTX_INIT & 0x1)
     794if( DEBUG_FATFS_CTX_INIT < cycle )
    371795{
    372796    uint32_t   line;
     
    387811#endif
    388812
    389     // check sector size from boot record
     813    // get sector size from boot record
    390814    uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 );
    391 
    392     assert( (sector_size == 512) ,
    393             "sector size must be 512 bytes\n" );
    394 
    395     // check cluster size from boot record
     815    if ( sector_size != 512 )
     816    {
     817        printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ );
     818        hal_core_sleep();
     819    }
     820
     821    // get cluster size from boot record
    396822    uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 );
    397 
    398     assert( (nb_sectors == 8) ,
    399     "cluster size must be 8 sectors\n" );
    400 
    401     // check number of FAT copies from boot record
     823    if ( nb_sectors != 8 )
     824    {
     825        printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ );
     826        hal_core_sleep();
     827    }
     828
     829    // get number of FAT copies from boot record
    402830    uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 );
    403 
    404     assert( (nb_fats == 1) ,
    405     "number of FAT copies must be 1\n" );
    406 
    407     // get & check number of sectors in FAT from boot record
     831    if ( nb_fats != 1 )
     832    {
     833        printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ );
     834        hal_core_sleep();
     835    }
     836
     837    // get number of sectors in FAT from boot record
    408838    uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 );
    409 
    410     assert( ((fat_sectors & 0xF) == 0) ,
    411     "FAT not multiple of 16 sectors\n");
    412 
    413     // get and check root cluster from boot record
     839    if ( (fat_sectors & 0xF) != 0 )
     840    {
     841        printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ );
     842        hal_core_sleep();
     843    }
     844
     845    // get root cluster from boot record
    414846    uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 );
    415 
    416     assert( (root_cluster == 2) ,
    417     "root cluster index must be  2\n");
     847    if ( root_cluster != 2 )
     848    {
     849        printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ );
     850        hal_core_sleep();
     851    }
    418852
    419853    // get FAT lba from boot record
    420854    uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 );
     855
     856    // get FS_INFO sector lba from boot record
     857    uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer , 1 );
     858
     859    // load the FS_INFO record from device
     860    error = dev_ioc_sync_read( buffer , fs_info_lba , 1 );
     861
     862    if ( error )
     863    {
     864        printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ );
     865        hal_core_sleep();
     866    }
     867
     868    // get free clusters number from FS_INFO record
     869    uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer , 1 );
     870    if ( free_clusters >= fat_sectors << 7 )
     871    {
     872        printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ );
     873        hal_core_sleep();
     874    }
     875
     876    // get cluster hint from FS_INFO record
     877    uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer , 1 );
     878    if ( free_cluster_hint >= fat_sectors << 7 )
     879    {
     880        printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ );
     881        hal_core_sleep();
     882    }
    421883
    422884    // release the 512 bytes buffer
     
    427889    // allocate a mapper for the FAT itself
    428890    mapper_t * fat_mapper = mapper_create( FS_TYPE_FATFS );
    429 
    430     assert( (fat_mapper != NULL) ,
    431     "no memory for FAT mapper" );
     891    if ( fat_mapper == NULL )
     892    {
     893        printk("\n[PANIC] in %s : no memory for FAT mapper\n", __FUNCTION__ );
     894        hal_core_sleep();
     895    }
    432896
    433897    // WARNING : the inode field MUST be NULL for the FAT mapper
     
    441905    fatfs_ctx->cluster_begin_lba     = fat_lba + fat_sectors;
    442906    fatfs_ctx->root_dir_cluster      = 2;
    443     fatfs_ctx->last_allocated_sector = 0;    // TODO ???
    444     fatfs_ctx->last_allocated_index  = 0;    // TODO ???
    445907    fatfs_ctx->fat_mapper_xp         = XPTR( local_cxy , fat_mapper );
    446 
    447 #if DEBUG_FATFS_INIT
     908    fatfs_ctx->free_clusters         = free_clusters;
     909    fatfs_ctx->free_cluster_hint     = free_cluster_hint;
     910
     911    remote_queuelock_init( XPTR( local_cxy , &fatfs_ctx->free_lock ) , LOCK_FATFS_FREE );
     912
     913#if DEBUG_FATFS_CTX_INIT
    448914cycle = (uint32_t)hal_get_cycles();
    449 if( DEBUG_FATFS_INIT < cycle )
    450 printk("\n[DBG] %s : thread %x exit for fatfs_ctx = %x / cycle %d\n",
    451 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx , cycle );
     915if( DEBUG_FATFS_CTX_INIT < cycle )
     916printk("\n[%s]  thread[%x,%x] exit for fatfs_ctx = %x / cycle %d\n",
     917__FUNCTION__, this->process->pid, this->trdid, fatfs_ctx, cycle );
    452918#endif
    453919
     
    463929}
    464930
    465 //////////////////////////////////////////////
    466 error_t fatfs_mapper_move_page( page_t * page,
    467                                 bool_t   to_mapper )
     931///////////////////////////////////////////////
     932error_t fatfs_add_dentry( vfs_inode_t  * inode,
     933                          vfs_dentry_t * dentry )
    468934{
    469935    error_t       error;
    470     vfs_inode_t * inode;
    471     mapper_t    * mapper;
    472     uint32_t      index;       // page index in mapper
    473     uint8_t     * buffer;      // page base address in mapper
    474     uint32_t      count;       // number of sectors in a page
    475     uint32_t      lba;         // block address on device
    476     fatfs_ctx_t * fatfs_ctx;   // pointer on local FATFS context
    477 
    478     // get pointer on mapper and page index from page descriptor
    479     mapper = page->mapper;
    480     index  = page->index;
    481 
    482     // get inode pointer from mapper
    483     inode = mapper->inode;
    484 
    485 #if DEBUG_FATFS_MOVE
    486 uint32_t cycle = (uint32_t)hal_get_cycles();
    487 if( DEBUG_FATFS_MOVE < cycle )
    488 printk("\n[DBG] %s : thread %x enter / page %d / inode %x / mapper %x / cycle %d\n",
    489 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle );
    490 #endif
    491 
    492     // get page base address
    493     xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    494     buffer = (uint8_t *)GET_PTR( base_xp );
    495  
    496     // get number of sectors for one page (from FATFS context)
    497     fatfs_ctx = (fatfs_ctx_t *)fs_context[FS_TYPE_FATFS].extend;
    498     count = fatfs_ctx->sectors_per_cluster;
    499 
    500     // test FAT/normal inode
    501     if( inode == NULL )      // it is the FAT mapper
    502     {
    503         // get lba from page index
    504         lba = fatfs_ctx->fat_begin_lba + (count * index);
    505  
    506 #if (DEBUG_FATFS_MOVE & 0x1)
    507 if( DEBUG_FATFS_MOVE < cycle )
    508 printk("\n[DBG] %s : access FAT on device / lba = %d\n", __FUNCTION__ , lba );
    509 #endif
    510 
    511         // access device
    512         if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count );
    513         else            error = dev_ioc_write( buffer , lba , count );     
    514 
    515         if( error ) return EIO;
    516     }
    517     else                     // it is a normal inode mapper
    518     {
    519         uint32_t  searched_cluster_id;
    520 
    521         // get first_cluster_id from inode extension
    522         uint32_t  first_cluster_id = (uint32_t)(intptr_t)inode->extend;
    523 
    524         // compute cluster_id
    525         if( index == 0 )            // no need to access FAT mapper
     936    uint32_t      length;        // dentry name length
     937    uint32_t      nb_lfn;        // number or required LFN
     938    char          sfn[11];       // buffer for SFN name
     939    uint8_t       checksum;      // name checksum
     940    mapper_t    * mapper;        // loal pointer on parent inode mapper
     941    xptr_t        mapper_xp;     // extended pointer on parent inode mapper
     942    xptr_t        child_xp;      // extended pointer on child inode
     943    cxy_t         child_cxy;     // child inode cluster
     944    vfs_inode_t * child_ptr;     // child inode local pointer
     945    uint32_t      size;          // child inode size
     946    uint32_t      type;          // child inode type
     947    uint32_t      cluster;       // child inode cluster index
     948
     949#if DEBUG_FATFS_ADD_DENTRY
     950char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     951uint32_t   cycle = (uint32_t)hal_get_cycles();
     952thread_t * this  = CURRENT_THREAD;
     953vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
     954if( DEBUG_FATFS_ADD_DENTRY < cycle )
     955printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     956__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     957#endif
     958
     959// check arguments
     960assert( (inode != NULL) , "inode pointer is NULL\n" );
     961assert( (dentry != NULL) , "dentry pointer is NULL\n" );
     962assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" );
     963assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
     964 
     965    // get pointers on directory mapper
     966    mapper    = inode->mapper;
     967    mapper_xp = XPTR( local_cxy , mapper );
     968
     969    // get extended pointers on remote child inode
     970    child_xp  = dentry->child_xp;
     971    child_cxy = GET_CXY( child_xp );
     972    child_ptr = GET_PTR( child_xp );
     973
     974    // get relevant infos from child inode
     975    type    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
     976    size    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->size ) );
     977    cluster = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( child_cxy , &child_ptr->extend ) );
     978
     979    // analyse dentry name
     980    error = fatfs_name_format( dentry->name,
     981                               &length,
     982                               &nb_lfn,
     983                               sfn,
     984                               &checksum );
     985    if ( error )
     986    {
     987        printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ );
     988        return -1;
     989    }
     990                               
     991    // Search end of directory with two embedded loops:
     992    // - scan the pages in the mapper
     993    // - scan the entries in each page to find NO_MORE_ENTRY
     994
     995    xptr_t     page_xp;                 // extended pointer on page descriptor
     996    xptr_t     base_xp;                 // extended pointer on page base
     997    uint8_t  * base;                    // local pointer on page base (array of bytes)
     998    uint32_t   page_id = 0;             // page index in mapper
     999    uint32_t   offset  = 0;             // position in page
     1000    uint32_t   found   = 0;             // NO_MORE_ENTRY found
     1001
     1002    // loop on pages in mapper
     1003    while ( found == 0 )
     1004    {
     1005        // get extended pointer on page descriptor in mapper
     1006        page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     1007
     1008        if ( page_xp == XPTR_NULL )
    5261009        {
    527             searched_cluster_id = first_cluster_id;
     1010            printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
     1011            return -1;
    5281012        }
    529         else                        // FAT mapper access required
     1013       
     1014        // get pointer on page base
     1015        base_xp = ppm_page2base( page_xp );
     1016        base = GET_PTR( base_xp );
     1017
     1018        // loop on directory entries in this page
     1019        while ( (offset < 4096) && (found == 0) )
    5301020        {
    531             // get cluster and local pointer on FAT mapper
    532             xptr_t     fat_mapper_xp  = fatfs_ctx->fat_mapper_xp;
    533             cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
    534             mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
    535 
    536             // access FAT mapper
    537             if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
     1021            if ( fatfs_get_record( LDIR_ORD, (base + offset), 0 ) == NO_MORE_ENTRY )
    5381022            {
    539 
    540 #if (DEBUG_FATFS_MOVE & 0x1)
    541 if( DEBUG_FATFS_MOVE < cycle )
    542 printk("\n[DBG] %s : access local FAT mapper\n"
    543 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n",
    544 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index );
    545 #endif
    546                 error = fatfs_get_cluster( fat_mapper_ptr,
    547                                            first_cluster_id,
    548                                            index,
    549                                            &searched_cluster_id );
     1023                found = 1;
     1024            } 
     1025            else
     1026            {
     1027                offset = offset + 32;
    5501028            }
    551             else                                 // FAT mapper is remote
     1029        }  // end loop on entries
     1030
     1031        if ( found == 0 )
     1032        {
     1033            page_id++;
     1034            offset = 0;
     1035        }
     1036    }  // end loop on pages
     1037
     1038    // Modify the directory mapper: depending on the name length,
     1039    // the new child requires to write (3, 4, or 5) directory entries.
     1040    // To actually register the new child, we use a 5 steps FSM
     1041    // (one state per entry to be written), that is traversed as:
     1042    // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
     1043    // At most two pages are modified:
     1044    // - the page containing the NO_MORE_ENTRY is always modified
     1045    // - the following page can be modified if the name spread on to pages.
     1046
     1047    char * name = dentry->name;
     1048
     1049    uint32_t step;          // FSM state
     1050
     1051    if      ( nb_lfn == 1 ) step = 3;
     1052    else if ( nb_lfn == 2 ) step = 4;
     1053    else if ( nb_lfn == 3 ) step = 5;
     1054   
     1055    uint8_t  * entry;       // pointer on directory entry to be written
     1056    uint32_t   i;           // byte index in one 32 bytes directory
     1057    uint32_t   c;           // character index in name
     1058
     1059    while ( step )   
     1060    {
     1061        // when the new child is split on two pages,
     1062        // we need to access a new page in mapper
     1063        if ( offset >= 4096 )
     1064        {
     1065            // copy the modified page to IOC device
     1066            fatfs_move_page( page_xp , false );   
     1067
     1068            // get the next page in FAT mapper
     1069            page_xp  = mapper_remote_get_page( mapper_xp , page_id + 1 );
     1070
     1071            if ( page_xp == XPTR_NULL )
    5521072            {
    553 
    554 #if (DEBUG_FATFS_MOVE & 0x1)
    555 if( DEBUG_FATFS_MOVE < cycle )
    556 printk("\n[DBG] %s : access remote FAT mapper\n"
    557 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n",
    558 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index );
    559 #endif
    560                 rpc_fatfs_get_cluster_client( fat_mapper_cxy,
    561                                               fat_mapper_ptr,
    562                                               first_cluster_id,
    563                                               index,
    564                                               &searched_cluster_id,
    565                                               &error );
     1073                printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
     1074                return -1;
    5661075            }
    567 
    568             if( error )  return EIO;
     1076       
     1077            // get pointer on page base
     1078            base_xp = ppm_page2base( page_xp );
     1079            base = GET_PTR( base_xp );
     1080           
     1081            // update offset
     1082            offset = 0;
    5691083        }
    5701084
    571 #if (DEBUG_FATFS_MOVE & 0x1)
    572 if( DEBUG_FATFS_MOVE < cycle )
    573 printk("\n[DBG] %s : access device for inode %x / cluster_id %d\n",
    574 __FUNCTION__ , inode , searched_cluster_id );
    575 #endif
    576 
    577         // get lba from cluster_id
    578         lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id );
    579 
    580         // access device
    581         if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count );
    582         else            error = dev_ioc_write( buffer , lba , count );     
    583 
    584         if( error ) return EIO;
    585     }
    586 
    587 #if DEBUG_FATFS_MOVE
     1085        // compute directory entry address
     1086        entry = base + offset;
     1087
     1088#if (DEBUG_FATFS_ADD_DENTRY & 1)
     1089if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1090printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d\n",
     1091__FUNCTION__, step, offset, nb_lfn );
     1092#endif
     1093
     1094        // write 32 bytes (one directory entry) per iteration
     1095        switch ( step )
     1096        {
     1097            case 5:   // write LFN3 entry
     1098            {
     1099                c = 26;
     1100                // scan the 32 bytes in dir_entry
     1101                for ( i = 0 ; i < 32 ; i++ )
     1102                {
     1103                    if (i == 0)
     1104                    {
     1105                        if ( nb_lfn == 3) entry[i] = 0x43;
     1106                        else              entry[i] = 0x03;
     1107                    }
     1108                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1109                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1110                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1111                              ( c < length ) )
     1112                    {
     1113                                          entry[i] = name[c];
     1114                                          c++;
     1115                    }
     1116                    else if (i == 11)     entry[i] = 0x0F;
     1117                    else if (i == 13)     entry[i] = checksum;
     1118                    else                  entry[i] = 0x00;
     1119                }
     1120                step--;
     1121                break;
     1122            }
     1123            case 4:   // write LFN2 entry 
     1124            {
     1125                c = 13;
     1126                // scan the 32 bytes in dir_entry
     1127                for ( i = 0 ; i < 32 ; i++ )
     1128                {
     1129                    if (i == 0)
     1130                    {
     1131                        if ( nb_lfn == 2) entry[i] = 0x42;
     1132                        else              entry[i] = 0x02;
     1133                    }
     1134                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1135                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1136                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1137                              ( c < length ) )
     1138                    {
     1139                                          entry[i] = name[c];
     1140                                          c++;
     1141                    }
     1142                    else if (i == 11)     entry[i] = 0x0F;
     1143                    else if (i == 13)     entry[i] = checksum;
     1144                    else                  entry[i] = 0x00;
     1145                }
     1146                step--;
     1147                break;
     1148            }
     1149            case 3:   // Write LFN1 entry   
     1150            {
     1151                c = 0;
     1152                // scan the 32 bytes in dir_entry
     1153                for ( i = 0 ; i < 32 ; i++ )
     1154                {
     1155                    if (i == 0)
     1156                    {
     1157                        if ( nb_lfn == 1) entry[i] = 0x41;
     1158                        else              entry[i] = 0x01;
     1159                    }
     1160                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1161                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1162                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1163                              ( c < length ) )
     1164                    {
     1165                                          entry[i] = name[c];
     1166                                          c++;
     1167                    }
     1168                    else if (i == 11)     entry[i] = 0x0F;
     1169                    else if (i == 13)     entry[i] = checksum;
     1170                    else                  entry[i] = 0x00;
     1171                }
     1172                step--;
     1173                break;
     1174            }
     1175            case 2:   // write NORMAL entry     
     1176            {
     1177                // scan the 32 bytes in dir_entry
     1178                for ( i = 0 ; i < 32 ; i++ )
     1179                {
     1180                    if      ( i < 11 )                              // 8.3 SFN
     1181                    {
     1182                                          entry[i] = sfn[i];
     1183                    }
     1184                    else if (i == 11)                               // ATTR
     1185                    {
     1186                        if (type == INODE_TYPE_DIR)  entry[i] = 0x10;
     1187                        else                         entry[i] = 0x20;
     1188                    }
     1189                    else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
     1190                    else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
     1191                    else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
     1192                    else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
     1193                    else if (i == 28)     entry[i] = size>>0;       // size.B0
     1194                    else if (i == 29)     entry[i] = size>>8;       // size.B1
     1195                    else if (i == 30)     entry[i] = size>>16;      // size.B2
     1196                    else if (i == 31)     entry[i] = size>>24;      // size.B3
     1197                    else                  entry[i] = 0x00;
     1198                }
     1199
     1200                // update the "extend" field in dentry descriptor
     1201                dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5);
     1202
     1203                step--;
     1204                break;
     1205            }
     1206            case 1:   // write NOMORE entry 
     1207            {
     1208                entry [0] = 0x00;
     1209                step--;
     1210                break;
     1211            }
     1212        } // end switch step
     1213
     1214        offset += 32;
     1215
     1216    } // exit while     
     1217
     1218    // copy the modified page to the IOC device
     1219    fatfs_move_page( page_xp , false );   
     1220
     1221#if DEBUG_FATFS_ADD_DENTRY
    5881222cycle = (uint32_t)hal_get_cycles();
    589 if( DEBUG_FATFS_MOVE < cycle )
    590 printk("\n[DBG] %s : thread %x exit / page %d / inode %x / mapper %x / cycle %d\n",
    591 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle );
    592 #endif
    593 
    594 #if (DEBUG_FATFS_MOVE & 0x1)
    595 if( DEBUG_FATFS_MOVE < cycle )
    596 {
    597     uint32_t * tab = (uint32_t *)buffer;
    598     uint32_t line , word;
    599     printk("\n***** %s : First 64 words of loaded page\n", __FUNCTION__ );
    600     for( line = 0 ; line < 8 ; line++ )
    601     {
    602         printk("%X : ", line );
    603         for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] );
    604         printk("\n");
    605     }
    606 }
     1223if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1224printk("\n[%s]  thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
     1225__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    6071226#endif
    6081227
    6091228    return 0;
    6101229
    611 }  // end fatfs_mapper_move_page()
    612 
    613 /////////////////////////////////////////////////////
    614 error_t fatfs_inode_load( vfs_inode_t * parent_inode,
     1230}  // end fatfs_add_dentry()
     1231
     1232//////////////////////////////////////////////////
     1233error_t fatfs_remove_dentry( vfs_inode_t  * inode,
     1234                             vfs_dentry_t * dentry )
     1235{
     1236    xptr_t     mapper_xp;  // extended pointer on mapper
     1237    mapper_t * mapper;     // local pointer on mapper
     1238    xptr_t     page_xp;    // extended pointer on mapper page descriptor
     1239    xptr_t     base_xp;    // extended pointer on mapper page base
     1240    uint8_t  * base;       // local pointer on mapper page base
     1241
     1242#if DEBUG_FATFS_REMOVE_DENTRY
     1243char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1244uint32_t   cycle = (uint32_t)hal_get_cycles();
     1245thread_t * this  = CURRENT_THREAD;
     1246vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
     1247if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     1248printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     1249__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     1250#endif
     1251
     1252// check arguments
     1253assert( (inode != NULL) , "inode pointer is NULL\n" );
     1254assert( (dentry != NULL) , "dentry pointer is NULL\n" );
     1255assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" );
     1256assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
     1257
     1258    // get pointers on directory mapper
     1259    mapper    = inode->mapper;
     1260    mapper_xp = XPTR( local_cxy , mapper );
     1261
     1262    // compute number of LFN entries
     1263    uint32_t nb_lfn;
     1264    uint32_t name_length = strlen( dentry->name );
     1265
     1266    if      ( name_length <= 13 ) nb_lfn  = 1;
     1267    else if ( name_length <= 26 ) nb_lfn  = 2;
     1268    else                          nb_lfn  = 3;
     1269
     1270    // we must invalidate (2, 3 or 4) 32 bytes entries:
     1271    // the NORMAL entry (registered in dentry->extend) and all preceding LFN entries
     1272    // At most two pages are modified:
     1273    // - the page containing the NORMAL entry is always modified.
     1274    // - the preceding page is modified when the name spread on two pages.
     1275
     1276    // get 32 bytes directory entry index from dentry->extend
     1277    uint32_t  dentry_id  = (uint32_t)(intptr_t)dentry->extend;
     1278
     1279    // get page index and offset in parent directory mapper
     1280    uint32_t  page_id    = dentry_id >> 7;
     1281    uint32_t  offset     = (dentry_id & 0x7F)<<5;
     1282
     1283    // get extended pointer on page descriptor from parent directory mapper
     1284    page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     1285
     1286    if ( page_xp == XPTR_NULL )
     1287    {
     1288        printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
     1289        return -1;
     1290    }
     1291       
     1292    // get pointers on page base
     1293    base_xp = ppm_page2base( page_xp );
     1294    base    = GET_PTR( base_xp );
     1295
     1296    // invalidate NORMAL entry in directory cache
     1297    base[offset] = 0xE5;
     1298
     1299    // invalidate LFN entries
     1300    while ( nb_lfn )
     1301    {
     1302        if (offset == 0)  // we must load page (page_id - 1)
     1303        {
     1304
     1305// check page_id
     1306assert( (page_id > 0), "page_id and offset cannot be both 0\n" );
     1307
     1308            // copy the modified page to the IOC device
     1309            fatfs_move_page( page_xp , false );   
     1310
     1311            // get extended pointer on page descriptor from parent directory mapper
     1312            page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     1313
     1314            if ( page_xp == XPTR_NULL )
     1315            {
     1316                printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
     1317                return -1;
     1318            }
     1319       
     1320            // get pointers on page base
     1321            base_xp = ppm_page2base( page_xp );
     1322            base    = GET_PTR( base_xp );
     1323
     1324            // update offset
     1325            offset = 4096;
     1326        }
     1327
     1328        offset = offset - 32;
     1329
     1330// check for LFN entry
     1331assert( (fatfs_get_record( DIR_ATTR, base + offset, 0 ) == ATTR_LONG_NAME_MASK ),
     1332"this directory entry must be a LFN\n");
     1333
     1334        // invalidate LFN entry
     1335        base[offset] = 0xE5;
     1336
     1337        nb_lfn--;
     1338    }     
     1339
     1340    // copy the modified page to the IOC device
     1341    fatfs_move_page( page_xp , false );   
     1342   
     1343
     1344#if DEBUG_FATFS_REMOVE_DENTRY
     1345cycle = (uint32_t)hal_get_cycles();
     1346if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     1347printk("\n[%s]  thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
     1348__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     1349#endif
     1350
     1351    return 0;
     1352
     1353}  // end fatfs_remove_dentry
     1354
     1355////////////////////////////////////////////////////////////////
     1356error_t fatfs_child_init( vfs_inode_t * parent_inode,
    6151357                          char        * name,
    6161358                          xptr_t        child_inode_xp )
    6171359{
    6181360    // Two embedded loops:
    619     // - scan the parent mapper pages
     1361    // - scan the parent directory mapper pages
    6201362    // - scan the directory entries in each 4 Kbytes page
    6211363
    622 #if DEBUG_FATFS_LOAD
    623 uint32_t cycle = (uint32_t)hal_get_cycles();
    624 if( DEBUG_FATFS_LOAD < cycle )
    625 printk("\n[DBG] %s : thread %x enter for child <%s> in parent inode %x / cycle %d\n",
    626 __FUNCTION__ , CURRENT_THREAD , name , parent_inode , cycle );
    627 #endif
    628 
    629     mapper_t * mapper = parent_inode->mapper;
    630 
    631     assert( (mapper != NULL) , "parent mapper undefined\n");
     1364#if DEBUG_FATFS_CHILD_INIT
     1365char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1366uint32_t   cycle = (uint32_t)hal_get_cycles();
     1367thread_t * this  = CURRENT_THREAD;
     1368vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
     1369if( DEBUG_FATFS_CHILD_INIT < cycle )
     1370printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
     1371__FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle );
     1372#endif
     1373
     1374// check parent_inode and child_inode
     1375assert( (parent_inode != NULL) , "parent_inode is NULL\n" );
     1376assert( (child_inode_xp != XPTR_NULL ) , "child_inode is XPTR_NULL\n" );
     1377
     1378    mapper_t * mapper    = parent_inode->mapper;
     1379    xptr_t     mapper_xp = XPTR( local_cxy , mapper );
     1380
     1381// check parent mapper
     1382assert( (mapper != NULL) , "parent mapper is NULL\n");
    6321383   
    6331384    char       cname[CONFIG_VFS_MAX_NAME_LENGTH];  // name extracter from each directory entry
     
    6361387    char       lfn2[16];         // buffer for one partial cname
    6371388    char       lfn3[16];         // buffer for one partial cname
    638     page_t   * page;             // pointer on current page descriptor
    639     uint8_t  * base;             // pointer on current page base
    640     uint32_t   offset  = 0;      // byte offset in page
    641     uint32_t   index   = 0;      // page index in mapper
     1389    xptr_t     page_xp;          // extended pointer on page descriptor
     1390    xptr_t     base_xp;          // extended pointer on page base
     1391    uint8_t  * base;             // local pointer on page base
    6421392    uint32_t   attr;             // directory entry ATTR field
    6431393    uint32_t   ord;              // directory entry ORD field
    6441394    uint32_t   seq;              // sequence index
    645     uint32_t   lfn     = 0;      // LFN entries number
    646     uint32_t   size    = 0;      // searched file/dir size (bytes)
    647     uint32_t   cluster = 0;      // searched file/dir cluster index
    648     uint32_t   is_dir  = 0;      // searched file/dir type
    649     uint32_t   dentry;           // directory entry index
    650     int32_t    found   = 0;      // not found (0) / name found (1) / end of dir (-1)
     1395    uint32_t   lfn       = 0;    // LFN entries number
     1396    uint32_t   size      = 0;    // searched file/dir size (bytes)
     1397    uint32_t   cluster   = 0;    // searched file/dir cluster index
     1398    uint32_t   is_dir    = 0;    // searched file/dir type
     1399    int32_t    found     = 0;    // not found (0) / name found (1) / end of dir (-1)
     1400    uint32_t   page_id   = 0;    // page index in mapper
     1401    uint32_t   dentry_id = 0;    // directory entry index
     1402    uint32_t   offset    = 0;    // byte offset in page
    6511403
    6521404    // scan the parent directory mapper
     
    6541406    {
    6551407        // get one page
    656         page = mapper_get_page( mapper , index );
    657 
    658         assert( (page != NULL) , "bad parent mapper\n");
     1408        page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1409
     1410        if( page_xp == XPTR_NULL) return EIO;
    6591411
    6601412        // get page base
    661         xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    662         base = (uint8_t *)GET_PTR( base_xp );
    663 
    664 #if (DEBUG_FATFS_LOAD & 0x1)
    665 if( DEBUG_FATFS_LOAD < cycle )
     1413        base_xp = ppm_page2base( page_xp );
     1414        base    = (uint8_t *)GET_PTR( base_xp );
     1415
     1416#if (DEBUG_FATFS_CHILD_INIT & 0x1)
     1417if( DEBUG_FATFS_CHILD_INIT < cycle )
    6661418{
    6671419    uint32_t * buf = (uint32_t *)base;
    6681420    uint32_t line , word;
    669     printk("\n***** %s : First 16 dentries for parent inode %x\n",
    670     __FUNCTION__ , parent_inode );
     1421    printk("\n[%s] First 16 dentries for <%s>\n",
     1422    __FUNCTION__ , parent_name );
    6711423    for( line = 0 ; line < 16 ; line++ )
    6721424    {
     
    7281480                    cluster = (fatfs_get_record( DIR_FST_CLUS_HI , base + offset , 1 ) << 16) |
    7291481                              (fatfs_get_record( DIR_FST_CLUS_LO , base + offset , 1 )      ) ;
    730                     dentry  = ((index<<12) + offset)>>5;
    731                     is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
    732                     size    = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );
    733                     found   = 1;
     1482                    dentry_id = ((page_id<<12) + offset)>>5;
     1483                    is_dir    = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     1484                    size      = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );
     1485                    found     = 1;
    7341486                }
    7351487                offset = offset + 32;
    7361488                lfn    = 0;
    7371489            }
    738         }  // end loop on directory entries
    739         index++;
     1490        }  // end loop on directory entries in page
     1491
     1492        page_id++;
    7401493        offset = 0;
     1494
    7411495    }  // end loop on pages
    7421496
     
    7461500    {
    7471501
    748 #if DEBUG_FATFS_LOAD
     1502#if DEBUG_FATFS_CHILD_INIT
    7491503cycle = (uint32_t)hal_get_cycles();
    750 if( DEBUG_FATFS_LOAD < cycle )
    751 printk("\n[DBG] %s : thread %x exit / child <%s> not found / cycle %d\n",
    752 __FUNCTION__ , CURRENT_THREAD, name, cycle );
    753 #endif
    754 
    755         return ENOENT;
    756     }
    757     else               // found searched child name
    758     {
    759         // get child inode cluster and local pointer
    760         cxy_t         child_cxy = GET_CXY( child_inode_xp );
    761         vfs_inode_t * child_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
    762 
    763         // update the child inode "type", "size", and "extend" fields
    764         vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
    765 
    766         hal_remote_s32( XPTR( child_cxy , &child_ptr->type   ) , type );
    767         hal_remote_s32( XPTR( child_cxy , &child_ptr->size   ) , size );
    768         hal_remote_s32( XPTR( child_cxy , &child_ptr->extend ) , cluster );
    769 
    770 #if DEBUG_FATFS_LOAD
     1504if( DEBUG_FATFS_CHILD_INIT < cycle )
     1505printk("\n[%s]  thread[%x,%x] exit / child <%s> not found / cycle %d\n",
     1506__FUNCTION__, this->process->pid, this->trdid, name, cycle );
     1507#endif
     1508
     1509        return -1;
     1510    }
     1511
     1512    // get child inode cluster and local pointer
     1513    cxy_t          inode_cxy = GET_CXY( child_inode_xp );
     1514    vfs_inode_t  * inode_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
     1515
     1516    // get dentry pointers and cluster
     1517    xptr_t         dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 
     1518    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
     1519    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
     1520
     1521// dentry descriptor must be in same cluster as parent inode
     1522assert( (dentry_cxy == local_cxy) , "illegal dentry cluster\n" );
     1523
     1524    // update the child inode "type", "size", and "extend" fields
     1525    vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
     1526
     1527    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->type   ) , type );
     1528    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->size   ) , size );
     1529    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->extend ) , cluster );
     1530
     1531    // update the dentry "extend" field
     1532    dentry_ptr->extend = (void *)(intptr_t)dentry_id;
     1533
     1534#if DEBUG_FATFS_CHILD_INIT
    7711535cycle = (uint32_t)hal_get_cycles();
    772 if( DEBUG_FATFS_LOAD < cycle )
    773 printk("\n[DBG] %s : thread %x exit / child <%s> loaded / cycle %d\n",
    774 __FUNCTION__ , CURRENT_THREAD, name, cycle );
    775 #endif
    776 
    777         return 0;
    778     }
    779 }  // end fatfs_inode_load()
     1536if( DEBUG_FATFS_CHILD_INIT < cycle )
     1537printk("\n[%s]  thread[%x,%x] exit / child <%s> loaded in <%s> / cycle %d\n",
     1538__FUNCTION__, this->process->pid, this->trdid, name, parent_name, cycle );
     1539#endif
     1540
     1541    return 0;
     1542
     1543}  // end fatfs_child_init()
     1544
     1545///////////////////////////////////////////////
     1546error_t fatfs_sync_inode( vfs_inode_t * inode )
     1547{
     1548
     1549// check inode pointer and cluster index
     1550assert( (inode != NULL)                  , "inode pointer undefined\n" );
     1551assert( (inode->mapper != NULL )         , "mapper pointer undefined\n" );
     1552assert( (inode->type == INODE_TYPE_FILE) , "inode must be a file\n" );     
     1553
     1554#if DEBUG_FATFS_SYNC_INODE
     1555char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     1556uint32_t   cycle = (uint32_t)hal_get_cycles();
     1557thread_t * this  = CURRENT_THREAD;
     1558vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     1559if( DEBUG_FATFS_SYNC_INODE < cycle )
     1560printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
     1561__FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     1562#endif
     1563
     1564    error_t    error;
     1565    mapper_t * mapper;
     1566    page_t   * page;
     1567    uint32_t   page_id;
     1568
     1569    // get mapper from inode
     1570    mapper = inode->mapper;
     1571
     1572    // compute max number of pages in mapper from file size
     1573    uint32_t size  = inode->size;
     1574    uint32_t pages = size >> CONFIG_PPM_PAGE_SHIFT;
     1575    if( size & CONFIG_PPM_PAGE_MASK ) pages++;
     1576         
     1577    // get pointer on mapper radix tree
     1578    grdxt_t * rt = &mapper->rt;
     1579
     1580    // scan all pages
     1581    for( page_id = 0 ; page_id < pages ; page_id++ )
     1582    {
     1583        // get page descriptor from mapper
     1584        page = grdxt_lookup( rt , page_id );
     1585
     1586        // check all existing pages
     1587        if ( page != NULL )
     1588        {
     1589            if ( page->flags & PG_DIRTY )
     1590            {
     1591
     1592#if (DEBUG_FATFS_SYNC_INODE & 1)
     1593if( DEBUG_FATFS_SYNC_INODE < cycle )
     1594printk("\n[%s] thread[%x,%x] synchronizes page %d from <%s> mapper to IOC device\n",
     1595__FUNCTION__, page_id, name );
     1596#endif
     1597                // build extended pointer on page descriptor
     1598                xptr_t page_xp = XPTR( local_cxy , page );
     1599
     1600                // move page from mapper to device
     1601                error = fatfs_move_page( page_xp , false );
     1602
     1603                if ( error )  return -1;
     1604
     1605                // reset page dirty flag
     1606                ppm_page_undo_dirty( page_xp );
     1607            }
     1608        }
     1609    }  // end loop on pages
     1610
     1611#if DEBUG_FATFS_SYNC_INODE
     1612cycle = (uint32_t)hal_get_cycles();
     1613if( DEBUG_FATFS_SYNC_INODE < cycle )
     1614printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n",
     1615__FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     1616#endif
     1617
     1618    return 0;
     1619
     1620}  // end fatfs_sync_inode()
     1621
     1622//////////////////////////////
     1623error_t fatfs_sync_fat( void )
     1624{
     1625
     1626#if DEBUG_FATFS_SYNC_FAT
     1627uint32_t   cycle = (uint32_t)hal_get_cycles();
     1628thread_t * this  = CURRENT_THREAD;
     1629if( DEBUG_FATFS_SYNC_FAT < cycle )
     1630printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1631__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1632#endif
     1633
     1634    uint32_t   page_id;
     1635    error_t    error;
     1636
     1637    // get FAT mapper pointers an cluster
     1638    fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
     1639    xptr_t        mapper_xp  = fatfs_ctx->fat_mapper_xp;
     1640    cxy_t         mapper_cxy = GET_CXY( mapper_xp );
     1641    mapper_t    * mapper_ptr = GET_PTR( mapper_xp );
     1642
     1643    // compute max number of 4 Kbytes pages in FAT mapper
     1644    // TODO : this could be improved (see fatfs.h) [AG]
     1645    uint32_t   pages = fatfs_ctx->fat_sectors_count >> 3;
     1646         
     1647    // get pointers on remote FAT mapper radix tree
     1648    grdxt_t  * rt_ptr = &mapper_ptr->rt;
     1649    xptr_t     rt_xp  = XPTR( mapper_cxy , rt_ptr );
     1650
     1651    // scan all pages
     1652    for( page_id = 0 ; page_id < pages ; page_id++ )
     1653    {
     1654        // get extended pointer on page descriptor from FAT mapper
     1655        xptr_t page_xp = grdxt_remote_lookup( rt_xp , page_id );
     1656
     1657        // check all existing pages
     1658        if ( page_xp != XPTR_NULL )
     1659        {
     1660            page_t * page_ptr = GET_PTR( page_xp );
     1661            uint32_t flags    = hal_remote_l32( XPTR( mapper_cxy , &page_ptr->flags ) );
     1662
     1663            if ( flags & PG_DIRTY )
     1664            {
     1665
     1666#if (DEBUG_FATFS_SYNC_FAT & 1)
     1667if( DEBUG_FATFS_SYNC_FAT < cycle )
     1668printk("\n[%s] thread[%x,%x] synchronizes page %d from FAT mapper to IOC device\n",
     1669__FUNCTION__, page_id );
     1670#endif
     1671                // move page from mapper to device
     1672                error = fatfs_move_page( page_xp , false );
     1673
     1674                if ( error )  return -1;
     1675
     1676                // reset page dirty flag
     1677                ppm_page_undo_dirty( page_xp );
     1678            }
     1679        }
     1680    }  // end loop on pages
     1681
     1682#if DEBUG_FATFS_SYNC_FAT
     1683cycle = (uint32_t)hal_get_cycles();
     1684if( DEBUG_FATFS_SYNC_FAT < cycle )
     1685printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1686__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1687#endif
     1688
     1689    return 0;
     1690
     1691}  // end fatfs_sync_fat()
     1692
     1693////////////////////////////////////
     1694error_t fatfs_sync_free_info( void )
     1695{
     1696
     1697#if DEBUG_FATFS_SYNC_FSINFO
     1698uint32_t   cycle = (uint32_t)hal_get_cycles();
     1699thread_t * this  = CURRENT_THREAD;
     1700if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1701printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1702__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1703#endif
     1704
     1705    uint8_t     * buffer;   // dynamically allocated aligned 512 bytes buffer
     1706    kmem_req_t    req;
     1707    error_t       error;
     1708
     1709    // get FS_INFO lba, free_ from FATFS context
     1710    fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
     1711    uint32_t      lba        = fatfs_ctx->fs_info_lba;
     1712    uint32_t      hint       = fatfs_ctx->free_cluster_hint;
     1713    uint32_t      number     = fatfs_ctx->free_clusters;
     1714
     1715    // allocate buffer to store the FS_INFO sector
     1716        req.type    = KMEM_512_BYTES;
     1717    req.flags   = AF_KERNEL | AF_ZERO;
     1718        buffer      = (uint8_t *)kmem_alloc( &req );
     1719    if( buffer == NULL )
     1720    {
     1721        printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
     1722        return ENOMEM;
     1723    }
     1724     
     1725    // load the FS_INFO sector from device to buffer
     1726    error = dev_ioc_read( buffer , lba , 1 );
     1727    if ( error )
     1728    {
     1729        printk("\n[PANIC] in %s : cannot read FS_INFO record\n", __FUNCTION__ );
     1730        return EIO;
     1731    }
     1732
     1733    // update buffer
     1734    fatfs_set_record( FS_FREE_CLUSTERS     , buffer , 1 , number );
     1735    fatfs_set_record( FS_FREE_CLUSTER_HINT , buffer , 1 , hint );
     1736
     1737    // write modified FS_INFO sector from buffer to device
     1738    error = dev_ioc_write( buffer , lba , 1 );
     1739    if ( error )
     1740    {
     1741        printk("\n[PANIC] in %s : cannot write FS_INFO record\n", __FUNCTION__ );
     1742        return EIO;
     1743    }
     1744
     1745    // release the 512 bytes buffer
     1746    req.type = KMEM_512_BYTES;
     1747    req.ptr  = buffer;
     1748    kmem_free( &req );
     1749
     1750#if DEBUG_FATFS_SYNC_FSINFO
     1751cycle = (uint32_t)hal_get_cycles();
     1752if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1753printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1754__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1755#endif
     1756
     1757    return 0;
     1758
     1759}  // end fatfs_sync_fs_info()
     1760
     1761//////////////////////////////////////////////////////////
     1762error_t fatfs_cluster_alloc( uint32_t * searched_cluster )
     1763{
     1764    uint32_t      page_id;        // page index in mapper
     1765    uint32_t      slot_id;        // slot index in page (1024 slots per page)
     1766    uint32_t      hint;           // first free cluster index in FAT
     1767    uint32_t      free_clusters;  // total number of free clusters
     1768    vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters)
     1769    fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
     1770    fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
     1771    xptr_t        mapper_xp;      // extended pointer on FAT mapper
     1772    cxy_t         mapper_cxy;     // Fat mapper cluster identifier
     1773    xptr_t        page_xp;        // extended pointer on current page descriptor in mapper
     1774    xptr_t        slot_xp;        // extended pointer on FAT slot defined by hint
     1775    xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info
     1776    xptr_t        hint_xp;        // extended pointer on free_cluster_hint in FAT cluster
     1777    xptr_t        numb_xp;        // extended pointer on free_clusters_number in FAT cluster
     1778
     1779#if DEBUG_FATFS_CLUSTER_ALLOC
     1780uint32_t   cycle = (uint32_t)hal_get_cycles();
     1781thread_t * this  = CURRENT_THREAD;
     1782if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1783printk("\n[%s] thread[%x,%x] enter / cycle = %d\n",
     1784__FUNCTION__, this->process->pid, this->trdid, cycle );
     1785#endif
     1786
     1787    // get local pointer on VFS context (same in all clusters)
     1788    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     1789
     1790    // get local pointer on local FATFS context
     1791    loc_fatfs_ctx = vfs_ctx->extend;
     1792
     1793    // get extended pointer and cluster on FAT mapper
     1794    mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
     1795    mapper_cxy = GET_CXY( mapper_xp );
     1796   
     1797    // get local pointer on FATFS context in FAT cluster
     1798    fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
     1799
     1800    // build relevant extended pointers in on free clusters info in FAT cluster
     1801    lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock );
     1802    hint_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint );
     1803    numb_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters );
     1804
     1805    // take the lock protecting free clusters
     1806    remote_queuelock_acquire( lock_xp );
     1807
     1808    // get hint and free_clusters values from FATFS context
     1809    hint          = hal_remote_l32( hint_xp );
     1810    free_clusters = hal_remote_l32( numb_xp );
     1811       
     1812    // get page index & slot index for the first free cluster
     1813    page_id  = (hint + 1) >> 10;
     1814    slot_id  = (hint + 1) & 0x3FF;
     1815
     1816    // get relevant page from mapper
     1817    page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1818
     1819    if( page_xp == XPTR_NULL )
     1820    {
     1821        printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
     1822        return -1;
     1823    }
     1824
     1825    // build extended pointer on free cluster slot
     1826    slot_xp = ppm_page2base( page_xp ) + (slot_id<<2);
     1827         
     1828#if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
     1829if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1830printk("\n[%s] thread[%x,%x] get free info / hint %x / free_clusters %x\n",
     1831__FUNCTION__, this->process->pid, this->trdid, hint, free_clusters );
     1832#endif
     1833
     1834    // check "free_clusters"
     1835    if ( free_clusters == 0 )
     1836    {
     1837        printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ );
     1838        remote_queuelock_acquire( lock_xp );
     1839        return -1;
     1840    }
     1841    else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN )
     1842    {
     1843        printk("\n[WARNING] in %s : only %n free FATFS clusters\n",
     1844        __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN );
     1845    }
     1846
     1847    // check "hint"
     1848    if( hal_remote_l32( slot_xp ) != FREE_CLUSTER )
     1849    {
     1850        printk("\n[ERROR] in %s : illegal hint cluster\n", __FUNCTION__ );
     1851        remote_queuelock_acquire( lock_xp );
     1852        return -1;
     1853    }
     1854
     1855    // update allocated cluster in FAT mapper
     1856    hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
     1857
     1858    // update free cluster info
     1859    fatfs_free_clusters_decrement( hint + 1 );
     1860
     1861    // release free clusters busylock
     1862    remote_queuelock_release( lock_xp );
     1863
     1864#if DEBUG_FATFS_CLUSTER_ALLOC
     1865cycle = (uint32_t)hal_get_cycles();
     1866if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1867printk("\n[%s] thread[%x,%x] exit / cluster %x / cycle %d\n",
     1868__FUNCTION__, this->process->pid, this->trdid, hint + 1, cycle );
     1869#endif
     1870
     1871    *searched_cluster = hint + 1;
     1872    return 0;
     1873
     1874}  // end fat_cluster_alloc()
     1875
     1876//////////////////////////////////////////////
     1877error_t fatfs_release_inode( xptr_t inode_xp )
     1878{
     1879    vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters).
     1880    fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
     1881    fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
     1882    xptr_t        mapper_xp;      // extended pointer on FAT mapper
     1883    cxy_t         mapper_cxy;     // Fat mapper cluster identifier
     1884    xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info.
     1885    xptr_t        first_xp;       // extended pointer on inode extension
     1886    uint32_t      first_cluster;  // first cluster index for released inode
     1887    vfs_inode_t * inode_ptr;
     1888    cxy_t         inode_cxy;
     1889
     1890// check inode pointer
     1891assert( (inode_xp != XPTR_NULL) , "inode pointer is NULL\n" );
     1892
     1893    // get first_cluster from inode extension
     1894    inode_ptr     = GET_PTR( inode_xp );
     1895    inode_cxy     = GET_CXY( inode_xp );
     1896    first_xp      = XPTR( inode_cxy , &inode_ptr->extend );
     1897    first_cluster = (uint32_t)(intptr_t)hal_remote_lpt( first_xp );
     1898
     1899// check first cluster index
     1900assert( (first_cluster != 0) , "inode extend is NULL\n" );
     1901
     1902#if DEBUG_FATFS_RELEASE_INODE
     1903char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     1904uint32_t   cycle = (uint32_t)hal_get_cycles();
     1905thread_t * this  = CURRENT_THREAD;
     1906vfs_inode_get_name( inode_xp , name );
     1907if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1908printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster %x / cycle %d\n",
     1909__FUNCTION__ , this->process->pid, this->trdid, name, first_cluster, cycle );
     1910#endif
     1911
     1912    // get local pointer on VFS context (same in all clusters)
     1913    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     1914
     1915    // get local pointer on local FATFS context
     1916    loc_fatfs_ctx = vfs_ctx->extend;
     1917
     1918    // get extended pointer and cluster on FAT mapper
     1919    mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
     1920    mapper_cxy = GET_CXY( mapper_xp );
     1921   
     1922    // get local pointer on FATFS context in FAT cluster
     1923    fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
     1924
     1925    // get extended pointer on free clusters lock in FAT cluster
     1926    lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock );
     1927
     1928    // take lock protecting free clusters
     1929    remote_queuelock_acquire( lock_xp );
     1930
     1931    // call the recursive function to release all clusters from FAT mapper
     1932    if ( fatfs_recursive_release( mapper_xp , first_cluster ) )
     1933    {
     1934        printk("\n[ERROR] in %s : cannot update FAT mapper\n", __FUNCTION__ );
     1935        remote_queuelock_release( lock_xp );
     1936        return -1;
     1937    }
     1938
     1939    // release lock protecting free cluster
     1940    remote_queuelock_release( lock_xp );
     1941
     1942#if (DEBUG_FATFS_RELEASE_INODE & 1)
     1943if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1944printk("\n[%s] inode <%s> removed from FAT mapper\n", __FUNCTION__, name );
     1945#endif
     1946
     1947    // update FAT on IOC device (from FAT mapper)
     1948    if ( fatfs_sync_fat() )
     1949    {
     1950        printk("\n[ERROR] in %s : cannot update FAT on device\n", __FUNCTION__ );
     1951        return -1;
     1952    }
     1953
     1954#if (DEBUG_FATFS_RELEASE_INODE & 1)
     1955if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1956printk("\n[%s] inode <%s> removed from FAT on IOC device\n", __FUNCTION__, name );
     1957#endif
     1958
     1959    // update FS-INFO sector on IOC device (from FATFS context)
     1960    if ( fatfs_sync_free_info() )
     1961    {
     1962        printk("\n[ERROR] in %s: cannot update FS_INFO on device\n", __FUNCTION__ );
     1963        return -1;
     1964    }
     1965
     1966#if DEBUG_FATFS_RELEASE_INODE
     1967cycle = (uint32_t)hal_get_cycles();
     1968if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1969printk("\n[%s] thread[%x,%x] removed <%s> inode from FATFS / cycle %d\n",
     1970__FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     1971#endif
     1972
     1973    return 0;
     1974
     1975}  // end fatfs_release_inode()
     1976
     1977/////////////////////////////////////////
     1978error_t fatfs_move_page( xptr_t  page_xp,
     1979                         bool_t  to_mapper )
     1980{
     1981    error_t       error;
     1982    vfs_inode_t * inode_ptr;
     1983    mapper_t    * mapper_ptr;     
     1984    uint32_t      page_id;     // page index in mapper
     1985
     1986#if DEBUG_FATFS_MOVE_PAGE
     1987uint32_t   cycle = (uint32_t)hal_get_cycles();
     1988thread_t * this  = CURRENT_THREAD;
     1989char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     1990#endif
     1991
     1992    // get page cluster an local pointer
     1993    cxy_t    page_cxy = GET_CXY( page_xp );
     1994    page_t * page_ptr = GET_PTR( page_xp );
     1995
     1996    // get mapper pointer and page index from page descriptor
     1997    mapper_ptr = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
     1998    page_id    = hal_remote_l32( XPTR( page_cxy , &page_ptr->index ) );
     1999
     2000    // get pointer on local FATFS context
     2001    fatfs_ctx_t * fatfs_ctx      = fs_context[FS_TYPE_FATFS].extend;
     2002
     2003    // get page base address
     2004    xptr_t    base_xp = ppm_page2base( page_xp );
     2005    uint8_t * buffer  = (uint8_t *)GET_PTR( base_xp );
     2006 
     2007    // get inode pointer from mapper
     2008    inode_ptr  = hal_remote_lpt( XPTR( page_cxy , &mapper_ptr->inode ) );
     2009
     2010    ////////////////////////////// it is the FAT mapper
     2011    if( inode_ptr == NULL )
     2012    {
     2013        // get lba from FATFS context and page_id
     2014        uint32_t      lba        = fatfs_ctx->fat_begin_lba + (page_id << 3);
     2015 
     2016        // access device
     2017        if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 );
     2018        else            error = dev_ioc_write( buffer , lba , 8 );     
     2019
     2020        if( error ) return EIO;
     2021
     2022#if (DEBUG_FATFS_MOVE_PAGE & 0x1)
     2023if( DEBUG_FATFS_MOVE_PAGE < cycle )
     2024{
     2025    uint32_t * tab = (uint32_t *)buffer;
     2026    uint32_t line , word;
     2027    printk("\n***** %s : First 64 words of page %d in FAT mapper\n",
     2028    __FUNCTION__ , page_id );
     2029    for( line = 0 ; line < 8 ; line++ )
     2030    {
     2031        printk("%X : ", line );
     2032        for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] );
     2033        printk("\n");
     2034    }
     2035}
     2036#endif
     2037
     2038#if DEBUG_FATFS_MOVE_PAGE
     2039cycle = (uint32_t)hal_get_cycles();
     2040if( DEBUG_FATFS_MOVE_PAGE < cycle )
     2041{
     2042    if (to_mapper)
     2043         printk("\n[%s] thread[%x,%x] load page %d of FAT / cycle %d\n",
     2044         __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     2045    else
     2046        printk("\n[%s] thread[%x,%x] sync page %d of FAT / cycle %d\n",
     2047        __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     2048}
     2049#endif
     2050
     2051    }
     2052    ///////////////////////// it is an inode mapper
     2053    else                       
     2054    {
     2055
     2056#if DEBUG_FATFS_MOVE_PAGE
     2057vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );
     2058#endif
     2059
     2060        uint32_t  searched_cluster;
     2061        uint32_t  first_cluster;
     2062
     2063        // get first_cluster from inode extension
     2064        void * extend = hal_remote_lpt( XPTR( page_cxy , &inode_ptr->extend ) );
     2065        first_cluster = (uint32_t)(intptr_t)extend;
     2066
     2067        // compute searched_cluster
     2068        if( page_id == 0 )            // no need to access FAT mapper
     2069        {
     2070            // searched cluster is first cluster
     2071            searched_cluster = first_cluster;
     2072        }
     2073        else                        // FAT mapper access required
     2074        {
     2075            // access FAT mapper to get searched cluster
     2076            error = fatfs_get_cluster( first_cluster,
     2077                                       page_id,
     2078                                       &searched_cluster );
     2079            if( error )  return EIO;
     2080        }
     2081
     2082        // get lba from searched_cluster
     2083        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster );
     2084
     2085        // access device
     2086        if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 );
     2087        else            error = dev_ioc_write( buffer , lba , 8 );     
     2088
     2089        if( error ) return EIO;
     2090
     2091#if (DEBUG_FATFS_MOVE_PAGE & 0x1)
     2092if( DEBUG_FATFS_MOVE_PAGE < cycle )
     2093{
     2094    uint32_t * tab = (uint32_t *)buffer;
     2095    uint32_t line , word;
     2096    printk("\n***** %s : First 64 words of page %d in <%s> mapper\n",
     2097    __FUNCTION__, page_id, name );
     2098    for( line = 0 ; line < 8 ; line++ )
     2099    {
     2100        printk("%X : ", line );
     2101        for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] );
     2102        printk("\n");
     2103    }
     2104}
     2105#endif
     2106
     2107#if DEBUG_FATFS_MOVE_PAGE
     2108cycle = (uint32_t)hal_get_cycles();
     2109if(DEBUG_FATFS_MOVE_PAGE < cycle)
     2110{
     2111    if(to_mapper)
     2112        printk("\n[%s] thread[%x,%x] load page %d of <%s> inode / cycle %d\n",
     2113        __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle );
     2114    else
     2115        printk("\n[%s] thread[%x,%x] sync page %d of <%s> inode / cycle %d\n",
     2116        __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle );
     2117}
     2118#endif
     2119
     2120    }
     2121
     2122    return 0;
     2123
     2124}  // end fatfs_move_page()
     2125
     2126
  • trunk/kernel/fs/fatfs.h

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

    r568 r602  
    3535                     char   * ramfs_root_name )
    3636{
    37     xptr_t    root_inode_xp;   // unused                      
     37    xptr_t    unused_xp;   // required by vfs_add_child_in_parent()                     
    3838 
    3939    cxy_t     cxy = cluster_random_select();
     
    4545                                     parent_inode_xp,
    4646                                     ramfs_root_name,
    47                                      NULL,
    48                                      &root_inode_xp );
     47                                     &unused_xp,
     48                                     &unused_xp );
    4949}
    5050
  • trunk/kernel/fs/vfs.c

    r598 r602  
    5757extern char *             lock_type_str[];            // allocated in kernel_init.c
    5858 
    59 //////////////////////////////////////////////////////////////////////////////////////////
    60 //           Context related functions
     59///////////////////////////////////////////////////////////////////////////////////////////
     60//           VFS Context related functions
    6161//////////////////////////////////////////////////////////////////////////////////////////
    6262
     
    123123
    124124//////////////////////////////////////////////////////////////////////////////////////////
    125 //           Inode related functions
     125//           VFS inode descriptor related functions
    126126//////////////////////////////////////////////////////////////////////////////////////////
    127127
     
    145145                          vfs_fs_type_t     fs_type,
    146146                          vfs_inode_type_t  inode_type,
    147                           void            * extend,
    148147                          uint32_t          attr,
    149148                          uint32_t          rights,
     
    228227    inode->ctx        = ctx;
    229228    inode->mapper     = mapper;
    230     inode->extend     = extend;
     229    inode->extend     = NULL;
    231230
    232231    // initialise inode field in mapper
     
    258257}  // end vfs_inode_create() 
    259258
    260 ////////////////////////////////////////////////
    261 error_t vfs_inode_destroy( vfs_inode_t * inode )
    262 {
    263     assert( (inode->refcount == 0) , "inode refcount non zero\n" );
     259/////////////////////////////////////////////
     260void vfs_inode_destroy( vfs_inode_t * inode )
     261{
     262
     263// check inode refcount
     264assert( (inode->refcount == 0) , "inode refcount non zero\n" );
    264265
    265266    // release memory allocated for mapper
     
    272273        kmem_free( &req );
    273274
    274     return 0;
    275 
    276275}  // end vfs_inode_destroy()
    277 
    278 /////////////////////////////////////////////
    279 error_t vfs_inode_load( vfs_inode_t * parent,
    280                         char        * name,
    281                         xptr_t        child_xp )
    282 {
    283 
    284 #if DEBUG_VFS_INODE_LOAD
    285 uint32_t cycle = (uint32_t)hal_get_cycles();
    286 if( DEBUG_VFS_INODE_LOAD < cycle )
    287 printk("\n[%s] thread %x enter for <%s> / cycle %d\n",
    288 __FUNCTION__, CURRENT_THREAD , name , cycle );
    289 #endif
    290 
    291     error_t error = 0;
    292 
    293     assert( (parent != NULL) , "parent pointer is NULL\n");
    294 
    295     assert( (child_xp != XPTR_NULL) , "child pointer is NULL\n");
    296 
    297     // get parent inode FS type
    298     vfs_fs_type_t fs_type = parent->ctx->type;
    299 
    300     // call relevant FS function
    301     if( fs_type == FS_TYPE_FATFS )
    302     {
    303         error = fatfs_inode_load( parent , name , child_xp );
    304     }
    305     else if( fs_type == FS_TYPE_RAMFS )
    306     {
    307         assert( false , "should not be called for RAMFS\n" );
    308     }
    309     else if( fs_type == FS_TYPE_DEVFS )
    310     {
    311         assert( false , "should not be called for DEVFS\n" );
    312     }
    313     else
    314     {
    315         assert( false , "undefined file system type\n" );
    316     }
    317 
    318 #if DEBUG_VFS_INODE_LOAD
    319 cycle = (uint32_t)hal_get_cycles();
    320 if( DEBUG_VFS_INODE_LOAD < cycle )
    321 printk("\n[%s] thread %x exit for <%s> / cycle %d\n",
    322 __FUNCTION__, CURRENT_THREAD , name , cycle );
    323 #endif
    324 
    325     return error;
    326 
    327 } // end vfs_inode_load()
    328276
    329277////////////////////////////////////////////
     
    429377}  // end vfs_inode_get_name()
    430378
     379///////////////////////////////////////////////////////
     380error_t vfs_inode_load_all_pages( vfs_inode_t * inode )
     381{
     382
     383assert( (inode != NULL) , "inode pointer is NULL\n" );
     384
     385    uint32_t   page_id;
     386    xptr_t     page_xp;
     387
     388    mapper_t * mapper = inode->mapper;
     389    uint32_t   size   = inode->size;
     390
     391assert( (mapper != NULL) , "mapper pointer is NULL\n" );
     392
     393#if DEBUG_VFS_INODE_LOAD_ALL
     394uint32_t   cycle = (uint32_t)hal_get_cycles();
     395thread_t * this  = CURRENT_THREAD;
     396char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     397vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     398if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
     399printk("\n[%s] thread[%x,%x] enter for <%s> in cluster %x / cycle %d\n",
     400__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
     401#endif
     402
     403    // compute number of pages
     404    uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
     405    if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++;
     406
     407    // loop on pages
     408    for( page_id = 0 ; page_id < npages ; page_id ++ )
     409    {
     410        // If the mage is missing, this function allocates the missing page,
     411        // and load the page from IOC device into mapper
     412        page_xp = mapper_remote_get_page( XPTR( local_cxy , mapper ), page_id );
     413
     414        if( page_xp == XPTR_NULL ) return -1;
     415    }
     416
     417#if DEBUG_VFS_INODE_LOAD_ALL
     418cycle = (uint32_t)hal_get_cycles();
     419if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
     420printk("\n[%s] thread[%x,%x] exit for <%x> in cluster %x / cycle %d\n",
     421__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
     422#endif
     423
     424    return 0;
     425
     426}  // end vfs_inode_load_all_pages()
     427
    431428////////////////////////////////////////////////////////////////////////////////////////////
    432 //           Dentry related functions
     429//          VFS dentry descriptor related functions
    433430//////////////////////////////////////////////////////////////////////////////////////////
    434431
     
    480477    dentry->length  = length;
    481478    dentry->parent  = parent;
     479    dentry->extend  = NULL;
    482480    strcpy( dentry->name , name );
    483481
     
    509507cycle = (uint32_t)hal_get_cycles();
    510508if( DEBUG_VFS_DENTRY_CREATE < cycle )
    511 printk("\n[%s] thread[%x,%x] exit for <%s> / dentry %x / cycle %d\n",
    512 __FUNCTION__, this->process->pid, this->trdid, name, dentry, cycle );
     509printk("\n[%s] thread[%x,%x] exit for <%s> / dentry [%x,%x] / cycle %d\n",
     510__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, dentry, cycle );
    513511#endif
    514512
     
    517515}  // end vfs_dentry_create()
    518516
    519 ///////////////////////////////////////////////////
    520 error_t vfs_dentry_destroy( vfs_dentry_t * dentry )
    521 {
    522     error_t error;
    523 
    524     assert( (dentry->refcount == 0) , __FUNCTION__ , "dentry refcount non zero\n" );
     517////////////////////////////////////////////////
     518void vfs_dentry_destroy( vfs_dentry_t * dentry )
     519{
     520
     521// check dentry refcount
     522assert( (dentry->refcount == 0) , "dentry refcount non zero\n" );
    525523
    526524    // get pointer on parent inode
     
    528526
    529527    // remove this dentry from parent inode htab
    530     error = xhtab_remove( XPTR( local_cxy , &parent->children ),
    531                           dentry->name,
    532                           XPTR( local_cxy , &dentry->list ) );
    533 
    534     if( error ) return EINVAL;     
     528    xhtab_remove( XPTR( local_cxy , &parent->children ),
     529                  dentry->name,
     530                  XPTR( local_cxy , &dentry->list ) );
    535531
    536532    // release memory allocated to dentry
     
    540536        kmem_free( &req );
    541537
    542     return 0;
     538}  // end vfs_dentry_destroy()
     539
     540//////////////////////////////////////////////
     541void vfs_dentry_remote_up( xptr_t  dentry_xp )
     542{
     543    // get dentry cluster and local pointer
     544    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
     545    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
     546
     547    hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , 1 );   
    543548}
    544549
     550////////////////////////////////////////////////
     551void vfs_dentry_remote_down( xptr_t  dentry_xp )
     552{
     553    // get dentry cluster and local pointer
     554    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
     555    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
     556
     557    hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , -1 );   
     558}
     559
    545560
    546561
    547562//////////////////////////////////////////////////////////////////////////////////////////
    548 //           File descriptor related functions
     563//       VFS file descriptor related functions
    549564//////////////////////////////////////////////////////////////////////////////////////////
    550565
     
    645660
    646661//////////////////////////////////////////////////////////////////////////////////////////
    647 //           File access related functions
     662//           "syscalls" API related functions
    648663//////////////////////////////////////////////////////////////////////////////////////////
    649664
     
    665680    uint32_t      file_id;      // created file descriptor index in reference fd_array
    666681
    667     assert( (mode == 0), __FUNCTION__,
    668     "the mode parameter is not supported yet\n" );
     682
     683    if( mode != 0 )
     684    {
     685        printk("\n[ERROR] in %s : the mode parameter is not supported yet\n" );
     686        return -1;
     687    }
    669688
    670689#if DEBUG_VFS_OPEN
     
    736755                   uint32_t size )
    737756{
    738     assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
    739 
    740757    cxy_t              file_cxy;     // remote file descriptor cluster
    741758    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
     
    745762    error_t            error;
    746763
     764// check argument
     765assert( (file_xp != XPTR_NULL), "file_xp == XPTR_NULL\n" );
     766
    747767    // get cluster and local pointer on remote file descriptor
    748768    file_cxy  = GET_CXY( file_xp );
     
    752772    inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) );
    753773   
    754     assert( (inode_type == INODE_TYPE_FILE) ,
    755     "inode type is not INODE_TYPE_FILE" );
     774// check inode type
     775assert( (inode_type == INODE_TYPE_FILE), "inode type is not INODE_TYPE_FILE" );
    756776
    757777    // get mapper pointer and file offset from file descriptor
     
    770790    else
    771791    {
    772         rpc_mapper_move_buffer_client( file_cxy,
    773                                        mapper,
    774                                        to_buffer,
    775                                        true,          // user buffer
    776                                        file_offset,
    777                                        (uint64_t)(intptr_t)buffer,
    778                                        size,
    779                                        &error );
     792        rpc_mapper_move_user_client( file_cxy,
     793                                     mapper,
     794                                     to_buffer,
     795                                     file_offset,
     796                                     buffer,
     797                                     size,
     798                                     &error );
    780799    }
    781800
    782     if( error ) return -1;
    783     else        return size;
     801    // update file offset in file descriptor
     802    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->offset ) , size );
     803
     804    if( error )
     805    {
     806        return -1;
     807    }
     808
     809    return size;
    784810
    785811}  // end vfs_user_move()
     
    791817                         uint32_t size )
    792818{
    793     assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
    794 
    795819    cxy_t              file_cxy;     // remote file descriptor cluster
    796820    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
    797     vfs_inode_type_t   inode_type;
     821    vfs_inode_type_t   inode_type;   // remote file type
    798822    uint32_t           file_offset;  // current offset in file
    799     mapper_t         * mapper;
     823    mapper_t         * mapper_ptr;   // remote mapper local pointer
     824    xptr_t             mapper_xp;    // remote mapper extended pointer
    800825    error_t            error;
     826
     827// check argument
     828assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" );
    801829
    802830    // get cluster and local pointer on remote file descriptor
     
    810838    if( inode_type == INODE_TYPE_FILE )
    811839    {
    812         // get mapper pointer and file offset from file descriptor
     840        // get mapper pointers and file offset from file descriptor
    813841        file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
    814         mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
     842        mapper_ptr  = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
     843        mapper_xp   = XPTR( file_cxy , mapper_ptr );
    815844
    816845        // move data between mapper and buffer
    817         if( file_cxy == local_cxy )
    818         {
    819             error = mapper_move_kernel( mapper,
    820                                         to_buffer,
    821                                         file_offset,
    822                                         buffer_xp,
    823                                         size );
    824         }
    825         else
    826         {
    827             rpc_mapper_move_buffer_client( file_cxy,
    828                                            mapper,
    829                                            to_buffer,
    830                                            false,          // kernel buffer
    831                                            file_offset,
    832                                            buffer_xp,
    833                                            size,
    834                                            &error );
    835         }
    836 
     846        error = mapper_move_kernel( mapper_xp,
     847                                    to_buffer,
     848                                    file_offset,
     849                                    buffer_xp,
     850                                    size );
    837851        if( error ) return -1;
    838         else        return 0;
    839852    }
    840853    else
     
    843856        return -1;
    844857    }
     858
     859    return 0;
     860
    845861}  // end vfs_kernel_move()
    846862
     
    853869    xptr_t         offset_xp;
    854870    xptr_t         lock_xp;
     871    xptr_t         size_xp;
    855872    cxy_t          file_cxy;
    856873    vfs_file_t  *  file_ptr;
     
    858875    uint32_t       new;
    859876
    860     assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
     877// check argument
     878assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" );
    861879
    862880    // get cluster and local pointer on remote file descriptor
     
    864882    file_ptr = GET_PTR( file_xp );
    865883
    866     // build extended pointers on lock and offset
     884    // get local pointer on remote inode
     885    inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
     886
     887    // build extended pointers on lock, offset and size
    867888    offset_xp = XPTR( file_cxy , &file_ptr->offset );
    868889    lock_xp   = XPTR( file_cxy , &file_ptr->lock );
     890    size_xp   = XPTR( file_cxy , &inode_ptr->size );
    869891
    870892    // take file descriptor lock
     
    881903    else if ( whence == SEEK_END )   // new = size + offset
    882904    {
    883         // get local pointer on remote inode
    884         inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
    885 
    886         new = hal_remote_l32( XPTR( file_cxy , &inode_ptr->size ) ) + offset;
     905        new = hal_remote_l32( size_xp ) + offset;
    887906    }
    888907    else
     
    893912    }
    894913
     914#if DEBUG_VFS_LSEEK
     915uint32_t   cycle = (uint32_t)hal_get_cycles();
     916thread_t * this  = CURRENT_THREAD;
     917char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     918vfs_inode_get_name( XPTR( file_cxy , inode_ptr ) , name );
     919if( cycle > DEBUG_VFS_LSEEK )
     920printk("\n[%s] thread[%x,%x] for <%s> / new offset %d / cycle %d\n",
     921__FUNCTION__ , this->process->pid, this->trdid, name, new, cycle );
     922#endif
     923
    895924    // set new offset
    896925    hal_remote_s32( offset_xp , new );
     
    900929
    901930    // success
    902     if ( new_offset != NULL )
    903         *new_offset = new;
     931    if ( new_offset != NULL ) *new_offset = new;
    904932    return 0;
    905933
     
    922950    process_t  * process_ptr;      // process copy local pointer
    923951
    924     assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
    925 
    926     assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , "illegal file_id" );
     952// check arguments
     953assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" );
     954assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , "illegal file_id\n" );
    927955
    928956    thread_t  * this    = CURRENT_THREAD;
     
    10191047                    char   * path )
    10201048{
    1021     assert( false , "not implemented cwd_xp %x, path <%s> \n",
    1022       cwd_xp, path );   
    1023     return 0;
    1024 }
     1049    error_t           error;
     1050    xptr_t            inode_xp;           // extended pointer on target inode
     1051    cxy_t             inode_cxy;          // target inode cluster identifier       
     1052    vfs_inode_t     * inode_ptr;          // target inode local pointer
     1053    uint32_t          inode_refcount;     // target inode refcount
     1054    vfs_inode_type_t  type;               // target inode type
     1055    mapper_t        * mapper;             // pointer on target inode mapper
     1056    xptr_t            dentry_xp;          // extended pointer on target dentry
     1057    cxy_t             dentry_cxy;         // target dentry cluster identifier
     1058    vfs_dentry_t    * dentry_ptr;         // target dentry local pointer
     1059    uint32_t          dentry_refcount;    // target dentry refcount
     1060    vfs_inode_t     * dentry_parent_ptr;  // parent inode local pointer
     1061
     1062#if DEBUG_VFS_UNLINK
     1063thread_t * this  = CURRENT_THREAD;
     1064uint32_t   cycle = (uint32_t)hal_get_cycles();
     1065if( DEBUG_VFS_UNLINK < cycle )
     1066printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
     1067__FUNCTION__, this->process->pid, this->trdid, path, cycle );
     1068#endif
     1069
     1070    // get extended pointer on target inode
     1071    error = vfs_lookup( cwd_xp , path , 0 , &inode_xp );
     1072
     1073    if( error ) return error;
     1074
     1075    // get inode cluster and local pointer
     1076    inode_cxy = GET_CXY( inode_xp );
     1077    inode_ptr = GET_PTR( inode_xp );
     1078
     1079    // get inode type, refcount, mapper, dentry_xp
     1080    type              = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     1081    inode_refcount    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) );
     1082    mapper            = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     1083    dentry_xp         = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
     1084
     1085    // get dentry cluster, local pointer, refcount, and pointers on parent inode
     1086    dentry_ptr        = GET_PTR( dentry_xp );
     1087    dentry_cxy        = GET_CXY( dentry_xp );
     1088    dentry_refcount   = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) );
     1089    dentry_parent_ptr = hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) );
     1090
     1091// check inode & dentry refcount
     1092assert( (inode_refcount  == 1), "illegal inode refcount for <%s>\n", path );
     1093assert( (dentry_refcount == 1), "illegal dentry refcount for <%s>\n", path );
     1094
     1095    /////////////////////////////
     1096    if( type == INODE_TYPE_FILE )
     1097    {
     1098        // 1. release clusters allocated to file in the FAT mapper
     1099        //    synchronize the FAT on IOC device
     1100        error = vfs_fs_release_inode( inode_xp );
     1101        if( error )
     1102        {
     1103            printk("\n[ERROR] in %s : cannot update FAT mapper <%s>\n", path );
     1104            return -1;
     1105        }
     1106
     1107#if(DEBUG_VFS_UNLINK & 1)
     1108if( DEBUG_VFS_UNLINK < cycle )
     1109printk("\n[%s] thread[%x,%x] removed <%s> inode from FAT (mapper and IOC device)\n",
     1110__FUNCTION__, this->process->pid, this->trdid, path );
     1111#endif
     1112
     1113        // 2. update parent directory in Inode Tree
     1114        //    synchronize the parent directory on IOC device
     1115        if (dentry_cxy == local_cxy)                           // dentry is local
     1116        {
     1117            error = vfs_fs_remove_dentry( dentry_parent_ptr,
     1118                                          dentry_ptr );
     1119        }
     1120        else                                                  // dentry is remote
     1121        {
     1122            rpc_vfs_fs_remove_dentry_client( dentry_cxy,
     1123                                             dentry_parent_ptr,
     1124                                             dentry_ptr,
     1125                                             &error );
     1126        }
     1127        if( error )
     1128        {
     1129            printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n", path );
     1130            return -1;
     1131        }
     1132
     1133#if(DEBUG_VFS_UNLINK & 1)
     1134if( DEBUG_VFS_UNLINK < cycle )
     1135printk("\n[%s] thread[%x,%x] removed <%s> inode from parent dir (mapper and IOC device)\n",
     1136__FUNCTION__, this->process->pid, this->trdid, path );
     1137#endif
     1138        // 3. remove inode (including mapper & dentry) from Inode Tree
     1139        vfs_remove_child_from_parent( inode_xp );
     1140
     1141#if DEBUG_VFS_UNLINK
     1142if( DEBUG_VFS_UNLINK < cycle )
     1143printk("\n[%s] thread[%x,%x] exit / removed <%s> inode from Inode Tree / cycle %d\n",
     1144__FUNCTION__, this->process->pid, this->trdid, path, cycle );
     1145#endif
     1146        return 0;
     1147    }
     1148    /////////////////////////////////
     1149    else if( type == INODE_TYPE_DIR )
     1150    {
     1151        printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) );
     1152        return -1;
     1153    }
     1154    ////
     1155    else
     1156    {
     1157        printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) );
     1158        return -1;
     1159    }
     1160
     1161}  // end vfs_unlink()
    10251162
    10261163//////////////////////////////////////
     
    10581195
    10591196    return 0;
    1060 }
     1197
     1198}  // end vfs_stat()
    10611199
    10621200/////////////////////////////////////////////
     
    11721310
    11731311//////////////////////////////////////////////////////////////////////////////////////////
    1174 //            Inode Tree functions
     1312//       Distributed Inode Tree access related functions
    11751313//////////////////////////////////////////////////////////////////////////////////////////
    11761314
     
    13361474}  // end vfs_display()
    13371475
     1476/*
    13381477//////////////////////////////////////////////////////////////////////////////////////////
    1339 // This function is used by the vfs_lookup() function.
     1478// This static function is used by the vfs_lookup() function.
    13401479// It takes an extended pointer on a remote inode (parent directory inode),
    13411480// and check access_rights violation for the calling thread.
     
    13471486// @ return true if access rights are violated.
    13481487//////////////////////////////////////////////////////////////////////////////////////////
    1349 bool_t vfs_access_denied( xptr_t   inode_xp,
     1488static bool_t vfs_access_denied( xptr_t   inode_xp,
    13501489                          uint32_t client_uid,
    13511490                          uint32_t client_gid )
     
    13641503    else                                             return true;
    13651504}
     1505*/
    13661506
    13671507//////////////////////////////////////////////////////////////////////////////////////////
     
    14651605    cxy_t              parent_cxy;   // cluster for parent inode
    14661606    vfs_inode_t      * parent_ptr;   // local pointer on parent inode 
     1607    xptr_t             dentry_xp;    // extended pointer on dentry       
    14671608    xptr_t             child_xp;     // extended pointer on child inode
    14681609    cxy_t              child_cxy;    // cluster for child inode
    1469     vfs_inode_t      * child_ptr;    // local pointer on child inode 
     1610    vfs_inode_t      * child_ptr;    // local pointer on child inode
     1611    vfs_inode_type_t   child_type;   // child inode type
    14701612    vfs_fs_type_t      fs_type;      // File system type
    14711613    vfs_ctx_t        * ctx_ptr;      // local pointer on FS context
     
    15191661#if (DEBUG_VFS_LOOKUP & 1)
    15201662if( DEBUG_VFS_LOOKUP < cycle )
    1521 printk("\n[%s]  look for <%s> / last = %d\n",
    1522 __FUNCTION__ , name , last );
     1663printk("\n[%s] thread[%x,%x] look for <%s> in <%s> / last = %d\n",
     1664__FUNCTION__, process->pid, this->trdid, name, pathname, last );
    15231665#endif
    15241666
     
    15331675#if (DEBUG_VFS_LOOKUP & 1)
    15341676if( DEBUG_VFS_LOOKUP < cycle )
    1535 printk("\n[%s] miss <%s> node => try to create it\n",
    1536 __FUNCTION__ , name );
     1677printk("\n[%s] thread[%x,%x] miss <%s> node => try to create it\n",
     1678__FUNCTION__, process->pid, this->trdid, name );
    15371679#endif
    15381680            // if a child node is not found in the inode tree,
     
    15441686            // . if it is not found in the parent mapper:
    15451687            //   - if ( not last or not create ) an error is reported
    1546             //   - if (last and create and dir) a new directory is created
    1547             //   - if (last and create and not dir) a new file is created
     1688            //   - if (last and create) a new file or directory is created
    15481689
    15491690            // release lock on parent inode
    15501691            vfs_inode_unlock( parent_xp );
    15511692 
    1552             // get parent inode FS type
     1693            // get parent inode cluster and local pointer
    15531694            parent_cxy = GET_CXY( parent_xp );
    15541695            parent_ptr = GET_PTR( parent_xp );
    1555             ctx_ptr    = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
     1696
     1697            // get parent inode FS type
     1698            ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
    15561699            fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
    15571700
    15581701            // select a cluster for missing inode
    15591702            child_cxy = cluster_random_select();
     1703
     1704            // define child inode type
     1705            if( dir ) child_type = INODE_TYPE_DIR;
     1706            else      child_type = INODE_TYPE_FILE;
    15601707 
    15611708            // insert a new child dentry/inode in inode tree
    15621709            error = vfs_add_child_in_parent( child_cxy,
    1563                                              0,           // type will be updated later
     1710                                             child_type,
    15641711                                             fs_type,
    15651712                                             parent_xp,
    15661713                                             name,
    1567                                              NULL,        // fs_type_specific inode extend
     1714                                             &dentry_xp,
    15681715                                             &child_xp );
    15691716            if( error )
    15701717            {
    1571                 printk("\n[ERROR] in %s : cannot create node %s for path <%s>\n",
     1718                printk("\n[ERROR] in %s : cannot create node <%s> in path <%s>\n",
    15721719                __FUNCTION__ , name, pathname );
    1573                 return ENOMEM;
     1720                return -1;
    15741721            }
    15751722
    1576             // get child inode cluster and local pointer
    1577             child_cxy = GET_CXY( child_xp );
     1723            // get child inode local pointer
    15781724            child_ptr = GET_PTR( child_xp );
    15791725
    15801726#if (DEBUG_VFS_LOOKUP & 1)
    15811727if( DEBUG_VFS_LOOKUP < cycle )
    1582 printk("\n[%s]  missing <%s> inode speculatively created / cxy %x / ptr %x\n",
    1583 __FUNCTION__ , name , child_cxy, child_ptr );
    1584 #endif
    1585              // scan parent mapper to complete the missing inode
     1728printk("\n[%s] thread[%x,%x] created missing inode <%s> in cluster %x\n",
     1729__FUNCTION__, process->pid, this->trdid, name, child_cxy );
     1730#endif
     1731            // scan parent mapper to find the missing dentry, and complete
     1732            // the initialisation of dentry and child inode desciptors
    15861733            if( parent_cxy == local_cxy )
     1734
    15871735            {
    1588                 error = vfs_inode_load( parent_ptr,
    1589                                         name,
    1590                                         child_xp );
     1736                error = vfs_fs_child_init( parent_ptr,
     1737                                           name,
     1738                                           child_xp );
    15911739            }
    15921740            else
    15931741            {
    1594                 rpc_vfs_inode_load_client( parent_cxy,
    1595                                            parent_ptr,
    1596                                            name,
    1597                                            child_xp,
    1598                                            &error );
     1742                rpc_vfs_fs_child_init_client( parent_cxy,
     1743                                              parent_ptr,
     1744                                              name,
     1745                                              child_xp,
     1746                                              &error );
    15991747            }
    16001748
    16011749            if ( error )   // child not found in parent mapper
    16021750            {
    1603                 if( last && create && dir )  // new directory  => update inode type
     1751                if ( last && create )  // add a new dentry in parent
    16041752                {
    1605                      hal_remote_s32( XPTR( child_cxy, &child_ptr->type ), INODE_TYPE_DIR );
     1753                    error = vfs_new_child_init( parent_xp,               
     1754                                                dentry_xp,
     1755                                                child_xp );
     1756                    if ( error )
     1757                    {
     1758                        printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
     1759                        __FUNCTION__, name, pathname );
     1760                        vfs_remove_child_from_parent( child_xp );
     1761                        return -1;
     1762                    }
    16061763
    16071764#if (DEBUG_VFS_LOOKUP & 1)
    16081765if( DEBUG_VFS_LOOKUP < cycle )
    1609 printk("\n[%s]  created node <%s> in path %s / type DIR\n",
    1610 __FUNCTION__ , name, pathname );
     1766printk("\n[%s] thread[%x,%x] created inode <%s> in path\n",
     1767__FUNCTION__, process->pid, this->trdid, name );
    16111768#endif
    16121769                }
    1613                 else if ( last && create )   // new file => update inode type
    1614                 {
    1615                      hal_remote_s32( XPTR( child_cxy, &child_ptr->type ), INODE_TYPE_FILE );
    1616 
    1617 #if (DEBUG_VFS_LOOKUP & 1)
    1618 if( DEBUG_VFS_LOOKUP < cycle )
    1619 printk("\n[%s]  created node <%s> in path %s / type FILE\n",
    1620 __FUNCTION__ , name, pathname );
    1621 #endif
    1622                 }
    1623                 else                         // not last or not create => remove created node
     1770                else                   // not last or not create => error
    16241771                {                       
    16251772                     printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
     
    16291776                }
    16301777            }
    1631             else          // child found in parent
     1778            else          // child found in parent mapper
    16321779            {
    16331780                // load child mapper from device if child is a directory (prefetch)
     
    16361783                    if( child_cxy == local_cxy )
    16371784                    {
    1638                         error = vfs_mapper_load_all( child_ptr );
     1785                        error = vfs_inode_load_all_pages( child_ptr );
    16391786                    }
    16401787                    else
    16411788                    {
    1642                         rpc_vfs_mapper_load_all_client( child_cxy,
    1643                                                         child_ptr,
    1644                                                         &error );
     1789                        rpc_vfs_inode_load_all_pages_client( child_cxy,
     1790                                                             child_ptr,
     1791                                                             &error );
    16451792                    }
    16461793                    if ( error )
     
    16541801#if (DEBUG_VFS_LOOKUP & 1)
    16551802if( DEBUG_VFS_LOOKUP < cycle )
    1656 printk("\n[%s]  load mapper from device for node <%s> in path %s\n",
    1657 __FUNCTION__ , name, pathname );
     1803printk("\n[%s] thread[%x,%x] loaded from IOC device mapper for <%s> in <%s>\n",
     1804__FUNCTION__ , process->pid, this->trdid, name, pathname );
    16581805#endif
    16591806                }
     
    16681815#if (DEBUG_VFS_LOOKUP & 1)
    16691816if( DEBUG_VFS_LOOKUP < cycle )
    1670 printk("\n[%s] found <%s> / inode %x in cluster %x\n",
    1671 __FUNCTION__ , name , GET_PTR(child_xp) , GET_CXY(child_xp) );
     1817printk("\n[%s] thread[%x,%x] found <%s> / inode %x in cluster %x\n",
     1818__FUNCTION__, process->pid, this->trdid, name, GET_PTR(child_xp), GET_CXY(child_xp) );
    16721819#endif
    16731820            child_ptr  = GET_PTR( child_xp );
     
    17101857cycle = (uint32_t)hal_get_cycles();
    17111858if( DEBUG_VFS_LOOKUP < cycle )
    1712 printk("\n[%s] thread[%x,%x] exit for <%s>\n"
    1713 "     parent %x in cluster %x / child %x in cluster %x / cycle %d\n",
    1714 __FUNCTION__ , process->pid, this->trdid, pathname,
    1715 parent_ptr, parent_cxy, child_ptr, child_cxy, cycle );
     1859printk("\n[%s] thread[%x,%x] exit for <%s> cycle %d\n",
     1860__FUNCTION__ , process->pid, this->trdid, pathname, cycle );
    17161861#endif
    17171862
     
    17231868
    17241869}  // end vfs_lookup()
     1870
     1871
     1872
     1873///////////////////////////////////////////////
     1874error_t vfs_new_child_init( xptr_t   parent_xp,
     1875                            xptr_t   dentry_xp,
     1876                            xptr_t   child_xp )
     1877{
     1878    error_t     error;
     1879    uint32_t    cluster;
     1880    uint32_t    child_type;
     1881    uint32_t    child_size;
     1882
     1883#if DEBUG_VFS_NEW_CHILD_INIT
     1884char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1885char child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1886vfs_inode_get_name( parent_xp , parent_name );
     1887vfs_inode_get_name( child_xp  , child_name );
     1888uint32_t   cycle = (uint32_t)hal_get_cycles();
     1889thread_t * this  = CURRENT_THREAD;
     1890if( DEBUG_VFS_NEW_CHILD_INIT < cycle )
     1891printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     1892__FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
     1893#endif
     1894
     1895    // get parent inode cluster and local pointer
     1896    cxy_t          parent_cxy = GET_CXY( parent_xp );
     1897    vfs_inode_t  * parent_ptr = GET_PTR( parent_xp );
     1898
     1899    // get dentry local pointer
     1900    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
     1901
     1902    // get child inode cluster and local pointer
     1903    cxy_t          child_cxy  = GET_CXY( child_xp );
     1904    vfs_inode_t  * child_ptr  = GET_PTR( child_xp );
     1905
     1906    // 1. allocate one free cluster to child inode
     1907    // depending on the child inode FS type
     1908    vfs_ctx_t * ctx = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) );
     1909
     1910    error = vfs_fs_cluster_alloc( ctx->type,
     1911                                  &cluster );
     1912    if ( error )
     1913    {
     1914        printk("\n[ERROR] in %s : cannot find a free VFS cluster\n",
     1915        __FUNCTION__ );
     1916        return -1;
     1917    }
     1918
     1919#if( DEBUG_VFS_NEW_CHILD_INIT & 1)
     1920if( DEBUG_VFS_NEW_CHILD_INIT < cycle )
     1921printk("\n[%s] thread[%x,%x] allocated one FAT cluster to <%s>\n",
     1922__FUNCTION__ , this->process->pid, this->trdid, child_name );
     1923#endif
     1924
     1925    // 2. update the child inode descriptor
     1926    child_type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
     1927    child_size = (child_type == INODE_TYPE_DIR) ? 4096 : 0;
     1928   
     1929    hal_remote_s32( XPTR( child_cxy , &child_ptr->size )   , child_size );
     1930    hal_remote_spt( XPTR( child_cxy , &child_ptr->extend ) , (void*)(intptr_t)cluster );
     1931
     1932    // 3. update the parent inode mapper, and
     1933    // update the dentry extension if required
     1934    if( local_cxy == parent_cxy )
     1935    {
     1936        error = vfs_fs_add_dentry( parent_ptr,
     1937                                   dentry_ptr );
     1938    }
     1939    else
     1940    {
     1941        rpc_vfs_fs_add_dentry_client( parent_cxy,
     1942                                      parent_ptr,
     1943                                      dentry_ptr,
     1944                                      &error );
     1945    }
     1946    if ( error )
     1947    {
     1948        printk("\n[ERROR] in %s : cannot register child in parent directory\n",
     1949        __FUNCTION__ );
     1950        return -1;
     1951    }
     1952
     1953#if DEBUG_VFS_NEW_CHILD_INIT
     1954cycle = (uint32_t)hal_get_cycles();
     1955if( DEBUG_VFS_NEW_CHILD_INIT < cycle )
     1956printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%> / cycle %d\n",
     1957__FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
     1958#endif
     1959
     1960    return 0;
     1961
     1962}  // end vfs_new_child_init()
    17251963
    17261964////////////////////////////////////////////
     
    17942032
    17952033     
    1796 //////////////////////////////////////////////////////////////
    1797 error_t vfs_add_child_in_parent( cxy_t              child_cxy,
    1798                                  vfs_inode_type_t   inode_type,
     2034////////////////////////////////////////////////////////////////////
     2035error_t vfs_add_child_in_parent( cxy_t              child_inode_cxy,
     2036                                 vfs_inode_type_t   child_inode_type,
    17992037                                 vfs_fs_type_t      fs_type,
    1800                                  xptr_t             parent_xp,
     2038                                 xptr_t             parent_inode_xp,
    18012039                                 char             * name,
    1802                                  void             * extend,
    1803                                  xptr_t           * child_xp )
     2040                                 xptr_t           * dentry_xp,
     2041                                 xptr_t           * child_inode_xp )
    18042042{
    18052043    error_t         error;
    1806     xptr_t          dentry_xp;   // extended pointer on created dentry
    1807     xptr_t          inode_xp;    // extended pointer on created inode
    1808     cxy_t           parent_cxy;  // parent inode cluster identifier
    1809     vfs_inode_t   * parent_ptr;  // parent inode local pointer
     2044    xptr_t          new_dentry_xp;       // extended pointer on created dentry
     2045    vfs_dentry_t  * new_dentry_ptr;      // created dentry local pointer
     2046    xptr_t          new_inode_xp;        // extended pointer on created child inode
     2047    cxy_t           parent_inode_cxy;    // parent inode cluster identifier
     2048    vfs_inode_t   * parent_inode_ptr;    // parent inode local pointer
    18102049
    18112050    // get parent inode cluster and local pointer
    1812     parent_cxy = GET_CXY( parent_xp );
    1813     parent_ptr = GET_PTR( parent_xp );
     2051    parent_inode_cxy = GET_CXY( parent_inode_xp );
     2052    parent_inode_ptr = GET_PTR( parent_inode_xp );
    18142053
    18152054#if DEBUG_VFS_ADD_CHILD
     2055char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2056vfs_inode_get_name( parent_inode_xp , parent_name );
    18162057uint32_t cycle = (uint32_t)hal_get_cycles();
    18172058thread_t * this = CURRENT_THREAD;
    18182059if( DEBUG_VFS_ADD_CHILD < cycle )
    1819 printk("\n[%s] thread[%x,%x] enter for <%s> / child_cxy %x / parent_cxy %x / cycle %d\n",
    1820 __FUNCTION__, this->process->pid, this->trdid, name,
    1821 child_cxy, parent_cxy, (uint32_t)hal_get_cycles() );
     2060printk("\n[%s] thread[%x,%x] enter / child <%s> cxy %x / parent <%s> cxy %x / cycle %d\n",
     2061__FUNCTION__, this->process->pid, this->trdid, name, child_inode_cxy,
     2062parent_name, parent_inode_cxy, (uint32_t)hal_get_cycles() );
    18222063#endif
    18232064
    18242065    // 1. create dentry
    1825     if( parent_cxy == local_cxy )      // parent cluster is the local cluster
     2066    if( parent_inode_cxy == local_cxy )      // parent cluster is the local cluster
    18262067    {
    18272068        error = vfs_dentry_create( fs_type,
    18282069                                   name,
    1829                                    parent_ptr,
    1830                                    &dentry_xp );
     2070                                   parent_inode_ptr,
     2071                                   &new_dentry_xp );
    18312072    }
    18322073    else                               // parent cluster is remote
    18332074    {
    1834         rpc_vfs_dentry_create_client( parent_cxy,
     2075        rpc_vfs_dentry_create_client( parent_inode_cxy,
    18352076                                      fs_type,
    18362077                                      name,
    1837                                       parent_ptr,
    1838                                       &dentry_xp,
     2078                                      parent_inode_ptr,
     2079                                      &new_dentry_xp,
    18392080                                      &error );
    18402081    }
     
    18432084    {
    18442085        printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n",
    1845         __FUNCTION__ , name , parent_cxy );
    1846         return ENOMEM;
    1847     }
     2086        __FUNCTION__ , name , parent_inode_cxy );
     2087        return -1;
     2088    }
     2089
     2090    // get dentry local pointer
     2091    new_dentry_ptr = GET_PTR( new_dentry_xp );
    18482092
    18492093#if(DEBUG_VFS_ADD_CHILD & 1)
    18502094if( DEBUG_VFS_ADD_CHILD < cycle )
    18512095printk("\n[%s] thread[%x,%x] / dentry <%s> created in cluster %x\n",
    1852 __FUNCTION__, this->process->pid, this->trdid, name, parent_cxy );
     2096__FUNCTION__, this->process->pid, this->trdid, name, parent_inode_cxy );
    18532097#endif
    18542098
     
    18592103    uint32_t gid  = 0;
    18602104   
    1861     if( child_cxy == local_cxy )      // child cluster is the local cluster
    1862     {
    1863         error = vfs_inode_create( dentry_xp,
     2105    if( child_inode_cxy == local_cxy )      // child cluster is the local cluster
     2106    {
     2107        error = vfs_inode_create( new_dentry_xp,
    18642108                                  fs_type,
    1865                                   inode_type,
    1866                                   extend,
     2109                                  child_inode_type,
    18672110                                  attr,
    18682111                                  mode,
    18692112                                  uid,
    18702113                                  gid,
    1871                                   &inode_xp );
     2114                                  &new_inode_xp );
    18722115    }
    18732116    else                              // child cluster is remote
    18742117    {
    1875         rpc_vfs_inode_create_client( child_cxy,
    1876                                      dentry_xp,
     2118        rpc_vfs_inode_create_client( child_inode_cxy,
     2119                                     new_dentry_xp,
    18772120                                     fs_type,
    1878                                      inode_type,
    1879                                      extend,
     2121                                     child_inode_type,
    18802122                                     attr,
    18812123                                     mode,
    18822124                                     uid,
    18832125                                     gid,
    1884                                      &inode_xp,
     2126                                     &new_inode_xp,
    18852127                                     &error );
    18862128    }
     
    18892131    {
    18902132        printk("\n[ERROR] in %s : cannot create inode in cluster %x\n",
    1891                __FUNCTION__ , child_cxy );
     2133               __FUNCTION__ , child_inode_cxy );
    18922134 
    1893         vfs_dentry_t * dentry = GET_PTR( dentry_xp );
    1894         if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry );
    1895         else rpc_vfs_dentry_destroy_client( parent_cxy , dentry , &error );
    1896         return ENOMEM;
     2135        if( parent_inode_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
     2136        else rpc_vfs_dentry_destroy_client( parent_inode_cxy , new_dentry_ptr );
     2137        return -1;
    18972138    }
    18982139
     
    19002141if( DEBUG_VFS_ADD_CHILD < cycle )
    19012142printk("\n[%s] thread[%x,%x] / inode <%s> created in cluster %x\n",
    1902 __FUNCTION__ , this->process->pid, this->trdid, name , child_cxy );
    1903 #endif
    1904 
    1905     // 3. update extended pointer on inode in dentry
    1906     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    1907     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    1908     hal_remote_s64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) , inode_xp );
     2143__FUNCTION__ , this->process->pid, this->trdid, name , child_inode_cxy );
     2144#endif
     2145
     2146    // 3. update "child_xp" field in dentry and increment refcounts
     2147    hal_remote_s64( XPTR( parent_inode_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp );
     2148    vfs_inode_remote_up( new_inode_xp );
     2149    vfs_dentry_remote_up( new_dentry_xp );
    19092150
    19102151#if DEBUG_VFS_ADD_CHILD
     
    19152156#endif
    19162157
    1917     // success : return extended pointer on child inode
    1918     *child_xp = inode_xp;
     2158    // return extended pointer on dentry & child inode
     2159    *dentry_xp      = new_dentry_xp;
     2160    *child_inode_xp = new_inode_xp;
    19192161    return 0;
    19202162
    1921     // FIXME update the refcount fields in both inode and dentry
    1922 
    19232163}  // end vfs_add_child_in_parent()
    19242164
    1925 ///////////////////////////////////////////////////////
    1926 error_t vfs_remove_child_from_parent( xptr_t inode_xp )
     2165////////////////////////////////////////////////////
     2166void vfs_remove_child_from_parent( xptr_t inode_xp )
    19272167{
    19282168    cxy_t          inode_cxy;
     
    19312171    cxy_t          dentry_cxy;
    19322172    vfs_dentry_t * dentry_ptr;
    1933     error_t        error;
    19342173   
    19352174    // get inode cluster and local pointer
     
    19372176    inode_ptr = GET_PTR( inode_xp );
    19382177
    1939     // get cluster and pointers of associated dentry
     2178    // get associated dentry cluster and pointers
    19402179    dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    19412180    dentry_cxy = GET_CXY( dentry_xp );
    19422181    dentry_ptr = GET_PTR( dentry_xp );
    19432182
    1944     // FIXME update the refcount fields in both inode and dentry
     2183// check dentry refcount
     2184assert( ( hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) ) == 1 ),
     2185"dentry refcount must be 1\n" );
     2186
     2187// check inode refcount
     2188assert( ( hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) ) == 1 ),
     2189"inode refcount must be 1\n" );
     2190
     2191    // decrement refcount for inode and dentry
     2192    vfs_inode_remote_down( inode_xp );
     2193    vfs_dentry_remote_down( dentry_xp );
    19452194
    19462195    // delete dentry
    19472196    if( dentry_cxy == local_cxy )
    19482197    {
    1949          error = vfs_dentry_destroy( dentry_ptr );
     2198         vfs_dentry_destroy( dentry_ptr );
    19502199    }
    19512200    else
    19522201    {
    19532202         rpc_vfs_dentry_destroy_client( dentry_cxy,
    1954                                         dentry_ptr,
    1955                                         &error );
    1956     }
    1957     if( error ) return EINVAL;
     2203                                        dentry_ptr );
     2204    }
    19582205
    19592206    // delete inode
     
    19652212    {
    19662213         rpc_vfs_inode_destroy_client( inode_cxy,
    1967                                        inode_ptr,
    1968                                        &error );
    1969     }
    1970     if( error ) return EINVAL;
    1971 
    1972     return 0;
     2214                                       inode_ptr );
     2215    }
    19732216
    19742217}  // end vfs_remove_child_from_parent()
    19752218
    19762219//////////////////////////////////////////////////////////////////////////////////////////
    1977 //            Mapper related functions
     2220//    API used by VFS to access a specific FS 
    19782221//////////////////////////////////////////////////////////////////////////////////////////
    19792222
    1980 ////////////////////////////////////////////
    1981 error_t vfs_mapper_move_page( page_t * page,
    1982                               bool_t   to_mapper )
     2223///////////////////////////////////////////
     2224error_t vfs_fs_move_page( xptr_t   page_xp,
     2225                          bool_t   to_mapper )
    19832226{
    19842227    error_t error = 0;
    19852228
    1986     assert( (page != NULL) , "page pointer is NULL\n" );
    1987 
    1988     mapper_t    * mapper = page->mapper;
    1989 
    1990     assert( (mapper != NULL) , "no mapper for page\n" );
    1991 
    1992 #if DEBUG_VFS_MAPPER_MOVE
    1993 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1994 thread_t * this  = CURRENT_THREAD;
    1995 if( DEBUG_VFS_MAPPER_MOVE < cycle )
    1996 printk("\n[%s] thread[%x,%x] enter for page %d / mapper %x / inode %x / cycle %d\n",
    1997 __FUNCTION__, this->process->pid, this->trdid, page->index, mapper, mapper->inode, cycle );
    1998 #endif
     2229assert( (page_xp != XPTR_NULL) , "page pointer is NULL\n" );
     2230
     2231    page_t * page_ptr = GET_PTR( page_xp );
     2232    cxy_t    page_cxy = GET_CXY( page_xp );
     2233
     2234    // get local pointer on page mapper
     2235    mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
     2236
     2237assert( (mapper != NULL) , "no mapper for page\n" );
     2238
     2239    // get FS type
     2240    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->type ) );
     2241
     2242    // call relevant FS function
     2243    if( fs_type == FS_TYPE_FATFS )
     2244    {
     2245        error = fatfs_move_page( page_xp , to_mapper );
     2246    }
     2247    else if( fs_type == FS_TYPE_RAMFS )
     2248    {
     2249        assert( false , "should not be called for RAMFS\n" );
     2250    }
     2251    else if( fs_type == FS_TYPE_DEVFS )
     2252    {
     2253        assert( false , "should not be called for DEVFS\n" );
     2254    }
     2255    else
     2256    {
     2257        assert( false , "undefined file system type\n" );
     2258    }
     2259
     2260    return error;
     2261
     2262}  // end vfs_fs_move_page()
     2263
     2264////////////////////////////////////////////////
     2265error_t vfs_fs_add_dentry( vfs_inode_t  * inode,
     2266                           vfs_dentry_t * dentry )
     2267{
     2268    error_t error = 0;
     2269
     2270assert( (inode  != NULL) , "inode  pointer is NULL\n" );
     2271assert( (dentry != NULL) , "dentry pointer is NULL\n" );
     2272
     2273    mapper_t * mapper = inode->mapper;
     2274
     2275assert( (mapper != NULL) , "mapper pointer is NULL\n" );
    19992276
    20002277    // get FS type
     
    20042281    if( fs_type == FS_TYPE_FATFS )
    20052282    {
    2006         // enter mapper in write mode
    2007         rwlock_wr_acquire( &mapper->lock );
    2008 
    2009         // move page to mapper
    2010         error = fatfs_mapper_move_page( page , to_mapper );
    2011 
    2012         // exit mapper in write mode
    2013         rwlock_wr_release( &mapper->lock );
     2283        error = fatfs_add_dentry( inode , dentry );
    20142284    }
    20152285    else if( fs_type == FS_TYPE_RAMFS )
     
    20262296    }
    20272297
    2028 #if DEBUG_VFS_MAPPER_MOVE
    2029 cycle = (uint32_t)hal_get_cycles();
    2030 if( DEBUG_VFS_MAPPER_MOVE < cycle )
    2031 printk("\n[%s] thread[%x,%x] exit for page %d / mapper %x / inode %x / cycle %d\n",
    2032 __FUNCTION__, this->process->pid, this->trdid, page->index, mapper, mapper->inode, cycle );
    2033 #endif
    2034 
    20352298    return error;
    20362299
    2037 }  // end vfs_move_page()
    2038 
    2039 //////////////////////////////////////////////////
    2040 error_t vfs_mapper_load_all( vfs_inode_t * inode )
    2041 {
    2042     assert( (inode != NULL) , "inode pointer is NULL\n" );
    2043 
    2044     uint32_t   index;
    2045     page_t   * page;
     2300}  // end vfs_fs_add_dentry()
     2301
     2302///////////////////////////////////////////////////
     2303error_t vfs_fs_remove_dentry( vfs_inode_t  * inode,
     2304                              vfs_dentry_t * dentry )
     2305{
     2306    error_t error = 0;
     2307
     2308assert( (inode  != NULL) , "inode  pointer is NULL\n" );
     2309assert( (dentry != NULL) , "dentry pointer is NULL\n" );
    20462310
    20472311    mapper_t * mapper = inode->mapper;
    2048     uint32_t   size   = inode->size;
    20492312
    20502313assert( (mapper != NULL) , "mapper pointer is NULL\n" );
    20512314
    2052 #if DEBUG_VFS_MAPPER_LOAD
    2053 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2054 thread_t * this  = CURRENT_THREAD;
    2055 if( DEBUG_VFS_MAPPER_MOVE < cycle )
    2056 printk("\n[%s] thread[%x,%x] enter for inode %x in cluster %x / cycle %d\n",
    2057 __FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle );
    2058 #endif
    2059 
    2060     // compute number of pages
    2061     uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
    2062     if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++;
    2063 
    2064     // loop on pages
    2065     for( index = 0 ; index < npages ; index ++ )
    2066     {
    2067         // this function allocates the missing page in mapper,
    2068         // and call the vfs_mapper_move_page() to load the page from device
    2069         page = mapper_get_page( mapper , index );
    2070 
    2071         if( page == NULL ) return EIO;
    2072     }
    2073 
    2074 #if DEBUG_VFS_MAPPER_LOAD
    2075 cycle = (uint32_t)hal_get_cycles();
    2076 if( DEBUG_VFS_MAPPER_MOVE < cycle )
    2077 printk("\n[%s] thread[%x,%x] exit for inode %x in cluster %x / cycle %d\n",
    2078 __FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle );
    2079 #endif
    2080 
    2081     return 0;
    2082 
    2083 }  // end vfs_mapper_load_all()
    2084 
     2315    // get FS type
     2316    vfs_fs_type_t fs_type = mapper->type;
     2317
     2318    // call relevant FS function
     2319    if( fs_type == FS_TYPE_FATFS )
     2320    {
     2321        error = fatfs_remove_dentry( inode , dentry );
     2322    }
     2323    else if( fs_type == FS_TYPE_RAMFS )
     2324    {
     2325        assert( false , "should not be called for RAMFS\n" );
     2326    }
     2327    else if( fs_type == FS_TYPE_DEVFS )
     2328    {
     2329        assert( false , "should not be called for DEVFS\n" );
     2330    }
     2331    else
     2332    {
     2333        assert( false , "undefined file system type\n" );
     2334    }
     2335
     2336    return error;
     2337
     2338}  // end vfs_fs_remove_dentry()
     2339
     2340////////////////////////////////////////////////
     2341error_t vfs_fs_child_init( vfs_inode_t * parent,
     2342                           char        * name,
     2343                           xptr_t        child_xp )
     2344{
     2345    error_t error = 0;
     2346
     2347// check arguments
     2348assert( (parent != NULL) , "parent pointer is NULL\n");
     2349assert( (child_xp != XPTR_NULL) , "child pointer is NULL\n");
     2350
     2351    // get parent inode FS type
     2352    vfs_fs_type_t fs_type = parent->ctx->type;
     2353
     2354    // call relevant FS function
     2355    if( fs_type == FS_TYPE_FATFS )
     2356    {
     2357        error = fatfs_child_init( parent , name , child_xp );
     2358    }
     2359    else if( fs_type == FS_TYPE_RAMFS )
     2360    {
     2361        assert( false , "should not be called for RAMFS\n" );
     2362    }
     2363    else if( fs_type == FS_TYPE_DEVFS )
     2364    {
     2365        assert( false , "should not be called for DEVFS\n" );
     2366    }
     2367    else
     2368    {
     2369        assert( false , "undefined file system type\n" );
     2370    }
     2371
     2372    return error;
     2373
     2374} // end vfs_fs_child_init()
     2375
     2376/////////////////////////////////////////////////
     2377error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
     2378                              uint32_t * cluster )
     2379{
     2380    error_t error = 0;
     2381
     2382    // call relevant FS function
     2383    if( fs_type == FS_TYPE_FATFS )
     2384    {
     2385        error = fatfs_cluster_alloc( cluster );
     2386    }
     2387    else if( fs_type == FS_TYPE_RAMFS )
     2388    {
     2389        assert( false , "should not be called for RAMFS\n" );
     2390    }
     2391    else if( fs_type == FS_TYPE_DEVFS )
     2392    {
     2393        assert( false , "should not be called for DEVFS\n" );
     2394    }
     2395    else
     2396    {
     2397        assert( false , "undefined file system type\n" );
     2398    }
     2399
     2400    return error;
     2401
     2402} // end vfs_fs_alloc_cluster()
     2403
     2404////////////////////////////////////////////////
     2405error_t vfs_fs_release_inode( xptr_t  inode_xp )
     2406{
     2407    error_t error = 0;
     2408
     2409assert( (inode_xp  != XPTR_NULL) , "inode pointer is NULL\n")       
     2410
     2411    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     2412    cxy_t         inode_cxy = GET_CXY( inode_xp );
     2413
     2414    // get local pointer on page mapper
     2415    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     2416
     2417assert( (mapper != NULL) , "mapper pointer is NULL\n")       
     2418
     2419    // get FS type from mapper
     2420    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->type ) );
     2421
     2422    // call relevant FS function
     2423    if( fs_type == FS_TYPE_FATFS )
     2424    {
     2425        error = fatfs_release_inode( inode_xp );
     2426    }
     2427    else if( fs_type == FS_TYPE_RAMFS )
     2428    {
     2429        assert( false , "should not be called for RAMFS\n" );
     2430    }
     2431    else if( fs_type == FS_TYPE_DEVFS )
     2432    {
     2433        assert( false , "should not be called for DEVFS\n" );
     2434    }
     2435    else
     2436    {
     2437        assert( false , "undefined file system type\n" );
     2438    }
     2439
     2440    return error;
     2441   
     2442}  // end vfs_fs_release_inode()
     2443
     2444
  • trunk/kernel/fs/vfs.h

    r598 r602  
    7878 * This structure defines a VFS context, that contains informations common to all inodes
    7979 * and dentries for a given file system. As it is declared as a global variable in the
    80  * kdata segment, it is handled as private by each OS intance in a given cluster.
     80 * kdata segment (fs_context[] array), it is replicated in all clusters.
     81 * The <extend> field is a pointer on the FS specific context extension.
     82 * This extension is dynamically allocated by kernel_init in all clusters.
     83 * In each cluster, both this VFS context and the FS specific context are handled as
     84 * private by the local OS intance.
    8185 *****************************************************************************************/
    8286
     
    252256
    253257
    254 /*****************************************************************************************/
    255 /******************** VFS global functions ***********************************************/
    256 /*****************************************************************************************/
    257 
    258 
    259 /******************************************************************************************
    260  * This function mount a given file system type for a given process TODO.     
    261  *****************************************************************************************/
    262 error_t vfs_mount_fs_root( struct device_s  * device,
    263                                        uint32_t           fs_type,
    264                                        struct process_s * process );
    265 
    266 
    267 /*****************************************************************************************/
    268 /******************* VFS Context related functions ****************************************/
    269 /*****************************************************************************************/
     258/******************************************************************************************
     259 *        These functions access / modify  a VFS context.
     260 *****************************************************************************************/
    270261
    271262/******************************************************************************************
     
    311302
    312303
    313 /*****************************************************************************************/
    314 /********************* Inode related functions *******************************************/
    315 /*****************************************************************************************/
     304/******************************************************************************************
     305 *        These low-level functions access / modify a VFS inode descriptor
     306 *****************************************************************************************/
     307
     308/******************************************************************************************
     309 * This function returns a printable string for the inode type.
     310 *****************************************************************************************/
     311const char * vfs_inode_type_str( vfs_inode_type_t type );
    316312
    317313/******************************************************************************************
     
    325321 * @ fs_type    : file system type.
    326322 * @ inode_type : inode type.
    327  * @ extend     : local pointer on vs_type_specific extension.
    328323 * @ attr       : inode attributes.
    329324 * @ rights     : inode access rights.
     
    336331                          vfs_fs_type_t     fs_type,
    337332                          vfs_inode_type_t  inode_type,
    338                           void            * extend,
    339333                          uint32_t          attr,
    340334                          uint32_t          rights,
     
    344338
    345339/******************************************************************************************
    346  * This function releases memory allocated to an inode descriptor.
    347  * It must be executed by a thread running in the cluster containing the inode,
    348  * and the inode refcount must be zero. If the client thread is not running in the owner
    349  * cluster, you must use the rpc_vfs_inode_destroy_client() function.
     340 * This function releases memory allocated to an inode descriptor, including
     341 * all memory allocated to the mapper (both mapper descriptor and radix tree).
     342 * The mapper should not contain any dirty page (shold be synchronized before deletion),
     343 * and the inode refcount must be zero.
     344 * It must be executed by a thread running in the cluster containing the inode.
     345 * Use the rpc_vfs_inode_destroy_client() function if required.
    350346 ******************************************************************************************
    351347 * @ inode  : local pointer on inode descriptor.
    352  * @ return 0 if success / return EINVAL if error.
    353  *****************************************************************************************/
    354 error_t vfs_inode_destroy( vfs_inode_t *  inode ); 
    355 
    356 /******************************************************************************************
    357  * This function scan an existing parent inode directory, identified by the <parent>
    358  * argument to find a directory entry identified by the <name> argument, and update
    359  * the remote child inode, identified by the <child_xp> argument.
    360  * Depending on the file system type, it calls the relevant, FS specific function,
    361  * to scan the directory, and set the "type", "size", and "extend" fields.
    362  * It must be called by a thread running in the cluster containing the parent inode.
    363  ******************************************************************************************
    364  * @ parent    : local pointer on parent inode (directory).
    365  * @ name      : child name.
    366  * @ child_xp  : extended pointer on remote child inode (file or directory)
    367  * @ return 0 if success / return ENOENT if not found.
    368  *****************************************************************************************/
    369 error_t vfs_inode_load( vfs_inode_t * parent,
    370                         char        * name,
    371                         xptr_t        child_xp );
     348 *****************************************************************************************/
     349void vfs_inode_destroy( vfs_inode_t *  inode ); 
    372350
    373351/******************************************************************************************
     
    399377/******************************************************************************************
    400378 * This function takes the main lock of a remote inode.
    401  * This lock protect all inode fiels, including the children dentries.
     379 * This lock protect all inode fields, including the children dentries.
    402380 *****************************************************************************************
    403381 * @ inode_xp  : extended pointer on the remote inode.
     
    424402                         char * name );
    425403
    426 
    427 /*****************************************************************************************/
    428 /***************** Dentry related functions **********************************************/
    429 /*****************************************************************************************/
     404/******************************************************************************************
     405 * This function accesses successively all pages of a file identified by the <inode>,
     406 * argument, to force misses, and load all pages into mapper.
     407 * The target inode can be a directory or a file, but this function is mainly used
     408 * to prefetch a complete directory to the mapper.
     409 * It must be executed by a thread running in the cluster containing the inode.
     410 * This function does NOT take any lock.
     411 ******************************************************************************************
     412 * @ inode  : local pointer on inode.
     413 * @ return 0 if success / return -1 if device access failure.
     414 *****************************************************************************************/
     415error_t vfs_inode_load_all_pages( vfs_inode_t * inode );
     416
     417
     418/******************************************************************************************
     419 *        These low-level functions access / modify a VFS dentry descriptor
     420 *****************************************************************************************/
    430421
    431422/******************************************************************************************
     
    449440/******************************************************************************************
    450441 * This function releases memory allocated to a dentry descriptor.
    451  * It must be executed by a thread running in the cluster containing the dentry,
    452  * and the dentry refcount must be zero. If the client thread is not running in the owner
    453  * cluster, you must use the rpc_dentry_destroy_client() function.
     442 * The dentry refcount must be zero.
     443 * It must be executed by a thread running in the cluster containing the dentry.
     444 * Use the rpc_vfs_dentry_destroy_client() function if required.
    454445 ******************************************************************************************
    455446 * @ dentry  : local pointer on dentry descriptor.
    456  * @ return 0 if success / return EINVAL if error.
    457  *****************************************************************************************/
    458 error_t vfs_dentry_destroy( vfs_dentry_t *  dentry ); 
     447 *****************************************************************************************/
     448void vfs_dentry_destroy( vfs_dentry_t *  dentry ); 
    459449
    460450/******************************************************************************************
     
    466456
    467457
    468 /*****************************************************************************************/
    469 /************************ File descriptor related functions ******************************/
    470 /*****************************************************************************************/
     458/******************************************************************************************
     459 *        These low-level functions access / modify a VFS file descriptor
     460 *****************************************************************************************/
    471461
    472462/******************************************************************************************
     
    505495
    506496
    507 /*****************************************************************************************/
    508 /******************* Inode-Tree related functions ****************************************/
    509 /*****************************************************************************************/
    510 
    511 /******************************************************************************************
    512  * This function returns a printable string for the inode type.
    513  *****************************************************************************************/
    514 const char * vfs_inode_type_str( vfs_inode_type_t type );
     497/******************************************************************************************
     498 *        These functions access / modify the distributed VFS Inode Treee
     499 *****************************************************************************************/
    515500
    516501/******************************************************************************************
     
    555540 * This function creates a new couple dentry/inode, and insert it in the Inode-Tree.
    556541 * It can be executed by any thread running in any cluster (can be different from both
    557  * the child cluster and the parent cluster), as it uses the rpc_dentry_create_client()
    558  * and rpc_inode_create client() if required. This is done in three steps:
    559  * 1) The dentry is created in the cluster containing the existing <parent_xp> inode.
    560  *    The new dentry name is defined by the <name> argument.
    561  * 2) The inode and its associated mapper are created in cluster identified by <child_cxy>.
    562  *    The new inode and the parent inode can have different FS types.
    563  * 3) The "child_xp" field in created dentry (pointing on the created inode) is updated.
    564  ******************************************************************************************
    565  * @ child_cxy  : target cluster for child inode.
    566  * @ inode_type : new inode type
    567  * @ fs_type    : new inode FS type.
    568  * @ parent_xp  : extended pointer on parent inode.
    569  * @ name       : new directory entry name.
    570  * @ extend     : fs_type_specific inode extension.
    571  * @ child_xp   : [out] buffer for extended pointer on child inode.
    572  * @ return 0 if success / ENOMEM if dentry or inode cannot be created.
    573  *****************************************************************************************/
    574 error_t vfs_add_child_in_parent( cxy_t              child_cxy,
    575                                  vfs_inode_type_t   inode_type,
     542 * the child cluster and the parent cluster), as it uses RPCs if required.
     543 * Only the distributed Inode Tree is modified: Even for a new file, this function
     544 * does NOT modify the parent mapper, and does NOT update the FS on IOC device.
     545 *
     546 * [Implementation]
     547 * As there are cross-references between the inode and the associated dentry, this
     548 * function implement a three steps scenario :
     549 * 1) The dentry descriptor is created in the cluster containing the existing <parent_xp>
     550 *    inode, and is only partially initialized : "fs_type", "name", "parent_xp" fields.
     551 * 2) The inode and its associated mapper are created in cluster identified by <child_cxy>,
     552 *    and initialised. The new inode and the parent inode can have different FS types.
     553 * 3) The "child_xp" field in dentry (pointing on the created inode) is updated,
     554 *    and the refcount is incremented for both the inode and the dentry.
     555 ******************************************************************************************
     556 * @ child_inode_cxy  : [in]  target cluster for child inode.
     557 * @ child_inode_type : [in]  child inode type
     558 * @ fs_type          : [in]  child inode FS type.
     559 * @ parent_inode_xp  : [in]  extended pointer on parent inode.
     560 * @ name             : [in]  new directory entry name.
     561 * @ dentry_xp        : [out] buffer for extended pointer on dentry
     562 * @ child_inode_xp   : [out] buffer for extended pointer on child inode.
     563 * @ return 0 if success / -1 if dentry or inode cannot be created.
     564 *****************************************************************************************/
     565error_t vfs_add_child_in_parent( cxy_t              child_inodecxy,
     566                                 vfs_inode_type_t   chilg_inode_type,
    576567                                 vfs_fs_type_t      fs_type,
    577                                  xptr_t             parent_xp,
    578                                  char             * name,   
    579                                  void             * extend,
    580                                  xptr_t           * child_xp );
    581 
    582 /******************************************************************************************
    583  * This function removes a couple dentry/inode from the Inode-Tree, and remove it from
    584  * the external device.
     568                                 xptr_t             parent_inode_xp,
     569                                 char             * name,
     570                                 xptr_t           * dentry_xp,   
     571                                 xptr_t           * child_inode_xp );
     572
     573/******************************************************************************************
     574 * This function removes a couple dentry/inode from the Inode-Tree.
     575 * Both the inode and dentry references counters must be 1.
     576 * It can be executed by any thread running in any cluster (can be different from both
     577 * the inode cluster and the dentry cluster), as it uses RPCs if required.
    585578 ******************************************************************************************
    586579 * @ child_xp   : extended pointer on removed inode.
    587580 *****************************************************************************************/
    588 error_t vfs_remove_child_from_parent( xptr_t inode_xp );
     581void vfs_remove_child_from_parent( xptr_t inode_xp );
     582
     583/******************************************************************************************
     584 * This function is called by the vfs_lookup() function when a new dentry/inode must
     585 * be created from scratch and introduced in both the Inode Tree and the IOC device.
     586 * The dentry and inode descriptors have been created by the caller:
     587 * - It allocates one cluster from the relevant FS, and updates the File Allocation
     588 *   Table (both the FAT mapper, and the IOC device).
     589 * - It set the "size", and "extend" fields in child inode descriptor.
     590 * - It updates the parent directory to introduce the new child in the parent directory
     591 *   inode descriptor (radix tree), in theparent inode mapper, and on IOC device.
     592 * - It set the "extend" field in dentry descriptor.
     593 * It can be called by a thread running in any cluster.
     594 ******************************************************************************************
     595 * @ parent_xp   : extended pointer on parent inode descriptor.
     596 * @ dentry_xp   : extended pointer on new dentry descriptor.
     597 * @ child_xp    : extended pointer on child inode descriptor.
     598 * @ return 0 if success / -1 if failure.
     599 *****************************************************************************************/
     600error_t vfs_new_child_init( xptr_t   parent_xp,
     601                         xptr_t   dentry_xp,
     602                         xptr_t   child_xp );
    589603
    590604/******************************************************************************************
     
    597611void vfs_display( xptr_t   inode_xp );
    598612
    599 
    600 
    601 
    602 
    603 /*****************************************************************************************/
    604 /****************** File access API ******************************************************/
    605 /*****************************************************************************************/
     613/******************************************************************************************
     614 * This function mount a given file system type for a given process
     615 * TODO non implemented yet [AG].     
     616 *****************************************************************************************/
     617error_t vfs_mount_fs_root( struct device_s  * device,
     618                                       uint32_t           fs_type,
     619                                       struct process_s * process );
     620
     621
     622
     623/******************************************************************************************
     624 *        These functions define the VFS "syscalls" API (user commands)
     625 *****************************************************************************************/
     626
     627/******************************************************************************************
     628 * This function moves <size> bytes between a remote file mapper, identified by the
     629 * <file_xp> argument, and a - possibly distributed - user space <buffer>, taken into
     630 * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>.
     631 * It is called by the sys_read() and sys_write() functions.
     632 ******************************************************************************************
     633 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.
     634 * @ file_xp   : extended pointer on the remote file descriptor.
     635 * @ buffer    : user space pointer on buffer (can be physically distributed).
     636 * @ size      : requested number of bytes from offset.
     637 * @ returns number of bytes actually moved if success / -1 if error.
     638 *****************************************************************************************/
     639int vfs_user_move( bool_t   to_buffer,
     640                   xptr_t   file_xp,
     641                   void   * buffer,
     642                   uint32_t size );
     643
     644/******************************************************************************************
     645 * This function moves <size> bytes between a remote file mapper, identified by the
     646 * <file_xp> argument, and a - possibly remote - kernel <buffer_xp>, taken into
     647 * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>.
     648 * It is called by the elf_load_process() function.
     649 ******************************************************************************************
     650 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.
     651 * @ file_xp   : extended pointer on the remote file descriptor.
     652 * @ buffer_xp : user space pointer on buffer (can be physically distributed).
     653 * @ size      : requested number of bytes from offset.
     654 * @ returns 0 if success / -1 if error.
     655 *****************************************************************************************/
     656error_t vfs_kernel_move( bool_t   to_buffer,
     657                         xptr_t   file_xp,
     658                         xptr_t   buffer_xp,
     659                         uint32_t size );
    606660
    607661/******************************************************************************************
     
    619673 * @ process     : local pointer on local process descriptor copy.
    620674 * @ path        : file pathname (absolute or relative to current directory).
    621  * @ flags       : defined above.
    622  * @ mode        : access rights (as defined by chmod)
     675 * @ flags       : defined in vfs_file_t structure.
     676 * @ mode        : access rights (as defined by chmod).
    623677 * @ file_xp     : [out] buffer for extended pointer on created remote file descriptor.
    624678 * @ file_id     : [out] buffer for created file descriptor index in reference fd_array.
     
    631685                          xptr_t           * file_xp,
    632686                          uint32_t         * file_id );
    633 
    634 /******************************************************************************************
    635  * This function moves <size> bytes between a remote file mapper, identified by the
    636  * <file_xp> argument, and a - possibly distributed - user space <buffer>, taken into
    637  * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>.
    638  * It is called by the sys_read() and sys_write() functions.
    639  ******************************************************************************************
    640  * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.
    641  * @ file_xp   : extended pointer on the remote file descriptor.
    642  * @ buffer    : user space pointer on buffer (can be physically distributed).
    643  * @ size      : requested number of bytes from offset.
    644  * @ returns number of bytes actually moved if success / -1 if error.
    645  *****************************************************************************************/
    646 int vfs_user_move( bool_t   to_buffer,
    647                    xptr_t   file_xp,
    648                    void   * buffer,
    649                    uint32_t size );
    650 
    651 /******************************************************************************************
    652  * This function moves <size> bytes between a remote file mapper, identified by the
    653  * <file_xp> argument, and a - possibly remote - kernel <buffer_xp>, taken into
    654  * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>.
    655  * It is called by the elf_load_process() function.
    656  ******************************************************************************************
    657  * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.
    658  * @ file_xp   : extended pointer on the remote file descriptor.
    659  * @ buffer_xp : user space pointer on buffer (can be physically distributed).
    660  * @ size      : requested number of bytes from offset.
    661  * @ returns 0 if success / -1 if error.
    662  *****************************************************************************************/
    663 error_t vfs_kernel_move( bool_t   to_buffer,
    664                          xptr_t   file_xp,
    665                          xptr_t   buffer_xp,
    666                          uint32_t size );
    667687
    668688/******************************************************************************************
     
    685705
    686706/******************************************************************************************
    687  * This function close the -non-replicated- file descriptor identified by the <file_xp>
     707 * This function close the - non-replicated - file descriptor identified by the <file_xp>
    688708 * and <file_id> arguments.
    689709 * 1) All entries in the fd_array copies are directly reset by the calling thread,
     
    700720
    701721/******************************************************************************************
    702  * This function remove from the file system a directory entry identified by the
    703  * <cwd_xp> & <path> arguments.
     722 * This function is called by the kernel to create in the file system a new directory
     723 * entry identified by the <cwd_xp> & <path_1>, linked to the node identified by the
     724 * <cwd_xp> & <path_2> arguments.  It can be any type of node.
     725 * If the link is successful, the link count of the target node is incremented.
     726 * <path_1> and <path_2> share equal access rights to the underlying object.
     727 * Both the IOC device and the Inode Tree are modified.
     728 ******************************************************************************************
     729 * @ cwd_xp   : extended pointer on current working directory file descriptor.
     730 * @ path_1   : new pathname (absolute or relative to current directory).
     731 * @ path_1   : existing pathname (absolute or relative to current directory).
     732 * @ returns 0 if success / -1 if error.
     733 *****************************************************************************************/
     734error_t vfs_link( xptr_t   cwd_xp,
     735                  char   * path_1,
     736                  char   * path_2 );
     737
     738/******************************************************************************************
     739 * This function is called by the kernel to remove from the file system a directory entry
     740 * identified by the  <cwd_xp> & <path> arguments. The target node can be any type of node.
     741 * The link count of the target node is decremented. If the removed link is the last,
     742 * the target node is deleted.
     743 * Both the IOC device and the Inode Tree are modified.
    704744 ******************************************************************************************
    705745 * @ cwd_xp   : extended pointer on the current working directory file descriptor.
     
    747787                   char     * path,
    748788                   uint32_t   mode );
    749 
    750 /******************************************************************************************
    751  * This function remove a directory identified by the <cwd_xp / path> arguments
    752  * from the file system.
    753  * TODO not implemented yet...
    754  ******************************************************************************************
    755  * @ cwd_xp   : extended pointer on the current working directory file descriptor.
    756  * @ path     : pathname (absolute or relative to current directory).                     
    757  * @ returns 0 if success / -1 if error.
    758  *****************************************************************************************/
    759 error_t vfs_rmdir( xptr_t   cwd_xp,
    760                    char   * path );
    761789
    762790/******************************************************************************************
     
    797825
    798826
    799 /*****************************************************************************************/
    800 /****************** Mapper access API ****************************************************/
    801 /*****************************************************************************************/
    802 
    803 /******************************************************************************************
    804  * This function makes an I/O operation to move one page to/from device from/to the mapper.
     827
     828/******************************************************************************************
     829 *        These functions define the VFS "FS" API (to a specific File System)
     830 *****************************************************************************************/
     831
     832/******************************************************************************************
     833 * This function updates the mapper associated to a directory inode identified by the
     834 * <parent> argument, to add a new entry identified by the <dentry> argument.
     835 * The directory inode descriptor and the dentry descriptor are in the same cluster.
     836 * Depending on the file system type, it calls the proper, FS specific function.
     837 * It ulso pdates the dentry descriptor and/or the inode descriptor extensions
     838 * as required by the specific file system type.
     839 * Finally, it synchronously updates the parent directory on IOC device.
     840 *
     841 * It must be executed by a thread running in the cluster containing the parent directory.
     842 * It can be the RPC_VFS_VS_ADD_DENTRY. This function does NOT take any lock.
     843 ******************************************************************************************
     844 * @ parent  : local pointer on parent (directory) inode.
     845 * @ dentry  : local pointer on dentry containing name.
     846 * @ return 0 if success / return -1 if device access failure.
     847 *****************************************************************************************/
     848error_t vfs_fs_add_dentry( vfs_inode_t  * parent,
     849                           vfs_dentry_t * dentry );
     850
     851/******************************************************************************************
     852 * This function updates the mapper associated to a directory inode identified by the
     853 * <parent> argument, to remove an entry identified by the <dentry> argument.
     854 * The directory inode descriptor and the dentry descriptor are in the same cluster.
     855 * Depending on the file system type, it calls the proper, FS specific function.
     856 * Finally, it synchronously updates the parent directory on IOC device.
     857 *
     858 * It must be executed by a thread running in the cluster containing the parent directory.
     859 * It can be the RPC_VFS_VS_REMOVE_DENTRY. This function does NOT take any lock.
     860 ******************************************************************************************
     861 * @ parent  : local pointer on parent (directory) inode.
     862 * @ dentry  : local pointer on dentry containing name.
     863 * @ return 0 if success / return -1 if device access failure.
     864 *****************************************************************************************/
     865error_t vfs_fs_remove_dentry( vfs_inode_t  * parent,
     866                              vfs_dentry_t * dentry );
     867
     868/******************************************************************************************
     869 * This function scan the mapper of an an existing parent inode directory, identified by
     870 * the <parent> argument to find a directory entry identified by the <name> argument,
     871 * and updates both the child inode descriptor, identified by the <child_xp> argument,
     872 * and the associated dentry descriptor :
     873 * - It set the "size", and "extend" fields in inode descriptor.
     874 * - It set the "extend" field in dentry descriptor.
     875 * It is called by the vfs_lookup() function in case of miss.
     876 *
     877 * Depending on the file system type, it calls the relevant, FS specific function.
     878 * It must be called by a thread running in the cluster containing the parent inode.
     879 * This function does NOT take any lock.
     880 ******************************************************************************************
     881 * @ parent    : local pointer on parent inode (directory).
     882 * @ name      : child name.
     883 * @ child_xp  : extended pointer on remote child inode (file or directory)
     884 * @ return 0 if success / return ENOENT if not found.
     885 *****************************************************************************************/
     886error_t vfs_fs_child_init( vfs_inode_t * parent,
     887                           char        * name,
     888                           xptr_t        child_xp );
     889
     890/*****************************************************************************************
     891 * This function  updates the FS on the IOC device for a given inode identified by
     892 * the <inode> argument. It scan all pages registered in the associated mapper,
     893 * and copies from mapper to device each page marked as dirty.
     894 * WARNING : The target <inode> cannot be a directory, because all modifications in a
     895 * directory are synchronously done on the IOC device by the two vfs_fs_add_dentry()
     896 * and vfs_fs_remove_dentry() functions.
     897 *
     898 * Depending on the file system type, it calls the relevant, FS specific function.
     899 * It must be called by a thread running in the inode cluster.
     900 *****************************************************************************************
     901 * @ inode   : local pointer on inode.
     902 * @ return 0 if success / return EIO if failure during device access.
     903 ****************************************************************************************/
     904error_t vfs_fs_sync_inode( struct vfs_inode_s * inode );
     905
     906/*****************************************************************************************
     907 * This function updates the FS on the IOC device for the FAT itself.
     908 * It scan all clusters registered in the FAT mapper, and copies to device
     909 * each page marked as dirty.
     910 *
     911 * Depending on the file system type, it calls the relevant, FS specific function.
     912 * It can be called by a thread running in any cluster.
     913 *****************************************************************************************
     914 * @ return 0 if success / return EIO if failure during device access.
     915 ****************************************************************************************/
     916error_t vfs_fs_sync_fat( void );
     917
     918/*****************************************************************************************
     919 * This function updates the free clusters info on the IOC device.
     920 *
     921 * Depending on the file system type, it calls the relevant, FS specific function.
     922 * It can be called by a thread running in any cluster.
     923 *****************************************************************************************
     924 * @ return 0 if success / return EIO if failure during device access.
     925 ****************************************************************************************/
     926error_t vfs_fs_sync_free_info( void );
     927
     928/******************************************************************************************
     929 * This function allocates a free cluster from the FS identified by the <fs_type>
     930 * argument. It updates the selected FS File Allocation Table.
     931 *
     932 * Depending on the file system type, it calls the relevant, FS specific function.
     933 * It can be called by a thread running in any cluster.
     934 ******************************************************************************************
     935 * @ fs_type   : [in]  File System type.
     936 * @ cluster   : [out] cluster index in File system.
     937 * @ return 0 if success / return -1 if no free cluster
     938 *****************************************************************************************/
     939error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
     940                              uint32_t * cluster );
     941
     942/******************************************************************************************
     943 * This function makes all I/O operations required to release all clusters allocated
     944 * on IOC device to a given inode, identified by the <inode_xp> argument.
     945 * Depending on the file system type, it calls the proper, FS specific function.
     946 * It is called by the vfs_unlink() function.
     947 * It can be executed by a thread running in any cluster.
     948 * This function does NOT take any lock.
     949 ******************************************************************************************
     950 * @ inode_xp  : extended pointer on inode.
     951 * @ return 0 if success / return -1 if device access failure.
     952 *****************************************************************************************/
     953error_t vfs_fs_release_inode( xptr_t  inode_xp );
     954
     955/******************************************************************************************
     956 * This function makes the I/O operation to move one page identified by the <page_xp>
     957 * argument to/from the IOC device from/to the mapper, as defined by <to_mapper>.
     958 * Depending on the file system type, it calls the proper, FS specific function.
    805959 * It is used in case of MISS on the mapper, or when a dirty page in the mapper must
    806960 * be updated in the File System.
    807  * Depending on the file system type, it calls the proper, FS specific function.
    808  * It must be executed by a thread running in the cluster containing the mapper.
    809961 * The mapper pointer is obtained from the page descriptor.
    810  * It takes the mapper lock before launching the IO operation.
    811  ******************************************************************************************
    812  * @ page      : local pointer on the page descriptor.
     962 * It can be executed by any thread running in any cluster.
     963 * This function does NOT take any lock.
     964 ******************************************************************************************
     965 * @ page_xp   : extended pointer on the page descriptor.
    813966 * @ to_mapper : transfer direction.
    814  * @ returns 0 if success / return EINVAL if it cannot access the external device.
    815  *****************************************************************************************/
    816 error_t vfs_mapper_move_page( struct page_s * page,
    817                               bool_t          to_mapper );
    818 
    819 /******************************************************************************************
    820  * This function makes the I/O operations required to move, from device to mapper,
    821  * all pages covering a given inode, identified by the <inode> argument. The target
    822  * inode can be a directory or a file, but this function is mainly used to load (prefetch)
    823  * a complete directory to the mapper.
    824  * Depending on the file system type, it calls the proper, FS specific function.
    825  * It must be executed by a thread running in the cluster containing the mapper.
    826  * The mapper pointer is obtained from the inode descriptor.
    827  * It takes the mapper lock before launching the IO operation.
    828  ******************************************************************************************
    829  * @ inode  : local pointer on inode.
    830  * @ return 0 if success / return EIO if device access failure.
    831  *****************************************************************************************/
    832 error_t vfs_mapper_load_all( vfs_inode_t * inode );
     967 * @ returns 0 if success / return -1 if device access failure.
     968 *****************************************************************************************/
     969error_t vfs_fs_move_page( xptr_t  page_xp,
     970                          bool_t  to_mapper );
    833971
    834972
Note: See TracChangeset for help on using the changeset viewer.