Index: trunk/kernel/vfs/vfs.c
===================================================================
--- trunk/kernel/vfs/vfs.c	(revision 14)
+++ trunk/kernel/vfs/vfs.c	(revision 23)
@@ -35,4 +35,5 @@
 #include <slist.h>
 #include <xhtab.h>
+#include <rpc.h>
 #include <errno.h>
 #include <kmem.h>
@@ -40,7 +41,9 @@
 #include <thread.h>
 #include <process.h>
+#include <vfs.h>
 #include <fatfs.h>
 #include <ramfs.h>
-#include <vfs.h>
+#include <devfs.h>
+#include <syscalls.h>
 
 
@@ -49,5 +52,5 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-// array of supported FS contexts (indexed by the FS type)
+// array of supported FS contexts 
 vfs_ctx_t   fs_context[FS_TYPES_NR];
 
@@ -56,5 +59,5 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-/////////////////////////////////////////////////
+////////////////////////////////////////////
 error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx,
                             uint32_t  * inum )
@@ -64,5 +67,5 @@
 
     // get lid from local inum allocator
-    uint32_t lid = bitmap_ffc( ctx->inum , CONFIG_VFS_MAX_INODES );
+    uint32_t lid = bitmap_ffc( ctx->bitmap , CONFIG_VFS_MAX_INODES );
 
     if( lid == -1 )   // no more free slot => error
@@ -77,5 +80,5 @@
     {
         // set slot allocated
-        bitmap_set( ctx->inum , lid );
+        bitmap_set( ctx->bitmap , lid );
 
         // release lock
@@ -92,5 +95,5 @@
                            uint32_t    inum )
 {
-    bitmap_clear( ctx->inum , inum & 0xFFFF ); 
+    bitmap_clear( ctx->bitmap , inum & 0xFFFF ); 
 }
 
@@ -99,12 +102,14 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////////////
-error_t vfs_inode_create( xptr_t      dentry_xp,
-                          uint32_t    type,
-                          uint32_t    attr,
-                          uint32_t    mode,
-                          uid_t       uid,
-                          gid_t       gid,
-                          xptr_t    * inode_xp )
+//////////////////////////////////////////////////////
+
+error_t vfs_inode_create( xptr_t            dentry_xp,
+                          vfs_fs_type_t     fs_type,
+                          vfs_inode_type_t  inode_type,
+                          uint32_t          attr,
+                          uint32_t          rights,
+                          uid_t             uid,
+                          gid_t             gid,
+                          xptr_t          * inode_xp )
 {
     mapper_t         * mapper;     // associated mapper( to be allocated)
@@ -115,7 +120,8 @@
     error_t            error;
 
-    // check type and get pointer on context
-    if     ( type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
-    else if( type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
+    // check fs type and get pointer on context
+    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
+    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
+    else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS];
     else
     {
@@ -144,5 +150,5 @@
     }
 
-    // allocate memory for inode descriptor
+    // allocate memory for VFS inode descriptor
 	req.type  = KMEM_VFS_INODE;
 	req.size  = sizeof(vfs_inode_t);
@@ -160,7 +166,8 @@
     // initialize inode descriptor
     inode->gc         = 0;
+    inode->type       = inode_type;
     inode->inum       = inum;
     inode->attr       = attr;
-    inode->mode       = mode;
+    inode->rights     = rights;
     inode->uid        = uid;
     inode->gid        = gid;
@@ -174,13 +181,9 @@
 
     // initialize dentries hash table, if new inode is a directory
-    if( attr & INODE_ATTR_DIR )  xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
+    if( inode_type == INODE_TYPE_DIR ) xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
 
     // initialize inode locks 
     remote_rwlock_init( XPTR( local_cxy , &inode->data_lock ) );
     remote_spinlock_init( XPTR( local_cxy , &inode->main_lock ) );
-
-    // create FS specific inode
-    if     ( ctx->type == FS_TYPE_FATFS )  fatfs_inode_create( inode );
-    else if( ctx->type == FS_TYPE_RAMFS )  ramfs_inode_create( inode );
 
     // return extended pointer on inode
@@ -284,19 +287,20 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-//////////////////////////////////////////////
-error_t vfs_dentry_create( uint32_t      type,
-                           char        * name,
-                           vfs_inode_t * parent,
-                           xptr_t      * dentry_xp )
+///////////////////////////////////////////////////
+error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
+                           char          * name,
+                           vfs_inode_t   * parent,
+                           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
-    xptr_t           xhtab_xp;   // extended pointer on xhtab_t embedded in inode
-    xptr_t           xlist_xp;   // extended pointer on xlist_entry_t in dentry
+
+printk("\n            @@@ dentry_create : 0 / name = %s\n", name );
 
     // check type and get pointer on context
-    if     ( type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
-    else if( type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
+    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
+    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
+    else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS];
     else
     {
@@ -309,9 +313,11 @@
     uint32_t length = strlen( name );
 
-    if( length > (CONFIG_VFS_MAX_NAME_LENGTH - 1) )
+    if( length >= CONFIG_VFS_MAX_NAME_LENGTH )
     {
         printk("\n[ERROR] in %s : name too long\n", __FUNCTION__ );
         return EINVAL;
     }
+
+printk("\n            @@@ dentry_create : 1 / name = %s\n", name );
 
     // allocate memory for dentry descriptor
@@ -328,4 +334,5 @@
 
     // initialize dentry descriptor
+
     dentry->ctx     = ctx;
     dentry->length  = length;
@@ -333,12 +340,16 @@
     strcpy( dentry->name , name );
 
-    // return extended pointer on dentry to caller
+printk("\n            @@@ dentry_create : 2 / name = %s\n", name );
+
+    // register dentry in hash table rooted in parent inode
+    xhtab_insert( XPTR( local_cxy , &parent->children ),
+                  name, 
+                  XPTR( local_cxy , &dentry->xlist ) );
+
+printk("\n            @@@ dentry_create : 3 / name = %s\n", name );
+
+    // return extended pointer on dentry 
     *dentry_xp = XPTR( local_cxy , dentry );
 
-    // register dentry in hash table rooted in parent inode
-    xhtab_xp    = XPTR( local_cxy , &parent->children );
-    xlist_xp    = XPTR( local_cxy , &dentry->xlist );
-    xhtab_register( xhtab_xp  , name , xlist_xp );
-    
     return 0;
 
@@ -365,45 +376,11 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////
-void vfs_file_count_up( xptr_t file_xp )
-{
-    // get file cluster and local pointer
-    cxy_t        file_cxy = GET_CXY( file_xp );
-    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 
-
-    // atomically increment count
-    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 
-}
-
-//////////////////////////////////////////
-void vfs_file_count_down( xptr_t file_xp )
-{
-    // get file cluster and local pointer
-    cxy_t        file_cxy = GET_CXY( file_xp );
-    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 
-
-    // atomically decrement count
-    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 
-}
-
-////////////////////////////////////////////////
-error_t vfs_file_create( xptr_t        inode_xp,
-                         uint32_t      type,
+/////////////////////////////////////////////
+error_t vfs_file_create( vfs_inode_t * inode,
                          uint32_t      attr,
-                         xptr_t      * file_xp )  
-{
-    vfs_file_t  * file_ptr;
+                         xptr_t      * file_xp )
+{
+    vfs_file_t  * file;
 	kmem_req_t    req;
-
-    // get inode cluster and local pointer
-    cxy_t         inode_cxy = GET_CXY( inode_xp );
-    vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
-
-    // check cluster identifier
-    if( inode_cxy != local_cxy )
-    {
-        printk("\n[PANIC] in %s : local cluster is not the inode owner\n", __FUNCTION__ );
-        hal_core_sleep();
-    }
 
     // allocate memory for new file descriptor
@@ -411,39 +388,29 @@
 	req.size  = sizeof(vfs_file_t);
     req.flags = AF_KERNEL | AF_ZERO;
-	file_ptr  = (vfs_file_t *)kmem_alloc( &req );
-
-    if( file_ptr == NULL ) return ENOMEM;
-
-    // get inode local pointer
+	file      = (vfs_file_t *)kmem_alloc( &req );
+
+    if( file == NULL ) return ENOMEM;
+
     // initializes new file descriptor
-    file_ptr->gc       = 0;
-    file_ptr->type     = type;
-    file_ptr->attr     = attr;
-    file_ptr->offset   = 0;
-    file_ptr->refcount = 0;
-    file_ptr->inode    = inode_ptr;
-    file_ptr->ctx      = inode_ptr->ctx;
-    file_ptr->mapper   = inode_ptr->mapper;
-
-    remote_rwlock_init( XPTR( local_cxy , &file_ptr->lock ) );
-
-    *file_xp = XPTR( local_cxy , file_ptr );
-    return 0;
-}
-
-////////////////////////////////////////
-void vfs_file_destroy( xptr_t  file_xp )
-{
-    // get file cluster and local pointer
-    cxy_t        file_cxy = GET_CXY( file_xp );
-    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp );
-
-    if( file_cxy != local_cxy )
-    {
-        printk("\n[PANIC] in %s : file descriptor not in local cluster\n", __FUNCTION__ );
-        hal_core_sleep(); 
-    }
-
-    if( file_ptr->refcount )
+    file->gc       = 0;
+    file->type     = inode->type;
+    file->attr     = attr;
+    file->offset   = 0;
+    file->refcount = 0;
+    file->inode    = inode;
+    file->ctx      = inode->ctx;
+    file->mapper   = inode->mapper;
+
+    remote_rwlock_init( XPTR( local_cxy , &file->lock ) );
+
+    *file_xp = XPTR( local_cxy , file );
+    return 0;
+
+}  // end vfs_file_create()
+
+///////////////////////////////////////////
+void vfs_file_destroy( vfs_file_t *  file )
+{
+    if( file->refcount )
     {
         printk("\n[PANIC] in %s : file refcount non zero\n", __FUNCTION__ );
@@ -452,11 +419,35 @@
 
 	kmem_req_t req;
-	req.ptr   = file_ptr;
+	req.ptr   = file;
 	req.type  = KMEM_VFS_FILE;
 	kmem_free( &req );
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//           File related functions
+
+}  // end vfs_file_destroy() 
+
+
+////////////////////////////////////////
+void vfs_file_count_up( xptr_t file_xp )
+{
+    // get file cluster and local pointer
+    cxy_t        file_cxy = GET_CXY( file_xp );
+    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 
+
+    // atomically increment count
+    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 
+}
+
+//////////////////////////////////////////
+void vfs_file_count_down( xptr_t file_xp )
+{
+    // get file cluster and local pointer
+    cxy_t        file_cxy = GET_CXY( file_xp );
+    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 
+
+    // atomically decrement count
+    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//           File access related functions
 //////////////////////////////////////////////////////////////////////////////////////////
 
@@ -465,24 +456,132 @@
 		          char     * path,
 		          uint32_t   flags,
-		          xptr_t   * file_xp )
-{
-    return 0;
-}
-
-///////////////////////////////////
-uint32_t vfs_read( xptr_t   file_xp, 
-                   void   * buffer,
-                   uint32_t size )
-{
-    return 0;
-}
-
-////////////////////////////////////
-uint32_t vfs_write( xptr_t   file_xp,
-                    void   * buffer,
-                    uint32_t size )
-{
-    return 0;
-}
+                  uint32_t   mode, 
+		          xptr_t   * new_file_xp,
+                  uint32_t * new_file_id )
+{
+    error_t       error;
+    xptr_t        inode_xp;     // extended pointer on target inode
+    cxy_t         inode_cxy;    // inode cluster identifier       
+    vfs_inode_t * inode_ptr;    // inode local pointer
+    uint32_t      file_attr;    // file descriptor attributes
+    uint32_t      lookup_mode;  // lookup working mode        
+    xptr_t        file_xp;      // extended pointer on created file descriptor
+    uint32_t      file_id;      // created file descriptor index in reference fd_array
+
+    // compute lookup working mode
+    lookup_mode = VFS_LOOKUP_OPEN;
+    if( (flags & O_DIR    )      )  lookup_mode |= VFS_LOOKUP_DIR;
+    if( (flags & O_CREAT  )      )  lookup_mode |= VFS_LOOKUP_CREATE;
+    if( (flags & O_EXCL   )      )  lookup_mode |= VFS_LOOKUP_EXCL;
+ 
+    // compute attributes for the created file
+    file_attr = 0;
+    if( (flags & O_RDONLY ) == 0 )  file_attr |= FD_ATTR_READ_ENABLE;
+    if( (flags & O_WRONLY ) == 0 )  file_attr |= FD_ATTR_WRITE_ENABLE;
+    if( (flags & O_SYNC   )      )  file_attr |= FD_ATTR_SYNC;
+    if( (flags & O_APPEND )      )  file_attr |= FD_ATTR_APPEND;
+    if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC;
+
+    // get extended pointer on target inode
+    error = vfs_lookup( cwd_xp , path , lookup_mode , &inode_xp );
+
+    if( error ) return error;
+
+    // get target inode cluster and local pointer
+    inode_cxy = GET_CXY( inode_xp );
+    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
+    
+    // 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 );
+    }
+
+    if( error )  return error;
+
+    // allocate and register a new file descriptor index in reference cluster fd_array
+    error = process_fd_register( file_xp , &file_id );
+
+    if( error ) return error;
+
+    // success
+    *new_file_xp = file_xp;
+    *new_file_id = file_id;
+    return 0;
+
+}  // end vfs_open()
+
+/////////////////////////////////////
+error_t vfs_move( bool_t   to_buffer,
+                  xptr_t   file_xp,
+                  void   * buffer,
+                  uint32_t size )
+{
+    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
+
+    cxy_t              file_cxy;     // remote file descriptor cluster 
+    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
+    vfs_inode_type_t   inode_type;
+    uint32_t           file_offset;  // current offset in file
+    mapper_t         * mapper;
+    error_t            error;
+
+    // get cluster and local pointer on remote file descriptor
+    file_cxy  = GET_CXY( file_xp );
+    file_ptr  = (vfs_file_t *)GET_PTR( file_xp );
+
+    // get inode type from remote file descriptor
+    inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type   ) );
+   
+    // action depends on inode type
+    if( inode_type == INODE_TYPE_FILE )
+    {
+        // get mapper pointer and file offset from file descriptor
+        file_offset = hal_remote_lw( XPTR( file_cxy , &file_ptr->offset ) );
+        mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
+
+        // move data between mapper and buffer
+        if( file_cxy == local_cxy )
+        {
+            error = mapper_move( mapper,
+                                 to_buffer,
+                                 file_offset,
+                                 buffer,
+                                 size );
+        }
+        else
+        {
+            rpc_mapper_move_client( file_cxy,
+                                    mapper,
+                                    to_buffer,
+                                    file_offset,
+                                    buffer,
+                                    size,
+                                    &error );
+        } 
+
+        return error;
+    }
+    else if (inode_type == INODE_TYPE_DIR )
+    {
+        printk("\n[ERROR] in %s : inode is a directory", __FUNCTION__ );
+        return EINVAL;
+    }
+    else if (inode_type == INODE_TYPE_DEV )
+    {
+        // TODO
+        return 0;
+    }
+    else
+    {
+        printk("\n[PANIC] in %s : illegal inode type\n", __FUNCTION__ );
+        hal_core_sleep();
+        return -1;
+    }
+}  // end vfs_access()
 
 //////////////////////////////////////
@@ -492,13 +591,73 @@
                    uint32_t * new_offset )
 {
-    return 0;
-}
-
-//////////////////////////////////////
-error_t vfs_close( xptr_t     file_xp, 
-                   uint32_t * refcount )
-{
-    return 0;
-}
+    printk("\n[PANIC] %s non implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+
+    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
+
+}  // vfs_lseek()
+
+///////////////////////////////////
+error_t vfs_close( xptr_t   file_xp,
+                   uint32_t file_id )
+{
+    assert( (file_xp != XPTR_NULL) , __FUNCTION__ , "file_xp == XPTR_NULL" );
+
+    assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , __FUNCTION__ , "illegal file_id" );
+
+    thread_t  * this    = CURRENT_THREAD;
+    process_t * process = this->process;
+
+    // get cluster and local pointer on remote file descriptor
+    cxy_t        file_cxy = GET_CXY( file_xp );
+    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp );
+
+    // get local pointer on local cluster manager
+    cluster_t * cluster = LOCAL_CLUSTER;
+
+    // get owner process cluster and lpid
+    cxy_t   owner_cxy  = CXY_FROM_PID( process->pid );
+    lpid_t  lpid       = LPID_FROM_PID( process->pid );
+
+    // get extended pointers on copies root and lock
+    xptr_t root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
+    xptr_t lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
+
+    // take the lock protecting the copies
+    remote_spinlock_lock( lock_xp );
+
+    // 1) loop on the process descriptor copies to cancel all fd_array[file_id] entries
+    xptr_t  iter_xp;
+    XLIST_FOREACH( root_xp , iter_xp )
+    {
+        xptr_t      process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
+        cxy_t       process_cxy = GET_CXY( process_xp );
+        process_t * process_ptr = (process_t *)GET_PTR( process_xp );
+
+        xptr_t lock_xp  = XPTR( process_cxy , &process_ptr->fd_array.lock );
+        xptr_t entry_xp = XPTR( process_cxy , &process_ptr->fd_array.array[file_id] );
+
+        // lock is required for atomic write of a 64 bits word
+        remote_rwlock_wr_lock( lock_xp );
+        hal_remote_swd( entry_xp , XPTR_NULL );
+        remote_rwlock_wr_unlock( lock_xp );
+
+        hal_wbflush();
+    }    
+
+    // 2) 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 );
+    }
+
+    return 0;
+
+}  // end vfs_close()
 
 ////////////////////////////////////
@@ -506,28 +665,134 @@
                     char   * path )
 {
+    printk("\n[PANIC] %s non implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+}  // vfs_unlink()
+
+///////////////////////////////////////
+error_t vfs_stat( xptr_t       file_xp,
+                  vfs_stat_t * k_stat )
+{
+    printk("\n[PANIC] %s non implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+}
+
+////////////////////////////////////////////
+error_t vfs_readdir( xptr_t         file_xp,
+                     vfs_dirent_t * k_dirent )
+{
+    printk("\n[PANIC] %s non implemented\n", __FUNCTION__ );
+    hal_core_sleep();
     return 0;
 }
 
 //////////////////////////////////////
-error_t vfs_stat( xptr_t       file_xp,
-                  vfs_stat_t * stat )
-{
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//           Directory related functions
-//////////////////////////////////////////////////////////////////////////////////////////
-
-
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
+error_t vfs_mkdir( xptr_t     file_xp,
+                   char     * path,
+                   uint32_t   mode )
+{
+    printk("\n[PANIC] %s non implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+}
+
+////////////////////////////////////
+error_t vfs_rmdir( xptr_t   file_xp,
+                   char   * path )
+{
+    printk("\n[PANIC] %s non implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+}
+
+///////////////////////////////////
+error_t vfs_chdir( xptr_t   cwd_xp,
+                   char   * path )
+{
+    error_t           error;
+    xptr_t            inode_xp;     // extended pointer on target inode
+    cxy_t             inode_cxy;    // target inode cluster identifier       
+    vfs_inode_t     * inode_ptr;    // target inode local pointer
+    uint32_t          mode;         // lookup working mode        
+    vfs_inode_type_t  inode_type;   // target inode type
+
+    // set lookup working mode
+    mode = 0;
+
+    // get extended pointer on target inode
+    error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
+
+    if( error ) return error;
+
+    // get inode cluster and local pointer
+    inode_cxy = GET_CXY( inode_xp );
+    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
+
+    // get inode type from remote file
+    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
+
+    if( inode_type != INODE_TYPE_DIR )
+    {
+        CURRENT_THREAD->errno = ENOTDIR;
+        return -1;
+    }
+
+    printk("\n[PANIC] %s non fully implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+}
+
+///////////////////////////////////
+error_t vfs_chmod( xptr_t   cwd_xp,
+                   char   * path,
+                   uint32_t rights )
+{
+    error_t           error;
+    xptr_t            inode_xp;     // extended pointer on target inode
+    cxy_t             inode_cxy;    // inode cluster identifier       
+    vfs_inode_t     * inode_ptr;    // inode local pointer
+    uint32_t          mode;         // lookup working mode
+    vfs_inode_type_t  inode_type;   // target inode type
+
+    // set lookup working mode
+    mode = 0;
+ 
+    // get extended pointer on target inode
+    error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
+
+    if( error ) return error;
+
+    // get inode cluster and local pointer
+    inode_cxy = GET_CXY( inode_xp );
+    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
+    
+    // get inode type from remote inode
+    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
+
+    
+    printk("\n[PANIC] %s non fully implemented\n", __FUNCTION__ );
+    hal_core_sleep();
+    return 0;
+}
+
+///////////////////////////////////
+error_t vfs_mkfifo( xptr_t   cwd_xp,
+                    char   * path,
+                    uint32_t rights )
+{
+    printk("\n[PANIC] in %s : not implemented yet\n", __FUNCTION__ );
+    hal_core_sleep(); 
+    return 0;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////r
 //            Inode Tree functions
 //////////////////////////////////////////////////////////////////////////////////////////
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This static function is used by the vfs_lookup() function.
+// This function is used by the vfs_lookup() function.
 // It takes an extended pointer on a remote inode (parent directory inode),
 // and check access_rights violation for the calling thread.
@@ -641,29 +906,28 @@
 }
 
-////////////////////////////////////////
-error_t vfs_lookup( xptr_t       cwd_xp,
-                    char       * pathname,
-                    uint32_t     client_uid,
-                    uint32_t     client_gid,
-					xptr_t     * inode_xp,
-                    xptr_t     * ctx_xp )
+//////////////////////////////////////////////
+error_t vfs_lookup( xptr_t             cwd_xp,
+                    char             * pathname,
+                    uint32_t           mode,
+					xptr_t           * inode_xp )
 {
     char          name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path 
 
-    xptr_t        parent_xp;    // extended pointer on parent inode
-    cxy_t         parent_cxy;   // cluster for parentc inode
-    vfs_inode_t * parent_ptr;   // local pointer on parent inode  
-    xptr_t        child_xp;     // extended pointer on child inode
-    cxy_t         child_cxy;    // cluster for child inode
-    vfs_inode_t * child_ptr;    // local pointer on child inode  
-    char        * current;      // current pointer on path
-    char        * next;         // next value for current pointer   
-    bool_t        last;         // true when the name is the last in path
-    bool_t        found;        // true when a child has been found
-    thread_t    * this;         // pointer on calling thread descriptor
-    process_t   * process;      // pointer on calling process descriptor
-    vfs_ctx_t   * ctx;          // parent inode context
-    uint32_t      type;         // file system type of parent inode
-    error_t       error;
+    xptr_t             parent_xp;    // extended pointer on parent inode
+    cxy_t              parent_cxy;   // cluster for parent inode
+    vfs_inode_t      * parent_ptr;   // local pointer on parent inode  
+    xptr_t             child_xp;     // extended pointer on child inode
+    cxy_t              child_cxy;    // cluster for child inode
+    vfs_inode_t      * child_ptr;    // local pointer on child inode  
+    vfs_inode_type_t   inode_type;   // child inode type
+    vfs_fs_type_t      fs_type;      // File system type
+    vfs_ctx_t        * ctx_ptr;      // local pointer on FS context
+    char             * current;      // current pointer on path
+    char             * next;         // next value for current pointer   
+    bool_t             last;         // true when the name is the last in path
+    bool_t             found;        // true when a child has been found
+    thread_t         * this;         // pointer on calling thread descriptor
+    process_t        * process;      // pointer on calling process descriptor
+    error_t            error;
 
     this    = CURRENT_THREAD;
@@ -687,13 +951,5 @@
     do
     {
-        // get cluster and local pointer for parent inode
-        parent_cxy = GET_CXY( parent_xp );
-        parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
-        
-        // get parent inode FS type
-        ctx = (vfs_ctx_t *)(intptr_t)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
-        type = ctx->type;
-
-        // get one name from path
+        // get one name from path and the last flag
         vfs_get_name_from_path( current , name , &next , &last );
 
@@ -708,6 +964,22 @@
             vfs_inode_remote_unlock( parent_xp );
 
-            // insert a new dentry/inode in parent inode
-            error = vfs_add_child_in_parent( type , parent_xp , name , &child_xp );
+            // get cluster and local pointer on parent inode
+            parent_cxy = GET_CXY( parent_xp );
+            parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
+
+            // get parent inode FS type
+            ctx_ptr = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
+            fs_type = ctx_ptr->type;
+
+            // get child inode type
+            if( (last == false) || (mode & VFS_LOOKUP_DIR) ) inode_type = INODE_TYPE_DIR;
+            else                                             inode_type = INODE_TYPE_FILE;
+
+            // insert a child dentry/inode in parent inode
+            error = vfs_add_child_in_parent( inode_type,
+                                             fs_type, 
+                                             parent_xp, 
+                                             name, 
+                                             &child_xp );
 
             if( error )
@@ -723,12 +995,12 @@
 
         // check access rights
-        error = vfs_access_denied( child_xp,
-                                   client_uid,
-                                   client_gid );
-        if( error ) 
-        {
-            printk("\n[ERROR] in %s : permission denied for %s\n", __FUNCTION__ , name );
-            return EACCES;
-        }
+        // error = vfs_access_denied( child_xp,
+        //                            client_uid,
+        //                            client_gid );
+        // if( error ) 
+        // {
+        //     printk("\n[ERROR] in %s : permission denied for %s\n", __FUNCTION__ , name );
+        //     return EACCES;
+        // }
 
         // take lock on child inode if not last
@@ -753,5 +1025,4 @@
     // return searched pointers
     *inode_xp = child_xp;
-    *ctx_xp   = (xptr_t)hal_remote_lwd( XPTR( child_cxy , &child_ptr->ctx ) );
 
     return 0;
@@ -770,5 +1041,5 @@
 	uint32_t     count;       // number of characters written in buffer
 	uint32_t     index;       // slot index in buffer
-    xptr_t       inode_xp;  // extended pointer on    
+    xptr_t       inode_xp;    // extended pointer on    
 
     // implementation note:
@@ -829,22 +1100,29 @@
 }  // end vfs_get_path()
 
-///////////////////////////////////////////////
-error_t vfs_add_child_in_parent( uint32_t type,
-                                 xptr_t   parent_xp,
-                                 char   * name,   
-                                 xptr_t * child_xp )
-{
-    xptr_t     dentry_xp;  // extended pointer on created dentry
-    xptr_t     inode_xp;   // extended pointer on created inode
-    error_t    error;
+///////////////////////////////////////////////////////////////
+error_t vfs_add_child_in_parent( vfs_inode_type_t   inode_type,
+                                 vfs_fs_type_t      fs_type,
+                                 xptr_t             parent_xp,
+                                 char             * name,
+                                 xptr_t           * child_xp )
+{
+    error_t         error;
+    xptr_t          dentry_xp;   // extended pointer on created dentry
+    xptr_t          inode_xp;    // extended pointer on created inode
+    cxy_t           parent_cxy;  // parent inode cluster identifier
+    vfs_inode_t   * parent_ptr;  // parent inode local pointer
+    vfs_ctx_t     * parent_ctx;  // parent inode context local pointer
 
     // get parent inode cluster and local pointer
-    cxy_t         parent_cxy = GET_CXY( parent_xp );
-    vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
+    parent_cxy = GET_CXY( parent_xp );
+    parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
+
+    // get parent inode context local pointer
+    parent_ctx = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
 
     // create dentry
     if( parent_cxy == local_cxy )      // parent cluster is the local cluster
     {
-        error = vfs_dentry_create( type,
+        error = vfs_dentry_create( fs_type,
                                    name,
                                    parent_ptr,
@@ -854,5 +1132,5 @@
     {
         rpc_vfs_dentry_create_client( parent_cxy,
-                                      type,
+                                      fs_type,
                                       name,
                                       parent_ptr,
@@ -887,5 +1165,6 @@
     {
         error = vfs_inode_create( dentry_xp,
-                                  type,
+                                  fs_type,
+                                  inode_type,
                                   attr,
                                   mode,
@@ -898,5 +1177,6 @@
         rpc_vfs_inode_create_client( child_cxy,
                                      dentry_xp,
-                                     type,
+                                     fs_type,
+                                     inode_type,
                                      attr,
                                      mode,
@@ -925,2 +1205,99 @@
 
 
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//            Mapper related functions
+//////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////
+error_t vfs_move_page_to_mapper( page_t * page )
+{
+    error_t         error = 0;
+
+    assert( (page != NULL) , __FUNCTION__ , "page pointer is NULL\n" );
+
+    mapper_t * mapper = page->mapper;
+
+    assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" );
+
+    // get FS type
+    vfs_fs_type_t fs_type = mapper->inode->ctx->type;
+
+    // update mapper if permitted by file system type
+    if( fs_type == FS_TYPE_FATFS )
+    {
+        // get mapper lock in WRITE_MODE
+        rwlock_wr_lock( &mapper->lock );
+
+        error = fatfs_read_page( page ); 
+
+        // release mapper lock 
+        rwlock_wr_unlock( &mapper->lock );
+    }
+    else if( fs_type == FS_TYPE_RAMFS )
+    {
+        assert( false , __FUNCTION__ , "should not be called for RAMFS\n" );
+    }
+    else if( fs_type == FS_TYPE_DEVFS )
+    {
+        assert( false , __FUNCTION__ , "should not be called for DEVFS\n" );
+    }
+    else
+    {
+        assert( false , __FUNCTION__ , "undefined file system type\n" );
+    }
+
+    return error;
+
+}  // end vfs_move_page_to_mapper()
+
+//////////////////////////////////////////////////
+error_t vfs_move_page_from_mapper( page_t * page )
+{
+    error_t         error = 0;
+
+    assert( (page != NULL) , __FUNCTION__ , "page pointer is NULL\n" );
+
+    mapper_t * mapper = page->mapper;
+
+    assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" );
+
+    // get FS type
+    vfs_fs_type_t  fs_type = mapper->inode->ctx->type;
+
+    // update file system if permitted by file system type
+    if( fs_type == FS_TYPE_FATFS )
+    {
+	    if( page_is_flag( page , PG_DIRTY ) ) 
+	    {
+            // get mapper lock in READ_MODE
+            rwlock_rd_lock( &mapper->lock );
+
+            error = fatfs_write_page( page );
+
+            // release mapper lock from READ_MODE
+            rwlock_rd_unlock( &mapper->lock );
+
+            // clear dirty bit if success
+		    if( error == 0 ) page_undo_dirty( page );
+         }
+    }
+    else if( fs_type == FS_TYPE_RAMFS )
+    {
+        assert( false , __FUNCTION__ , "should not be called for RAMFS\n" );
+    }
+    else if( fs_type == FS_TYPE_DEVFS )
+    {
+        assert( false , __FUNCTION__ , "should not be called for DEVFS\n" );
+    }
+    else
+    {
+        assert( false , __FUNCTION__ , "undefined file system type\n" );
+    }
+	
+    return error;
+
+}  // end vfs_move_page_from_mapper()
+
+
