Index: trunk/kernel/fs/fatfs.c
===================================================================
--- trunk/kernel/fs/fatfs.c	(revision 625)
+++ trunk/kernel/fs/fatfs.c	(revision 626)
@@ -37,4 +37,5 @@
 #include <fatfs.h>
 
+#define LITTLE_ENDIAN  1
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -72,28 +73,27 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This function return an integer record value (one, two, or four bytes) 
-// from a memory buffer, taking into account endianness.
-//////////////////////////////////////////////////////////////////////////////////////////
-// @ offset        : first byte of record in buffer.
-// @ size          : record length in bytes (1/2/4).
-// @ buffer        : pointer on buffer base.
-// @ little endian : the most significant byte has the highest address when true.
+// This function return an integer record value (one, two, or four bytes) from a local
+// array of bytes, taking into account the global LITTLE_ENDIAN parameter:
+// if LITTLE_ENDIAN is true, the most significant byte has the highest address.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ offset        : first byte in array.
+// @ nbytes        : record length in bytes (1/2/4).
+// @ buffer        : local pointer on byte array.
 // @ return the integer value in a 32 bits word.
 //////////////////////////////////////////////////////////////////////////////////////////
 static uint32_t fatfs_get_record( uint32_t    offset,
-                                  uint32_t    size,
-                                  uint8_t   * buffer,
-                                  uint32_t    little_endian )
-{
-    uint32_t n;
-    uint32_t res  = 0;
-
-    if ( little_endian )
-    {
-        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
-    }
-    else // big_endian
-    {
-        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
+                                  uint32_t    nbytes,
+                                  uint8_t   * buffer )
+{
+    uint32_t i;
+    uint32_t res = 0;
+
+    if ( LITTLE_ENDIAN )
+    {
+        for( i = nbytes ; i > 0 ; i-- ) res = (res<<8) | buffer[offset+i-1];
+    }
+    else 
+    {
+        for( i = 0 ; i < nbytes ; i++ ) res = (res<<8) | buffer[offset+i];
     }
     return res;
@@ -102,28 +102,96 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This function writes one, two, or four bytes from a 32 bits integer to a memory buffer,
-// taking into account endianness.
-//////////////////////////////////////////////////////////////////////////////////////////
-// @ offset        : first byte of record in buffer.
-// @ size          : record length in bytes (1/2/4).
-// @ buffer        : pointer on buffer base.
-// @ little endian : the most significant byte has the highest address when true.
+// This function return an integer record value (one, two, or four bytes) from a remote
+// array of bytes, taking into account the global LITTLE_ENDIAN parameter:
+// if LITTLE_ENDIAN is true, the most significant byte has the highest address.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ offset        : first byte in array.
+// @ nbytes        : record length in bytes (1/2/4).
+// @ buffer_xp     : extended pointer on byte array.
 // @ return the integer value in a 32 bits word.
 //////////////////////////////////////////////////////////////////////////////////////////
+static uint32_t fatfs_get_remote_record( uint32_t   offset,
+                                         uint32_t   nbytes,
+                                         xptr_t     buffer_xp )
+{
+    uint32_t i;
+    uint32_t res = 0;
+
+    if ( LITTLE_ENDIAN )
+    {
+        for( i = nbytes ; i > 0 ; i-- )
+        {
+            res = (res<<8) | hal_remote_lb( buffer_xp+offset+i-1 );
+        }
+    }
+    else 
+    {
+        for( i = 0 ; i < nbytes ; i++ )
+        {
+            res = (res<<8) | hal_remote_lb( buffer_xp+offset+i );
+        }
+    }
+    return res;
+
+}  // end fatfs_get_remote_record()
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// This function writes one, two, or four bytes from a 32 bits integer to a local
+// array of bytes, taking into account the global LITTLE_ENDIAN parameter:
+// if LITTLE_ENDIAN is true, the most significant byte has the highest address.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ offset        : first byte in array.
+// @ nbytes        : record length in bytes (1/2/4).
+// @ buffer        : local pointer on byte array.
+// @ value         : 32 bits integer value.
+//////////////////////////////////////////////////////////////////////////////////////////
 static void fatfs_set_record( uint32_t    offset,
-                              uint32_t    size,
+                              uint32_t    nbytes,
                               uint8_t   * buffer,
-                              uint32_t    little_endian,
                               uint32_t    value )
 {
-    uint32_t n;
-
-    if ( little_endian )
-    {
-        for( n = size ; n > 0 ; n-- ) buffer[offset+n-1] = (uint8_t)(value>>((n-1)<<3));
-    }
-    else // big_endian
-    {
-        for( n = 0 ; n < size ; n++ ) buffer[offset+n] = (uint8_t)(value>>((size-1-n)<<3));
+    uint32_t i;
+
+    if ( LITTLE_ENDIAN )
+    {
+        for( i = nbytes ; i > 0 ; i-- ) buffer[offset+i-1] = (uint8_t)(value>>((i-1)<<3));
+    }
+    else
+    {
+        for( i = 0 ; i < nbytes ; i++ ) buffer[offset+i] = (uint8_t)(value>>((nbytes-1-i)<<3));
+    }
+
+}  // end fatfs_set_record()
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// This function writes one, two, or four bytes from a 32 bits integer to a remote
+// array of bytes, taking into account the global LITTLE_ENDIAN parameter:
+// if LITTLE_ENDIAN is true, the most significant byte has the highest address.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ offset        : first byte in array.
+// @ nbytes        : record length in bytes (1/2/4).
+// @ buffer_xp     : extended pointer on byte array.
+// @ value         : 32 bits integer value.
+//////////////////////////////////////////////////////////////////////////////////////////
+static void fatfs_set_remote_record( uint32_t    offset,
+                                     uint32_t    nbytes,
+                                     xptr_t      buffer_xp,
+                                     uint32_t    value )
+{
+    uint32_t i;
+
+    if ( LITTLE_ENDIAN )
+    {
+        for( i = nbytes ; i > 0 ; i-- )
+        {
+            hal_remote_sb( (buffer_xp+offset+i-1) , (uint8_t)(value>>((i-1)<<3)) );
+        }
+    }
+    else
+    {
+        for( i = 0 ; i < nbytes ; i++ )
+        {
+            hal_remote_sb( (buffer_xp+offset+i) , (uint8_t)(value>>((nbytes-1-i)<<3)) );
+        }
     }
 
@@ -374,25 +442,71 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
+// This static function is called by both the fatfs_free_clusters_increment(), 
+// and the fatfs_free_cluster_decrement() functions defined below.
+// It synchronously updates the  "free_clusters" and "free_cluster_hint" variables
+// in FS_INFO sector on the IOC device, each times these variables are modified.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ fatfs_ctx_xp      : extended pointer on fatfs context in FAT cluster.
+// @ free_clusters     : new free_clusters value. 
+// @ free_cluster_hint : new free_cluster_hint value.
+// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
+//////////////////////////////////////////////////////////////////////////////////////////
+static error_t fatfs_free_clusters_update_ioc( xptr_t    fatfs_ctx_xp,
+                                               uint32_t  free_clusters,
+                                               uint32_t  free_cluster_hint )
+{
+    cxy_t         fat_cxy;             // FAT cluster identifier
+    fatfs_ctx_t * fatfs_ctx_ptr;       // local pointer on fatfs context in FAT cluster
+    uint8_t     * fs_info_buffer_ptr;  // local pointer on FS_INFO buffer in FAT cluster
+    xptr_t        fs_info_buffer_xp;   // extended pointer on FS_INFO buffer in FAT cluster
+    uint32_t      fs_info_lba;         // FS_INFO sector lba on IOC device
+
+    // get cluster and local pointer on FAT cluster context
+    fat_cxy       = GET_CXY( fatfs_ctx_xp ); 
+    fatfs_ctx_ptr = GET_PTR( fatfs_ctx_xp ); 
+
+    // get pointers on FS_INFO buffer in FAT cluster
+    fs_info_buffer_ptr = hal_remote_lpt( XPTR( fat_cxy , &fatfs_ctx_ptr->fs_info_buffer ) );
+    fs_info_buffer_xp  = XPTR( fat_cxy , fs_info_buffer_ptr );
+
+    // get lba of FS_INFO sector on IOC device from fatfs context
+    fs_info_lba = hal_remote_l32( XPTR( fat_cxy , &fatfs_ctx_ptr->fs_info_lba ) );
+
+    // update the FS_INFO buffer in FAT cluster
+    fatfs_set_remote_record( FS_FREE_CLUSTERS     , fs_info_buffer_xp , free_clusters );
+    fatfs_set_remote_record( FS_FREE_CLUSTER_HINT , fs_info_buffer_xp , free_cluster_hint );
+    
+    // update the FS_INFO sector on IOC device
+    return dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
+ 
+}  // fatfs_free_clusters_update_ioc()
+
+//////////////////////////////////////////////////////////////////////////////////////////
 // This static function decrements the  "free_clusters" variable, and updates the 
-// "free_cluster_hint" variable in the FATFS context, identified by the <fat_ctx_cxy>
-// and <fat_ctx_ptr> arguments (cluster containing the FAT mapper).
+// "free_cluster_hint" variable in the FATFS context in FAT cluster, identified 
+// by the <fat_ctx_xp> argument, when a new <cluster> has been allocated from FAT.
 // It scan all slots in the FAT mapper seen as an array of 32 bits words, looking for the
 // first free slot larger than the <cluster> argument, to update "free_cluster_hint".
+// It calls the fatfs_free_clusters_update_ioc() function to synchronously update the
+// FS_INFO sector on the IOC device. It can be called by a thead running in any cluster. 
 //
 // WARNING : The free_lock protecting exclusive access to these variables
 //           must be taken by the calling function. 
 //////////////////////////////////////////////////////////////////////////////////////////
-// @ fat_ctx_cxy  : FAT mapper cluster identifier. 
-// @ fat_ctx_ptr  : local pointer on FATFS context. 
-// @ cluster      : recently allocated cluster index in FAT.
-//////////////////////////////////////////////////////////////////////////////////////////
-static error_t fatfs_free_clusters_decrement( cxy_t         fat_ctx_cxy,
-                                              fatfs_ctx_t * fat_ctx_ptr,
-                                              uint32_t      cluster )
-{
+// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster. 
+// @ cluster       : recently allocated cluster index in FAT.
+// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
+//////////////////////////////////////////////////////////////////////////////////////////
+static error_t fatfs_free_clusters_decrement( xptr_t    fatfs_ctx_xp,
+                                              uint32_t  cluster )
+{
+    error_t       error;
+    cxy_t         fat_cxy;      // FAT cluster identifier
+    fatfs_ctx_t * fat_ctx_ptr;  // local pointer on fatfs context in FAT cluster
     xptr_t        mapper_xp;    // extended pointer on FAT mapper
     xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
     xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable 
     uint32_t      numb;         // "free_clusters" variable current value
+    uint32_t      hint;         // "free_cluster_hint" variable current value
     uint32_t      page_id;      // page index in FAT mapper
     uint32_t      slot_id;      // slot index in one page of FAT (1024 slots per page)
@@ -405,19 +519,23 @@
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
-if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
+if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
 printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
 #endif
 
-    // build extended pointers on free_clusters, and free_cluster_hint
-    hint_xp = XPTR( fat_ctx_cxy , &fat_ctx_ptr->free_cluster_hint );
-    numb_xp = XPTR( fat_ctx_cxy , &fat_ctx_ptr->free_clusters );
-
-    // update "free_clusters"
-    numb = hal_remote_l32( numb_xp );
-    hal_remote_s32( numb_xp , numb - 1 );
+    // get FAT cluster an local pointer on fatfs context in FAT cluster
+    fat_cxy      = GET_CXY( fatfs_ctx_xp );
+    fat_ctx_ptr  = GET_PTR( fatfs_ctx_xp );
+    
+    // build extended pointers on free_clusters, and free_cluster_hint in fatfs context
+    hint_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_cluster_hint );
+    numb_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_clusters );
+
+    // update "free_clusters" value
+    numb = hal_remote_l32( numb_xp ) - 1;
+    hal_remote_s32( numb_xp , numb );
 
     // get extended pointer on FAT mapper
-    mapper_xp = hal_remote_l64( XPTR( fat_ctx_cxy , &fat_ctx_ptr->fat_mapper_xp ) );
+    mapper_xp = hal_remote_l64( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper_xp ) );
 
     // initialise variables to scan the FAT mapper
@@ -425,5 +543,5 @@
     page_id  = (cluster + 1) >> 10;
     slot_id  = (cluster + 1) & 0x3FF;
-    page_max = hal_remote_l32( XPTR( fat_ctx_cxy, &fat_ctx_ptr->fat_sectors_count ) ) >> 3;
+    page_max = hal_remote_l32( XPTR( fat_cxy, &fat_ctx_ptr->fat_sectors_count ) ) >> 3;
 
     // scan FAT mapper / loop on pages
@@ -451,13 +569,23 @@
             if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER )
             {
-                // update "free_cluster_hint"
-                hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 );
+                // update "free_cluster_hint" value
+                hint = (page_id << 10) + slot_id - 1;
+                hal_remote_s32( hint_xp , hint );
+
+                // update FS_INFO sector on IOC device
+                error = fatfs_free_clusters_update_ioc( fatfs_ctx_xp , numb , hint );
+
+                if( error ) 
+                {
+                    printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
+                    return -1;
+                }
 
 #if DEBUG_FATFS_FREE_CLUSTERS 
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
-printk("\n[%s] thread[%x,%x] exit / hint %x / free_clusters %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid,
-hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle );
+printk("\n[%s] thread[%x,%x] updated free cluster info  / hint %x / number %x\n",
+__FUNCTION__, this->process->pid, this->trdid, 
+hal_remote_l32(hint_xp), hal_remote_l32(numb_xp) );
 #endif
                 return 0;
@@ -469,5 +597,5 @@
         }  // end loop on slots
 
-        // update (page_id,slot_id) variables
+        // update page_id & slot_id variables
         page_id++;
         slot_id = 0;
@@ -483,20 +611,24 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 // This static function increments the "free_clusters" variable, and updates the
-// "free_cluster_hint" variables in the FATFS context, identified by the <fat_ctx_cxy> 
-// and <fat_ctx_ptr> argument (cluster containing the FAT mapper).
+// "free_cluster_hint" variables in the FATFS context in FAT cluster, identified 
+// by the <fat_ctx_xp> argument, when a cluster is released to FAT.
 // If the released cluster index is smaller than the current (hint) value, 
 // it set "free_cluster_hint" <= cluster.
+// It calls the fatfs_free_clusters_update_ioc() function to synchronously update the
+// FS_INFO sector on the IOC device. It can be called by a thead running in any cluster. 
 //
 // WARNING : The free_lock protecting exclusive access to these variables
 //           must be taken by the calling function. 
 //////////////////////////////////////////////////////////////////////////////////////////
-// @ fat_ctx_cxy  : FAT mapper cluster identifier. 
-// @ fat_ctx_ptr  : local pointer on FATFS context. 
-// @ cluster     : recently released cluster index in FAT.
-//////////////////////////////////////////////////////////////////////////////////////////
-static void fatfs_free_clusters_increment( cxy_t         fat_ctx_cxy,
-                                           fatfs_ctx_t * fat_ctx_ptr,
-                                           uint32_t      cluster )
-{
+// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster. 
+// @ cluster       : recently released cluster index in FAT.
+// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
+//////////////////////////////////////////////////////////////////////////////////////////
+static error_t fatfs_free_clusters_increment( xptr_t   fatfs_ctx_xp,
+                                              uint32_t cluster )
+{
+    error_t       error;
+    cxy_t         fat_cxy;      // FAT cluster identifier
+    fatfs_ctx_t * fat_ctx_ptr;  // local pointer on fatfs context in FAT cluster
     xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
     xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable 
@@ -504,7 +636,19 @@
     uint32_t      numb;         // "free_clusters" variable current value
 
+#if DEBUG_FATFS_FREE_CLUSTERS
+uint32_t   cycle = (uint32_t)hal_get_cycles();
+thread_t * this  = CURRENT_THREAD;
+if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
+printk("\n[%s] thread[%x,%x] enter for released cluster %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
+#endif
+
+    // get FAT cluster an local pointer on fatfs context in FAT cluster
+    fat_cxy      = GET_CXY( fatfs_ctx_xp );
+    fat_ctx_ptr  = GET_PTR( fatfs_ctx_xp );
+    
     // build extended pointers on free_clusters, and free_cluster_hint
-    hint_xp = XPTR( fat_ctx_cxy , &fat_ctx_ptr->free_cluster_hint );
-    numb_xp = XPTR( fat_ctx_cxy , &fat_ctx_ptr->free_clusters );
+    hint_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_cluster_hint );
+    numb_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_clusters );
 
     // get current value of free_cluster_hint and free_clusters
@@ -512,17 +656,30 @@
     numb = hal_remote_l32( numb_xp );
 
-    // update free_cluster_hint if required
-    if ( (cluster - 1) < hint ) hal_remote_s32( hint_xp , (cluster - 1) );
+    // update "numb" and "hint" variables as required
+    numb++;
+    if ( (cluster - 1) < hint ) hint = cluster - 1;
 
     // update free_clusters
-    hal_remote_s32( numb_xp , numb + 1 );
+    hal_remote_s32( numb_xp , numb );
+    hal_remote_s32( hint_xp , hint );
+
+    // update FS_INFO sector on IOC device
+    error = fatfs_free_clusters_update_ioc( fatfs_ctx_xp , numb , hint );
+
+    if( error ) 
+    {
+        printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
+        return -1;
+    }
 
 #if DEBUG_FATFS_FREE_CLUSTERS 
 thread_t * this = CURRENT_THREAD;
 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
-printk("\n[%s] thread[%x,%x] updates free cluster info : hint %x / number %x\n",
+printk("\n[%s] thread[%x,%x] updated free cluster info : hint %x / number %x\n",
 __FUNCTION__, this->process->pid, this->trdid,
 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) );
 #endif
+
+    return 0;
 
 }  // end fatfs_free_clusters_increment()
@@ -576,10 +733,6 @@
                                FREE_CLUSTER ) ) return -1;
 
-    // Update free_cluster_hint and free_clusters in FAT context
-    fatfs_free_clusters_increment( mapper_cxy,
-                                   fatfs_ctx,
-                                   cluster );
-
-    return 0;
+    // Update free_cluster info in FATFS context and in FS_INFO sector
+    return fatfs_free_clusters_increment( XPTR( mapper_cxy , fatfs_ctx ) , cluster );
 
 }  // end fatfs_recursive_release()
@@ -590,28 +743,49 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-///////////////////////////////////////////
-void fatfs_ctx_display( fatfs_ctx_t * ctx )
-{
-    printk("\n*** FAT context ***\n" 
+///////////////////////////////////
+void fatfs_display_ctx( cxy_t cxy )
+{
+    // get pointer on local FATFS context
+    vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
+	fatfs_ctx_t * ctx     = hal_remote_lpt( XPTR( cxy , &vfs_ctx->extend ) );
+
+    uint32_t fat_sectors       = hal_remote_l32( XPTR( cxy , &ctx->fat_sectors_count ) );
+    uint32_t sector_size       = hal_remote_l32( XPTR( cxy , &ctx->bytes_per_sector ) );
+    uint32_t sec_per_clus      = hal_remote_l32( XPTR( cxy , &ctx->sectors_per_cluster ) );
+    uint32_t fat_lba           = hal_remote_l32( XPTR( cxy , &ctx->fat_begin_lba ) );
+    uint32_t data_lba          = hal_remote_l32( XPTR( cxy , &ctx->cluster_begin_lba ) );
+    uint32_t fsinfo_lba        = hal_remote_l32( XPTR( cxy , &ctx->fs_info_lba ) );
+    uint32_t root_dir_clus     = hal_remote_l32( XPTR( cxy , &ctx->root_dir_cluster ) );
+    uint32_t free_clusters     = hal_remote_l32( XPTR( cxy , &ctx->free_clusters ) );
+    uint32_t free_cluster_hint = hal_remote_l32( XPTR( cxy , &ctx->free_cluster_hint ) );
+    xptr_t   mapper_xp         = hal_remote_l64( XPTR( cxy , &ctx->fat_mapper_xp ) );
+    void   * fs_info_buffer    = hal_remote_lpt( XPTR( cxy , &ctx->fs_info_buffer ) );
+
+    printk("\n*** FAT context in cluster %x\n" 
            "- fat_sectors       = %d\n"
            "- sector size       = %d\n"
            "- cluster size      = %d\n"
-           "- fat_first_lba     = %d\n"
-           "- data_first_lba    = %d\n"
-           "- root_dir_cluster  = %d\n"
-           "- free_clusters     = %d\n"
-           "- free_cluster_hint = %d\n"
-           "- fat_mapper_xp     = %l\n",
-           ctx->fat_sectors_count,
-           ctx->bytes_per_sector,
-           ctx->sectors_per_cluster * ctx->bytes_per_sector,
-           ctx->fat_begin_lba,
-           ctx->cluster_begin_lba,
-           ctx->root_dir_cluster,
-           ctx->free_clusters,
-           ctx->free_cluster_hint,
-           ctx->fat_mapper_xp );
-
-}  // end ctx_display()
+           "- fat_lba           = %x\n"
+           "- data_lba          = %x\n"
+           "- fsinfo_lba        = %x\n"
+           "- root_dir_cluster  = %x\n"
+           "- free_clusters     = %x\n"
+           "- free_cluster_hint = %x\n"
+           "- fat_mapper_ptr    = %x\n"
+           "- fs_info_buffer    = %x\n",
+           cxy,
+           fat_sectors,
+           sector_size,
+           sector_size * sec_per_clus,
+           fat_lba,
+           data_lba,
+           fsinfo_lba,
+           root_dir_clus,
+           free_clusters,
+           free_cluster_hint,
+           GET_PTR( mapper_xp ),
+           fs_info_buffer );
+
+}  // end fatfs_ctx_display()
 
 //////////////////////////////////////////
@@ -622,22 +796,35 @@
     uint32_t maxline;
 
-    // copute numner of lines to display
+    // compute number of lines to display
     maxline = nentries >> 3;
     if( nentries & 0x7 ) maxline++;
 
     // get pointer on local FATFS context
-    vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
-    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
+    vfs_ctx_t   * vfs_ctx       = &fs_context[FS_TYPE_FATFS];
+    fatfs_ctx_t * loc_fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
 
     // get extended pointer on FAT mapper
-    xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp;
-
-    // get extended pointer and cluster of FAT mapper requested page 
+    xptr_t fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
+
+    // get FAT cluster identifier
+    cxy_t  fat_cxy = GET_CXY( fat_mapper_xp );
+
+    // get pointer on FATFS context in FAT cluster
+    fatfs_ctx_t * fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
+ 
+    // get current value of hint and free_clusters
+    uint32_t hint = hal_remote_l32( XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint ) );
+    uint32_t free = hal_remote_l32( XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters ) );
+ 
+    // get extended pointer on requested page in FAT mapper 
     xptr_t     page_xp  = mapper_remote_get_page( fat_mapper_xp , page_id );
 
     // get extended pointer on requested page base
     xptr_t     base_xp  = ppm_page2base( page_xp );
-
-    printk("\n***** FAT content / page %d *****\n", page_id );
+    void     * base     = GET_PTR( base_xp );
+
+    printk("\n***** FAT mapper / cxy %x / page_id %d / base %x / free_clusters %x / hint %x\n",
+    fat_cxy, page_id, base, free, hint );
+
     for( line = 0 ; line < maxline ; line++ )
     {
@@ -766,4 +953,5 @@
     kmem_req_t    req;
     uint8_t     * buffer;
+    xptr_t        buffer_xp;
 
 #if DEBUG_FATFS_CTX_INIT
@@ -778,11 +966,14 @@
 assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL" );
 
-// check only cluster 0 does FATFS init
+// check only cluster 0 does FATFS initialization
 assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS");
 
-    // allocate a 512 bytes buffer to store the boot record
+    // allocate a permanent 512 bytes buffer to store
+    // - temporarily the BOOT sector
+    // - permanently the FS_INFO sector
 	req.type    = KMEM_512_BYTES;
     req.flags   = AF_KERNEL | AF_ZERO;
 	buffer      = (uint8_t *)kmem_alloc( &req );
+    buffer_xp   = XPTR( local_cxy , buffer );
 
     if( buffer == NULL ) 
@@ -793,5 +984,5 @@
      
     // load the BOOT record from device
-    error = dev_ioc_sync_read( buffer , 0 , 1 );
+    error = dev_ioc_sync_read( buffer_xp , 0 , 1 );
 
     if ( error )
@@ -807,5 +998,5 @@
 
     // get sector size from boot record
-    uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 );
+    uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer );
     if ( sector_size != 512 )
     {
@@ -815,5 +1006,5 @@
 
     // get cluster size from boot record
-    uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 );
+    uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer );
     if ( nb_sectors != 8 )
     {
@@ -823,5 +1014,5 @@
 
     // get number of FAT copies from boot record
-    uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 );
+    uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer );
     if ( nb_fats != 1 )
     {
@@ -831,5 +1022,5 @@
 
     // get number of sectors in FAT from boot record
-    uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 );
+    uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer );
     if ( (fat_sectors & 0xF) != 0 )
     {
@@ -839,5 +1030,5 @@
 
     // get root cluster from boot record
-    uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 );
+    uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer );
     if ( root_cluster != 2 ) 
     {
@@ -847,11 +1038,11 @@
 
     // get FAT lba from boot record
-    uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 );
+    uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer );
 
     // get FS_INFO sector lba from boot record
-    uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer , 1 );
+    uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer );
 
     // load the FS_INFO record from device
-    error = dev_ioc_sync_read( buffer , fs_info_lba , 1 );
+    error = dev_ioc_sync_read( buffer_xp , fs_info_lba , 1 );
 
     if ( error )
@@ -861,6 +1052,6 @@
     }
 
-    // get free clusters number from FS_INFO record
-    uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer , 1 );
+    // get free_clusters number from FS_INFO record
+    uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer );
     if ( free_clusters >= fat_sectors << 7 )
     {
@@ -869,6 +1060,7 @@
     }
 
-    // get cluster hint from FS_INFO record
-    uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer , 1 );
+    // get free_cluster_hint from FS_INFO record
+    uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer );
+
     if ( free_cluster_hint >= fat_sectors << 7 )
     {
@@ -876,9 +1068,4 @@
         hal_core_sleep();
     }
-
-    // release the 512 bytes buffer
-    req.type = KMEM_512_BYTES;
-    req.ptr  = buffer;
-    kmem_free( &req );
 
     // allocate a mapper for the FAT itself
@@ -890,7 +1077,6 @@
     }
 
-    // WARNING : the inode field MUST be NULL for the FAT mapper
+    // the inode field is NULL for the FAT mapper
     fat_mapper->inode = NULL;
-
 
     // initialize the FATFS context
@@ -902,6 +1088,8 @@
     fatfs_ctx->root_dir_cluster      = 2;
     fatfs_ctx->fat_mapper_xp         = XPTR( local_cxy , fat_mapper );
+    fatfs_ctx->fs_info_lba           = fs_info_lba;
     fatfs_ctx->free_clusters         = free_clusters;
     fatfs_ctx->free_cluster_hint     = free_cluster_hint;
+    fatfs_ctx->fs_info_buffer        = buffer;
 
     remote_queuelock_init( XPTR( local_cxy , &fatfs_ctx->free_lock ) , LOCK_FATFS_FREE );
@@ -1019,5 +1207,5 @@
         while ( (offset < 4096) && (found == 0) )
         {
-            if ( fatfs_get_record( LDIR_ORD, (base + offset), 0 ) == NO_MORE_ENTRY )
+            if ( fatfs_get_record( LDIR_ORD, (base + offset) ) == NO_MORE_ENTRY )
             {
                 found = 1;
@@ -1335,5 +1523,5 @@
 
 // check for LFN entry
-assert( (fatfs_get_record( DIR_ATTR, base + offset, 0 ) == ATTR_LONG_NAME_MASK ),
+assert( (fatfs_get_record( DIR_ATTR, base + offset ) == ATTR_LONG_NAME_MASK ),
 "this directory entry must be a LFN\n");
 
@@ -1439,6 +1627,6 @@
         while( (offset < 4096) && (found == 0) )
         {
-            attr = fatfs_get_record( DIR_ATTR , base + offset , 0 );   
-            ord  = fatfs_get_record( LDIR_ORD , base + offset , 0 );   
+            attr = fatfs_get_record( DIR_ATTR , base + offset );   
+            ord  = fatfs_get_record( LDIR_ORD , base + offset );   
 
             if (ord == NO_MORE_ENTRY)                 // no more entry => break
@@ -1559,7 +1747,17 @@
 
 // check arguments
-assert( (parent_inode != NULL)         , "parent_inode is NULL\n" );
-assert( (name         != NULL)         , "name is NULL\n" );
-assert( (child_inode_xp != XPTR_NULL ) , "child_inode is XPTR_NULL\n" );
+assert( (parent_inode   != NULL)       , "parent_inode is NULL\n" );
+assert( (name           != NULL)       , "name is NULL\n" );
+assert( (child_inode_xp != XPTR_NULL ) , "child_inode is NULL\n" );
+
+    // get child inode cluster and local pointer
+    child_inode_cxy = GET_CXY( child_inode_xp );
+    child_inode_ptr = GET_PTR( child_inode_xp );
+
+    // build extended pointer on root of list of parent dentries
+    root_xp = XPTR( child_inode_cxy , &child_inode_ptr->parents );
+
+// check child inode has at least one parent
+assert( (xlist_is_empty( root_xp ) == false ), "child inode must have one parent\n");
 
 #if DEBUG_FATFS_GET_DENTRY
@@ -1578,27 +1776,12 @@
     error  = fatfs_scan_directory( mapper, name , &entry , &index );
 
-    if( error )
-    { 
-        vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , dir_name );
-        printk("\n[ERROR] in %s : cannot find <%s> in parent mapper <%s>\n",
-        __FUNCTION__, name , dir_name );
-        return -1;
-    }
+    // return non fatal error if not found
+    if( error ) return -1;
 
     // get relevant infos from FAT32 directory entry
-    cluster = (fatfs_get_record( DIR_FST_CLUS_HI , entry , 1 ) << 16) |
-              (fatfs_get_record( DIR_FST_CLUS_LO , entry , 1 )      ) ;
-    is_dir  = (fatfs_get_record( DIR_ATTR        , entry , 1 ) & ATTR_DIRECTORY);
-    size    =  fatfs_get_record( DIR_FILE_SIZE   , entry , 1 );
-
-    // get child inode cluster and local pointer
-    child_inode_cxy = GET_CXY( child_inode_xp );
-    child_inode_ptr = GET_PTR( child_inode_xp );
-
-    // build extended pointer on root of list of parent dentries
-    root_xp = XPTR( child_inode_cxy , &child_inode_ptr->parents );
-
-// check child inode has at least one parent
-assert( (xlist_is_empty( root_xp ) == false ), "child inode must have one parent\n");
+    cluster = (fatfs_get_record( DIR_FST_CLUS_HI , entry ) << 16) |
+              (fatfs_get_record( DIR_FST_CLUS_LO , entry )      ) ;
+    is_dir  = (fatfs_get_record( DIR_ATTR        , entry ) & ATTR_DIRECTORY);
+    size    =  fatfs_get_record( DIR_FILE_SIZE   , entry );
 
     // scan list of parent dentries to search the parent_inode
@@ -1692,5 +1875,5 @@
 
     // set size in FAT32 directory entry
-    fatfs_set_record( DIR_FILE_SIZE , entry , 1 , size );
+    fatfs_set_record( DIR_FILE_SIZE , entry , size );
 
     // get local pointer on modified page base
@@ -1795,6 +1978,6 @@
             bool_t valid = (dentry_id >= min_dentry) && (dirent_id <  max_dirent );
 
-            attr = fatfs_get_record( DIR_ATTR , base + offset , 0 );   
-            ord  = fatfs_get_record( LDIR_ORD , base + offset , 0 );   
+            attr = fatfs_get_record( DIR_ATTR , base + offset );   
+            ord  = fatfs_get_record( LDIR_ORD , base + offset );   
 
             if (ord == NO_MORE_ENTRY)                 // no more entry => break
@@ -2033,4 +2216,15 @@
 error_t fatfs_sync_free_info( void )
 {
+    error_t       error;
+    fatfs_ctx_t * fatfs_ctx_ptr;              // local pointer on fatfs context in cluster 0
+    uint32_t      ctx_free_clusters;          // number of free clusters from fatfs context
+    uint32_t      ctx_free_cluster_hint;      // free cluster hint from fatfs context
+    uint32_t      ioc_free_clusters;          // number of free clusters from fatfs context
+    uint32_t      ioc_free_cluster_hint;      // free cluster hint from fatfs context
+    uint32_t      fs_info_lba;                // lba of FS_INFO sector on IOC device
+    uint8_t     * fs_info_buffer;             // local pointer on FS_INFO buffer in cluster 0
+    xptr_t        fs_info_buffer_xp;          // extended pointer on FS_INFO buffer in cluster 0
+    uint8_t       tmp_buf[512];               // 512 bytes temporary buffer 
+    xptr_t        tmp_buf_xp;                 // extended pointer on temporary buffer
 
 #if DEBUG_FATFS_SYNC_FSINFO
@@ -2042,48 +2236,56 @@
 #endif
 
-    uint8_t     * buffer;   // dynamically allocated aligned 512 bytes buffer
-    kmem_req_t    req;
-    error_t       error;
-
-    // get FS_INFO lba, free_ from FATFS context
-    fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
-    uint32_t      lba        = fatfs_ctx->fs_info_lba;
-    uint32_t      hint       = fatfs_ctx->free_cluster_hint;
-    uint32_t      number     = fatfs_ctx->free_clusters;
-
-    // allocate buffer to store the FS_INFO sector
-	req.type    = KMEM_512_BYTES;
-    req.flags   = AF_KERNEL | AF_ZERO;
-	buffer      = (uint8_t *)kmem_alloc( &req );
-    if( buffer == NULL ) 
-    {
-        printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
-        return ENOMEM;
-    }
-     
-    // load the FS_INFO sector from device to buffer
-    error = dev_ioc_read( buffer , lba , 1 );
+    // get pointer on fatfs context in cluster 0
+    fatfs_ctx_ptr = hal_remote_lpt( XPTR( 0 , &fs_context[FS_TYPE_FATFS].extend ) );
+
+    // get "free_clusters" and "free_cluster_hint" from fatfs context in cluster 0
+    ctx_free_clusters     = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_clusters ) );
+    ctx_free_cluster_hint = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_cluster_hint ) );
+
+    // get fs_info_lba 
+    fs_info_lba = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->fs_info_lba ) );
+
+    // build extended pointer on temporary buffer
+    tmp_buf_xp = XPTR( local_cxy , tmp_buf );
+
+    // copy FS_INFO sector from IOC to local buffer
+    error = dev_ioc_sync_read( tmp_buf_xp , fs_info_lba , 1 );
+
     if ( error )
     {
-        printk("\n[PANIC] in %s : cannot read FS_INFO record\n", __FUNCTION__ );
-        return EIO;
-    }
-
-    // update buffer 
-    fatfs_set_record( FS_FREE_CLUSTERS     , buffer , 1 , number );
-    fatfs_set_record( FS_FREE_CLUSTER_HINT , buffer , 1 , hint );
-
-    // write modified FS_INFO sector from buffer to device
-    error = dev_ioc_write( buffer , lba , 1 );
-    if ( error )
-    {
-        printk("\n[PANIC] in %s : cannot write FS_INFO record\n", __FUNCTION__ );
-        return EIO;
-    }
-
-    // release the 512 bytes buffer
-    req.type = KMEM_512_BYTES;
-    req.ptr  = buffer;
-    kmem_free( &req );
+        printk("\n[ERROR] in %s : cannot access FS_INFO on IOC device\n", __FUNCTION__ );
+        return -1;
+    }
+
+    // get current values of "free_clusters" and "free_cluster_hint" from FS_INFO on IOC
+    ioc_free_clusters     = fatfs_get_remote_record( FS_FREE_CLUSTERS     , tmp_buf_xp );
+    ioc_free_cluster_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , tmp_buf_xp );
+
+    // check values
+    if( (ioc_free_clusters     != ctx_free_clusters) || 
+        (ioc_free_cluster_hint != ctx_free_cluster_hint) )
+    {
+        printk("\n[WARNING] in %s : unconsistent free clusters info\n"
+        " ioc_free %x / ctx_free %x / ioc_hint %x / ctx_hint %x\n",
+        __FUNCTION__, ioc_free_clusters, ctx_free_clusters,
+        ioc_free_cluster_hint, ctx_free_cluster_hint );
+
+        // get pointers on FS_INFO buffer in cluster 0
+        fs_info_buffer    = hal_remote_lpt( XPTR( 0 , &fatfs_ctx_ptr->fs_info_buffer ) );
+        fs_info_buffer_xp = XPTR( 0 , fs_info_buffer );
+
+        // update FS_INFO buffer in cluster 0 
+        fatfs_set_remote_record(FS_FREE_CLUSTERS    ,fs_info_buffer_xp,ctx_free_clusters );
+        fatfs_set_remote_record(FS_FREE_CLUSTER_HINT,fs_info_buffer_xp,ctx_free_cluster_hint);
+
+        // update the FS_INFO sector on IOC device
+        error = dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
+
+        if ( error )
+        {
+            printk("\n[ERROR] in %s : cannot update FS_INFO on IOC device\n", __FUNCTION__ );
+            return -1;
+        }
+    }
 
 #if DEBUG_FATFS_SYNC_FSINFO
@@ -2096,9 +2298,10 @@
     return 0;
 
-}  // end fatfs_sync_fs_info()
+}  // end fatfs_sync_free_info()
 
 //////////////////////////////////////////////////////////
 error_t fatfs_cluster_alloc( uint32_t * searched_cluster )
 {
+    error_t       error;
     uint32_t      page_id;        // page index in FAT mapper
     uint32_t      slot_id;        // slot index in page (1024 slots per page)
@@ -2109,10 +2312,10 @@
     fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
     xptr_t        mapper_xp;      // extended pointer on FAT mapper
-    cxy_t         mapper_cxy;     // Fat mapper cluster identifier
+    cxy_t         fat_cxy;        // Fat mapper cluster identifier
     xptr_t        page_xp;        // extended pointer on current page descriptor in mapper
     xptr_t        slot_xp;        // extended pointer on FAT slot defined by hint
     xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info
     xptr_t        hint_xp;        // extended pointer on free_cluster_hint in FAT cluster
-    xptr_t        numb_xp;        // extended pointer on free_clusters_number in FAT cluster
+    xptr_t        free_xp;        // extended pointer on free_clusters_number in FAT cluster
 
 #if DEBUG_FATFS_CLUSTER_ALLOC
@@ -2130,22 +2333,24 @@
     loc_fatfs_ctx = vfs_ctx->extend;
 
-    // get extended pointer and cluster on FAT mapper
+    // get extended pointer on FAT mapper
     mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
-    mapper_cxy = GET_CXY( mapper_xp );
+
+    // get FAT cluster
+    fat_cxy = GET_CXY( mapper_xp );
     
     // get local pointer on FATFS context in FAT cluster 
-    fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
+    fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
 
     // build relevant extended pointers on free clusters info in mapper cluster 
-    lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock );
-    hint_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint );
-    numb_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters );
+    lock_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_lock );
+    hint_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint );
+    free_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters );
 
     // take the lock protecting free clusters
     remote_queuelock_acquire( lock_xp );
 
-    // get hint and free_clusters values from FATFS context 
+    // get hint and free_clusters values from FATFS context in FAT cluster
     cluster       = hal_remote_l32( hint_xp ) + 1;
-    free_clusters = hal_remote_l32( numb_xp );
+    free_clusters = hal_remote_l32( free_xp );
         
 #if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
@@ -2168,11 +2373,9 @@
     }
 
-
-
     // get page index & slot index for selected cluster 
     page_id  = cluster >> 10;
     slot_id  = cluster & 0x3FF;
 
-    // get relevant page descriptor from mapper
+    // get relevant page descriptor from FAT mapper
     page_xp = mapper_remote_get_page( mapper_xp , page_id );
 
@@ -2194,20 +2397,34 @@
     }
 
-    // update free cluster info in FATFS context
-    fatfs_free_clusters_decrement( mapper_cxy , fat_fatfs_ctx , cluster );
+    // update free cluster info in FATFS context and in FS_INFO sector
+    error = fatfs_free_clusters_decrement( XPTR( fat_cxy , fat_fatfs_ctx ) , cluster );
+
+    if( error )
+    { 
+        printk("\n[ERROR] in %s : cannot update free cluster info\n", __FUNCTION__ );
+        remote_queuelock_acquire( lock_xp );
+        return -1;
+    }
+
+    // update FAT mapper
+    hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
+
+    // synchronously update FAT on device
+    error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
+
+    if( error )
+    { 
+        printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
+        remote_queuelock_acquire( lock_xp );
+        return -1;
+    }
 
     // release free clusters busylock
     remote_queuelock_release( lock_xp );
-
-    // update FAT mapper
-    hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
-
-    // synchronously update FAT on device
-    fatfs_move_page( page_xp , IOC_SYNC_WRITE );
 
 #if DEBUG_FATFS_CLUSTER_ALLOC 
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
-printk("\n[%s] thread[%x,%x] exit / updated cluster %x in FAT / cycle %d\n",
+printk("\n[%s] thread[%x,%x] exit / allocated cluster %x in FAT / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, cluster, cycle );
 #endif
@@ -2230,6 +2447,6 @@
     xptr_t        first_xp;       // extended pointer on inode extension
     uint32_t      first_cluster;  // first cluster index for released inode
-    vfs_inode_t * inode_ptr;
-    cxy_t         inode_cxy;
+    vfs_inode_t * inode_ptr;      // local pointer on target inode
+    cxy_t         inode_cxy;      // target inode cluster identifier
 
 // check inode pointer 
@@ -2357,11 +2574,18 @@
 
     // get page base address
-    xptr_t    base_xp = ppm_page2base( page_xp );
-    uint8_t * buffer  = (uint8_t *)GET_PTR( base_xp );
+    xptr_t    buffer_xp  = ppm_page2base( page_xp );
+    uint8_t * buffer_ptr = (uint8_t *)GET_PTR( buffer_xp );
  
     // get inode pointer from mapper
     inode_ptr  = hal_remote_lpt( XPTR( page_cxy , &mapper_ptr->inode ) );
 
-    ////////////////////////////// it is the FAT mapper
+#if DEBUG_FATFS_MOVE_PAGE
+if( DEBUG_FATFS_MOVE_PAGE < cycle )
+printk("\n[%s] thread[%x,%x] enters : %s / cxy %x / mapper %x / inode %x / page %x\n",
+__FUNCTION__, this->process->pid, this->trdid,
+dev_ioc_cmd_str( cmd_type ), page_cxy, mapper_ptr, inode_ptr, buffer_ptr );
+#endif
+
+    //////////////////////////////  FAT mapper
     if( inode_ptr == NULL )
     {
@@ -2370,11 +2594,15 @@
  
         // access device
-        if     ( cmd_type == IOC_SYNC_READ  ) error = dev_ioc_sync_read ( buffer , lba , 8 );
-        else if( cmd_type == IOC_SYNC_WRITE ) error = dev_ioc_sync_write( buffer , lba , 8 );
-        else if( cmd_type == IOC_READ       ) error = dev_ioc_read      ( buffer , lba , 8 );
-        else if( cmd_type == IOC_WRITE      ) error = dev_ioc_write     ( buffer , lba , 8 );
-        else                                  error = -1;
-
-        if( error ) return EIO;
+        if     (cmd_type == IOC_SYNC_READ ) error = dev_ioc_sync_read ( buffer_xp  , lba , 8 );
+        else if(cmd_type == IOC_SYNC_WRITE) error = dev_ioc_sync_write( buffer_xp  , lba , 8 );
+        else if(cmd_type == IOC_READ      ) error = dev_ioc_read      ( buffer_ptr , lba , 8 );
+        else if(cmd_type == IOC_WRITE     ) error = dev_ioc_write     ( buffer_ptr , lba , 8 );
+        else                                error = -1;
+
+        if( error )
+        {
+            printk("\n[ERROR] in %s : cannot access device\n", __FUNCTION__ );
+            return -1;
+        }
 
 #if DEBUG_FATFS_MOVE_PAGE
@@ -2382,8 +2610,8 @@
 {
     if ( (cmd_type == IOC_READ) || (cmd_type == IOC_SYNC_READ) )
-         printk("\n[%s] thread[%x,%x] load page %d of FAT / cycle %d\n",
-         __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
+        printk("\n[%s] thread[%x,%x] load FAT mapper page %d from IOC / cycle %d\n",
+        __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     else
-        printk("\n[%s] thread[%x,%x] sync page %d of FAT / cycle %d\n",
+        printk("\n[%s] thread[%x,%x] sync FAT mapper page %d to IOC / cycle %d\n",
         __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
 }
@@ -2391,5 +2619,5 @@
 
     }
-    ///////////////////////// it is an inode mapper
+    /////////////////////////  inode mapper
     else                       
     {
@@ -2425,6 +2653,19 @@
         }
 
-        // get lba from searched_cluster
+        // get lba for searched_cluster
         uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster );
+
+        // access device
+        if     (cmd_type == IOC_SYNC_READ ) error = dev_ioc_sync_read ( buffer_xp  , lba , 8 );
+        else if(cmd_type == IOC_SYNC_WRITE) error = dev_ioc_sync_write( buffer_xp  , lba , 8 );
+        else if(cmd_type == IOC_READ      ) error = dev_ioc_read      ( buffer_ptr , lba , 8 );
+        else if(cmd_type == IOC_WRITE     ) error = dev_ioc_write     ( buffer_ptr , lba , 8 );
+        else                                error = -1;
+
+        if( error )
+        {
+            printk("\n[ERROR] in %s : cannot access device\n", __FUNCTION__ );
+            return -1;
+        }
 
 #if DEBUG_FATFS_MOVE_PAGE
@@ -2440,16 +2681,4 @@
 #endif
 
-        // access device
-        if     ( cmd_type == IOC_SYNC_READ  ) error = dev_ioc_sync_read ( buffer , lba , 8 );
-        else if( cmd_type == IOC_SYNC_WRITE ) error = dev_ioc_sync_write( buffer , lba , 8 );
-        else if( cmd_type == IOC_READ       ) error = dev_ioc_read      ( buffer , lba , 8 );
-        else if( cmd_type == IOC_WRITE      ) error = dev_ioc_write     ( buffer , lba , 8 );
-        else                                  error = -1;
-
-        if( error )
-        {
-            printk("\n[ERROR] in %s : cannot access device\n", __FUNCTION__ );
-            return -1;
-        }
     }
 
