Index: trunk/kernel/fs/vfs.c
===================================================================
--- trunk/kernel/fs/vfs.c	(revision 656)
+++ trunk/kernel/fs/vfs.c	(revision 657)
@@ -3,5 +3,5 @@
  *
  * Author  Mohamed Lamine Karaoui (2015)
- *         Alain Greiner (2016,2017,2018,2019)
+ *         Alain Greiner (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -33,5 +33,4 @@
 #include <xhtab.h>
 #include <string.h>
-#include <rpc.h>
 #include <errno.h>
 #include <kmem.h>
@@ -59,7 +58,7 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////
-void vfs_ctx_init( vfs_fs_type_t   type,
-                   uint32_t        attr,
+///////////////////////////////////////
+void vfs_ctx_init( cxy_t           cxy,
+                   vfs_fs_type_t   fs_type,
 	               uint32_t        total_clusters,
 	               uint32_t        cluster_size,
@@ -67,43 +66,58 @@
                    void          * extend )
 {
-    vfs_ctx_t * vfs_ctx = &fs_context[type];
-
-    vfs_ctx->type           = type;
-    vfs_ctx->attr           = attr;
-    vfs_ctx->total_clusters = total_clusters;
-    vfs_ctx->cluster_size   = cluster_size;
-    vfs_ctx->vfs_root_xp    = vfs_root_xp;
-    vfs_ctx->extend         = extend;
-
-    busylock_init( &vfs_ctx->lock , LOCK_VFS_CTX );
-
-    bitmap_init( vfs_ctx->bitmap , BITMAP_SIZE(CONFIG_VFS_MAX_INODES) ); 
-}
-
-////////////////////////////////////////////
-error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx,
+    // get pointer on relevant VFS context (same in all clusters) 
+    vfs_ctx_t * vfs_ctx_ptr = &fs_context[fs_type];
+
+    // initialise VFS context fields 
+    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->type           ) , fs_type );
+    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->total_clusters ) , total_clusters );
+    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->cluster_size   ) , cluster_size );
+    hal_remote_s64( XPTR( cxy , &vfs_ctx_ptr->vfs_root_xp    ) , vfs_root_xp );
+    hal_remote_spt( XPTR( cxy , &vfs_ctx_ptr->extend         ) , extend );
+
+    // initialize VFS context lock
+    remote_busylock_init( XPTR( cxy , &vfs_ctx_ptr->lock ) , LOCK_VFS_CTX );
+
+    // initialize inum allocator
+    bitmap_remote_init( XPTR( cxy , &vfs_ctx_ptr->bitmap ),
+                        BITMAP_SIZE(CONFIG_VFS_MAX_INODES) ); 
+
+} // end vfs_ctx_init()
+
+///////////////////////////////////////////////
+error_t vfs_ctx_inum_alloc( xptr_t      ctx_xp,
                             uint32_t  * inum )
 {
+    // get context cluster and local pointer
+    cxy_t       ctx_cxy = GET_CXY( ctx_xp );
+    vfs_ctx_t * ctx_ptr = GET_PTR( ctx_xp );
+
+    // build extended pointer on lock protecting the inum allocator
+    xptr_t lock_xp = XPTR( ctx_cxy , &ctx_ptr->lock );
+
+    // build extended pointer on inum bitmap
+    xptr_t bitmap_xp = XPTR( ctx_cxy , &ctx_ptr->bitmap );
+
     // get lock on inum allocator
-    busylock_acquire( &ctx->lock );
+    remote_busylock_acquire( lock_xp );
 
     // get lid from local inum allocator
-    uint32_t lid = bitmap_ffc( ctx->bitmap , CONFIG_VFS_MAX_INODES );
+    uint32_t lid = bitmap_remote_ffc( bitmap_xp , CONFIG_VFS_MAX_INODES );
 
     if( lid == 0xFFFFFFFF )   // no more free slot => error
     {
         // release lock
-        busylock_release( &ctx->lock );
+        remote_busylock_release( lock_xp );
 
         // return error
-        return 1;
+        return -1;
     }
     else              // found => return inum
     {
         // set slot allocated
-        bitmap_set( ctx->bitmap , lid );
+        bitmap_remote_set( bitmap_xp , lid );
 
         // release lock
-        busylock_release( &ctx->lock );
+        remote_busylock_release( lock_xp );
 
         // return inum
@@ -111,12 +125,29 @@
         return 0;
     }
-}
-
-////////////////////////////////////////////
-void vfs_ctx_inum_release( vfs_ctx_t * ctx,
-                           uint32_t    inum )
-{
-    bitmap_clear( ctx->bitmap , inum & 0xFFFF ); 
-}
+}  // end vfs_ctx_inum_alloc()
+
+/////////////////////////////////////////////
+void vfs_ctx_inum_release( xptr_t     ctx_xp,
+                           uint32_t   inum )
+{
+    // get context cluster and local pointer
+    cxy_t       ctx_cxy = GET_CXY( ctx_xp );
+    vfs_ctx_t * ctx_ptr = GET_PTR( ctx_xp );
+
+    // build extended pointer on inum bitmap
+    xptr_t bitmap_xp = XPTR( ctx_cxy , &ctx_ptr->bitmap );
+
+    // build extended pointer on lock
+    xptr_t lock_xp = XPTR( ctx_cxy , &ctx_ptr->lock );
+
+    // get lock 
+    remote_busylock_acquire( lock_xp );
+
+    bitmap_remote_clear( bitmap_xp , inum & 0xFFFF ); 
+
+    // release lock
+    remote_busylock_release( lock_xp );
+
+}  // end vfs_ctx_inum_release()
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -140,6 +171,7 @@
 }
 
-////////////////////////////////////////////////////
-error_t vfs_inode_create( vfs_fs_type_t     fs_type,
+////////////////////////////////////////////////
+error_t vfs_inode_create( cxy_t             cxy,
+                          vfs_fs_type_t     fs_type,
                           uint32_t          attr,
                           uint32_t          rights,
@@ -148,10 +180,10 @@
                           xptr_t          * inode_xp )
 {
-    mapper_t         * mapper;     // associated mapper( to be allocated)
-    vfs_inode_t      * inode;      // inode descriptor (to be allocated)
-    
-    uint32_t           inum;       // inode identifier (to be allocated)
-    vfs_ctx_t        * ctx;        // file system context 
-	kmem_req_t         req;        // request to kernel memory allocator
+    xptr_t             mapper_xp;    // extended pointer on associated mapper
+    mapper_t         * mapper_ptr;   // local pointer on associated mapper
+    vfs_inode_t      * inode_ptr;    // local pointer on allocated inode
+    uint32_t           inum;         // inode identifier (to be allocated)
+    vfs_ctx_t        * ctx;          // file system context 
+	kmem_req_t         req;          // request to kernel memory allocator
     error_t            error;
 
@@ -166,71 +198,73 @@
     }
 
-    // allocate inum
-    error = vfs_ctx_inum_alloc( ctx , &inum );
-
-    if( error )
-    {
-        printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ );
-        return -1;
-    }
-
-    // allocate memory for mapper
-    mapper = mapper_create( fs_type );
-
-    if( mapper == NULL )
-    {
-        printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ );
-        vfs_ctx_inum_release( ctx , inum );
-        return ENOMEM;
-    }
-
 // check inode descriptor contained in one page
 assert( (sizeof(vfs_inode_t) <= CONFIG_PPM_PAGE_SIZE),
 "inode descriptor must fit in one page" );
 
+    // allocate inum
+    error = vfs_ctx_inum_alloc( XPTR( cxy , ctx ) , &inum );
+
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ );
+        return -1;
+    }
+
+    // allocate memory for mapper in cluster cxy
+    mapper_xp = mapper_create( cxy , fs_type );
+
+    if( mapper_xp == XPTR_NULL )
+    {
+        printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ );
+        vfs_ctx_inum_release( XPTR( cxy , ctx ) , inum );
+        return -1;
+    }
+
+    mapper_ptr = GET_PTR( mapper_xp );
+
     // allocate one page for VFS inode descriptor
-    // because the embedded "children xhtab footprint
-	req.type  = KMEM_PPM;
-	req.order = 0;
-    req.flags = AF_KERNEL | AF_ZERO;
-	inode     = kmem_alloc( &req );
-
-    if( inode == NULL )
+    // because the embedded "children" xhtab footprint
+	req.type   = KMEM_PPM;
+	req.order  = 0;
+    req.flags  = AF_KERNEL | AF_ZERO;
+	inode_ptr  = kmem_remote_alloc( cxy , &req );
+
+    if( inode_ptr == NULL )
     {
         printk("\n[ERROR] in %s : cannot allocate inode descriptor\n", __FUNCTION__ );
-        vfs_ctx_inum_release( ctx , inum );
-        mapper_destroy( mapper );
+        vfs_ctx_inum_release( XPTR( cxy , ctx ) , inum );
+        mapper_destroy( mapper_xp );
         return -1;
     }
 
+    // initialise inode field in mapper
+    hal_remote_spt( XPTR( cxy , &mapper_ptr->inode ) , inode_ptr );
+ 
     // initialize inode descriptor
-    inode->type       = INODE_TYPE_FILE;     // default value
-    inode->inum       = inum;
-    inode->attr       = attr;
-    inode->rights     = rights;
-    inode->uid        = uid;
-    inode->gid        = gid;
-    inode->ctx        = ctx;
-    inode->mapper     = mapper;
-    inode->extend     = NULL;
-    inode->links      = 0;
-
-    // initialise inode field in mapper
-    mapper->inode     = inode;
- 
+    hal_remote_s32( XPTR( cxy , &inode_ptr->type   ) , INODE_TYPE_FILE );  // default value
+    hal_remote_s32( XPTR( cxy , &inode_ptr->inum   ) , inum );  
+    hal_remote_s32( XPTR( cxy , &inode_ptr->attr   ) , attr );  
+    hal_remote_s32( XPTR( cxy , &inode_ptr->rights ) , rights );  
+    hal_remote_s32( XPTR( cxy , &inode_ptr->links  ) , 0 );
+    hal_remote_s32( XPTR( cxy , &inode_ptr->uid    ) , uid );  
+    hal_remote_s32( XPTR( cxy , &inode_ptr->gid    ) , gid );  
+    hal_remote_spt( XPTR( cxy , &inode_ptr->ctx    ) , ctx );  
+    hal_remote_spt( XPTR( cxy , &inode_ptr->mapper ) , mapper_ptr );  
+    hal_remote_spt( XPTR( cxy , &inode_ptr->extend ) , NULL );  
+
     // initialize chidren dentries xhtab
-    xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
+    xhtab_init( XPTR( cxy , &inode_ptr->children ) , XHTAB_DENTRY_TYPE );
 
     // initialize parents dentries xlist
-    xlist_root_init( XPTR( local_cxy , &inode->parents ) );
+    xlist_root_init( XPTR( cxy , &inode_ptr->parents ) );
  
     // initialize lock protecting size 
-    remote_rwlock_init( XPTR( local_cxy , &inode->size_lock ), LOCK_VFS_SIZE );
+    remote_rwlock_init( XPTR( cxy , &inode_ptr->size_lock ), LOCK_VFS_SIZE );
 
     // initialise lock protecting inode tree traversal
-    remote_rwlock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN );
+    remote_rwlock_init( XPTR( cxy , &inode_ptr->main_lock ), LOCK_VFS_MAIN );
 
     // return extended pointer on inode
-    *inode_xp = XPTR( local_cxy , inode );
+    *inode_xp = XPTR( cxy , inode_ptr );
 
 #if DEBUG_VFS_INODE_CREATE
@@ -238,6 +272,6 @@
 thread_t *     this       = CURRENT_THREAD;
 if( DEBUG_VFS_INODE_CREATE < cycle )
-printk("\n[%s] thread[%x,%x] created inode (%x,%x) / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, local_cxy, inode, cycle );
+printk("\n[%s] thread[%x,%x] created inode (%x,%x) / ctx %x / fs_type %d / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, cxy, inode_ptr, ctx, ctx->type, cycle );
 #endif
  
@@ -246,15 +280,19 @@
 }  // end vfs_inode_create()  
 
-/////////////////////////////////////////////
-void vfs_inode_destroy( vfs_inode_t * inode )
-{
+//////////////////////////////////////////
+void vfs_inode_destroy( xptr_t  inode_xp )
+{
+    // get cluster and local pointer
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
     // release memory allocated for mapper
-    mapper_destroy( inode->mapper );
-
-    // release memory allocate for inode descriptor
+    mapper_destroy( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+    // release memory allocated for inode descriptor
 	kmem_req_t req;
 	req.type  = KMEM_PPM;
-	req.ptr   = inode;
-	kmem_free( &req );
+	req.ptr   = inode_ptr;
+	kmem_remote_free( inode_cxy , &req );
 
 }  // end vfs_inode_destroy()
@@ -339,6 +377,6 @@
     
     // get inode cluster and local pointer
+    inode_ptr = GET_PTR( inode_xp );
     inode_cxy = GET_CXY( inode_xp );
-    inode_ptr = GET_PTR( inode_xp );
 
     // build extended pointer on parents dentries root
@@ -367,26 +405,27 @@
 }  // end vfs_inode_get_name()
 
-///////////////////////////////////////////////////////
-error_t vfs_inode_load_all_pages( vfs_inode_t * inode )
-{
-
-assert( (inode != NULL) , "inode pointer is NULL" );
-
+////////////////////////////////////////////////////
+error_t vfs_inode_load_all_pages( xptr_t  inode_xp )
+{
     uint32_t   page_id;
     xptr_t     page_xp;
 
-    mapper_t * mapper = inode->mapper;
-    uint32_t   size   = inode->size;
-
-assert( (mapper != NULL) , "mapper pointer is NULL" );
+
+    // get inode cluster and local pointer
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get pointer on mapper and size
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+    uint32_t   size   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size ) );
 
 #if DEBUG_VFS_INODE_LOAD_ALL
+char       name[CONFIG_VFS_MAX_NAME_LENGTH];
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
-char       name[CONFIG_VFS_MAX_NAME_LENGTH];
-vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
+vfs_inode_get_name( inode_xp , name );
 if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
 printk("\n[%s] thread[%x,%x] enter for <%s> in cluster %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
+__FUNCTION__, this->process->pid, this->trdid, name, inode_cxy, cycle );
 #endif
 
@@ -400,5 +439,5 @@
         // If the mage is missing, this function allocates the missing page,
         // and load the page from IOC device into mapper
-        page_xp = mapper_remote_get_page( XPTR( local_cxy , mapper ), page_id );
+        page_xp = mapper_get_page( XPTR( inode_cxy , mapper ), page_id );
 
         if( page_xp == XPTR_NULL ) return -1;
@@ -408,6 +447,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
-printk("\n[%s] thread[%x,%x] exit for <%x> in cluster %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
+printk("\n[%s] thread[%x,%x] exit for <%s> in cluster %x\n",
+__FUNCTION__, this->process->pid, this->trdid, name, inode_cxy );
 #endif
 
@@ -425,4 +464,5 @@
     vfs_inode_get_name( inode_xp , name );
 
+    // get inode cluster and local pointer
     cxy_t         inode_cxy = GET_CXY( inode_xp );
     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
@@ -461,12 +501,21 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-///////////////////////////////////////////////////
-error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
+///////////////////////////////////////////////
+error_t vfs_dentry_create( cxy_t           cxy,
+                           vfs_fs_type_t   fs_type,
                            char          * name,
                            xptr_t        * dentry_xp )
 {
-    vfs_ctx_t      * ctx;        // context descriptor
-    vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated)
-	kmem_req_t       req;        // request to kernel memory allocator
+	kmem_req_t       req;            // request to kernel memory allocator
+    vfs_ctx_t      * ctx = NULL;     // context descriptor
+    vfs_dentry_t   * dentry_ptr;     // dentry descriptor (to be allocated)
+
+#if DEBUG_VFS_DENTRY_CREATE
+thread_t * this  = CURRENT_THREAD;
+uint32_t   cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_VFS_DENTRY_CREATE < cycle )
+printk("\n[%s] thread[%x,%x] enters for <%s> /  fs_type %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, name, fs_type, cycle );
+#endif
 
     // get pointer on context
@@ -476,5 +525,5 @@
     else 
     {
-        ctx = NULL;
+        printk("\n[ERROR] in %s undefined fs_type %d\n", __FUNCTION__, fs_type );
         return -1;
     }
@@ -483,13 +532,13 @@
     uint32_t length = strlen( name );
 
-    if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return EINVAL;
+    if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return -1;
 
     // allocate memory for dentry descriptor
-	req.type  = KMEM_KCM;
-	req.order = bits_log2( sizeof(vfs_dentry_t) );
-    req.flags = AF_KERNEL | AF_ZERO;
-	dentry    = kmem_alloc( &req );
-
-    if( dentry == NULL ) 
+	req.type   = KMEM_KCM;
+	req.order  = bits_log2( sizeof(vfs_dentry_t) );
+    req.flags  = AF_KERNEL | AF_ZERO;
+	dentry_ptr = kmem_remote_alloc( cxy , &req );
+
+    if( dentry_ptr == NULL ) 
     {
         printk("\n[ERROR] in %s : cannot allocate dentry descriptor\n",
@@ -499,18 +548,19 @@
 
     // initialize dentry descriptor
-    dentry->ctx     = ctx;
-    dentry->length  = length;
-    dentry->extend  = NULL;
-    strcpy( dentry->name , name );
+    hal_remote_spt( XPTR( cxy , &dentry_ptr->ctx    ) , ctx );
+    hal_remote_s32( XPTR( cxy , &dentry_ptr->length ) , length );
+    hal_remote_spt( XPTR( cxy , &dentry_ptr->extend ) , NULL );
+
+    // register name
+    hal_remote_strcpy( XPTR( cxy, dentry_ptr->name ),
+                       XPTR( local_cxy, name ) );
 
     // return extended pointer on dentry 
-    *dentry_xp = XPTR( local_cxy , dentry );
+    *dentry_xp = XPTR( cxy , dentry_ptr );
 
 #if DEBUG_VFS_DENTRY_CREATE
-thread_t * this  = CURRENT_THREAD;
-uint32_t   cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VFS_DENTRY_CREATE < cycle )
-printk("\n[%s] thread[%x,%x] created dentry <%s> : (%x,%x) / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, dentry, cycle );
+printk("\n[%s] thread[%x,%x] exit for <%s> / dentry (%x,%x)\n",
+__FUNCTION__, this->process->pid, this->trdid, name, cxy, dentry_ptr );
 #endif
 
@@ -519,12 +569,16 @@
 }  // end vfs_dentry_create()
 
-////////////////////////////////////////////////
-void vfs_dentry_destroy( vfs_dentry_t * dentry )
-{
+////////////////////////////////////////////
+void vfs_dentry_destroy( xptr_t  dentry_xp )
+{
+    // get cluster and local pointer
+    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
+    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
+  
     // release memory allocated to dentry
 	kmem_req_t req;
 	req.type  = KMEM_KCM;
-	req.ptr   = dentry;
-	kmem_free( &req );
+	req.ptr   = dentry_ptr;
+	kmem_remote_free( dentry_cxy , &req );
 
 }  // end vfs_dentry_destroy()
@@ -536,10 +590,17 @@
 
 /////////////////////////////////////////////
-error_t vfs_file_create( vfs_inode_t * inode,
-                         uint32_t      attr,
-                         xptr_t      * file_xp )
-{
-    vfs_file_t  * file;
+error_t vfs_file_create( xptr_t     inode_xp,
+                         uint32_t   attr,
+                         xptr_t   * file_xp )
+{
+    vfs_file_t  * file_ptr;
 	kmem_req_t    req;
+    uint32_t      type;
+    mapper_t    * mapper;
+    vfs_ctx_t   * ctx;
+
+    // get inode cluster and local pointer
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
 
 #if DEBUG_VFS_FILE_CREATE
@@ -547,6 +608,6 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VFS_OPEN < cycle )
-printk("\n[%s] thread[%x,%x] enter for inode %x in cluster %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle );
+printk("\n[%s] thread[%x,%x] enter for inode (%x,%x) / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, inode_cxy, inode_ptr, cycle );
 #endif
 
@@ -555,27 +616,31 @@
 	req.order = bits_log2( sizeof(vfs_file_t) );
     req.flags = AF_KERNEL | AF_ZERO;
-	file      = kmem_alloc( &req );
-
-    if( file == NULL ) return ENOMEM;
+	file_ptr  = kmem_remote_alloc( inode_cxy , &req );
+
+    if( file_ptr == NULL ) return -1;
+
+    // get type, ctx and mapper from inode descriptor
+    type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
+    ctx    = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) );
+    mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
 
     // initializes new file descriptor
-    file->gc       = 0;
-    file->type     = inode->type;
-    file->attr     = attr;
-    file->offset   = 0;
-    file->refcount = 1;
-    file->inode    = inode;
-    file->ctx      = inode->ctx;
-    file->mapper   = inode->mapper;
-
-    remote_rwlock_init( XPTR( local_cxy , &file->lock ), LOCK_VFS_FILE );
-
-    *file_xp = XPTR( local_cxy , file );
+    hal_remote_s32( XPTR( inode_cxy , &file_ptr->type     ) , type );
+    hal_remote_s32( XPTR( inode_cxy , &file_ptr->attr     ) , attr );
+    hal_remote_s32( XPTR( inode_cxy , &file_ptr->offset   ) , 0 );
+    hal_remote_s32( XPTR( inode_cxy , &file_ptr->refcount ) , 1 );
+    hal_remote_spt( XPTR( inode_cxy , &file_ptr->inode    ) , inode_ptr );
+    hal_remote_spt( XPTR( inode_cxy , &file_ptr->ctx      ) , ctx );
+    hal_remote_spt( XPTR( inode_cxy , &file_ptr->mapper   ) , mapper );
+
+    remote_rwlock_init( XPTR( inode_cxy , &file_ptr->lock ), LOCK_VFS_FILE );
+
+    *file_xp = XPTR( inode_cxy , file_ptr );
 
 #if DEBUG_VFS_FILE_CREATE
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VFS_OPEN < cycle )
-printk("\n[%s] thread[%x,%x] created file %x in cluster %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, file, local_cxy, cycle );
+printk("\n[%s] thread[%x,%x] created file (%x,%x) %x\n",
+__FUNCTION__, this->process->pid, this->trdid, inode_cxy, file_ptr, cycle );
 #endif
 
@@ -584,20 +649,25 @@
 }  // end vfs_file_create()
 
-///////////////////////////////////////////
-void vfs_file_destroy( vfs_file_t *  file )
-{
+////////////////////////////////////////
+void vfs_file_destroy( xptr_t  file_xp )
+{
+    // get file cluster and local pointer
+    vfs_file_t * file_ptr = GET_PTR( file_xp );
+    cxy_t        file_cxy = GET_CXY( file_xp );
+
+    // release file descriptor
 	kmem_req_t req;
 	req.type  = KMEM_KCM;
-	req.ptr   = file;
-	kmem_free( &req );
+	req.ptr   = file_ptr;
+	kmem_remote_free( file_cxy , &req );
 
 #if DEBUG_VFS_CLOSE
 char name[CONFIG_VFS_MAX_NAME_LENGTH];
-vfs_file_get_name( XPTR( local_cxy , file ) , name );
+vfs_file_get_name( file_xp , name );
 thread_t * this = CURRENT_THREAD;
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VFS_CLOSE < cycle )
 printk("\n[%s] thread[%x,%x] deleted file <%s> in cluster %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle );
+__FUNCTION__, this->process->pid, this->trdid, name, file_cxy, cycle );
 #endif
 
@@ -738,12 +808,5 @@
 
     // create a new file descriptor in cluster containing inode
-    if( inode_cxy == local_cxy )      // target cluster is local
-    {
-        error = vfs_file_create( inode_ptr , file_attr , &file_xp );
-    }
-    else                              // target cluster is remote
-    {
-        rpc_vfs_file_create_client( inode_cxy , inode_ptr , file_attr , &file_xp , &error );
-    }
+    error = vfs_file_create( inode_xp , file_attr , &file_xp );
 
     if( error )  return error;
@@ -764,6 +827,7 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VFS_OPEN < cycle )
-printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / cxy %x / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle );
+printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / file(%x,%x) / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, path, file_id,
+GET_CXY( file_xp ), GET_PTR( file_xp ), cycle );
 #endif
 
@@ -880,6 +944,6 @@
     __FUNCTION__ , this->process->pid, nbytes );
     else            
-    printk("\n[%s] thread[%x,%x] exit / %d bytes moved from buffer to mapper / size %d\n",
-    __FUNCTION__ , this->process->pid, nbytes, hal_remote_l32(XPTR(file_cxy,&inode->size)) );
+    printk("\n[%s] thread[%x,%x] exit / %d bytes moved from buffer to mapper\n",
+    __FUNCTION__ , this->process->pid, nbytes );
 }
 #endif
@@ -1035,5 +1099,5 @@
 {
     cxy_t         file_cxy;         // cluster containing the file descriptor.
-    vfs_file_t  * file_ptr;         // local ponter on file descriptor
+    vfs_file_t  * file_ptr;         // local pointer on file descriptor
     cxy_t         owner_cxy;        // process owner cluster
     pid_t         pid;              // process identifier
@@ -1076,14 +1140,5 @@
 
     // copy all dirty pages from mapper to device
-    if( file_cxy == local_cxy )
-    {
-        error = mapper_sync( mapper_ptr );
-    }
-    else
-    {
-        rpc_mapper_sync_client( file_cxy,
-                                mapper_ptr,
-                                &error );
-    }
+    error = mapper_sync( XPTR( file_cxy , mapper_ptr ) );
 
     if( error )
@@ -1128,18 +1183,6 @@
  
         // update dentry size in parent directory mapper
-        if( parent_cxy == local_cxy )
-        {
-            error = vfs_fs_update_dentry( parent_inode_ptr,
-                                          parent_dentry_ptr,
-                                          size );
-        }
-        else
-        {
-            rpc_vfs_fs_update_dentry_client( parent_cxy,
-                                             parent_inode_ptr,
-                                             parent_dentry_ptr,
-                                             size,
-                                             &error );
-        }
+        error = vfs_fs_update_dentry( XPTR( parent_cxy , parent_inode_ptr ),
+                                      parent_dentry_ptr );
 
         if( error )
@@ -1159,14 +1202,5 @@
 
         // copy all dirty pages from parent mapper to device
-        if( parent_cxy == local_cxy )
-        {
-            error = mapper_sync( parent_mapper_ptr );
-        }
-        else
-        {
-            rpc_mapper_sync_client( parent_cxy,
-                                    parent_mapper_ptr,
-                                    &error );
-        }
+        error = mapper_sync( XPTR( parent_cxy , parent_mapper_ptr ) );
 
         if( error )
@@ -1222,12 +1256,5 @@
     //////// 4) release memory allocated to file descriptor in remote cluster
 
-    if( file_cxy == local_cxy )             // file cluster is local
-    {
-        vfs_file_destroy( file_ptr );
-    }
-    else                                    // file cluster is local
-    {
-        rpc_vfs_file_destroy_client( file_cxy , file_ptr );
-    }
+    vfs_file_destroy( file_xp );
 
 #if DEBUG_VFS_CLOSE
@@ -1320,19 +1347,8 @@
 
     // 2. create one new dentry in parent cluster
-    if( parent_cxy == local_cxy )  
-    {
-        error = vfs_dentry_create( parent_fs_type,
-                                   last_name,
-                                   &dentry_xp );
-    }
-    else
-    {
-        rpc_vfs_dentry_create_client( parent_cxy,
-                                      parent_fs_type,
-                                      last_name,
-                                      &dentry_xp,
-                                      &error );
-    }
-
+    error = vfs_dentry_create( parent_cxy,
+                               parent_fs_type,
+                               last_name,
+                               &dentry_xp );
     if( error )
     {
@@ -1361,32 +1377,18 @@
     inode_cxy = cluster_random_select();
     
-    if( inode_cxy == local_cxy )      // target cluster is local 
-    {
-        error = vfs_inode_create( parent_fs_type,
-                                  attr,
-                                  rights,
-                                  uid,
-                                  gid,
-                                  &inode_xp );
-    }
-    else                              // target cluster is remote
-    {
-        rpc_vfs_inode_create_client( inode_cxy,
-                                     parent_fs_type,
-                                     attr,
-                                     rights,
-                                     uid,
-                                     gid,
-                                     &inode_xp,
-                                     &error );
-    }
-                                     
+    // create inode
+    error = vfs_inode_create( inode_cxy,
+                              parent_fs_type,
+                              attr,
+                              rights,
+                              uid,
+                              gid,
+                              &inode_xp );
     if( error )
     {
         remote_rwlock_wr_release( lock_xp );
         printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
-               __FUNCTION__ , inode_cxy , path );
-        if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr );
-        else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr );
+         __FUNCTION__ , inode_cxy , path );
+        vfs_dentry_destroy( dentry_xp );
         return -1;
     }
@@ -1434,7 +1436,6 @@
         remote_rwlock_wr_release( lock_xp );
         printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
-               __FUNCTION__ , inode_cxy , path );
-        if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr );
-        else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr );
+        __FUNCTION__ , inode_cxy , path );
+        vfs_dentry_destroy( dentry_xp );
         return -1;
     }
@@ -1445,17 +1446,6 @@
     // 8. update parent directory mapper 
     //    and synchronize the parent directory on IOC device
-    if (parent_cxy == local_cxy)
-    {
-        error = vfs_fs_add_dentry( parent_ptr,
-                                   dentry_ptr );
-    }
-    else
-    {
-        rpc_vfs_fs_add_dentry_client( parent_cxy,
-                                      parent_ptr,
-                                      dentry_ptr,
-                                      &error );
-    }
-
+    error = vfs_fs_add_dentry( parent_xp,
+                               dentry_ptr );
     if( error )
     {
@@ -1589,19 +1579,8 @@
     {
         // 1. create one new dentry
-        if( new_parent_cxy == local_cxy )  
-        {
-            error = vfs_dentry_create( inode_fs_type,
-                                       new_name,
-                                       &dentry_xp );
-        }
-        else
-        {
-            rpc_vfs_dentry_create_client( new_parent_cxy,
-                                          inode_fs_type,
-                                          new_name,
-                                          &dentry_xp,
-                                          &error );
-        }
-
+        error = vfs_dentry_create( new_parent_cxy,
+                                   inode_fs_type,
+                                   new_name,
+                                   &dentry_xp );
         if( error )
         {
@@ -1643,15 +1622,6 @@
         //    and synchronize the parent directory on IOC device
         if (new_parent_cxy == local_cxy)
-        {
-            error = vfs_fs_add_dentry( new_parent_ptr,
-                                       dentry_ptr );
-        }
-        else
-        {
-            rpc_vfs_fs_add_dentry_client( new_parent_cxy,
-                                          new_parent_ptr,
-                                          dentry_ptr,
-                                          &error );
-        }
+        error = vfs_fs_add_dentry( new_parent_xp,
+                                   dentry_ptr );
         if( error )
         {
@@ -1703,5 +1673,6 @@
     vfs_fs_type_t     fs_type;            // File system type
 
-    char              name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of link to remove
+    char              child_name[CONFIG_VFS_MAX_NAME_LENGTH];   // name of link to remove
+    char              parent_name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of parent directory
 
     thread_t  * this    = CURRENT_THREAD;
@@ -1731,20 +1702,19 @@
                         VFS_LOOKUP_PARENT,
                         &parent_xp,
-                        name );
+                        child_name );
     if( error ) 
     {
         remote_rwlock_wr_release( lock_xp );
         printk("\n[ERROR] in %s : cannot get parent inode for <%s> in <%s>\n",
-        __FUNCTION__, name, path );
+        __FUNCTION__, child_name, path );
         return -1;
     }
-
-    // get parent inode cluster and local pointer
+    
+    // get parent inode name, cluster and local pointer
+    vfs_inode_get_name( parent_xp , parent_name );
     parent_cxy = GET_CXY( parent_xp );
     parent_ptr = GET_PTR( parent_xp );
  
 #if( DEBUG_VFS_UNLINK & 1 )
-char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
-vfs_inode_get_name( parent_xp , parent_name );
 if( DEBUG_VFS_UNLINK < cycle )
 printk("\n[%s] thread[%x,%x] : parent inode <%s> is (%x,%x)\n",
@@ -1756,7 +1726,7 @@
 
     // try to get extended pointer on dentry from Inode Tree
-    dentry_xp = xhtab_lookup( children_xp , name );
+    dentry_xp = xhtab_lookup( children_xp , child_name );
     
-    // when dentry not found in Inode Tree, try to get it from inode tree
+    // when dentry not found in Inode Tree, try to get it from mapper
 
     if( dentry_xp == XPTR_NULL )           // miss target dentry in Inode Tree
@@ -1765,6 +1735,6 @@
 #if( DEBUG_VFS_UNLINK & 1 )
 if( DEBUG_VFS_UNLINK < cycle )
-printk("\n[%s] thread[%x,%x] : inode <%s> not found => scan parent mapper\n",
-__FUNCTION__, process->pid, this->trdid, name );
+printk("\n[%s] thread[%x,%x] : inode <%s> not found => scan parent mapper <%s>\n",
+__FUNCTION__, process->pid, this->trdid, child_name , parent_name );
 #endif
         // get parent inode FS type
@@ -1779,13 +1749,11 @@
                                          fs_type, 
                                          parent_xp, 
-                                         name, 
+                                         child_name, 
                                          &dentry_xp,
                                          &inode_xp );
         if( error )
         {
-            printk("\n[ERROR] in %s : cannot create inode <%s> in path <%s>\n",
-            __FUNCTION__ , name, path );
-
-            vfs_remove_child_from_parent( dentry_xp );
+            printk("\n[ERROR] in %s : cannot create inode <%s> in Inode Tree\n",
+            __FUNCTION__ , child_name );
             return -1;
         }
@@ -1797,23 +1765,10 @@
         // scan parent mapper to find the missing dentry, and complete 
         // initialisation of new dentry and new inode descriptors In Inode Tree
-        if( parent_cxy == local_cxy )
+        error = vfs_fs_new_dentry_from_mapper( parent_xp,
+                                               dentry_ptr );
+        if ( error ) 
         {
-            error = vfs_fs_new_dentry( parent_ptr,
-                                       name,
-                                       inode_xp );
-        }
-        else
-        {
-            rpc_vfs_fs_new_dentry_client( parent_cxy,
-                                          parent_ptr,
-                                          name,
-                                          inode_xp,
-                                          &error );
-        }
-
-        if ( error )   // dentry not found in parent mapper
-        {
-            printk("\n[ERROR] in %s : cannot get dentry <%s> in path <%s>\n",
-            __FUNCTION__ , name, path );
+            printk("\n[ERROR] in %s : cannot get entry <%s> in parent <%s> mapper\n",
+            __FUNCTION__ , child_name, parent_name );
             return -1;
         }
@@ -1822,5 +1777,5 @@
 if( DEBUG_VFS_UNLINK < cycle )
 printk("\n[%s] thread[%x,%x] : created missing inode & dentry <%s> in cluster %x\n",
-__FUNCTION__, process->pid, this->trdid, name, inode_cxy );
+__FUNCTION__, process->pid, this->trdid, child_name, inode_cxy );
 #endif
 
@@ -1856,5 +1811,6 @@
 if( DEBUG_VFS_UNLINK < cycle )
 printk("\n[%s] thread[%x,%x] : unlink inode <%s> / type %s / %d links\n",
-__FUNCTION__, process->pid, this->trdid, name, vfs_inode_type_str(inode_type), inode_links );
+__FUNCTION__, process->pid, this->trdid, child_name, 
+vfs_inode_type_str(inode_type), inode_links );
 #endif
 
@@ -1898,17 +1854,6 @@
         // 2. update parent directory mapper
         //    and synchronize the parent directory on IOC device
-        if (parent_cxy == local_cxy)
-        {
-            error = vfs_fs_remove_dentry( parent_ptr,
-                                          dentry_ptr );
-        }
-        else            
-        {
-            rpc_vfs_fs_remove_dentry_client( parent_cxy,
-                                             parent_ptr,
-                                             dentry_ptr,
-                                             &error );
-        }
-
+        error = vfs_fs_remove_dentry( parent_xp,
+                                      dentry_ptr );
         if( error )
         {
@@ -2172,5 +2117,5 @@
 
 //////////////////////////////////////////////////////////////////////////
-// This static function is called by the vfs_display() function.
+// This recursive function is called by the vfs_display() function.
 // that is supposed to take the TXT0 lock.
 //////////////////////////////////////////////////////////////////////////
@@ -2184,5 +2129,4 @@
     uint32_t           inode_size;
     uint32_t           inode_attr;
-    uint32_t           inode_dirty;
     void             * inode_extd;
 
@@ -2234,10 +2178,10 @@
 
     // compute dirty
-    inode_dirty = ((inode_attr & INODE_ATTR_DIRTY) != 0);
+    // inode_dirty = ((inode_attr & INODE_ATTR_DIRTY) != 0); unused [AG] dec 2019
 
     // display inode
-    nolock_printk("%s<%s> : %s / extd %x / %d bytes / dirty %d / cxy %x / inode %x / mapper %x\n",
+    nolock_printk("%s<%s> : %s / extd %x / %d bytes / cxy %x / inode %x / mapper %x\n",
     indent_str[indent], name, vfs_inode_type_str( inode_type ), (uint32_t)inode_extd,
-    inode_size, inode_dirty, inode_cxy, inode_ptr, mapper_ptr );
+    inode_size, inode_cxy, inode_ptr, mapper_ptr );
 
     // scan directory entries when current inode is a directory
@@ -2328,5 +2272,5 @@
 
     // print header
-    nolock_printk("\n***** file system state\n\n");
+    nolock_printk("\n***** current VFS state\n\n");
 
     // call recursive function
@@ -2484,4 +2428,5 @@
     vfs_inode_t      * parent_ptr;   // local pointer on parent inode  
     xptr_t             dentry_xp;    // extended pointer on dentry       
+    vfs_dentry_t     * dentry_ptr;   // local pointer on dentry
     xptr_t             child_xp;     // extended pointer on child inode
     cxy_t              child_cxy;    // cluster for child inode
@@ -2532,4 +2477,6 @@
     last      = false;
     child_xp  = XPTR_NULL;
+    child_cxy = 0;
+    child_ptr = NULL;
 
     // loop on nodes in pathname
@@ -2570,9 +2517,5 @@
                                &child_xp );
 
-        // get child inode local pointer and cluster
-        child_ptr  = GET_PTR( child_xp );
-        child_cxy  = GET_CXY( child_xp );
-
-        if( found == false )                              // not found in Inode Tree 
+        if( found == false )                          // child not found in Inode Tree 
         {
             // when a inode is not found in the Inode Tree:
@@ -2606,5 +2549,5 @@
 #endif
                 // get parent inode FS type
-                ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
+                ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
                 fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
 
@@ -2626,6 +2569,7 @@
                 }
 
-                // get child inode local pointer
-                child_ptr = GET_PTR( child_xp );
+                // get child inode and dentry local pointers
+                child_ptr  = GET_PTR( child_xp );
+                dentry_ptr = GET_PTR( dentry_xp );
 
 #if (DEBUG_VFS_LOOKUP & 1)
@@ -2636,32 +2580,17 @@
                 // scan parent mapper to find the missing dentry, and complete 
                 // the initialisation of dentry and child inode descriptors
-                if( parent_cxy == local_cxy )
-                {
-                    error = vfs_fs_new_dentry( parent_ptr,
-                                               name,
-                                               child_xp );
-                }
-                else
-                {
-                    rpc_vfs_fs_new_dentry_client( parent_cxy,
-                                                  parent_ptr,
-                                                  name,
-                                                  child_xp,
-                                                  &error );
-                }
-
-                // when the missing dentry is not in the parent mapper,
-                // a new dentry must be registered in parent directory mapper
-                if ( error )
+                error = vfs_fs_new_dentry_from_mapper( parent_xp,
+                                                       dentry_ptr );
+
+                if ( error )  // an error can be fatal or non-fatal :
                 {
                     if ( last && create )  // add a brand new dentry in parent directory
                     {
-                        error = vfs_new_dentry_init( parent_xp,                
-                                                     dentry_xp,
-                                                     child_xp );
+                        error = vfs_fs_new_dentry_to_mapper( parent_xp,                
+                                                             dentry_ptr );
                         if ( error )
                         {
-                            printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
-                            __FUNCTION__, name, pathname );
+                            printk("\n[ERROR] in %s : cannot add dentry <%s> in parent dir\n",
+                            __FUNCTION__, name );
                             vfs_remove_child_from_parent( dentry_xp );
                             return -1;
@@ -2674,6 +2603,4 @@
 vfs_inode_display( child_xp );
 #endif
-
-
                     }
                     else                   // not last or not create => error
@@ -2704,14 +2631,6 @@
                     if( type == INODE_TYPE_DIR ) 
                     {
-                        if( child_cxy == local_cxy )
-                        {
-                            error = vfs_inode_load_all_pages( child_ptr );
-                        }
-                        else
-                        {
-                            rpc_vfs_inode_load_all_pages_client( child_cxy,
-                                                                 child_ptr,
-                                                                 &error );
-                        }
+                        error = vfs_inode_load_all_pages( child_xp );
+
                         if ( error )
                         {
@@ -2731,6 +2650,9 @@
             }
         }
-        else                                    // child directly found in inode tree
+        else                                    // child found in Inode Tree
         {
+            // get child inode local pointer and cluster
+            child_ptr  = GET_PTR( child_xp );
+            child_cxy  = GET_CXY( child_xp );
         
 #if (DEBUG_VFS_LOOKUP & 1)
@@ -2759,8 +2681,4 @@
         // }
 
-        // take lock on child inode and release lock on parent
-        // vfs_inode_lock( child_xp );
-        // vfs_inode_unlock( parent_xp );
-
         // exit when last
         if ( last )           // last inode in path  => return relevant info
@@ -2792,106 +2710,19 @@
             }
         }
-        else                     // not the last inode in path => update loop variables
+        else                     // not the last node in path => update loop variables
         {
             parent_xp = child_xp;
             current   = next;
         }
-    }
+    }  // end while loop on nodes in pathname
+
+#if ( DEBUG_VFS_LOOKUP & 1 )
+if( DEBUG_VFS_LOOKUP < cycle )
+vfs_display( root_xp );
+#endif
 
     return 0;
 
 }  // end vfs_lookup()
-
-////////////////////////////////////////////////
-error_t vfs_new_dentry_init( xptr_t   parent_xp,
-                             xptr_t   dentry_xp,
-                             xptr_t   child_xp )
-{
-    error_t     error;
-    uint32_t    cluster_id;
-    uint32_t    child_type;
-    uint32_t    child_size;
-
-#if DEBUG_VFS_NEW_DENTRY_INIT
-char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
-char child_name[CONFIG_VFS_MAX_NAME_LENGTH];
-vfs_inode_get_name( parent_xp , parent_name );
-vfs_inode_get_name( child_xp  , child_name );
-uint32_t   cycle = (uint32_t)hal_get_cycles();
-thread_t * this  = CURRENT_THREAD;
-if( DEBUG_VFS_NEW_DENTRY_INIT < cycle )
-printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
-__FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
-#endif
-
-    // get parent inode cluster and local pointer
-    cxy_t          parent_cxy = GET_CXY( parent_xp );
-    vfs_inode_t  * parent_ptr = GET_PTR( parent_xp );
-
-    // get dentry local pointer
-    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
-
-    // get child inode cluster and local pointer
-    cxy_t          child_cxy  = GET_CXY( child_xp );
-    vfs_inode_t  * child_ptr  = GET_PTR( child_xp );
-
-    // 1. allocate one free cluster_id in file system to child inode,
-    // and update the File Allocation Table in both the FAT mapper and IOC device.
-    // It depends on the child inode FS type.
-    vfs_ctx_t * ctx = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) );
-
-    error = vfs_fs_cluster_alloc( ctx->type,
-                                  &cluster_id );
-    if ( error )
-    {
-        printk("\n[ERROR] in %s : cannot find a free VFS cluster_id\n",
-        __FUNCTION__ );
-        return -1;
-    }
-
-#if( DEBUG_VFS_NEW_DENTRY_INIT & 1)
-if( DEBUG_VFS_NEW_DENTRY_INIT < cycle )
-printk("\n[%s] thread[%x,%x] allocated FS cluster_id %x to <%s>\n",
-__FUNCTION__ , this->process->pid, this->trdid, cluster_id, child_name );
-#endif
-
-    // 2. update the child inode descriptor size and extend
-    child_type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
-    child_size = 0;
-    
-    hal_remote_s32( XPTR( child_cxy , &child_ptr->size )   , child_size );
-    hal_remote_spt( XPTR( child_cxy , &child_ptr->extend ) , (void*)(intptr_t)cluster_id );
-
-    // 3. update the parent inode mapper, and 
-    // update the dentry extension if required
-    if( local_cxy == parent_cxy )
-    {
-        error = vfs_fs_add_dentry( parent_ptr,
-                                   dentry_ptr );
-    }
-    else
-    {
-        rpc_vfs_fs_add_dentry_client( parent_cxy,
-                                      parent_ptr,
-                                      dentry_ptr,
-                                      &error );
-    }
-    if ( error )
-    {
-        printk("\n[ERROR] in %s : cannot register child in parent directory\n",
-        __FUNCTION__ );
-        return -1;
-    }
-
-#if DEBUG_VFS_NEW_DENTRY_INIT
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VFS_NEW_DENTRY_INIT < cycle )
-printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n",
-__FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
-#endif
-
-    return 0;
-
-}  // end vfs_new_dentry_init()
 
 ///////////////////////////////////////////////////
@@ -2906,7 +2737,4 @@
     xptr_t          dentry_xp;         // extended pointer on dentry (used for . and ..)
     vfs_dentry_t  * dentry_ptr;        // local pointer on dentry (used for . and ..) 
-
-    // xptr_t          parents_root_xp;   // extended pointer on inode "parents" field
-    // xptr_t          parents_entry_xp;  // extended pointer on dentry "parents" field
     xptr_t          children_xhtab_xp; // extended pointer on inode "children" field
     xptr_t          children_entry_xp; // extended pointer on dentry "children" field
@@ -2924,5 +2752,5 @@
 #endif
 
-    // get new directory cluster and local pointer
+    // get child directory cluster and local pointer
     child_cxy  = GET_CXY( child_xp );
     child_ptr  = GET_PTR( child_xp );
@@ -2933,18 +2761,8 @@
 
     //////////////////////////// create <.> dentry //////////////////////
-    if( child_cxy == local_cxy )     
-    {
-        error = vfs_dentry_create( fs_type,
-                                   ".",
-                                   &dentry_xp );
-    }
-    else
-    {
-        rpc_vfs_dentry_create_client( child_cxy,
-                                      fs_type,
-                                      ".",
-                                      &dentry_xp,
-                                      &error );
-    }
+    error = vfs_dentry_create( child_cxy,
+                               fs_type,
+                               ".",
+                               &dentry_xp );
     if( error )
     {
@@ -2967,5 +2785,7 @@
     children_xhtab_xp = XPTR( child_cxy , &child_ptr->children );
     children_entry_xp = XPTR( child_cxy , &dentry_ptr->children );
+
     error = xhtab_insert( children_xhtab_xp , "." , children_entry_xp );
+
     if( error )
     {
@@ -2974,12 +2794,5 @@
         return -1;
     }
-
     
-    // don't register <.> dentry in child_inode xlist of parents 
-    // parents_root_xp  = XPTR( child_cxy , &child_ptr->parents );
-    // parents_entry_xp = XPTR( child_cxy , &dentry_ptr->parents );
-    // xlist_add_first( parents_root_xp , parents_entry_xp );
-    // hal_remote_atomic_add( XPTR( child_cxy , &child_ptr->links ) , 1 );
-
     // update "parent" and "child_xp" fields in <.> dentry
     hal_remote_s64( XPTR( child_cxy , &dentry_ptr->child_xp ) , child_xp );
@@ -2997,16 +2810,6 @@
     if( child_xp != parent_xp )
     {
-        if( child_cxy == local_cxy )
-        { 
-            error = vfs_fs_add_dentry( child_ptr,
-                                       dentry_ptr );
-        }
-        else
-        {
-            rpc_vfs_fs_add_dentry_client( child_cxy,
-                                          child_ptr,
-                                          dentry_ptr,
-                                          &error );
-        }
+        error = vfs_fs_add_dentry( child_xp,
+                                   dentry_ptr );
         if( error )
         {
@@ -3026,18 +2829,8 @@
 
     ///////////////////////////// create <..> dentry ///////////////////////
-    if( child_cxy == local_cxy )     
-    {
-        error = vfs_dentry_create( fs_type,
-                                   "..",
-                                   &dentry_xp );
-    }
-    else
-    {
-        rpc_vfs_dentry_create_client( child_cxy,
-                                      fs_type,
-                                      "..",
-                                      &dentry_xp,
-                                      &error );
-    }
+    error = vfs_dentry_create( child_cxy,
+                               fs_type,
+                               "..",
+                               &dentry_xp );
     if( error )
     {
@@ -3085,16 +2878,6 @@
     if( child_xp != parent_xp )
     {
-        if( child_cxy == local_cxy )
-        { 
-            error = vfs_fs_add_dentry( child_ptr,
-                                       dentry_ptr );
-        }
-        else
-        {
-            rpc_vfs_fs_add_dentry_client( child_cxy,
-                                          child_ptr,
-                                          dentry_ptr,
-                                          &error );
-        }
+        error = vfs_fs_add_dentry( child_xp,
+                                   dentry_ptr );
         if( error )
         {
@@ -3259,5 +3042,5 @@
 
       
-////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////
 error_t vfs_add_child_in_parent( cxy_t              child_cxy,
                                  vfs_fs_type_t      fs_type,
@@ -3296,19 +3079,8 @@
 
     // 1. create dentry in parent cluster
-    if( parent_cxy == local_cxy )           // parent cluster is local
-    {
-        error = vfs_dentry_create( fs_type,
-                                   name,
-                                   &new_dentry_xp );
-    }
-    else                                    // parent cluster is remote
-    {
-        rpc_vfs_dentry_create_client( parent_cxy,
-                                      fs_type,
-                                      name,
-                                      &new_dentry_xp,
-                                      &error );
-    }
-                                      
+    error = vfs_dentry_create( parent_cxy,
+                               fs_type,
+                               name,
+                               &new_dentry_xp );
     if( error )
     {
@@ -3334,25 +3106,11 @@
     uint32_t gid  = 0;
     
-    if( child_cxy == local_cxy )      // child cluster is local 
-    {
-        error = vfs_inode_create( fs_type,
-                                  attr,
-                                  mode,
-                                  uid,
-                                  gid,
-                                  &new_inode_xp );
-    }
-    else                              // child cluster is remote
-    {
-        rpc_vfs_inode_create_client( child_cxy,
-                                     fs_type,
-                                     attr,
-                                     mode,
-                                     uid,
-                                     gid,
-                                     &new_inode_xp,
-                                     &error );
-    }
-                                     
+    error = vfs_inode_create( child_cxy,
+                              fs_type,
+                              attr,
+                              mode,
+                              uid,
+                              gid,
+                              &new_inode_xp );
     if( error )
     {
@@ -3360,6 +3118,5 @@
                __FUNCTION__ , child_cxy );
  
-        if( parent_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
-        else rpc_vfs_dentry_destroy_client( parent_cxy , new_dentry_ptr );
+        vfs_dentry_destroy( new_dentry_xp );
         return -1;
     }
@@ -3374,5 +3131,4 @@
 #endif
 
-
     // 3. register new_dentry in new_inode xlist of parents 
     parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents );
@@ -3457,26 +3213,8 @@
 
     // delete dentry descriptor
-    if( parent_cxy == local_cxy )
-    {
-         vfs_dentry_destroy( dentry_ptr );
-    }
-    else
-    {
-         rpc_vfs_dentry_destroy_client( parent_cxy,
-                                        dentry_ptr );
-    }
+    vfs_dentry_destroy( dentry_xp );
 
     // delete child_inode descriptor if last link
-    if( links == 1 )
-    {
-        if( child_cxy == local_cxy )
-        {
-            vfs_inode_destroy( child_inode_ptr );
-        }
-        else
-        {
-            rpc_vfs_inode_destroy_client( child_cxy , child_inode_ptr );
-        }
-    }
+    if( links == 1 )  vfs_inode_destroy( child_inode_xp );
 
 }  // end vfs_remove_child_from_parent()
@@ -3489,35 +3227,36 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-//////////////////////////////////////////////
-error_t vfs_fs_move_page( xptr_t      page_xp,
-                          cmd_type_t  cmd_type )
+///////////////////////////////////////////////////
+error_t vfs_fs_add_dentry( xptr_t         inode_xp,
+                           vfs_dentry_t * dentry_ptr )
 {
     error_t error = 0;
 
-assert( (page_xp != XPTR_NULL) , "page pointer is NULL" );
-
-    page_t * page_ptr = GET_PTR( page_xp );
-    cxy_t    page_cxy = GET_CXY( page_xp );
-
-    // get local pointer on page mapper
-    mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
-
-assert( (mapper != NULL) , "no mapper for page" );
+assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
+assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
+
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get inode mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+assert( (mapper != NULL) , "mapper pointer is NULL")        
 
     // get FS type
-    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->type ) );
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
     if( fs_type == FS_TYPE_FATFS )
     {
-        error = fatfs_move_page( page_xp , cmd_type ); 
+        error = fatfs_add_dentry( inode_xp , dentry_ptr ); 
     }
     else if( fs_type == FS_TYPE_RAMFS )
     {
-        assert( false , "should not be called for RAMFS\n" );
+        error = 0;     // does nothing for RAMFS
     }
     else if( fs_type == FS_TYPE_DEVFS )
     {
-        assert( false , "should not be called for DEVFS\n" );
+        error = 0;     // does nothing for DEVFS
     }
     else
@@ -3528,26 +3267,31 @@
     return error;
 
-}  // end vfs_fs_move_page()
-
-////////////////////////////////////////////////
-error_t vfs_fs_add_dentry( vfs_inode_t  * inode,
-                           vfs_dentry_t * dentry )
+}  // end vfs_fs_add_dentry()
+
+//////////////////////////////////////////////////////
+error_t vfs_fs_remove_dentry( xptr_t         inode_xp,
+                              vfs_dentry_t * dentry_ptr )
 {
     error_t error = 0;
 
-assert( (inode  != NULL) , "inode  pointer is NULL" );
-assert( (dentry != NULL) , "dentry pointer is NULL" );
-
-    mapper_t * mapper = inode->mapper;
-
-assert( (mapper != NULL) , "mapper pointer is NULL" );
+assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
+assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
+
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get inode mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+assert( (mapper != NULL) , "mapper pointer is NULL")        
 
     // get FS type
-    vfs_fs_type_t fs_type = mapper->type;
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
     if( fs_type == FS_TYPE_FATFS )
     {
-        error = fatfs_add_dentry( inode , dentry ); 
+        error = fatfs_remove_dentry( inode_xp , dentry_ptr ); 
+
     }
     else if( fs_type == FS_TYPE_RAMFS )
@@ -3566,34 +3310,38 @@
     return error;
 
-}  // end vfs_fs_add_dentry()
-
-///////////////////////////////////////////////////
-error_t vfs_fs_remove_dentry( vfs_inode_t  * inode,
-                              vfs_dentry_t * dentry )
+}  // end vfs_fs_remove_dentry()
+
+///////////////////////////////////////////////////////////////
+error_t vfs_fs_new_dentry_from_mapper( xptr_t         inode_xp,
+                                       vfs_dentry_t * dentry_ptr )
 {
     error_t error = 0;
 
-assert( (inode  != NULL) , "inode  pointer is NULL" );
-assert( (dentry != NULL) , "dentry pointer is NULL" );
-
-    mapper_t * mapper = inode->mapper;
-
-assert( (mapper != NULL) , "mapper pointer is NULL" );
+assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
+assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
+
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get inode mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+assert( (mapper != NULL) , "mapper pointer is NULL")        
 
     // get FS type
-    vfs_fs_type_t fs_type = mapper->type;
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
     if( fs_type == FS_TYPE_FATFS )
     {
-        error = fatfs_remove_dentry( inode , dentry ); 
+        error = fatfs_new_dentry_from_mapper( inode_xp , dentry_ptr );
     }
     else if( fs_type == FS_TYPE_RAMFS )
     {
-        error = 0;     // does nothing for RAMFS
+        assert( false , "should not be called for RAMFS" );
     }
     else if( fs_type == FS_TYPE_DEVFS )
     {
-        error = 0;     // does nothing for DEVFS
+        assert( false , "should not be called for DEVFS" );
     }
     else
@@ -3604,24 +3352,30 @@
     return error;
 
-}  // end vfs_fs_remove_dentry()
-
-////////////////////////////////////////////////
-error_t vfs_fs_new_dentry( vfs_inode_t * parent,
-                           char        * name,
-                           xptr_t        child_xp )
+} // end vfs_fs_new_dentry_from_mapper()
+
+///////////////////////////////////////////////////////////////
+error_t vfs_fs_new_dentry_to_mapper( xptr_t         inode_xp,
+                                     vfs_dentry_t * dentry_ptr )
 {
     error_t error = 0;
 
-// check arguments
-assert( (parent != NULL) , "parent pointer is NULL");
-assert( (child_xp != XPTR_NULL) , "child pointer is NULL");
-
-    // get parent inode FS type
-    vfs_fs_type_t fs_type = parent->ctx->type;
+assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
+assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
+
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get inode mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+assert( (mapper != NULL) , "mapper pointer is NULL")        
+
+    // get FS type
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
     if( fs_type == FS_TYPE_FATFS )
     {
-        error = fatfs_new_dentry( parent , name , child_xp );
+        error = fatfs_new_dentry_to_mapper( inode_xp , dentry_ptr );
     }
     else if( fs_type == FS_TYPE_RAMFS )
@@ -3640,24 +3394,30 @@
     return error;
 
-} // end vfs_fs_new_dentry()
-
-///////////////////////////////////////////////////
-error_t vfs_fs_update_dentry( vfs_inode_t  * inode,
-                              vfs_dentry_t * dentry,
-                              uint32_t       size )
+} // end vfs_fs_new_dentry_to_mapper()
+
+//////////////////////////////////////////////////////
+error_t vfs_fs_update_dentry( xptr_t         inode_xp,
+                              vfs_dentry_t * dentry_ptr )
 {
     error_t error = 0;
 
-// check arguments
-assert( (inode  != NULL) , "inode  pointer is NULL");
-assert( (dentry != NULL) , "dentry pointer is NULL");
-
-    // get parent inode FS type
-    vfs_fs_type_t fs_type = inode->ctx->type;
+assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
+assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
+
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get inode mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+assert( (mapper != NULL) , "mapper pointer is NULL")        
+
+    // get FS type
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
     if( fs_type == FS_TYPE_FATFS )
     {
-        error = fatfs_update_dentry( inode , dentry , size );
+        error = fatfs_update_dentry( inode_xp , dentry_ptr );
     }
     else if( fs_type == FS_TYPE_RAMFS )
@@ -3739,19 +3499,26 @@
 }  // end vfs_fs_get_user_dir()
  
-////////////////////////////////////////////////
-error_t vfs_fs_sync_inode( vfs_inode_t * inode )
+/////////////////////////////////////////////
+error_t vfs_fs_sync_inode( xptr_t  inode_xp )
 {
     error_t error = 0;
 
-// check arguments
-assert( (inode != NULL) , "inode pointer is NULL");
-
-    // get inode FS type
-    vfs_fs_type_t fs_type = inode->ctx->type;
+assert( (inode_xp != XPTR_NULL) , "inode_xp argument is NULL");
+
+    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
+    cxy_t         inode_cxy = GET_CXY( inode_xp );
+
+    // get inode mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
+
+assert( (mapper != NULL) , "mapper pointer is NULL")        
+
+    // get FS type
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
     if( fs_type == FS_TYPE_FATFS )
     {
-        error = fatfs_sync_inode( inode );
+        error = fatfs_sync_inode( inode_xp );
     }
     else if( fs_type == FS_TYPE_RAMFS )
@@ -3799,59 +3566,4 @@
 }  // end vfs_fs_sync_fat()
 
-//////////////////////////////////////////////////////
-error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type )
-{
-    error_t error = 0;
-
-    // call relevant FS function
-    if( fs_type == FS_TYPE_FATFS )
-    {
-        error = fatfs_sync_free_info();
-    }
-    else if( fs_type == FS_TYPE_RAMFS )
-    {
-        assert( false , "should not be called for RAMFS" );
-    }
-    else if( fs_type == FS_TYPE_DEVFS )
-    {
-        assert( false , "should not be called for DEVFS" );
-    }
-    else
-    {
-        assert( false , "undefined file system type" );
-    }
-
-    return error;
-
-}  // end vfs_fs_sync_fat()
-
-/////////////////////////////////////////////////
-error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
-                              uint32_t * cluster )
-{
-    error_t error = 0;
-
-    // call relevant FS function
-    if( fs_type == FS_TYPE_FATFS )
-    {
-        error = fatfs_cluster_alloc( cluster );
-    }
-    else if( fs_type == FS_TYPE_RAMFS )
-    {
-        assert( false , "should not be called for RAMFS" );
-    }
-    else if( fs_type == FS_TYPE_DEVFS )
-    {
-        assert( false , "should not be called for DEVFS" );
-    }
-    else
-    {
-        assert( false , "undefined file system type" );
-    }
-
-    return error;
-
-} // end vfs_fs_cluster_alloc()
-
 ////////////////////////////////////////////////
 error_t vfs_fs_release_inode( xptr_t  inode_xp )
@@ -3859,10 +3571,10 @@
     error_t error = 0;
 
-assert( (inode_xp  != XPTR_NULL) , "inode pointer is NULL")        
+assert( (inode_xp  != XPTR_NULL) , "inode_xp argument is NULL")        
 
     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
     cxy_t         inode_cxy = GET_CXY( inode_xp );
 
-    // get local pointer on page mapper 
+    // get local pointer on mapper 
     mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
 
@@ -3870,5 +3582,5 @@
 
     // get FS type from mapper
-    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->type ) );
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
 
     // call relevant FS function
@@ -3894,3 +3606,44 @@
 }  // end vfs_fs_release_inode()
 
-
+//////////////////////////////////////////////////
+error_t vfs_fs_move_page( xptr_t          page_xp,
+                          ioc_cmd_type_t  cmd_type )
+{
+    error_t error = 0;
+
+assert( (page_xp != XPTR_NULL) , "page pointer is NULL" );
+
+    page_t * page_ptr = GET_PTR( page_xp );
+    cxy_t    page_cxy = GET_CXY( page_xp );
+
+    // get local pointer on  mapper
+    mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
+
+assert( (mapper != NULL) , "no mapper for page" );
+
+    // get FS type
+    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->fs_type ) );
+
+    // call relevant FS function
+    if( fs_type == FS_TYPE_FATFS )
+    {
+        error = fatfs_move_page( page_xp , cmd_type ); 
+    }
+    else if( fs_type == FS_TYPE_RAMFS )
+    {
+        assert( false , "should not be called for RAMFS\n" );
+    }
+    else if( fs_type == FS_TYPE_DEVFS )
+    {
+        assert( false , "should not be called for DEVFS\n" );
+    }
+    else
+    {
+        assert( false , "undefined file system type" );
+    }
+
+    return error;
+
+}  // end vfs_fs_move_page()
+
+
