Changeset 610 for trunk/kernel/fs


Ignore:
Timestamp:
Dec 27, 2018, 7:38:58 PM (5 years ago)
Author:
alain
Message:

Fix several bugs in VFS to support the following
ksh commandis : cp, mv, rm, mkdir, cd, pwd

Location:
trunk/kernel/fs
Files:
5 edited

Legend:

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

    r602 r610  
    9393    xptr_t   unused_xp;   // required by vfs_add_child_in_parent()
    9494
    95     // creates DEVFS "dev" inode in cluster 0
     95    // create DEVFS "dev" inode in cluster 0
    9696    error = vfs_add_child_in_parent( 0,                // cxy
    9797                                     INODE_TYPE_DIR,
     
    102102                                     devfs_dev_inode_xp );
    103103
    104     assert( (error == 0) , "cannot create <dev>\n" );
     104// check success
     105assert( (error == 0) , "cannot create <dev>\n" );
    105106
    106107#if DEBUG_DEVFS_INIT
     
    149150    // create "internal" directory
    150151    snprintf( node_name , 16 , "internal_%x" , local_cxy );
     152
    151153    vfs_add_child_in_parent( local_cxy,
    152154                             INODE_TYPE_DIR,
     
    169171    {
    170172        chdev_ptr = GET_PTR( chdev_xp );
     173        chdev_cxy = GET_CXY( chdev_xp );
     174
     175assert( (chdev_cxy == local_cxy ),
     176"illegal MMC chdev_xp in cluster %x\n", local_cxy );
     177
    171178        vfs_add_child_in_parent( local_cxy,
    172179                                 INODE_TYPE_DEV,
     
    198205        {
    199206            chdev_ptr = GET_PTR( chdev_xp );
     207            chdev_cxy = GET_CXY( chdev_xp );
     208
     209assert( (chdev_cxy == local_cxy ),
     210"illegal DMA[%d] chdev_xp in cluster %x\n", channel, local_cxy );
     211
    200212            vfs_add_child_in_parent( local_cxy,
    201213                                     INODE_TYPE_DEV,
     
    226238        chdev_cxy = GET_CXY( chdev_xp );
    227239        chdev_ptr = GET_PTR( chdev_xp );
     240
    228241        if( chdev_cxy == local_cxy )
    229242        {
     
    256269        chdev_cxy = GET_CXY( chdev_xp );
    257270        chdev_ptr = GET_PTR( chdev_xp );
     271
    258272        if( chdev_cxy == local_cxy )
    259273        {
     
    288302            chdev_cxy = GET_CXY( chdev_xp );
    289303            chdev_ptr = GET_PTR( chdev_xp );
     304
    290305            if( chdev_cxy == local_cxy )
    291306            {
     
    321336            chdev_cxy = GET_CXY( chdev_xp );
    322337            chdev_ptr = GET_PTR( chdev_xp );
     338
    323339            if( chdev_cxy == local_cxy )
    324340            {
     
    354370            chdev_cxy = GET_CXY( chdev_xp );
    355371            chdev_ptr = GET_PTR( chdev_xp );
     372
    356373            if( chdev_cxy == local_cxy )
    357374            {
     
    387404            chdev_cxy = GET_CXY( chdev_xp );
    388405            chdev_ptr = GET_PTR( chdev_xp );
     406
    389407            if( chdev_cxy == local_cxy )
    390408            {
     
    419437        {
    420438            chdev_cxy = GET_CXY( chdev_xp );
    421             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     439            chdev_ptr = GET_PTR( chdev_xp );
     440
    422441            if( chdev_cxy == local_cxy )
    423442            {
     
    447466            chdev_cxy = GET_CXY( chdev_xp );
    448467            chdev_ptr = GET_PTR( chdev_xp );
     468
    449469            if( chdev_cxy == local_cxy )
    450470            {
  • trunk/kernel/fs/fatfs.c

    r602 r610  
    12461246vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    12471247if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1248 printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     1248printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    12491249__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    12501250#endif
     
    12801280    uint32_t  page_id    = dentry_id >> 7;
    12811281    uint32_t  offset     = (dentry_id & 0x7F)<<5;
     1282
     1283#if DEBUG_FATFS_REMOVE_DENTRY & 1
     1284if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     1285printk("\n[%s] dentry_id %x / page_id %x / offset %x\n",
     1286__FUNCTION__, dentry_id, page_id, offset );
     1287#endif
    12821288
    12831289    // get extended pointer on page descriptor from parent directory mapper
     
    13451351cycle = (uint32_t)hal_get_cycles();
    13461352if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1347 printk("\n[%s]  thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
     1353printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
    13481354__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    13491355#endif
     
    13581364                          xptr_t        child_inode_xp )
    13591365{
    1360     // Two embedded loops:
     1366    // Two embedded loops to scan the directory mapper:
    13611367    // - scan the parent directory mapper pages
    13621368    // - scan the directory entries in each 4 Kbytes page
     
    15121518    // get child inode cluster and local pointer
    15131519    cxy_t          inode_cxy = GET_CXY( child_inode_xp );
    1514     vfs_inode_t  * inode_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
     1520    vfs_inode_t  * inode_ptr = GET_PTR( child_inode_xp );
     1521
     1522    // build extended pointer on parent dentried root
     1523    xptr_t parents_root_xp = XPTR( inode_cxy , &inode_ptr->parents );
     1524
     1525// check child inode has at least one parent
     1526assert( (xlist_is_empty( parents_root_xp ) == false ), "child inode must have one parent\n");
    15151527
    15161528    // get dentry pointers and cluster
    1517     xptr_t         dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 
     1529    xptr_t         dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
    15181530    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    15191531    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    15201532
    1521 // dentry descriptor must be in same cluster as parent inode
     1533// check dentry descriptor in same cluster as parent inode
    15221534assert( (dentry_cxy == local_cxy) , "illegal dentry cluster\n" );
    15231535
  • trunk/kernel/fs/fatfs.h

    r602 r610  
    311311 * This function implements the generic vfs_fs_child_init() function for the FATFS.
    312312 *****************************************************************************************
    313  * It scan the mapper of an existing parent directory, identified by the <parent>
    314  * argument, to find a directory entry identified by the <name> argument.
    315  * It updates the existing remote child inode, identified by the <child_xp> argument,
     313 * It tries to initialise a new child (new inode/dentry couple in Inode Tree), identified
     314 * by the <child_inode_xp> argument, from the parent directory mapper, identified by the
     315 * <parent_inode> argument.
     316 * - It scan the parent mapper to find the <name> argument.
    316317 * - it set the "type", "size", and "extend" fields in inode descriptor.
    317318 * - it set the " extend" field in dentry descriptor.
  • trunk/kernel/fs/vfs.c

    r602 r610  
    141141}
    142142
    143 //////////////////////////////////////////////////////
    144 error_t vfs_inode_create( xptr_t            dentry_xp,
    145                           vfs_fs_type_t     fs_type,
     143////////////////////////////////////////////////////
     144error_t vfs_inode_create( vfs_fs_type_t     fs_type,
    146145                          vfs_inode_type_t  inode_type,
    147146                          uint32_t          attr,
     
    212211        vfs_ctx_inum_release( ctx , inum );
    213212        mapper_destroy( mapper );
    214         return ENOMEM;
     213        return -1;
    215214    }
    216215
    217216    // initialize inode descriptor
    218     inode->gc         = 0;
    219217    inode->type       = inode_type;
    220218    inode->inum       = inum;
     
    223221    inode->uid        = uid;
    224222    inode->gid        = gid;
    225     inode->refcount   = 0;
    226     inode->parent_xp  = dentry_xp;
    227223    inode->ctx        = ctx;
    228224    inode->mapper     = mapper;
    229225    inode->extend     = NULL;
     226    inode->links      = 0;
    230227
    231228    // initialise inode field in mapper
     
    233230 
    234231    // initialise threads waiting queue
    235     xlist_root_init( XPTR( local_cxy , &inode->wait_root ) );
    236 
    237     // initialize dentries hash table
     232    // xlist_root_init( XPTR( local_cxy , &inode->wait_root ) );
     233
     234    // initialize chidren dentries xhtab
    238235    xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
    239236
    240     // initialize inode lock
    241     remote_rwlock_init( XPTR( local_cxy , &inode->data_lock ), LOCK_VFS_INODE );
    242 
    243     // initialise lock protecting inode three traversal
    244     remote_busylock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN );
     237    // initialize parents dentries xlist
     238    xlist_root_init( XPTR( local_cxy , &inode->parents ) );
     239 
     240    // initialize lock protecting size
     241    remote_rwlock_init( XPTR( local_cxy , &inode->size_lock ), LOCK_VFS_SIZE );
     242
     243    // initialise lock protecting inode tree traversal
     244    remote_rwlock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN );
     245
     246    // return extended pointer on inode
     247    *inode_xp = XPTR( local_cxy , inode );
    245248
    246249#if DEBUG_VFS_INODE_CREATE
     
    251254#endif
    252255 
    253     // return extended pointer on inode
    254     *inode_xp = XPTR( local_cxy , inode );
    255256    return 0;
    256257
     
    260261void vfs_inode_destroy( vfs_inode_t * inode )
    261262{
    262 
    263 // check inode refcount
    264 assert( (inode->refcount == 0) , "inode refcount non zero\n" );
    265 
    266263    // release memory allocated for mapper
    267264    mapper_destroy( inode->mapper );
     
    275272}  // end vfs_inode_destroy()
    276273
    277 ////////////////////////////////////////////
    278 void vfs_inode_remote_up( xptr_t  inode_xp )
    279 {
    280     // get inode cluster and local pointer
    281     cxy_t         inode_cxy = GET_CXY( inode_xp );
    282     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    283 
    284     hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , 1 );   
    285 }
    286 
    287 //////////////////////////////////////////////
    288 void vfs_inode_remote_down( xptr_t  inode_xp )
    289 {
    290     // get inode cluster and local pointer
    291     cxy_t         inode_cxy = GET_CXY( inode_xp );
    292     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    293 
    294     hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , -1 );   
    295 }
    296 
    297274//////////////////////////////////////////////
    298275uint32_t vfs_inode_get_size( xptr_t inode_xp )
     
    303280
    304281    // get size
    305     remote_rwlock_rd_acquire( XPTR( cxy , &ptr->data_lock ) );
     282    remote_rwlock_rd_acquire( XPTR( cxy , &ptr->size_lock ) );
    306283    uint32_t size = hal_remote_l32( XPTR( cxy , &ptr->size ) );
    307     remote_rwlock_rd_release( XPTR( cxy , &ptr->data_lock ) );
     284    remote_rwlock_rd_release( XPTR( cxy , &ptr->size_lock ) );
    308285    return size;
    309286}
     
    318295
    319296    // set size
    320     remote_rwlock_wr_release( XPTR( cxy , &ptr->data_lock ) );
     297    remote_rwlock_wr_release( XPTR( cxy , &ptr->size_lock ) );
    321298    hal_remote_s32( XPTR( cxy , &ptr->size ) , size );
    322     remote_rwlock_wr_release( XPTR( cxy , &ptr->data_lock ) );
     299    remote_rwlock_wr_release( XPTR( cxy , &ptr->size_lock ) );
    323300}
    324301
     
    345322}
    346323
    347 /////////////////////////////////////////
    348 void vfs_inode_get_name( xptr_t inode_xp,
    349                          char * name )
    350 {
    351     cxy_t          inode_cxy;
    352     vfs_inode_t  * inode_ptr;
    353     xptr_t         dentry_xp;
    354     cxy_t          dentry_cxy;
    355     vfs_dentry_t * dentry_ptr;
     324///////////////////////////////////////////
     325void vfs_inode_get_name( xptr_t   inode_xp,
     326                         char   * name )
     327{
     328    cxy_t          inode_cxy;          // inode cluster identifier
     329    vfs_inode_t  * inode_ptr;          // local pointer on inode
     330    xptr_t         parents_root_xp;    // extended pointer on inode parents root
    356331   
    357332    // get inode cluster and local pointer
     
    359334    inode_ptr = GET_PTR( inode_xp );
    360335
    361     // get parent dentry
    362     dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    363 
    364     // get local copy of name
    365     if( dentry_xp == XPTR_NULL )  // it is the VFS root
     336    // build extended pointer on parents dentries root
     337    parents_root_xp  = XPTR( inode_cxy , &inode_ptr->parents );
     338
     339    // check VFS root
     340    if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root
    366341    {
    367342        strcpy( name , "/" );
    368343    }
    369     else                          // not the VFS root
    370     {
     344    else                                     // not the VFS root
     345    {
     346        xptr_t         dentry_xp;
     347        cxy_t          dentry_cxy;
     348        vfs_dentry_t * dentry_ptr;
     349
     350        // get first name in list of parents
     351        dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
    371352        dentry_cxy = GET_CXY( dentry_xp );
    372353        dentry_ptr = GET_PTR( dentry_xp );
    373354
    374355        hal_remote_strcpy( XPTR( local_cxy  , name ) ,
    375                            XPTR( dentry_cxy , &dentry_ptr->name ) );
    376     }
     356                           XPTR( dentry_cxy , dentry_ptr->name ) );
     357    }
     358
    377359}  // end vfs_inode_get_name()
    378360
     
    433415error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
    434416                           char          * name,
    435                            vfs_inode_t   * parent,
    436417                           xptr_t        * dentry_xp )
    437418{
     
    439420    vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated)
    440421        kmem_req_t       req;        // request to kernel memory allocator
    441     error_t          error;
    442422
    443423#if DEBUG_VFS_DENTRY_CREATE
     
    456436    {
    457437        ctx = NULL;
    458         return EINVAL;
     438        return -1;
    459439    }
    460440
     
    470450        dentry     = (vfs_dentry_t *)kmem_alloc( &req );
    471451
    472     if( dentry == NULL ) return ENOMEM;
     452    if( dentry == NULL )
     453    {
     454        printk("\n[ERROR] in %s : cannot allocate dentry descriptor\n",
     455        __FUNCTION__ );
     456        return -1;
     457    }
    473458
    474459    // initialize dentry descriptor
    475 
    476460    dentry->ctx     = ctx;
    477461    dentry->length  = length;
    478     dentry->parent  = parent;
    479462    dentry->extend  = NULL;
    480463    strcpy( dentry->name , name );
    481 
    482 #if( DEBUG_VFS_DENTRY_CREATE & 1 )
    483 cycle = (uint32_t)hal_get_cycles();
    484 if( DEBUG_VFS_DENTRY_CREATE < cycle )
    485 printk("\n[%s] thread[%x,%x] / dentry <%s> initialised / cycle %d\n",
    486 __FUNCTION__, this->process->pid, this->trdid, dentry->name, cycle );
    487 #endif
    488 
    489     // register dentry in hash table rooted in parent inode
    490     error = xhtab_insert( XPTR( local_cxy , &parent->children ),
    491                           name,
    492                           XPTR( local_cxy , &dentry->list ) );
    493 
    494     if( error ) return EINVAL;
    495 
    496 #if( DEBUG_VFS_DENTRY_CREATE & 1 )
    497 cycle = (uint32_t)hal_get_cycles();
    498 if( DEBUG_VFS_DENTRY_CREATE < cycle )
    499 printk("\n[%s] thread[%x,%x] / dentry <%s> registered / cycle %d\n",
    500 __FUNCTION__, this->process->pid, this->trdid, dentry->name, cycle );
    501 #endif
    502464
    503465    // return extended pointer on dentry
     
    518480void vfs_dentry_destroy( vfs_dentry_t * dentry )
    519481{
    520 
    521 // check dentry refcount
    522 assert( (dentry->refcount == 0) , "dentry refcount non zero\n" );
    523 
    524     // get pointer on parent inode
    525     vfs_inode_t * parent = dentry->parent;
    526 
    527     // remove this dentry from parent inode htab
    528     xhtab_remove( XPTR( local_cxy , &parent->children ),
    529                   dentry->name,
    530                   XPTR( local_cxy , &dentry->list ) );
    531 
    532482    // release memory allocated to dentry
    533483        kmem_req_t req;
     
    537487
    538488}  // end vfs_dentry_destroy()
    539 
    540 //////////////////////////////////////////////
    541 void vfs_dentry_remote_up( xptr_t  dentry_xp )
    542 {
    543     // get dentry cluster and local pointer
    544     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    545     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    546 
    547     hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , 1 );   
    548 }
    549 
    550 ////////////////////////////////////////////////
    551 void vfs_dentry_remote_down( xptr_t  dentry_xp )
    552 {
    553     // get dentry cluster and local pointer
    554     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    555     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    556 
    557     hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , -1 );   
    558 }
    559 
    560489
    561490
     
    616545void vfs_file_destroy( vfs_file_t *  file )
    617546{
    618     if( file->refcount )
    619     {
    620         assert( false , "refcount non zero\n" );
    621     }       
     547
     548// check refcount
     549assert( (file->refcount == 0) , "refcount non zero\n" );
    622550
    623551        kmem_req_t req;
     
    664592
    665593//////////////////////////////////////
    666 error_t vfs_open( process_t * process,
     594error_t vfs_open( xptr_t      root_xp,
    667595                          char      * path,
     596                  xptr_t      process_xp,
    668597                          uint32_t    flags,
    669598                  uint32_t    mode,
     
    671600                  uint32_t  * new_file_id )
    672601{
    673     error_t       error;
    674     xptr_t        inode_xp;     // extended pointer on target inode
    675     cxy_t         inode_cxy;    // inode cluster identifier       
    676     vfs_inode_t * inode_ptr;    // inode local pointer
    677     uint32_t      file_attr;    // file descriptor attributes
    678     uint32_t      lookup_mode;  // lookup working mode       
    679     xptr_t        file_xp;      // extended pointer on created file descriptor
    680     uint32_t      file_id;      // created file descriptor index in reference fd_array
    681 
     602    error_t        error;
     603    xptr_t         inode_xp;       // extended pointer on target inode
     604    cxy_t          inode_cxy;      // inode cluster identifier       
     605    vfs_inode_t  * inode_ptr;      // inode local pointer
     606    uint32_t       file_attr;      // file descriptor attributes
     607    uint32_t       lookup_mode;    // lookup working mode       
     608    xptr_t         file_xp;        // extended pointer on created file descriptor
     609    uint32_t       file_id;        // created file descriptor index in reference fd_array
     610    xptr_t         vfs_root_xp;    // extended pointer on VFS root inode
     611    vfs_inode_t  * vfs_root_ptr;   // local pointer on VFS root inode
     612    cxy_t          vfs_root_cxy;   // VFS root inode cluster identifier
     613    xptr_t         lock_xp;        // extended pointer on Inode Tree lock
    682614
    683615    if( mode != 0 )
     
    687619    }
    688620
     621    thread_t  * this    = CURRENT_THREAD;
     622    process_t * process = this->process;
     623
    689624#if DEBUG_VFS_OPEN
    690 thread_t * this = CURRENT_THREAD;
    691625uint32_t cycle = (uint32_t)hal_get_cycles();
    692626if( DEBUG_VFS_OPEN < cycle )
    693 printk("\n[%s]   thread[%x,%x] enter for <%s> / cycle %d\n",
    694 __FUNCTION__, this->process->pid, this->trdid, path, cycle );
     627printk("\n[%s] thread[%x,%x] enter for <%s> / root_inode (%x,%x) / cycle %d\n",
     628__FUNCTION__, process->pid, this->trdid, path, GET_CXY(root_xp), GET_PTR(root_xp), cycle );
    695629#endif
    696630
     
    709643    if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC;
    710644
     645    // build extended pointer on lock protecting Inode Tree
     646    vfs_root_xp  = process->vfs_root_xp;
     647    vfs_root_ptr = GET_PTR( vfs_root_xp );
     648    vfs_root_cxy = GET_CXY( vfs_root_xp );
     649    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     650
     651    // take lock protecting Inode Tree in read mode
     652    remote_rwlock_rd_acquire( lock_xp );
     653
    711654    // get extended pointer on target inode
    712     error = vfs_lookup( process->vfs_cwd_xp , path , lookup_mode , &inode_xp );
    713 
    714     if( error ) return error;
     655    error = vfs_lookup( root_xp,
     656                        path,
     657                        lookup_mode,
     658                        &inode_xp,
     659                        NULL );
     660
     661    // release lock protecting Inode Tree
     662    remote_rwlock_rd_release( lock_xp );
     663
     664    if( error )
     665    {
     666        printk("\n[ERROR] in %s : cannot get inode <%s>\n",
     667        __FUNCTION__ , path );
     668        return -1;
     669    }
    715670
    716671    // get target inode cluster and local pointer
     
    718673    inode_ptr = GET_PTR( inode_xp );
    719674   
     675#if (DEBUG_VFS_OPEN & 1)
     676cycle = (uint32_t)hal_get_cycles();
     677if( DEBUG_VFS_OPEN < cycle )
     678printk("\n[%s] thread[%x,%x] found inode(%x,%x) for <%s>\n",
     679__FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr, path );
     680#endif
     681
    720682    // create a new file descriptor in cluster containing inode
    721683    if( inode_cxy == local_cxy )      // target cluster is local
     
    730692    if( error )  return error;
    731693
     694#if (DEBUG_VFS_OPEN & 1)
     695cycle = (uint32_t)hal_get_cycles();
     696if( DEBUG_VFS_OPEN < cycle )
     697printk("\n[%s] thread[%x,%x] created file descriptor (%x,%x) for <%s>\n",
     698__FUNCTION__, process->pid, this->trdid, GET_CXY(file_xp), GET_PTR(file_xp), path );
     699#endif
     700
    732701    // allocate and register a new file descriptor index in reference process
    733     error = process_fd_register( process , file_xp , &file_id );
     702    error = process_fd_register( process_xp , file_xp , &file_id );
    734703
    735704    if( error ) return error;
     
    738707cycle = (uint32_t)hal_get_cycles();
    739708if( DEBUG_VFS_OPEN < cycle )
    740 printk("\n[%s]   thread[%x,%x] exit for <%s> / fdid %d / cluster %x / cycle %d\n",
    741 __FUNCTION__, this->process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle );
     709printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / cluster %x / cycle %d\n",
     710__FUNCTION__, process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle );
    742711#endif
    743712
     
    780749
    781750    // move data between mapper and buffer
    782     if( file_cxy == local_cxy )
    783     {
    784         error = mapper_move_user( mapper,
    785                                   to_buffer,
    786                                   file_offset,
    787                                   buffer,
    788                                   size );
    789     }
    790     else
    791     {
    792         rpc_mapper_move_user_client( file_cxy,
    793                                      mapper,
    794                                      to_buffer,
    795                                      file_offset,
    796                                      buffer,
    797                                      size,
    798                                      &error );
    799     }
     751    error = mapper_move_user( XPTR( file_cxy , mapper ),
     752                              to_buffer,
     753                              file_offset,
     754                              buffer,
     755                              size );
    800756
    801757    // update file offset in file descriptor
     
    834790    // get inode type from remote file descriptor
    835791    inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) );
    836    
     792
    837793    // action depends on inode type
    838794    if( inode_type == INODE_TYPE_FILE )
     
    10441000
    10451001////////////////////////////////////
    1046 error_t vfs_unlink( xptr_t   cwd_xp,
     1002error_t vfs_mkdir( xptr_t   root_xp,
     1003                   char   * path,
     1004                   uint32_t rights )
     1005{
     1006    error_t        error;
     1007    xptr_t         vfs_root_xp;        // extended pointer on VFS root inode
     1008    vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode
     1009    cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier
     1010    xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree
     1011    xptr_t         inode_xp;           // extended pointer on target inode
     1012    vfs_inode_t  * inode_ptr;          // local pointer on target inode
     1013    cxy_t          inode_cxy;          // target inode cluster identifier
     1014    xptr_t         dentry_xp;          // extended pointer on new dentry
     1015    vfs_dentry_t * dentry_ptr;         // target dentry local pointer
     1016    xptr_t         parent_xp;          // extended pointer on new parent inode
     1017    vfs_inode_t  * parent_ptr;         // local pointer on new parent inode 
     1018    cxy_t          parent_cxy;         // new parent inode cluster identifier
     1019    vfs_ctx_t    * parent_ctx_ptr;     // local pointer on target inode context
     1020    uint32_t       parent_fs_type;     // target inode file system type
     1021
     1022    xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root)
     1023    xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry
     1024    xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root)
     1025    xptr_t         children_entry_xp;  // extended pointer on children field in dentry
     1026
     1027    char           last_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1028
     1029    thread_t  * this    = CURRENT_THREAD;
     1030    process_t * process = this->process;
     1031
     1032#if DEBUG_VFS_MKDIR
     1033char root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1034vfs_inode_get_name( root_xp , root_name );
     1035uint32_t   cycle = (uint32_t)hal_get_cycles();
     1036if( DEBUG_VFS_MKDIR < cycle )
     1037printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n",
     1038__FUNCTION__, process->pid, this->trdid, root_name, path, cycle );
     1039#endif
     1040
     1041    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1042    vfs_root_xp  = process->vfs_root_xp;
     1043    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1044    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1045    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1046
     1047    // take the lock protecting Inode Tree in write mode
     1048    remote_rwlock_wr_acquire( lock_xp );
     1049
     1050    // 1. get pointers on parent inode
     1051    error = vfs_lookup( root_xp,
     1052                        path,
     1053                        VFS_LOOKUP_DIR | VFS_LOOKUP_PARENT,
     1054                        &parent_xp,
     1055                        last_name );
     1056    if( error )
     1057    {
     1058        remote_rwlock_wr_release( lock_xp );
     1059        printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n",
     1060        __FUNCTION__, path );
     1061        return -1;
     1062    }
     1063
     1064    // get parent inode cluster and local pointer
     1065    parent_cxy = GET_CXY( parent_xp );
     1066    parent_ptr = GET_PTR( parent_xp );
     1067
     1068#if( DEBUG_VFS_MKDIR & 1 )
     1069if( DEBUG_VFS_MKDIR < cycle )
     1070printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n",
     1071__FUNCTION__, process->pid, this->trdid, parent_cxy, parent_ptr, path );
     1072#endif
     1073
     1074    // get parent inode context, and FS type
     1075    parent_ctx_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
     1076    parent_fs_type = hal_remote_l32( XPTR( parent_cxy , &parent_ctx_ptr->type ) );
     1077
     1078    // 2. create one new dentry in parent cluster
     1079    if( parent_cxy == local_cxy ) 
     1080    {
     1081        error = vfs_dentry_create( parent_fs_type,
     1082                                   last_name,
     1083                                   &dentry_xp );
     1084    }
     1085    else
     1086    {
     1087        rpc_vfs_dentry_create_client( parent_cxy,
     1088                                      parent_fs_type,
     1089                                      last_name,
     1090                                      &dentry_xp,
     1091                                      &error );
     1092    }
     1093
     1094    if( error )
     1095    {
     1096        remote_rwlock_wr_release( lock_xp );
     1097        printk("\n[ERROR] in %s : cannot create new dentry in cluster %x for <%s>\n",
     1098        __FUNCTION__, parent_cxy, path );
     1099        return -1;
     1100    }
     1101
     1102    // get local pointer on dentry
     1103    dentry_ptr = GET_PTR( dentry_xp );
     1104
     1105#if( DEBUG_VFS_MKDIR & 1 )
     1106if( DEBUG_VFS_MKDIR < cycle )
     1107printk("\n[%s] thread[%x,%x] created new dentry (%x,%x) for <%s>\n",
     1108__FUNCTION__, process->pid, this->trdid, parent_cxy, dentry_ptr, path );
     1109#endif
     1110
     1111    // 3. create new directory inode in child cluster
     1112    // TODO : define attr / uid / gid
     1113    uint32_t attr = 0;
     1114    uint32_t uid  = 0;
     1115    uint32_t gid  = 0;
     1116
     1117    // select a target cluster for new inode
     1118    inode_cxy = cluster_random_select();
     1119   
     1120    if( inode_cxy == local_cxy )      // child cluster is local
     1121    {
     1122        error = vfs_inode_create( parent_fs_type,
     1123                                  INODE_TYPE_DIR,
     1124                                  attr,
     1125                                  rights,
     1126                                  uid,
     1127                                  gid,
     1128                                  &inode_xp );
     1129    }
     1130    else                              // child cluster is remote
     1131    {
     1132        rpc_vfs_inode_create_client( inode_cxy,
     1133                                     parent_fs_type,
     1134                                     INODE_TYPE_DIR,
     1135                                     attr,
     1136                                     rights,
     1137                                     uid,
     1138                                     gid,
     1139                                     &inode_xp,
     1140                                     &error );
     1141    }
     1142                                     
     1143    if( error )
     1144    {
     1145        printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
     1146               __FUNCTION__ , inode_cxy , path );
     1147 
     1148        if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr );
     1149        else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr );
     1150        return -1;
     1151    }
     1152
     1153    // get new inode local pointer
     1154    inode_ptr = GET_PTR( inode_xp );
     1155   
     1156#if(DEBUG_VFS_MKDIR & 1)
     1157if( DEBUG_VFS_MKDIR < cycle )
     1158printk("\n[%s] thread[%x,%x] created new inode (%x,%x) for <%s>\n",
     1159__FUNCTION__ , process->pid, this->trdid, inode_cxy, inode_ptr, path );
     1160#endif
     1161
     1162    // 4. register dentry in new inode list of parents
     1163    parents_root_xp  = XPTR( inode_cxy  , &inode_ptr->parents );
     1164    parents_entry_xp = XPTR( parent_cxy , &dentry_ptr->parents );
     1165    xlist_add_first( parents_root_xp , parents_entry_xp );
     1166    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 );
     1167
     1168    // 5. register dentry in parent inode
     1169    children_xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
     1170    children_entry_xp = XPTR( parent_cxy , &dentry_ptr->children );
     1171    xhtab_insert( children_xhtab_xp , last_name , children_entry_xp );
     1172
     1173    // 6. update "parent" and "child_xp" fields in dentry
     1174    hal_remote_s64( XPTR( parent_cxy , &dentry_ptr->child_xp ) , inode_xp );
     1175    hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->parent ) , parent_ptr );
     1176
     1177#if(DEBUG_VFS_MKDIR & 1)
     1178if( DEBUG_VFS_MKDIR < cycle )
     1179printk("\n[%s] thread[%x,%x] updated Inode Tree for <%s>\n",
     1180__FUNCTION__, process->pid, this->trdid, path );
     1181#endif
     1182
     1183    // release the lock protecting Inode Tree
     1184    remote_rwlock_wr_release( lock_xp );
     1185
     1186    // 5. update parent directory mapper
     1187    //    and synchronize the parent directory on IOC device
     1188    if (parent_cxy == local_cxy)
     1189    {
     1190        error = vfs_fs_add_dentry( parent_ptr,
     1191                                   dentry_ptr );
     1192    }
     1193    else
     1194    {
     1195        rpc_vfs_fs_add_dentry_client( parent_cxy,
     1196                                      parent_ptr,
     1197                                      dentry_ptr,
     1198                                      &error );
     1199    }
     1200
     1201    if( error )
     1202    {
     1203        printk("\n[ERROR] in %s : cannot update parent directory for <%s>\n",
     1204        __FUNCTION__, path );
     1205        return -1;
     1206    }
     1207
     1208#if(DEBUG_VFS_MKDIR & 1)
     1209if( DEBUG_VFS_MKDIR < cycle )
     1210printk("\n[%s] thread[%x,%x] updated parent dir (mapper and IOC) for <%s>\n",
     1211__FUNCTION__, process->pid, this->trdid, path );
     1212#endif
     1213
     1214    return 0;
     1215
     1216}  // end vfs_mkdir()
     1217
     1218///////////////////////////////////////
     1219error_t vfs_link( xptr_t   old_root_xp,
     1220                  char   * old_path,
     1221                  xptr_t   new_root_xp,
     1222                  char   * new_path )
     1223{
     1224    error_t        error;
     1225    xptr_t         vfs_root_xp;        // extended pointer on VFS root inode
     1226    vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode
     1227    cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier
     1228    xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree
     1229    xptr_t         inode_xp;           // extended pointer on target inode
     1230    vfs_inode_t  * inode_ptr;          // local pointer on target inode
     1231    cxy_t          inode_cxy;          // target inode cluster identifier
     1232    uint32_t       inode_type;         // target inode type
     1233    vfs_ctx_t    * inode_ctx_ptr;      // local pointer on target inode context
     1234    uint32_t       inode_fs_type;      // target inode file system type
     1235    xptr_t         dentry_xp;          // extended pointer on new dentry
     1236    vfs_dentry_t * dentry_ptr;         // target dentry local pointer
     1237    xptr_t         new_parent_xp;      // extended pointer on new parent inode
     1238    vfs_inode_t  * new_parent_ptr;     // local pointer on new parent inode 
     1239    cxy_t          new_parent_cxy;     // new parent inode cluster identifier
     1240
     1241    xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root)
     1242    xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry
     1243    xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root)
     1244    xptr_t         children_entry_xp;  // extended pointer on children field in dentry
     1245
     1246    char           new_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1247
     1248    thread_t  * this    = CURRENT_THREAD;
     1249    process_t * process = this->process;
     1250
     1251#if DEBUG_VFS_LINK
     1252char old_root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1253char new_root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1254vfs_inode_get_name( old_root_xp , old_root_name );
     1255vfs_inode_get_name( new_root_xp , new_root_name );
     1256uint32_t   cycle = (uint32_t)hal_get_cycles();
     1257if( DEBUG_VFS_LINK < cycle )
     1258printk("\n[%s] thread[%x,%x] enter / old_root <%s> / old_path <%s> / "
     1259"new_root <%s> / new_path <%s> / cycle %d\n",
     1260__FUNCTION__, process->pid, this->trdid,
     1261old_root_name, old_path, new_root_name, new_path, cycle );
     1262#endif
     1263
     1264    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1265    vfs_root_xp  = process->vfs_root_xp;
     1266    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1267    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1268    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1269
     1270    // take the lock protecting Inode Tree in write mode
     1271    remote_rwlock_wr_acquire( lock_xp );
     1272
     1273    // get extended pointer on target inode
     1274    error = vfs_lookup( old_root_xp,
     1275                        old_path,
     1276                        0,
     1277                        &inode_xp,
     1278                        NULL );
     1279    if( error )
     1280    {
     1281        remote_rwlock_wr_release( lock_xp );
     1282        printk("\n[ERROR] in %s : cannot get target inode for <%s>\n",
     1283        __FUNCTION__, old_path );
     1284        return -1;
     1285    }
     1286
     1287#if( DEBUG_VFS_LINK & 1 )
     1288if( DEBUG_VFS_LINK < cycle )
     1289printk("\n[%s] thread[%x,%x] get child inode (%x,%x) for <%s>\n",
     1290__FUNCTION__, process->pid, this->trdid,
     1291GET_CXY(inode_xp), GET_PTR(inode_xp), old_path, cycle );
     1292#endif
     1293
     1294    // get extended pointer on parent inode in new path
     1295    error = vfs_lookup( new_root_xp,
     1296                        new_path,
     1297                        VFS_LOOKUP_PARENT,
     1298                        &new_parent_xp,
     1299                        new_name );
     1300    if( error )
     1301    {
     1302        remote_rwlock_wr_release( lock_xp );
     1303        printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n",
     1304        __FUNCTION__, new_path );
     1305        return -1;
     1306    }
     1307
     1308#if( DEBUG_VFS_LINK & 1 )
     1309if( DEBUG_VFS_LINK < cycle )
     1310printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n",
     1311__FUNCTION__, process->pid, this->trdid,
     1312GET_CXY(new_parent_xp), GET_PTR(new_parent_xp), new_path );
     1313#endif
     1314
     1315    // get target inode cluster and local pointer
     1316    inode_cxy = GET_CXY( inode_xp );
     1317    inode_ptr = GET_PTR( inode_xp );
     1318
     1319    // get target inode type, context, and FS type
     1320    inode_type        = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     1321    inode_ctx_ptr     = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) );
     1322    inode_fs_type     = hal_remote_l32( XPTR( inode_cxy , &inode_ctx_ptr->type ) );
     1323
     1324    // get new parent inode cluster an local pointer
     1325    new_parent_ptr = GET_PTR( new_parent_xp );
     1326    new_parent_cxy = GET_CXY( new_parent_xp );
     1327
     1328    ///////////////////////////////////////////////////////////////////////
     1329    if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) )
     1330    {
     1331        // 1. create one new dentry
     1332        if( new_parent_cxy == local_cxy ) 
     1333        {
     1334            error = vfs_dentry_create( inode_fs_type,
     1335                                       new_name,
     1336                                       &dentry_xp );
     1337        }
     1338        else
     1339        {
     1340            rpc_vfs_dentry_create_client( new_parent_cxy,
     1341                                          inode_fs_type,
     1342                                          new_name,
     1343                                          &dentry_xp,
     1344                                          &error );
     1345        }
     1346
     1347        if( error )
     1348        {
     1349            remote_rwlock_wr_release( lock_xp );
     1350            printk("\n[ERROR] in %s : cannot create new dentry for <%s>\n",
     1351            __FUNCTION__, new_path );
     1352            return -1;
     1353        }
     1354
     1355        // get local pointer on dentry
     1356        dentry_ptr = GET_PTR( dentry_xp );
     1357
     1358        // 2. register dentry in target inode
     1359        parents_root_xp  = XPTR( inode_cxy      , &inode_ptr->parents );
     1360        parents_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->parents );
     1361        xlist_add_first( parents_root_xp , parents_entry_xp );
     1362        hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 );
     1363
     1364        // 3. register dentry in parent inode
     1365        children_xhtab_xp = XPTR( new_parent_cxy , &new_parent_ptr->children );
     1366        children_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->children );
     1367        xhtab_insert( children_xhtab_xp , new_name , children_entry_xp );
     1368
     1369        // 4. update "parent" and "child_xp" fields in dentry
     1370        hal_remote_s64( XPTR( new_parent_cxy , &dentry_ptr->child_xp ) , inode_xp );
     1371        hal_remote_spt( XPTR( new_parent_cxy , &dentry_ptr->parent ) , new_parent_ptr );
     1372
     1373#if(DEBUG_VFS_LINK & 1)
     1374if( DEBUG_VFS_LINK < cycle )
     1375printk("\n[%s] thread[%x,%x] updated Inode Tree / old <%s> / new <%s>\n",
     1376__FUNCTION__, process->pid, this->trdid, old_path, new_path );
     1377vfs_display( new_parent_xp );
     1378#endif
     1379
     1380        // release the lock protecting Inode Tree
     1381        remote_rwlock_wr_release( lock_xp );
     1382
     1383        // 5. update new parent directory mapper in Inode Tree
     1384        //    and synchronize the parent directory on IOC device
     1385        if (new_parent_cxy == local_cxy)
     1386        {
     1387            error = vfs_fs_add_dentry( new_parent_ptr,
     1388                                       dentry_ptr );
     1389        }
     1390        else
     1391        {
     1392            rpc_vfs_fs_add_dentry_client( new_parent_cxy,
     1393                                          new_parent_ptr,
     1394                                          dentry_ptr,
     1395                                          &error );
     1396        }
     1397        if( error )
     1398        {
     1399            printk("\n[ERROR] in %s : cannot update new parent directory for <%s>\n",
     1400            __FUNCTION__, new_path );
     1401            return -1;
     1402        }
     1403
     1404#if(DEBUG_VFS_LINK & 1)
     1405if( DEBUG_VFS_LINK < cycle )
     1406printk("\n[%s] thread[%x,%x] updated new parent dir (mapper and IOC) / old <%s> / new <%s>\n",
     1407__FUNCTION__, process->pid, this->trdid, old_path, new_path );
     1408#endif
     1409        return 0;
     1410    }
     1411    else
     1412    {
     1413        // release the lock protecting Inode Tree
     1414        remote_rwlock_wr_release( lock_xp );
     1415
     1416        printk("\n[ERROR] in %s : unsupported inode type %s\n",
     1417        __FUNCTION__ , vfs_inode_type_str( inode_type ) );
     1418        return -1;
     1419    }
     1420
     1421}  // end vfs_link()
     1422
     1423/////////////////////////////////////
     1424error_t vfs_unlink( xptr_t   root_xp,
    10471425                    char   * path )
    10481426{
    10491427    error_t           error;
     1428    xptr_t            vfs_root_xp;        // extended pointer on VFS root inode
     1429    vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode
     1430    cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier
     1431    xptr_t            lock_xp;            // extended pointer on lock protecting Inode Tree
     1432    xptr_t            parent_xp;          // extended pointer on target inode
     1433    cxy_t             parent_cxy;         // target inode cluster identifier       
     1434    vfs_inode_t     * parent_ptr;         // target inode local pointer
    10501435    xptr_t            inode_xp;           // extended pointer on target inode
    10511436    cxy_t             inode_cxy;          // target inode cluster identifier       
    10521437    vfs_inode_t     * inode_ptr;          // target inode local pointer
    1053     uint32_t          inode_refcount;     // target inode refcount
    1054     vfs_inode_type_t  type;               // target inode type
    1055     mapper_t        * mapper;             // pointer on target inode mapper
    1056     xptr_t            dentry_xp;          // extended pointer on target dentry
    1057     cxy_t             dentry_cxy;         // target dentry cluster identifier
    1058     vfs_dentry_t    * dentry_ptr;         // target dentry local pointer
    1059     uint32_t          dentry_refcount;    // target dentry refcount
    1060     vfs_inode_t     * dentry_parent_ptr;  // parent inode local pointer
     1438    uint32_t          inode_links;        // target inode links count
     1439    vfs_inode_type_t  inode_type;         // target inode type
     1440    uint32_t          inode_children;     // target inode number of children
     1441    xptr_t            dentry_xp;          // extended pointer on dentry to unlink
     1442    vfs_dentry_t    * dentry_ptr;         // local pointer on dentry to unlink
     1443
     1444    char              name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of link to remove
     1445
     1446    thread_t  * this    = CURRENT_THREAD;
     1447    process_t * process = this->process;
    10611448
    10621449#if DEBUG_VFS_UNLINK
    1063 thread_t * this  = CURRENT_THREAD;
    10641450uint32_t   cycle = (uint32_t)hal_get_cycles();
     1451char root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1452vfs_inode_get_name( root_xp , root_name );
    10651453if( DEBUG_VFS_UNLINK < cycle )
    1066 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
    1067 __FUNCTION__, this->process->pid, this->trdid, path, cycle );
    1068 #endif
    1069 
    1070     // get extended pointer on target inode
    1071     error = vfs_lookup( cwd_xp , path , 0 , &inode_xp );
    1072 
    1073     if( error ) return error;
    1074 
    1075     // get inode cluster and local pointer
     1454printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n",
     1455__FUNCTION__, process->pid, this->trdid, root_name, path, cycle );
     1456#endif
     1457
     1458    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1459    vfs_root_xp  = process->vfs_root_xp;
     1460    vfs_root_ptr = GET_PTR( root_xp );
     1461    vfs_root_cxy = GET_CXY( root_xp );
     1462    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1463
     1464    // take the lock protecting Inode Tree
     1465    remote_rwlock_wr_acquire( lock_xp );
     1466
     1467    // get extended pointer on parent inode
     1468    error = vfs_lookup( root_xp,
     1469                        path,
     1470                        VFS_LOOKUP_PARENT,
     1471                        &parent_xp,
     1472                        name );
     1473    if( error )
     1474    {
     1475        remote_rwlock_wr_release( lock_xp );
     1476        printk("\n[ERROR] in %s : cannot get parent inode for <%s> in <%s>\n",
     1477        __FUNCTION__, name, path );
     1478        return -1;
     1479    }
     1480
     1481    // get parent inode cluster and local pointer
     1482    parent_cxy = GET_CXY( parent_xp );
     1483    parent_ptr = GET_PTR( parent_xp );
     1484 
     1485#if( DEBUG_VFS_UNLINK & 1 )
     1486char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1487vfs_inode_get_name( parent_xp , parent_name );
     1488if( DEBUG_VFS_UNLINK < cycle )
     1489printk("\n[%s] thread[%x,%x] parent inode <%s> is (%x,%x)\n",
     1490__FUNCTION__, process->pid, this->trdid, parent_name, parent_cxy, parent_ptr );
     1491#endif
     1492
     1493    // build extended pointer on parent inode "children" xhtab
     1494    xptr_t children_xp = XPTR( parent_cxy , &parent_ptr->children );
     1495
     1496    // get extended pointer on dentry to unlink
     1497    dentry_xp = xhtab_lookup( children_xp , name );
     1498   
     1499    if( dentry_xp == XPTR_NULL )
     1500    {
     1501        remote_rwlock_wr_release( lock_xp );
     1502        printk("\n[ERROR] in %s : cannot get target dentry <%s> in <%s>\n",
     1503        __FUNCTION__, name, path );
     1504        return -1;
     1505    }
     1506   
     1507    // get local pointer on dentry to unlink
     1508    dentry_ptr = GET_PTR( dentry_xp );
     1509
     1510#if( DEBUG_VFS_UNLINK & 1 )
     1511if( DEBUG_VFS_UNLINK < cycle )
     1512printk("\n[%s] thread[%x,%x] dentry <%s> to unlink is (%x,%x)\n",
     1513__FUNCTION__, process->pid, this->trdid, name, parent_cxy, dentry_ptr );
     1514#endif
     1515
     1516    // get pointer on target inode
     1517    inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
    10761518    inode_cxy = GET_CXY( inode_xp );
    10771519    inode_ptr = GET_PTR( inode_xp );
    1078 
    1079     // get inode type, refcount, mapper, dentry_xp
    1080     type              = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
    1081     inode_refcount    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) );
    1082     mapper            = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
    1083     dentry_xp         = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    1084 
    1085     // get dentry cluster, local pointer, refcount, and pointers on parent inode
    1086     dentry_ptr        = GET_PTR( dentry_xp );
    1087     dentry_cxy        = GET_CXY( dentry_xp );
    1088     dentry_refcount   = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) );
    1089     dentry_parent_ptr = hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) );
    1090 
    1091 // check inode & dentry refcount
    1092 assert( (inode_refcount  == 1), "illegal inode refcount for <%s>\n", path );
    1093 assert( (dentry_refcount == 1), "illegal dentry refcount for <%s>\n", path );
    1094 
    1095     /////////////////////////////
    1096     if( type == INODE_TYPE_FILE )
    1097     {
    1098         // 1. release clusters allocated to file in the FAT mapper
    1099         //    synchronize the FAT on IOC device
    1100         error = vfs_fs_release_inode( inode_xp );
    1101         if( error )
     1520 
     1521#if( DEBUG_VFS_UNLINK & 1 )
     1522char inode_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1523vfs_inode_get_name( inode_xp , inode_name );
     1524if( DEBUG_VFS_UNLINK < cycle )
     1525printk("\n[%s] thread[%x,%x] target inode <%s> is (%x,%x) / cycle %d\n",
     1526__FUNCTION__, process->pid, this->trdid, inode_name, inode_cxy, inode_ptr, cycle );
     1527#endif
     1528
     1529    // get target inode "type" and "links"
     1530    inode_type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     1531    inode_links  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->links ) );
     1532
     1533// check target inode links counter
     1534assert( (inode_links >= 1), "illegal inode links count %d for <%s>\n", inode_links, path );
     1535
     1536    ///////////////////////////////////////////////////////////////////////
     1537    if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) )
     1538    {
     1539        // 1. Release clusters allocated to target inode
     1540        //    and synchronize the FAT on IOC device if last link.
     1541        if( inode_links == 1 )
    11021542        {
    1103             printk("\n[ERROR] in %s : cannot update FAT mapper <%s>\n", path );
    1104             return -1;
    1105         }
     1543            // build extended pointer on target inode "children" number
     1544            xptr_t inode_children_xp = XPTR( inode_cxy , &inode_ptr->children.items );
     1545
     1546            // get target inode number of children
     1547            inode_children = hal_remote_l32( inode_children_xp );
     1548
     1549            // check no children
     1550            if( inode_children != 0 )
     1551            {
     1552                remote_rwlock_wr_release( lock_xp );
     1553                printk("\n[ERROR] in %s : cannot remove <%s> inode that has children\n",
     1554                __FUNCTION__, path );
     1555                return -1;
     1556            }
     1557
     1558            // release clusters on IOC device
     1559            error = vfs_fs_release_inode( inode_xp );
     1560
     1561            if( error )
     1562            {
     1563                remote_rwlock_wr_release( lock_xp );
     1564                printk("\n[ERROR] in %s : cannot update FAT mapper to remove <%s> inode\n",
     1565                __FUNCTION__ , path );
     1566                return -1;
     1567            }
    11061568
    11071569#if(DEBUG_VFS_UNLINK & 1)
    11081570if( DEBUG_VFS_UNLINK < cycle )
    11091571printk("\n[%s] thread[%x,%x] removed <%s> inode from FAT (mapper and IOC device)\n",
    1110 __FUNCTION__, this->process->pid, this->trdid, path );
    1111 #endif
    1112 
    1113         // 2. update parent directory in Inode Tree
    1114         //    synchronize the parent directory on IOC device
    1115         if (dentry_cxy == local_cxy)                           // dentry is local
     1572__FUNCTION__, process->pid, this->trdid, path );
     1573#endif
     1574        }
     1575
     1576        // 2. update parent directory mapper
     1577        //    and synchronize the parent directory on IOC device
     1578        if (parent_cxy == local_cxy)
    11161579        {
    1117             error = vfs_fs_remove_dentry( dentry_parent_ptr,
     1580            error = vfs_fs_remove_dentry( parent_ptr,
    11181581                                          dentry_ptr );
    11191582        }
    1120         else                                                  // dentry is remote
     1583        else           
    11211584        {
    1122             rpc_vfs_fs_remove_dentry_client( dentry_cxy,
    1123                                              dentry_parent_ptr,
     1585            rpc_vfs_fs_remove_dentry_client( parent_cxy,
     1586                                             parent_ptr,
    11241587                                             dentry_ptr,
    11251588                                             &error );
    11261589        }
     1590
    11271591        if( error )
    11281592        {
    1129             printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n", path );
     1593            remote_rwlock_wr_release( lock_xp );
     1594            printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n",
     1595            __FUNCTION__ , path );
    11301596            return -1;
    11311597        }
     
    11341600if( DEBUG_VFS_UNLINK < cycle )
    11351601printk("\n[%s] thread[%x,%x] removed <%s> inode from parent dir (mapper and IOC device)\n",
    1136 __FUNCTION__, this->process->pid, this->trdid, path );
    1137 #endif
    1138         // 3. remove inode (including mapper & dentry) from Inode Tree
    1139         vfs_remove_child_from_parent( inode_xp );
     1602__FUNCTION__, process->pid, this->trdid, path );
     1603#endif
     1604        // 3. remove dentry from Inode Tree (and associated chils inode when last link)
     1605        vfs_remove_child_from_parent( dentry_xp );
     1606
     1607        // release the lock protecting Inode Tree
     1608        remote_rwlock_wr_release( lock_xp );
    11401609
    11411610#if DEBUG_VFS_UNLINK
    11421611if( DEBUG_VFS_UNLINK < cycle )
    11431612printk("\n[%s] thread[%x,%x] exit / removed <%s> inode from Inode Tree / cycle %d\n",
    1144 __FUNCTION__, this->process->pid, this->trdid, path, cycle );
     1613__FUNCTION__, process->pid, this->trdid, path, cycle );
    11451614#endif
    11461615        return 0;
    11471616    }
    1148     /////////////////////////////////
    1149     else if( type == INODE_TYPE_DIR )
    1150     {
    1151         printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) );
     1617    else
     1618    {
     1619        remote_rwlock_wr_release( lock_xp );
     1620        printk("\n[ERROR] in %s : unsupported inode type %s\n",
     1621        __FUNCTION__ , vfs_inode_type_str( inode_type ) );
    11521622        return -1;
    11531623    }
    1154     ////
    1155     else
    1156     {
    1157         printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) );
     1624
     1625}  // end vfs_unlink()
     1626
     1627///////////////////////////////////////////
     1628error_t vfs_stat( xptr_t     root_inode_xp,
     1629                  char     * path,
     1630                  stat_t   * st )
     1631{
     1632    error_t       error;
     1633    xptr_t        inode_xp;           // extended pointer on target inode
     1634    vfs_inode_t * inode_ptr;          // local pointer on target inode
     1635    cxy_t         inode_cxy;          // target inode cluster identifier
     1636    xptr_t        vfs_root_xp;        // extended pointer on VFS root inode
     1637    vfs_inode_t * vfs_root_ptr;       // local_pointer on VFS root inode
     1638    cxy_t         vfs_root_cxy;       // VFS root inode cluster identifier
     1639    xptr_t        lock_xp;            // extended pointer on lock protecting Inode Tree
     1640
     1641    thread_t  * this    = CURRENT_THREAD;
     1642    process_t * process = this->process;
     1643
     1644    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1645    vfs_root_xp  = process->vfs_root_xp;
     1646    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1647    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1648    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1649
     1650    // get the lock protecting Inode Tree in read mode
     1651    remote_rwlock_rd_acquire( lock_xp );
     1652
     1653    // get extended pointer on target inode
     1654    error = vfs_lookup( root_inode_xp,
     1655                        path,
     1656                        0,
     1657                        &inode_xp,
     1658                        NULL );
     1659
     1660    // release the lock protecting Inode Tree
     1661    remote_rwlock_rd_release( lock_xp );
     1662
     1663    if( error )
     1664    {
     1665        printk("\n[ERROR] in %s : cannot found inode <%s>\n",
     1666        __FUNCTION__ , path );
    11581667        return -1;
    11591668    }
    11601669
    1161 }  // end vfs_unlink()
    1162 
    1163 //////////////////////////////////////
    1164 error_t vfs_stat( xptr_t     inode_xp,
    1165                   stat_t   * st )
    1166 {
    11671670    // get cluster and local pointer on inode descriptor
    1168     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    1169     cxy_t         inode_cxy = GET_CXY( inode_xp );
     1671    inode_ptr = GET_PTR( inode_xp );
     1672    inode_cxy = GET_CXY( inode_xp );
    11701673
    11711674    // get relevant infos from inode descriptor
     
    11861689#if DEBUG_VFS_STAT
    11871690uint32_t cycle  = (uint32_t)hal_get_cycles();
    1188 thread_t * this = CURRENT_THREAD;
    11891691if( DEBUG_VFS_STAT < cycle )
    11901692printk("\n[%s] thread[%x,%x] set stat %x for inode %x in cluster %x / cycle %d\n"
    11911693       " %s / inum %d / size %d\n",
    1192 __FUNCTION__, this->process->pid, this->trdid, st, inode_ptr, inode_cxy, cycle,
     1694__FUNCTION__, process->pid, this->trdid, st, inode_ptr, inode_cxy, cycle,
    11931695vfs_inode_type_str( type ), inum, size );
    11941696#endif
     
    12071709}
    12081710
    1209 //////////////////////////////////////
    1210 error_t vfs_mkdir( xptr_t     file_xp,
    1211                    char     * path,
    1212                    uint32_t   mode )
    1213 {
    1214     assert( false , "not implemented file_xp: %x, path <%s>, mode: %x\n",
    1215       file_xp, path, mode );
    1216     return 0;
    1217 }
    1218 
    12191711////////////////////////////////////
    12201712error_t vfs_rmdir( xptr_t   file_xp,
     
    12261718}
    12271719
    1228 ///////////////////////////////////
    1229 error_t vfs_chdir( xptr_t   cwd_xp,
     1720////////////////////////////////////
     1721error_t vfs_chdir( xptr_t   root_xp,
    12301722                   char   * path )
    12311723{
    12321724    error_t           error;
    1233     xptr_t            inode_xp;     // extended pointer on target inode
    1234     cxy_t             inode_cxy;    // target inode cluster identifier       
    1235     vfs_inode_t     * inode_ptr;    // target inode local pointer
    1236     uint32_t          mode;         // lookup working mode       
    1237     vfs_inode_type_t  inode_type;   // target inode type
    1238 
    1239     // set lookup working mode
    1240     mode = 0;
     1725    xptr_t            inode_xp;           // extended pointer on target inode
     1726    cxy_t             inode_cxy;          // target inode cluster identifier       
     1727    vfs_inode_t     * inode_ptr;          // target inode local pointer
     1728    vfs_inode_type_t  inode_type;         // target inode type
     1729    xptr_t            vfs_root_xp;        // extended pointer on VFS root inode
     1730    vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode
     1731    cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier
     1732    xptr_t            main_lock_xp;       // extended pointer on lock protecting Inode Tree
     1733    xptr_t            ref_xp;             // extended pointer on reference process
     1734    process_t       * ref_ptr;            // local pointer on reference process
     1735    cxy_t             ref_cxy;            // reference process cluster
     1736    xptr_t            cwd_lock_xp;        // extended pointer on lock protecting CWD change
     1737    xptr_t            cwd_xp_xp;          // extended pointer on cwd_xp in reference process
     1738
     1739    thread_t  * this    = CURRENT_THREAD;
     1740    process_t * process = this->process;
     1741
     1742#if DEBUG_VFS_CHDIR
     1743uint32_t cycle = (uint32_t)hal_get_cycles();
     1744if( DEBUG_VFS_CHDIR < cycle )
     1745printk("\n[%s] thread[%x,%x] enter for path <%s> / cycle %d\n",
     1746__FUNCTION__, process->pid, this->trdid, path, cycle );
     1747#endif
     1748
     1749    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1750    vfs_root_xp  = process->vfs_root_xp;
     1751    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1752    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1753    main_lock_xp = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1754
     1755    // take lock protecting Inode Tree in read mode
     1756    remote_rwlock_rd_acquire( main_lock_xp );
    12411757
    12421758    // get extended pointer on target inode
    1243     error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
    1244 
    1245     if( error ) return error;
    1246 
    1247     // get inode cluster and local pointer
     1759    error = vfs_lookup( root_xp,
     1760                        path,
     1761                        VFS_LOOKUP_DIR,
     1762                        &inode_xp,
     1763                        NULL );
     1764
     1765    // release lock protecting Inode Tree in read mode
     1766    remote_rwlock_rd_release( main_lock_xp );
     1767
     1768    if( error )
     1769    {
     1770        printk("\n[ERROR] in %s : <%s> not found\n",
     1771        __FUNCTION__, path );
     1772        return -1;
     1773    }
     1774
     1775    // get inode type from remote file
    12481776    inode_cxy = GET_CXY( inode_xp );
    12491777    inode_ptr = GET_PTR( inode_xp );
    1250 
    1251     // get inode type from remote file
    12521778    inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
    12531779
    12541780    if( inode_type != INODE_TYPE_DIR )
    12551781    {
    1256         CURRENT_THREAD->errno = ENOTDIR;
     1782        printk("\n[ERROR] in %s : <%s> is not a directory\n",
     1783        __FUNCTION__, path );
    12571784        return -1;
    12581785    }
    12591786
    1260     // TODO implement this function using process CWD lock
    1261 
    1262 assert( false , "not implemented\n" );
     1787    // build extended pointer on cwd_lock and cwd_xp
     1788    ref_xp       = process->ref_xp;
     1789    ref_ptr      = GET_PTR( ref_xp );
     1790    ref_cxy      = GET_CXY( ref_xp );
     1791    cwd_lock_xp  = XPTR( ref_cxy , &ref_ptr->cwd_lock );
     1792    cwd_xp_xp    = XPTR( ref_cxy , &ref_ptr->cwd_xp );
     1793
     1794    // take lock protecting CWD changes
     1795    remote_busylock_acquire( cwd_lock_xp );
     1796
     1797    // update cwd_xp field in reference process descriptor
     1798    hal_remote_s64( cwd_xp_xp , inode_xp );
     1799
     1800    // release lock protecting CWD changes
     1801    remote_busylock_release( cwd_lock_xp );
     1802
     1803#if DEBUG_VFS_CHDIR
     1804cycle = (uint32_t)hal_get_cycles();
     1805if( DEBUG_VFS_CHDIR < cycle )
     1806printk("\n[%s] thread[%x,%x] exit : inode (%x,%x) / &cwd_xp (%x,%x) / cycle %d\n",
     1807__FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr,
     1808GET_CXY(cwd_xp_xp), GET_PTR(cwd_xp_xp), cycle );
     1809#endif
    12631810
    12641811    return 0;
    1265 }
     1812
     1813}  // end vfs_chdir()
    12661814
    12671815///////////////////////////////////
     
    12811829 
    12821830    // get extended pointer on target inode
    1283     error = vfs_lookup( cwd_xp , path , 0 , &inode_xp );
     1831    error = vfs_lookup( cwd_xp,
     1832                        path,
     1833                        0,
     1834                        &inode_xp,
     1835                        NULL );
    12841836
    12851837    if( error ) return error;
     
    12921844    inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
    12931845
    1294    
    1295     assert( false , "not implemented\n" );
     1846    // TODO implement this function
     1847
     1848assert( false , "not implemented\n" );
     1849
    12961850    return 0;
    12971851}
     
    13601914assert( (indent < 16)           , "depth cannot be larger than 15\n" );
    13611915   
    1362     // get inode cluster and local pointer
     1916    // get current inode cluster and local pointer
    13631917    inode_cxy = GET_CXY( inode_xp );
    13641918    inode_ptr = GET_PTR( inode_xp );
     
    14281982    cxy_t          dentry_cxy;
    14291983    vfs_dentry_t * dentry_ptr;
     1984    xptr_t         parents_root_xp;   // root of parent dentries xlist
    14301985
    14311986    // get target inode cluster and local pointer
     
    14331988    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    14341989
    1435     // get extended pointer on associated dentry
    1436     dentry_xp   = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    1437 
    1438     // check if target inode is the File System root
    1439     if( dentry_xp == XPTR_NULL )
     1990    // build extended pointer on parents dentries root
     1991    parents_root_xp = XPTR( inode_cxy , &inode_ptr->parents );
     1992
     1993    // check VFS root     
     1994    if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root
    14401995    {
    14411996        // build extended pointer on root name
     
    14441999    else
    14452000    {
    1446         // get dentry cluster and local pointer
     2001        // get first parent dentry cluster and pointers
     2002        dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
    14472003        dentry_cxy = GET_CXY( dentry_xp );
    14482004        dentry_ptr = GET_PTR( dentry_xp );
     
    15202076                             xptr_t * child_xp )
    15212077{
    1522     xptr_t  xhtab_xp;    // extended pointer on hash table containing children dentries
    1523     xptr_t  dentry_xp;   // extended pointer on children dentry
     2078    xptr_t         xhtab_xp;    // extended pointer on hash table for children dentries
     2079    xptr_t         dentry_xp;   // extended pointer on children dentry
     2080    cxy_t          dentry_cxy;
     2081    vfs_dentry_t * dentry_ptr;
    15242082
    15252083    // get parent inode cluster and local pointer
     
    15302088    xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
    15312089
    1532     // search extended pointer on matching dentry
    1533     dentry_xp = xhtab_lookup( xhtab_xp , name );
    1534 
    1535     if( dentry_xp == XPTR_NULL ) return false;
    1536 
    1537     // get dentry cluster and local pointer
    1538     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    1539     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    1540 
    1541     // return child inode
    1542     *child_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
    1543     return true;
     2090    // get pointers on matching dentry
     2091    dentry_xp  = xhtab_lookup( xhtab_xp , name );
     2092    dentry_cxy = GET_CXY( dentry_xp );
     2093    dentry_ptr = GET_PTR( dentry_xp );
     2094
     2095    if( dentry_xp == XPTR_NULL )
     2096    {
     2097        return false;
     2098    }
     2099    else
     2100    {
     2101        *child_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
     2102        return true;
     2103    }
    15442104
    15452105}  // end vfs_get_child()
     
    15532113// last name in the path. The names are supposed to be separated by one or several '/'
    15542114// characters, that are not written in  the <name> buffer.
     2115//
     2116// WARNING: the leading characters '/' in the path are skiped before analysis.
     2117//          The path "/" identifies the VFS root, and is therefore anaysed as an empty
     2118//          string. This empty string is dignaled by the (-1) return value. 
    15552119//////////////////////////////////////////////////////////////////////////////////////////
    15562120// @ current   : pointer on first character to analyse in buffer containing the path.
     
    15582122// @ next      : [out] pointer on next character to analyse in buffer containing the path.
    15592123// @ last      : [out] true if the returned name is the last (NUL character found).
    1560 // @ return 0 if success / return EINVAL if string empty (first chracter is NUL).
     2124// @ return 0 if success / return -1 if string empty (first chracter is NUL).
    15612125//////////////////////////////////////////////////////////////////////////////////////////
    15622126static error_t vfs_get_name_from_path( char     * current,
     
    15702134    while( *ptr == '/' ) ptr++;
    15712135
    1572     // return EINVAL if string empty
    1573     if( *ptr == 0 ) return EINVAL;
     2136    // signal empty string
     2137    if( *ptr == 0 )
     2138    {
     2139        *last = true;
     2140        return -1;
     2141    }
    15742142
    15752143    // copy all characters in name until NUL or '/'
     
    15942162}  // end vfs_get name_from_path()
    15952163   
    1596 //////////////////////////////////////////////
    1597 error_t vfs_lookup( xptr_t             cwd_xp,
     2164///////////////////////////////////////////////
     2165error_t vfs_lookup( xptr_t             root_xp,
    15982166                    char             * pathname,
    1599                     uint32_t           mode,
    1600                                         xptr_t           * inode_xp )
     2167                    uint32_t           lookup_mode,
     2168                                        xptr_t           * inode_xp,
     2169                                        char             * last_name )
    16012170{
    16022171    char               name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path
     
    16192188    bool_t             create;       // searched inode must be created if not found
    16202189    bool_t             excl;         // searched inode must not exist
     2190    bool_t             par;          // searched inode is the parent
    16212191    thread_t         * this;         // pointer on calling thread descriptor
    16222192    process_t        * process;      // pointer on calling process descriptor
     
    16262196    process = this->process;
    16272197
     2198// check pathname / root_xp consistency
     2199assert( ((pathname[0] != '/') || (root_xp == process->vfs_root_xp)),
     2200"root inode must be VFS root for path <%s>\n", pathname );
     2201
    16282202#if DEBUG_VFS_LOOKUP
    16292203uint32_t cycle = (uint32_t)hal_get_cycles();
     2204char     root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2205vfs_inode_get_name( root_xp , root_name );
    16302206if( DEBUG_VFS_LOOKUP < cycle )
    1631 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
    1632 __FUNCTION__, process->pid, this->trdid, pathname, cycle );
     2207printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / mode %x / cycle %d\n",
     2208__FUNCTION__, process->pid, this->trdid, root_name, pathname, lookup_mode, cycle );
    16332209#endif
    16342210
    16352211    // compute lookup flags
    1636     dir    = mode & VFS_LOOKUP_DIR;
    1637     create = mode & VFS_LOOKUP_CREATE;
    1638     excl   = mode & VFS_LOOKUP_EXCL;
    1639    
    1640     // get extended pointer on first inode to search
    1641     if( pathname[0] == '/' ) parent_xp = process->vfs_root_xp;
    1642     else                     parent_xp = cwd_xp;
    1643 
    1644     // initialise other loop variables
    1645     current  = pathname;
    1646     next     = NULL;
    1647     last     = false;
    1648     child_xp = XPTR_NULL;
    1649 
    1650     // take lock on parent inode
    1651     vfs_inode_lock( parent_xp );
    1652 
    1653     // sequencially loop on nodes in pathname
    1654     // load from device if one node in path not found in inode tree
     2212    dir    = (lookup_mode & VFS_LOOKUP_DIR)    == VFS_LOOKUP_DIR;
     2213    create = (lookup_mode & VFS_LOOKUP_CREATE) == VFS_LOOKUP_CREATE;
     2214    excl   = (lookup_mode & VFS_LOOKUP_EXCL)   == VFS_LOOKUP_EXCL;
     2215    par    = (lookup_mode & VFS_LOOKUP_PARENT) == VFS_LOOKUP_PARENT;
     2216
     2217    // initialise loop variables
     2218    parent_xp = root_xp;
     2219    current   = pathname;
     2220    next      = NULL;
     2221    last      = false;
     2222    child_xp  = XPTR_NULL;
     2223
     2224    // loop on nodes in pathname
     2225    // load from device if one node in path not found in Inode Tree
    16552226    // exit loop when last name found (i.e. last == true)
    1656     do
    1657     {
    1658         // get one name from path, and "last" flag
    1659         vfs_get_name_from_path( current , name , &next , &last );
     2227    while( 1 )
     2228    {
     2229        // get parent inode cluster and local pointer
     2230        parent_cxy = GET_CXY( parent_xp );
     2231        parent_ptr = GET_PTR( parent_xp );
     2232
     2233        // get one "name" from path, and "last" flag
     2234        error = vfs_get_name_from_path( current , name , &next , &last );
     2235
     2236        // VFS root case
     2237        if ( error )
     2238        {
     2239
     2240#if DEBUG_VFS_LOOKUP
     2241cycle = (uint32_t)hal_get_cycles();
     2242if( DEBUG_VFS_LOOKUP < cycle )
     2243printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n",
     2244__FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle );
     2245#endif
     2246            *inode_xp = process->vfs_root_xp;
     2247            break;
     2248        }
    16602249
    16612250#if (DEBUG_VFS_LOOKUP & 1)
     
    16652254#endif
    16662255
    1667         // search a child dentry matching name in parent inode
     2256        // search the child dentry matching name in parent inode
    16682257        found = vfs_get_child( parent_xp,
    16692258                               name,
    16702259                               &child_xp );
    16712260
    1672         if (found == false )  // child not found in inode tree
     2261        // analyse found & last, depending on lookup_mode
     2262        if( found == false )                              // not found in Inode Tree
    16732263        {
     2264            // when a inode is not found in the Inode Tree:
     2265            // - if (last and par) the Inode Tree is not modified
     2266            // - else we speculatively introduce a new (dentry/inode) in inode tree,
     2267            //        and scan the parent directory mapper to initialise it.
     2268            //     . if it is not found in the parent mapper:
     2269            //         - if(last and create), a brand new file or directory is created
     2270            //         - else, an error is reported
     2271            //     . if it is found in parent mapper:
     2272            //         - if( last and excl ), an error is reported
     2273            //         - else the new child (inode & dentry) is initialised in Inode Tree
     2274            //         - if the child is a directory, the child mapper is loaded from device
     2275
     2276            if( last && par )   //  does nothing
     2277            {
    16742278
    16752279#if (DEBUG_VFS_LOOKUP & 1)
    16762280if( DEBUG_VFS_LOOKUP < cycle )
    1677 printk("\n[%s] thread[%x,%x] miss <%s> node => try to create it\n",
     2281printk("\n[%s] thread[%x,%x] child not found but only parent requested in <%s>\n",
     2282__FUNCTION__, process->pid, this->trdid, pathname );
     2283#endif
     2284            }
     2285            else                                    // try to get it from parent mapper
     2286            {
     2287
     2288#if (DEBUG_VFS_LOOKUP & 1)
     2289if( DEBUG_VFS_LOOKUP < cycle )
     2290printk("\n[%s] thread[%x,%x] miss <%s> inode in Inode Tree => build from parent mapper\n",
    16782291__FUNCTION__, process->pid, this->trdid, name );
    16792292#endif
    1680             // if a child node is not found in the inode tree,
    1681             // we introduce a new (dentry/inode) in inode tree,
    1682             // and try to find it by scanning the parent directory mapper.
    1683             // . if it is found in parent mapper:
    1684             //   - if the child is a directory, the child mapper is loaded from device
    1685             //   - if the child is not a directory, the search is completed
    1686             // . if it is not found in the parent mapper:
    1687             //   - if ( not last or not create ) an error is reported
    1688             //   - if (last and create) a new file or directory is created
    1689 
    1690             // release lock on parent inode
    1691             vfs_inode_unlock( parent_xp );
     2293                // get parent inode FS type
     2294                ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
     2295                fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
     2296
     2297                // select a cluster for new inode
     2298                child_cxy = cluster_random_select();
     2299
     2300                // define child inode type
     2301                if( dir ) child_type = INODE_TYPE_DIR;
     2302                else      child_type = INODE_TYPE_FILE;
    16922303 
    1693             // get parent inode cluster and local pointer
    1694             parent_cxy = GET_CXY( parent_xp );
    1695             parent_ptr = GET_PTR( parent_xp );
    1696 
    1697             // get parent inode FS type
    1698             ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
    1699             fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
    1700 
    1701             // select a cluster for missing inode
    1702             child_cxy = cluster_random_select();
    1703 
    1704             // define child inode type
    1705             if( dir ) child_type = INODE_TYPE_DIR;
    1706             else      child_type = INODE_TYPE_FILE;
    1707  
    1708             // insert a new child dentry/inode in inode tree
    1709             error = vfs_add_child_in_parent( child_cxy,
    1710                                              child_type,
    1711                                              fs_type,
    1712                                              parent_xp,
    1713                                              name,
    1714                                              &dentry_xp,
    1715                                              &child_xp );
    1716             if( error )
    1717             {
    1718                 printk("\n[ERROR] in %s : cannot create node <%s> in path <%s>\n",
    1719                 __FUNCTION__ , name, pathname );
    1720                 return -1;
    1721             }
    1722 
    1723             // get child inode local pointer
    1724             child_ptr = GET_PTR( child_xp );
     2304                // insert (speculatively) a new child dentry/inode in inode tree
     2305                error = vfs_add_child_in_parent( child_cxy,
     2306                                                 child_type,
     2307                                                 fs_type,
     2308                                                 parent_xp,
     2309                                                 name,
     2310                                                 &dentry_xp,
     2311                                                 &child_xp );
     2312                if( error )
     2313                {
     2314                    printk("\n[ERROR] in %s : cannot create inode <%s> in path <%s>\n",
     2315                    __FUNCTION__ , name, pathname );
     2316                    return -1;
     2317                }
     2318
     2319                // get child inode local pointer
     2320                child_ptr = GET_PTR( child_xp );
    17252321
    17262322#if (DEBUG_VFS_LOOKUP & 1)
     
    17292325__FUNCTION__, process->pid, this->trdid, name, child_cxy );
    17302326#endif
    1731             // scan parent mapper to find the missing dentry, and complete
    1732             // the initialisation of dentry and child inode desciptors
    1733             if( parent_cxy == local_cxy )
    1734 
    1735             {
    1736                 error = vfs_fs_child_init( parent_ptr,
    1737                                            name,
    1738                                            child_xp );
    1739             }
    1740             else
    1741             {
    1742                 rpc_vfs_fs_child_init_client( parent_cxy,
    1743                                               parent_ptr,
    1744                                               name,
    1745                                               child_xp,
    1746                                               &error );
    1747             }
    1748 
    1749             if ( error )   // child not found in parent mapper
    1750             {
    1751                 if ( last && create )  // add a new dentry in parent
     2327                // scan parent mapper to find the missing dentry, and complete
     2328                // the initialisation of dentry and child inode desciptors
     2329                if( parent_cxy == local_cxy )
     2330
    17522331                {
    1753                     error = vfs_new_child_init( parent_xp,               
    1754                                                 dentry_xp,
    1755                                                 child_xp );
    1756                     if ( error )
     2332                    error = vfs_fs_child_init( parent_ptr,
     2333                                               name,
     2334                                               child_xp );
     2335                }
     2336                else
     2337                {
     2338                    rpc_vfs_fs_child_init_client( parent_cxy,
     2339                                                  parent_ptr,
     2340                                                  name,
     2341                                                  child_xp,
     2342                                                  &error );
     2343                }
     2344
     2345                if ( error )   // child not found in parent mapper
     2346                {
     2347                    if ( last && create )  // add a brand new dentry in parent
    17572348                    {
    1758                         printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
    1759                         __FUNCTION__, name, pathname );
    1760                         vfs_remove_child_from_parent( child_xp );
     2349                        error = vfs_new_child_init( parent_xp,               
     2350                                                    dentry_xp,
     2351                                                    child_xp );
     2352                        if ( error )
     2353                        {
     2354                            printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
     2355                            __FUNCTION__, name, pathname );
     2356                            vfs_remove_child_from_parent( dentry_xp );
     2357                            return -1;
     2358                        }
     2359
     2360#if (DEBUG_VFS_LOOKUP & 1)
     2361if( DEBUG_VFS_LOOKUP < cycle )
     2362printk("\n[%s] thread[%x,%x] child <%s> not found in parent mapper => create it\n",
     2363__FUNCTION__, process->pid, this->trdid, name );
     2364#endif
     2365                    }
     2366                    else                   // not last or not create => error
     2367                    {                       
     2368                        printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
     2369                        __FUNCTION__ , name , pathname );
     2370                        vfs_remove_child_from_parent( dentry_xp );
    17612371                        return -1;
    17622372                    }
     2373                }
     2374                else          // child has been found in parent mapper
     2375                {
     2376                    // check the excl
     2377                    if( last && create && excl )
     2378                    {
     2379                        printk("\n[ERROR] in %s : node already exist <%s>\n",
     2380                        __FUNCTION__, name );
     2381                       return -1;
     2382                    }
    17632383
    17642384#if (DEBUG_VFS_LOOKUP & 1)
    17652385if( DEBUG_VFS_LOOKUP < cycle )
    1766 printk("\n[%s] thread[%x,%x] created inode <%s> in path\n",
     2386printk("\n[%s] thread[%x,%x] initialised inode <%s> from parent mapper\n",
    17672387__FUNCTION__, process->pid, this->trdid, name );
    17682388#endif
    1769                 }
    1770                 else                   // not last or not create => error
    1771                 {                       
    1772                      printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
    1773                      __FUNCTION__ , name , pathname );
    1774                      vfs_remove_child_from_parent( child_xp );
    1775                      return ENOENT;
     2389                    // load child mapper from device if child is a directory (prefetch)
     2390                    uint32_t type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
     2391                    if( type == INODE_TYPE_DIR )
     2392                    {
     2393                        if( child_cxy == local_cxy )
     2394                        {
     2395                            error = vfs_inode_load_all_pages( child_ptr );
     2396                        }
     2397                        else
     2398                        {
     2399                            rpc_vfs_inode_load_all_pages_client( child_cxy,
     2400                                                                 child_ptr,
     2401                                                                 &error );
     2402                        }
     2403                        if ( error )
     2404                        {
     2405                            printk("\n[ERROR] in %s : cannot load <%s> from device\n",
     2406                            __FUNCTION__ , name );
     2407                            vfs_remove_child_from_parent( dentry_xp );
     2408                            return -1;
     2409                        }
     2410
     2411#if (DEBUG_VFS_LOOKUP & 1)
     2412if( DEBUG_VFS_LOOKUP < cycle )
     2413printk("\n[%s] thread[%x,%x] loaded directory mapper for <%s> from IOC\n",
     2414__FUNCTION__ , process->pid, this->trdid, name );
     2415#endif
     2416                    }
    17762417                }
    17772418            }
    1778             else          // child found in parent mapper
    1779             {
    1780                 // load child mapper from device if child is a directory (prefetch)
    1781                 if( hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ) == INODE_TYPE_DIR )
    1782                 {
    1783                     if( child_cxy == local_cxy )
    1784                     {
    1785                         error = vfs_inode_load_all_pages( child_ptr );
    1786                     }
    1787                     else
    1788                     {
    1789                         rpc_vfs_inode_load_all_pages_client( child_cxy,
    1790                                                              child_ptr,
    1791                                                              &error );
    1792                     }
    1793                     if ( error )
    1794                     {
    1795                         printk("\n[ERROR] in %s : cannot load <%s> from device\n",
    1796                         __FUNCTION__ , name );
    1797                         vfs_remove_child_from_parent( child_xp );
    1798                         return EIO;
    1799                     }
    1800 
    1801 #if (DEBUG_VFS_LOOKUP & 1)
    1802 if( DEBUG_VFS_LOOKUP < cycle )
    1803 printk("\n[%s] thread[%x,%x] loaded from IOC device mapper for <%s> in <%s>\n",
    1804 __FUNCTION__ , process->pid, this->trdid, name, pathname );
    1805 #endif
    1806                 }
    1807             }
    1808 
    1809             // take lock on parent inode
    1810             vfs_inode_lock( parent_xp );
    18112419        }
    1812         else   // child found in inode tree
     2420        else                                    // child directly found in inode tree
    18132421        {
    18142422       
    18152423#if (DEBUG_VFS_LOOKUP & 1)
    18162424if( DEBUG_VFS_LOOKUP < cycle )
    1817 printk("\n[%s] thread[%x,%x] found <%s> / inode %x in cluster %x\n",
    1818 __FUNCTION__, process->pid, this->trdid, name, GET_PTR(child_xp), GET_CXY(child_xp) );
    1819 #endif
     2425printk("\n[%s] thread[%x,%x] found <%s> in Inode Tree / inode (%x,%x)\n",
     2426__FUNCTION__, process->pid, this->trdid, name, GET_CXY(child_xp), GET_PTR(child_xp) );
     2427#endif
     2428            // get child inode local pointer and cluster
    18202429            child_ptr  = GET_PTR( child_xp );
    18212430            child_cxy  = GET_CXY( child_xp );
    1822             parent_cxy = GET_CXY( parent_xp );
    1823             parent_ptr = GET_PTR( parent_xp );
    1824 
    1825             if( last && (mode & VFS_LOOKUP_CREATE) && (mode & VFS_LOOKUP_EXCL) )
     2431
     2432            // check the excl flag
     2433            if( last && create && excl )
    18262434            {
    1827                 printk("\n[ERROR] in %s : node already exist <%s>\n", __FUNCTION__, name );
    1828                 return EINVAL;
     2435                printk("\n[ERROR] in %s : node <%s> already exist\n",
     2436                __FUNCTION__, name );
     2437                return -1;
    18292438            }
    18302439        }
     
    18422451
    18432452        // take lock on child inode and release lock on parent
    1844         vfs_inode_lock( child_xp );
    1845         vfs_inode_unlock( parent_xp );
    1846 
    1847         // update loop variables
    1848         parent_xp = child_xp;
    1849         current   = next;
    1850     }
    1851     while( last == false );
    1852 
    1853     // release lock
    1854     vfs_inode_unlock( parent_xp );
     2453        // vfs_inode_lock( child_xp );
     2454        // vfs_inode_unlock( parent_xp );
     2455
     2456        // exit when last
     2457        if ( last )           // last inode in path  => return relevant info
     2458        {
     2459            if ( par )  // return parent inode and child name
     2460            {
    18552461
    18562462#if DEBUG_VFS_LOOKUP
    18572463cycle = (uint32_t)hal_get_cycles();
    18582464if( DEBUG_VFS_LOOKUP < cycle )
    1859 printk("\n[%s] thread[%x,%x] exit for <%s> cycle %d\n",
    1860 __FUNCTION__ , process->pid, this->trdid, pathname, cycle );
    1861 #endif
    1862 
    1863     // return searched pointer
    1864     if( mode & VFS_LOOKUP_PARENT ) *inode_xp = parent_xp;
    1865     else                           *inode_xp = child_xp;
     2465printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n",
     2466__FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle );
     2467#endif
     2468                *inode_xp = parent_xp;
     2469                strcpy( last_name , name );
     2470                break;
     2471            }
     2472            else        // return child inode name     
     2473            {
     2474
     2475#if DEBUG_VFS_LOOKUP
     2476cycle = (uint32_t)hal_get_cycles();
     2477if( DEBUG_VFS_LOOKUP < cycle )
     2478printk("\n[%s] thread[%x,%x] exit / child inode (%x,%x) / <%s> / cycle %d\n",
     2479__FUNCTION__ , process->pid, this->trdid, child_cxy, child_ptr, pathname, cycle );
     2480#endif
     2481                *inode_xp = child_xp;
     2482                break;
     2483            }
     2484        }
     2485        else                     // not the last inode in path => update loop variables
     2486        {
     2487            parent_xp = child_xp;
     2488            current   = next;
     2489        }
     2490    }
    18662491
    18672492    return 0;
    18682493
    18692494}  // end vfs_lookup()
    1870 
    1871 
    18722495
    18732496///////////////////////////////////////////////
     
    19542577cycle = (uint32_t)hal_get_cycles();
    19552578if( DEBUG_VFS_NEW_CHILD_INIT < cycle )
    1956 printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%> / cycle %d\n",
     2579printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n",
    19572580__FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
    19582581#endif
     
    19622585}  // end vfs_new_child_init()
    19632586
    1964 ////////////////////////////////////////////
    1965 error_t vfs_get_path( xptr_t    searched_xp,
    1966                       char    * buffer,
    1967                       uint32_t  max_size )
    1968 {
    1969         xptr_t       dentry_xp;   // extended pointer on current dentry
    1970     char       * name;        // local pointer on current dentry name
    1971         uint32_t     length;      // length of current dentry name
    1972         uint32_t     count;       // number of characters written in buffer
    1973         uint32_t     index;       // slot index in buffer
    1974     xptr_t       inode_xp;    // extended pointer on   
    1975 
    1976     // implementation note:
    1977     // we use two variables "index" and "count" because the buffer
    1978     // is written in decreasing index order (from leaf to root)
    1979     // TODO  : handle conflict with a concurrent rename [AG]
    1980     // FIXME : handle synchro in the loop  [AG]
    1981 
    1982         // set the NUL character in buffer / initialise buffer index and count
     2587//////////////////////////////////////////
     2588error_t vfs_get_path( xptr_t     inode_xp,
     2589                      char     * buffer,
     2590                      char    ** first,
     2591                      uint32_t   max_size )
     2592{
     2593        xptr_t         dentry_xp;        // extended pointer on current dentry
     2594    vfs_dentry_t * dentry_ptr;       // local pointer on current dentry
     2595    cxy_t          dentry_cxy;       // current dentry cluster identifier
     2596    xptr_t         name_xp;          // extended pointer on current dentry name
     2597        uint32_t       length;           // length of current dentry name
     2598        int32_t        index;            // slot index in buffer
     2599    xptr_t         current_xp;       // extended pointer on current inode
     2600    vfs_inode_t  * current_ptr;      // local pointer on current inode
     2601    cxy_t          current_cxy;      // current inode cluster identifier
     2602    xptr_t         vfs_root_xp;      // extended pointer on VFS root inode
     2603    vfs_inode_t  * vfs_root_ptr;     // local pointer on VFS root inode
     2604    cxy_t          vfs_root_cxy;     // VFS root inode cluster identifier
     2605    xptr_t         lock_xp;          // extended pointer on Inode Tree lock
     2606    xptr_t         parents_root_xp;  // extended pointer on current inode parents root
     2607    bool_t         found;            // condition to exit the while loop
     2608
     2609    thread_t  * this    = CURRENT_THREAD;
     2610    process_t * process = this->process;
     2611
     2612#if DEBUG_VFS_GET_PATH
     2613uint32_t cycle = (uint32_t)hal_get_cycles();
     2614if( DEBUG_VFS_GET_PATH < cycle )
     2615printk("\n[%s] thread[%x,%x] enter : inode (%x,%x) / cycle %d\n",
     2616__FUNCTION__ , process->pid, this->trdid,
     2617GET_CXY( inode_xp ), GET_PTR( inode_xp ), cycle );
     2618#endif
     2619
     2620        // set the NUL character in buffer / initialise buffer index
    19832621        buffer[max_size - 1] = 0;
    1984         count    = 1;
    1985     index    = max_size - 2;
     2622    index    = (int32_t)(max_size - 1);
    19862623
    19872624    // initialize current inode
    1988     inode_xp  = searched_xp;
    1989 
    1990     // exit when root inode found (i.e. dentry_xp == XPTR_NULL)
     2625    current_xp  = inode_xp;
     2626
     2627    // build extended pointer on lock protecting Inode Tree
     2628    vfs_root_xp  = process->vfs_root_xp;
     2629    vfs_root_ptr = GET_PTR( vfs_root_xp );
     2630    vfs_root_cxy = GET_CXY( vfs_root_xp );
     2631    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     2632
     2633    // take lock protecting Inode Tree in read mode
     2634    remote_rwlock_rd_acquire( lock_xp );
     2635
     2636    // traverse Inode Tree from target inode to VFS root
     2637    // selecting always the first parent dentry
     2638    // the buffer is written in "reverse order" (from target inode to root)
     2639    // exit the while loop when the VFS root has been found
    19912640        do
    19922641    {
    1993         // get inode cluster and local pointer
    1994         cxy_t         inode_cxy = GET_CXY( inode_xp );
    1995         vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    1996 
    1997         // get extended pointer on parent dentry               
    1998         dentry_xp = (xptr_t)hal_remote_l64( XPTR( inode_cxy , inode_ptr->parent_xp ) );
    1999 
    2000         // get dentry cluster and local pointer
    2001         cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    2002         vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    2003 
    2004         // get dentry name length and pointer
    2005         length =  hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->length ) );
    2006         name   = (char *)hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->name ) );
    2007 
    2008         // update index and count
    2009         index -= (length + 1);
    2010         count += (length + 1);
    2011 
    2012         // check buffer overflow
    2013         if( count >= max_size )
     2642        // get current inode cluster and local pointer
     2643        current_cxy = GET_CXY( current_xp );
     2644        current_ptr = GET_PTR( current_xp );
     2645
     2646        // build extended pointer on parents dentries root
     2647        parents_root_xp = XPTR( current_cxy , &current_ptr->parents );
     2648
     2649        // compute exit condition <=> current inode is VFS root   
     2650        found = xlist_is_empty( parents_root_xp );
     2651
     2652        if( found )                              // parent is the VFS root
    20142653        {
    2015             printk("\n[ERROR] in %s : kernel buffer too small\n", __FUNCTION__ );
    2016             return EINVAL;
     2654            if( index == (int32_t)(max_size - 1) )
     2655            {
     2656                // update index
     2657                index--;
     2658                 
     2659                // set separator 
     2660                        buffer[index] = '/';
     2661
     2662// check buffer overflow
     2663assert( (index >= 0) , "kernel buffer too small\n" );
     2664
     2665            }
    20172666        }
    2018 
    2019         // update pathname
    2020         hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
    2021                            XPTR( dentry_cxy , name ) , length );
    2022                 buffer[index] = '/';
    2023 
    2024                 // get extended pointer on next inode
    2025         inode_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , dentry_ptr->parent ) );
    2026     }
    2027     while( (dentry_xp != XPTR_NULL) );
    2028 
     2667        else                                     // not the VFS root
     2668        {
     2669            // get first parent dentry cluster and pointers
     2670            dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
     2671            dentry_cxy = GET_CXY( dentry_xp );
     2672            dentry_ptr = GET_PTR( dentry_xp );
     2673
     2674            // get extended pointer on dentry name and name length
     2675            name_xp = XPTR( dentry_cxy , dentry_ptr->name );
     2676            length  = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->length ) );
     2677
     2678#if (DEBUG_VFS_GET_PATH & 1)
     2679char debug_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2680hal_remote_strcpy( XPTR( local_cxy , debug_name ) , name_xp );
     2681if( DEBUG_VFS_GET_PATH < cycle )
     2682printk("\n[%s] thread(%x,%s) get current dentry <%s> in cluster %x\n",
     2683__FUNCTION__ , process->pid, this->trdid, debug_name, current_cxy );
     2684#endif
     2685            // update index
     2686            index -= (length + 1);
     2687
     2688// check buffer overflow
     2689assert( (index >= 0) , "kernel buffer too small\n" );
     2690
     2691            // update pathname
     2692            hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
     2693                               name_xp , length );
     2694
     2695            // set separator 
     2696                    buffer[index] = '/';
     2697
     2698            // get extended pointer on parent inode
     2699            current_xp = XPTR( dentry_cxy ,
     2700                               hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) ) );
     2701        }
     2702    }
     2703    while( found == false );
     2704
     2705    // release lock protecting Inode Tree in read mode
     2706    remote_rwlock_rd_release( lock_xp );
     2707
     2708#if DEBUG_VFS_GET_PATH
     2709cycle = (uint32_t)hal_get_cycles();
     2710if( DEBUG_VFS_GET_PATH < cycle )
     2711printk("\n[%s] thread[%x,%x] exit : path <%s> / cycle %d\n",
     2712__FUNCTION__ , process->pid, this->trdid, &buffer[index], cycle );
     2713#endif
     2714
     2715    // return pointer on first character in buffer
     2716    *first = &buffer[index];
    20292717        return 0;
    20302718
     
    20332721     
    20342722////////////////////////////////////////////////////////////////////
    2035 error_t vfs_add_child_in_parent( cxy_t              child_inode_cxy,
    2036                                  vfs_inode_type_t   child_inode_type,
     2723error_t vfs_add_child_in_parent( cxy_t              child_cxy,
     2724                                 vfs_inode_type_t   child_type,
    20372725                                 vfs_fs_type_t      fs_type,
    20382726                                 xptr_t             parent_inode_xp,
    20392727                                 char             * name,
    2040                                  xptr_t           * dentry_xp,
     2728                                 xptr_t           * child_dentry_xp,
    20412729                                 xptr_t           * child_inode_xp )
    20422730{
    2043     error_t         error;
    2044     xptr_t          new_dentry_xp;       // extended pointer on created dentry
    2045     vfs_dentry_t  * new_dentry_ptr;      // created dentry local pointer
    2046     xptr_t          new_inode_xp;        // extended pointer on created child inode
    2047     cxy_t           parent_inode_cxy;    // parent inode cluster identifier
    2048     vfs_inode_t   * parent_inode_ptr;    // parent inode local pointer
    2049 
    2050     // get parent inode cluster and local pointer
    2051     parent_inode_cxy = GET_CXY( parent_inode_xp );
     2731    error_t        error;
     2732    cxy_t          parent_cxy;          // parent inode cluster identifier
     2733    vfs_inode_t  * parent_inode_ptr;    // parent inode local pointer
     2734    xptr_t         new_dentry_xp;       // extended pointer on created dentry
     2735    vfs_dentry_t * new_dentry_ptr;      // created dentry local pointer
     2736    xptr_t         new_inode_xp;        // extended pointer on created child inode
     2737    vfs_inode_t  * new_inode_ptr;       // local pointer on created child inode
     2738
     2739    xptr_t         parents_root_xp;     // extended pointer on child inode  "parents" field
     2740    xptr_t         parents_entry_xp;    // extended pointer on child dentry "parents" field
     2741    xptr_t         children_xhtab_xp;   // extended pointer on parent inode "children" field
     2742    xptr_t         children_entry_xp;   // extended pointer on child dentry "children" field
     2743   
     2744    // get parent inode cluster and pointer
     2745    parent_cxy       = GET_CXY( parent_inode_xp );
    20522746    parent_inode_ptr = GET_PTR( parent_inode_xp );
    20532747
     
    20582752thread_t * this = CURRENT_THREAD;
    20592753if( DEBUG_VFS_ADD_CHILD < cycle )
    2060 printk("\n[%s] thread[%x,%x] enter / child <%s> cxy %x / parent <%s> cxy %x / cycle %d\n",
    2061 __FUNCTION__, this->process->pid, this->trdid, name, child_inode_cxy,
    2062 parent_name, parent_inode_cxy, (uint32_t)hal_get_cycles() );
    2063 #endif
    2064 
    2065     // 1. create dentry
    2066     if( parent_inode_cxy == local_cxy )      // parent cluster is the local cluster
     2754printk("\n[%s] thread[%x,%x] enter / child <%s> / parent <%s> / cycle %d\n",
     2755__FUNCTION__, this->process->pid, this->trdid, name,
     2756parent_name, (uint32_t)hal_get_cycles() );
     2757#endif
     2758
     2759    // 1. create dentry in parent cluster
     2760    if( parent_cxy == local_cxy )           // parent cluster is local
    20672761    {
    20682762        error = vfs_dentry_create( fs_type,
    20692763                                   name,
    2070                                    parent_inode_ptr,
    20712764                                   &new_dentry_xp );
    20722765    }
    2073     else                               // parent cluster is remote
    2074     {
    2075         rpc_vfs_dentry_create_client( parent_inode_cxy,
     2766    else                                    // parent cluster is remote
     2767    {
     2768        rpc_vfs_dentry_create_client( parent_cxy,
    20762769                                      fs_type,
    20772770                                      name,
    2078                                       parent_inode_ptr,
    20792771                                      &new_dentry_xp,
    20802772                                      &error );
     
    20842776    {
    20852777        printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n",
    2086         __FUNCTION__ , name , parent_inode_cxy );
     2778        __FUNCTION__ , name , parent_cxy );
    20872779        return -1;
    20882780    }
     
    20932785#if(DEBUG_VFS_ADD_CHILD & 1)
    20942786if( DEBUG_VFS_ADD_CHILD < cycle )
    2095 printk("\n[%s] thread[%x,%x] / dentry <%s> created in cluster %x\n",
    2096 __FUNCTION__, this->process->pid, this->trdid, name, parent_inode_cxy );
    2097 #endif
    2098 
    2099     // 2. create child inode TODO : define attr / mode / uid / gid
     2787printk("\n[%s] thread[%x,%x] / dentry <%s> created (%x,%x)\n",
     2788__FUNCTION__, this->process->pid, this->trdid, name, parent_cxy, new_dentry_ptr );
     2789#endif
     2790
     2791    // 2. create child inode in child cluster
     2792    // TODO : define attr / mode / uid / gid
    21002793    uint32_t attr = 0;
    21012794    uint32_t mode = 0;
     
    21032796    uint32_t gid  = 0;
    21042797   
    2105     if( child_inode_cxy == local_cxy )      // child cluster is the local cluster
    2106     {
    2107         error = vfs_inode_create( new_dentry_xp,
    2108                                   fs_type,
    2109                                   child_inode_type,
     2798    if( child_cxy == local_cxy )      // child cluster is local
     2799    {
     2800        error = vfs_inode_create( fs_type,
     2801                                  child_type,
    21102802                                  attr,
    21112803                                  mode,
     
    21162808    else                              // child cluster is remote
    21172809    {
    2118         rpc_vfs_inode_create_client( child_inode_cxy,
    2119                                      new_dentry_xp,
     2810        rpc_vfs_inode_create_client( child_cxy,
    21202811                                     fs_type,
    2121                                      child_inode_type,
     2812                                     child_type,
    21222813                                     attr,
    21232814                                     mode,
     
    21312822    {
    21322823        printk("\n[ERROR] in %s : cannot create inode in cluster %x\n",
    2133                __FUNCTION__ , child_inode_cxy );
     2824               __FUNCTION__ , child_cxy );
    21342825 
    2135         if( parent_inode_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
    2136         else rpc_vfs_dentry_destroy_client( parent_inode_cxy , new_dentry_ptr );
     2826        if( parent_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
     2827        else rpc_vfs_dentry_destroy_client( parent_cxy , new_dentry_ptr );
    21372828        return -1;
    21382829    }
    21392830
     2831    // get new inode local pointer
     2832    new_inode_ptr = GET_PTR( new_inode_xp );
     2833   
    21402834#if(DEBUG_VFS_ADD_CHILD & 1)
    21412835if( DEBUG_VFS_ADD_CHILD < cycle )
    2142 printk("\n[%s] thread[%x,%x] / inode <%s> created in cluster %x\n",
    2143 __FUNCTION__ , this->process->pid, this->trdid, name , child_inode_cxy );
    2144 #endif
    2145 
    2146     // 3. update "child_xp" field in dentry and increment refcounts
    2147     hal_remote_s64( XPTR( parent_inode_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp );
    2148     vfs_inode_remote_up( new_inode_xp );
    2149     vfs_dentry_remote_up( new_dentry_xp );
     2836printk("\n[%s] thread[%x,%x] / inode <%s> created (%x,%x)\n",
     2837__FUNCTION__ , this->process->pid, this->trdid, name , child_cxy, new_inode_ptr );
     2838#endif
     2839
     2840    // 3. register new_dentry in new_inode xlist of parents
     2841    parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents );
     2842    parents_entry_xp = XPTR( parent_cxy, &new_dentry_ptr->parents );
     2843    xlist_add_first( parents_root_xp , parents_entry_xp );
     2844    hal_remote_atomic_add( XPTR( child_cxy , &new_inode_ptr->links ) , 1 );
     2845
     2846#if(DEBUG_VFS_ADD_CHILD & 1)
     2847if( local_cxy == 1 )
     2848// if( DEBUG_VFS_ADD_CHILD < cycle )
     2849printk("\n[%s] thread[%x,%x] / dentry (%x,%x) registered in child inode (%x,%x)\n",
     2850__FUNCTION__, this->process->pid, this->trdid,
     2851parent_cxy, new_dentry_ptr, child_cxy, new_inode_ptr );
     2852#endif
     2853
     2854    // 4. register new_dentry in parent_inode xhtab of children
     2855    children_xhtab_xp = XPTR( parent_cxy , &parent_inode_ptr->children );
     2856    children_entry_xp = XPTR( parent_cxy , &new_dentry_ptr->children );
     2857    xhtab_insert( children_xhtab_xp , name , children_entry_xp );
     2858
     2859#if(DEBUG_VFS_ADD_CHILD & 1)
     2860if( DEBUG_VFS_ADD_CHILD < cycle )
     2861printk("\n[%s] thread[%x,%x] / dentry (%x,%x) registered in parent inode (%x,%x)\n",
     2862__FUNCTION__, this->process->pid, this->trdid,
     2863parent_cxy, new_dentry_ptr, parent_cxy, parent_inode_ptr );
     2864#endif
     2865
     2866    // 5. update "parent" and "child_xp" fields in new_dentry
     2867    hal_remote_s64( XPTR( parent_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp );
     2868    hal_remote_spt( XPTR( parent_cxy , &new_dentry_ptr->parent ) , parent_inode_ptr );
    21502869
    21512870#if DEBUG_VFS_ADD_CHILD
     
    21572876
    21582877    // return extended pointer on dentry & child inode
    2159     *dentry_xp      = new_dentry_xp;
    2160     *child_inode_xp = new_inode_xp;
     2878    *child_dentry_xp = new_dentry_xp;
     2879    *child_inode_xp  = new_inode_xp;
    21612880    return 0;
    21622881
    21632882}  // end vfs_add_child_in_parent()
    21642883
    2165 ////////////////////////////////////////////////////
    2166 void vfs_remove_child_from_parent( xptr_t inode_xp )
    2167 {
    2168     cxy_t          inode_cxy;
    2169     vfs_inode_t  * inode_ptr;
    2170     xptr_t         dentry_xp;
    2171     cxy_t          dentry_cxy;
    2172     vfs_dentry_t * dentry_ptr;
     2884/////////////////////////////////////////////////////
     2885void vfs_remove_child_from_parent( xptr_t dentry_xp )
     2886{
     2887    cxy_t          parent_cxy;         // parent inode cluster identifier
     2888    cxy_t          child_cxy;          // child inode cluster identifier
     2889    vfs_dentry_t * dentry_ptr;         // local pointer on dentry
     2890    xptr_t         child_inode_xp;     // extended pointer on child inode
     2891    vfs_inode_t  * child_inode_ptr;    // local pointer on child inode
     2892    vfs_inode_t  * parent_inode_ptr;   // local pointer on parent inode
     2893    uint32_t       links;              // number of child inode parents
     2894
     2895    char dentry_name[CONFIG_VFS_MAX_NAME_LENGTH];
    21732896   
    2174     // get inode cluster and local pointer
    2175     inode_cxy = GET_CXY( inode_xp );
    2176     inode_ptr = GET_PTR( inode_xp );
    2177 
    2178     // get associated dentry cluster and pointers
    2179     dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    2180     dentry_cxy = GET_CXY( dentry_xp );
     2897    // get parent cluster and dentry local pointer
     2898    parent_cxy = GET_CXY( dentry_xp );
    21812899    dentry_ptr = GET_PTR( dentry_xp );
    21822900
    2183 // check dentry refcount
    2184 assert( ( hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) ) == 1 ),
    2185 "dentry refcount must be 1\n" );
    2186 
    2187 // check inode refcount
    2188 assert( ( hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) ) == 1 ),
    2189 "inode refcount must be 1\n" );
    2190 
    2191     // decrement refcount for inode and dentry
    2192     vfs_inode_remote_down( inode_xp );
    2193     vfs_dentry_remote_down( dentry_xp );
    2194 
    2195     // delete dentry
    2196     if( dentry_cxy == local_cxy )
     2901    // get a local copy of dentry name
     2902    hal_remote_strcpy( XPTR( local_cxy  , dentry_name ),
     2903                       XPTR( parent_cxy , &dentry_ptr->name ) );
     2904
     2905    // get parent_inode local pointer
     2906    parent_inode_ptr = hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->parent ) );
     2907 
     2908    // get child cluster and child_inode pointers
     2909    child_inode_xp   = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2910    child_cxy        = GET_CXY( child_inode_xp );
     2911    child_inode_ptr  = GET_PTR( child_inode_xp );
     2912
     2913    // remove dentry from parent_inode
     2914    xhtab_remove( XPTR( parent_cxy , &parent_inode_ptr->children ),
     2915                  dentry_name,
     2916                  XPTR( parent_cxy , &dentry_ptr->children ) );
     2917
     2918    // remove dentry from child_inode
     2919    xlist_unlink( XPTR( parent_cxy , &dentry_ptr->parents ) );
     2920    links = hal_remote_atomic_add( XPTR( child_cxy , &child_inode_ptr->links ) , -1 );
     2921
     2922    // delete dentry descriptor
     2923    if( parent_cxy == local_cxy )
    21972924    {
    21982925         vfs_dentry_destroy( dentry_ptr );
     
    22002927    else
    22012928    {
    2202          rpc_vfs_dentry_destroy_client( dentry_cxy,
     2929         rpc_vfs_dentry_destroy_client( parent_cxy,
    22032930                                        dentry_ptr );
    22042931    }
    22052932
    2206     // delete inode
    2207     if( inode_cxy == local_cxy )
    2208     {
    2209          vfs_inode_destroy( inode_ptr );
    2210     }
    2211     else
    2212     {
    2213          rpc_vfs_inode_destroy_client( inode_cxy,
    2214                                        inode_ptr );
     2933    // delete child_inode descriptor if last link
     2934    if( links == 1 )
     2935    {
     2936        if( child_cxy == local_cxy )
     2937        {
     2938            vfs_inode_destroy( child_inode_ptr );
     2939        }
     2940        else
     2941        {
     2942            rpc_vfs_inode_destroy_client( child_cxy , child_inode_ptr );
     2943        }
    22152944    }
    22162945
     
    23743103} // end vfs_fs_child_init()
    23753104
     3105////////////////////////////////////////////////
     3106error_t vfs_fs_sync_inode( vfs_inode_t * inode )
     3107{
     3108    error_t error = 0;
     3109
     3110// check arguments
     3111assert( (inode != NULL) , "inode pointer is NULL\n");
     3112
     3113    // get inode FS type
     3114    vfs_fs_type_t fs_type = inode->ctx->type;
     3115
     3116    // call relevant FS function
     3117    if( fs_type == FS_TYPE_FATFS )
     3118    {
     3119        error = fatfs_sync_inode( inode );
     3120    }
     3121    else if( fs_type == FS_TYPE_RAMFS )
     3122    {
     3123        assert( false , "should not be called for RAMFS\n" );
     3124    }
     3125    else if( fs_type == FS_TYPE_DEVFS )
     3126    {
     3127        assert( false , "should not be called for DEVFS\n" );
     3128    }
     3129    else
     3130    {
     3131        assert( false , "undefined file system type\n" );
     3132    }
     3133
     3134    return error;
     3135
     3136}  // end vfs_fs_sync_inode()
     3137
     3138////////////////////////////////////////////////
     3139error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type )
     3140{
     3141    error_t error = 0;
     3142
     3143    // call relevant FS function
     3144    if( fs_type == FS_TYPE_FATFS )
     3145    {
     3146        error = fatfs_sync_fat();
     3147    }
     3148    else if( fs_type == FS_TYPE_RAMFS )
     3149    {
     3150        assert( false , "should not be called for RAMFS\n" );
     3151    }
     3152    else if( fs_type == FS_TYPE_DEVFS )
     3153    {
     3154        assert( false , "should not be called for DEVFS\n" );
     3155    }
     3156    else
     3157    {
     3158        assert( false , "undefined file system type\n" );
     3159    }
     3160
     3161    return error;
     3162
     3163}  // end vfs_fs_sync_fat()
     3164
     3165//////////////////////////////////////////////////////
     3166error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type )
     3167{
     3168    error_t error = 0;
     3169
     3170    // call relevant FS function
     3171    if( fs_type == FS_TYPE_FATFS )
     3172    {
     3173        error = fatfs_sync_free_info();
     3174    }
     3175    else if( fs_type == FS_TYPE_RAMFS )
     3176    {
     3177        assert( false , "should not be called for RAMFS\n" );
     3178    }
     3179    else if( fs_type == FS_TYPE_DEVFS )
     3180    {
     3181        assert( false , "should not be called for DEVFS\n" );
     3182    }
     3183    else
     3184    {
     3185        assert( false , "undefined file system type\n" );
     3186    }
     3187
     3188    return error;
     3189
     3190}  // end vfs_fs_sync_fat()
     3191
    23763192/////////////////////////////////////////////////
    23773193error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
  • trunk/kernel/fs/vfs.h

    r602 r610  
    6969 *****************************************************************************************/
    7070
    71 #define VFS_LOOKUP_DIR      0x01     /* the searched inode is a directory                */
     71#define VFS_LOOKUP_DIR      0x01     /* the searched inode must be a directory           */
    7272#define VFS_LOOKUP_OPEN         0x02     /* the search is for an open/opendir                */
    7373#define VFS_LOOKUP_PARENT       0x04     /* return the parent inode (not the inode itself)   */
    7474#define VFS_LOOKUP_CREATE   0x10     /* file must be created if missing                  */
    75 #define VFS_LOOKUP_EXCL     0x20     /* file cannot previously exist                     */   
     75#define VFS_LOOKUP_EXCL     0x20     /* file cannot previously exist                     */
    7676
    7777/******************************************************************************************
     
    117117/******************************************************************************************
    118118 * This structure define a VFS inode.
    119  * It contains an extended pointer on the parent dentry, and (for directory only)
    120  * an hash table (xhtab) registering all children dentries.
    121  * The <parent> inode is unique for a directory (no hard links for directories).
    122  * For a file, the parent field points to the first dentry who created this inode.
     119 * An inode has several children dentries (if it is a directory), an can have several
     120 * parents dentries (if it hass several aliases links):
     121 * - The "parents" field is the root of the xlist of parents dentries, and the "links"
     122 *   fiels define the number of aliases parent dentries. only a FILE inode can have
     123 *   several parents (no hard links for directories).
     124 * - The "children" field is an embedded xhtab containing pointers on all local children
     125 *   dentries. This set of children is empty for a FILE inode.
    123126 * Synchronisation:
    124  * - the main_lock (remote_busylock) is used during the inode tree traversal,
    125  *   or for inode modification (add/remove children).
    126  * - the data_lock (remote_rwlock) is used during read/write accesses to the data
    127  *   stored in the mapper.
    128  * - the mapper lock (remote rwlock) is only used during the radix tree traversal
    129  *   to return the relevant page for read/write.
     127 * - the main_lock (remote_rwlock) is used during the inode tree traversal,
     128 *   or for inode modification (add/remove children in xhtab).
     129 * - the size_lock (remote_rwlock) is used during read/write accesses to the size
     130 *   field in the mapper.
     131 * - access to the data stored in the associated mapper use the mapper remote_rwlock
     132 *   protecting radix tree traversal and modifications.
    130133 *****************************************************************************************/
    131134
     
    158161{
    159162        struct vfs_ctx_s * ctx;              /*! local pointer on FS context                 */
    160     uint32_t           gc;               /*! generation counter                          */
    161163        uint32_t           inum;             /*! inode identifier (unique in file system)    */
    162164        uint32_t           attr;             /*! inode attributes (see above)                */
    163165        vfs_inode_type_t   type;             /*! inode type (see above)                      */
    164166        uint32_t           size;             /*! number of bytes                             */
    165         uint32_t           links;            /*! number of alias dentry                      */
    166167        uint32_t           uid;              /*! user owner identifier                       */
    167168        uint32_t           gid;              /*! group owner identifier                      */
    168169    uint32_t           rights;           /*! access rights                               */
    169         uint32_t               refcount;         /*! reference counter (all pointers)            */
    170         xptr_t             parent_xp;        /*! extended pointer on parent dentry           */
     170        xlist_entry_t      parents;          /*! root of list of parents dentries            */
     171        uint32_t           links;            /*! number of parent dentries (hard links)      */
    171172        xhtab_t            children;         /*! embedded xhtab of children dentries         */
    172         remote_rwlock_t    data_lock;        /*! protect read/write to data and to size      */
    173         remote_busylock_t  main_lock;        /*! protect inode tree traversal and modifs     */
    174         list_entry_t       list;             /*! member of set of inodes in same cluster     */
    175         xlist_entry_t      wait_root;        /*! root of threads waiting on this inode       */
     173        remote_rwlock_t    size_lock;        /*! protect read/write to size                  */
     174        remote_rwlock_t    main_lock;        /*! protect inode tree traversal and modifs     */
     175//  list_entry_t       list;             /*! member of set of inodes in same cluster     */
     176//  list_entry_t       wait_root;        /*! root of threads waiting on this inode       */
    176177        struct mapper_s  * mapper;           /*! associated file cache                       */
    177178        void             * extend;           /*! fs_type_specific inode extension            */
     
    183184#define VFS_ISUID          0x0004000
    184185#define VFS_ISGID          0x0002000
    185 #define VFS_ISVTX          0x0001000
     186define VFS_ISVTX           0x0001000
    186187
    187188#define VFS_IRWXU      0x0000700
     
    203204 * This structure defines a directory entry.
    204205 * A dentry contains the name of a remote file/dir, an extended pointer on the
    205  * inode representing this file/dir, and a local pointer on the inode representing
     206 * inode representing this file/dir, a local pointer on the inode representing
    206207 * the parent directory.
     208 * A dentry can be member of the set of children of a given directory inode (xhtab).
     209 * A dentry can be member of the set of parents  of a given inode (xlist).
    207210 *****************************************************************************************/
    208211
     
    212215        char                 name[CONFIG_VFS_MAX_NAME_LENGTH];
    213216        uint32_t             length;         /*! name length (bytes)                         */
    214         uint32_t             refcount;       /*! reference counter (all pointers)            */
    215217    struct vfs_inode_s * parent;         /*! local pointer on parent inode               */
    216218    xptr_t               child_xp;       /*! extended pointer on child inode             */
    217     xlist_entry_t        list;           /*! member of list of dentries with same key    */
     219    xlist_entry_t        children;       /*! member of set of children dentries          */
     220    xlist_entry_t        parents;        /*! member of set of parent dentries            */
    218221        void               * extend;         /*! FS specific extension                       */
    219222}
     
    301304
    302305
    303 
    304306/******************************************************************************************
    305307 *        These low-level functions access / modify a VFS inode descriptor
     
    314316 * This function allocates memory from local cluster for an inode descriptor and the
    315317 * associated mapper. It initialise these descriptors from arguments values.
    316  * The parent dentry must have been previously created.
    317318 * If the client thread is not running in the cluster containing this inode,
    318319 * it must use the rpc_vfs_inode_create_client() function.
    319320 ******************************************************************************************
    320  * @ dentry_xp  : extended pointer on associated dentry (in parent inode cluster).
    321321 * @ fs_type    : file system type.
    322322 * @ inode_type : inode type.
     
    328328 * @ return 0 if success / return ENOMEM or EINVAL if error.
    329329 *****************************************************************************************/
    330 error_t vfs_inode_create( xptr_t            dentry_xp,
    331                           vfs_fs_type_t     fs_type,
     330error_t vfs_inode_create( vfs_fs_type_t     fs_type,
    332331                          vfs_inode_type_t  inode_type,
    333332                          uint32_t          attr,
     
    340339 * This function releases memory allocated to an inode descriptor, including
    341340 * all memory allocated to the mapper (both mapper descriptor and radix tree).
    342  * The mapper should not contain any dirty page (shold be synchronized before deletion),
    343  * and the inode refcount must be zero.
     341 * The mapper should not contain any dirty page (should be synchronized before deletion).
    344342 * It must be executed by a thread running in the cluster containing the inode.
    345343 * Use the rpc_vfs_inode_destroy_client() function if required.
     
    348346 *****************************************************************************************/
    349347void vfs_inode_destroy( vfs_inode_t *  inode ); 
    350 
    351 /******************************************************************************************
    352  * This function atomically increment/decrement the inode refcount.
    353  * It can be called by any thread running in any cluster.
    354  *****************************************************************************************/
    355 void vfs_inode_remote_up( xptr_t  inode_xp );
    356 void vfs_inode_remote_down( xptr_t  inode_xp );
    357348
    358349/******************************************************************************************
     
    423414 * This function allocates memory from local cluster for a dentry descriptor,
    424415 * initialises it from  arguments values, and returns the extended pointer on dentry.
    425  * The inode field is not initialized, because the inode does not exist yet.
    426416 * If the client thread is not running in the target cluster for this inode,
    427417 * it must use the rpc_dentry_create_client() function.
     
    429419 * @ fs_type    : file system type.
    430420 * @ name       : directory entry file/dir name.
    431  * @ parent     : local pointer on parent inode.
    432421 * @ dentry_xp  : [out] buffer for extended pointer on created dentry.
    433422 * @ return 0 if success / return ENOMEM or EINVAL if error.
     
    435424error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
    436425                           char          * name,
    437                            vfs_inode_t   * parent,
    438426                           xptr_t        * dentry_xp );
    439427 
    440428/******************************************************************************************
    441  * This function releases memory allocated to a dentry descriptor.
    442  * The dentry refcount must be zero.
     429 * This function removes the dentry from the parent inode xhtab, and releases the memory
     430 * allocated to the dentry descriptor.
    443431 * It must be executed by a thread running in the cluster containing the dentry.
    444432 * Use the rpc_vfs_dentry_destroy_client() function if required.
     
    447435 *****************************************************************************************/
    448436void vfs_dentry_destroy( vfs_dentry_t *  dentry ); 
    449 
    450 /******************************************************************************************
    451  * These functions atomically increment/decrement the dentry refcount.
    452  * It can be called by any thread running in any cluster.
    453  *****************************************************************************************/
    454 void vfs_dentry_remote_up( xptr_t dentry_xp );
    455 void vfs_dentry_remote_down( xptr_t dentry_xp );
    456437
    457438
     
    496477
    497478/******************************************************************************************
    498  *        These functions access / modify the distributed VFS Inode Treee
    499  *****************************************************************************************/
    500 
    501 /******************************************************************************************
    502  * This function returns in a kernel buffer allocated by the caller function,
    503  * the pathname of a file/dir identified by an extended pointer on the inode.
     479 *        These functions access / modify the distributed VFS Inode Tree
     480 *****************************************************************************************/
     481
     482/******************************************************************************************
     483 * This function returns in a kernel <buffer> allocated by the caller function,
     484 * the pathname of a file/dir identified by the <inode_xp> argument.
    504485 * It traverse the Inode Tree from the target node to the root.
    505486 * It can be called by any thread running in any cluster.
    506  ******************************************************************************************
    507  * @ inode_xp    : pointer on inode descriptor.
    508  * @ buffer      : kernel buffer for pathname (must be allocated by caller).
    509  * @ size        : max number of characters in buffer.
     487 * As this buffer if filled in "reverse order" (i.e. from the target inode to the root),
     488 * the pathname is stored in the higher part of the buffer.
     489 * A pointer on the first character of the pathname is returned in <first> buffer.
     490 *
     491 * WARNING : This function takes & releases the remote_rwlock protecting the Inode Tree.
     492 ******************************************************************************************
     493 * @ inode_xp    : [in]  extended pointer on target inode descriptor.
     494 * @ buffer      : [in]  kernel buffer for pathname (allocated by caller).
     495 * @ first       : [out] pointer on first character in buffer.
     496 * @ max_size    : [in]  max number of characters in buffer.
    510497 * @ return 0 if success / return EINVAL if buffer too small.
    511498 *****************************************************************************************/
    512499error_t vfs_get_path( xptr_t    inode_xp,
    513500                      char    * buffer,
     501                      char   ** first,
    514502                      uint32_t  max_size );
    515503
    516504/******************************************************************************************
    517  * This function takes a pathname (absolute or relative to cwd) and returns an extended
    518  * pointer on the associated inode.
     505 * This function traverses the the Inode Tree, from inode identified by the <root_xp>
     506 * argument, and returns in <inode_xp> the inode identified by the < pathname> argument.
     507 * It can be called by a thread running in any cluster.
     508 * It supports the following flags that define the lookup modes :
     509 * - VFS_LOOKUP_DIR    : the searched inode must be a directory
     510 * - VFS_LOOKUP_OPEN   : the search is for an open/opendir
     511 * - VFS_LOOKUP_PARENT : return the parent inode (not the inode itself)
     512 * - VFS_LOOKUP_CREATE : file/directory must be created if missing on IOC
     513 * - VFS_LOOKUP_EXCL   : file cannot previously exist
     514 * As the inode Tree is a cache, the search policy is the following :
    519515 * - If a given directory name in the path is not found in the inode tree, it try to load
    520516 *   the missing dentry/inode couple, from informations found in the parent directory.
    521  * - If this directory entry does not exist on device, it returns an error.
    522  * - If the the file identified by the pathname does not exist on device but the
    523  *   flag CREATE is set, the inode is created.
    524  * - If the the file identified by the pathname exist on device but both flags EXCL
     517 * - If this directory entry does not exist on IOC, it returns an error.
     518 * - If the the file identified by the pathname does not exist on IOC but the
     519 *   flag CREATE is set, the inode is created. It returns an error otherwise.
     520 * - If the the file identified by the pathname exist on device, but both flags EXCL
    525521 *   and CREATE are set, an error is returned.
    526  ******************************************************************************************
    527  * @ cwd_xp      : extended pointer on current directory (for relative path).
    528  * @ pathname    : path in kernel space (can be relative or absolute).
    529  * @ lookup_mode : flags defining the working mode (defined above in this file).
     522 * - If the PARENT flag is set, it returns in <inode_xp> an extended pointer on the parent
     523 *   inode, and copies in <last_name> buffer a string containing the last name in path.
     524 *
     525 * WARNING : The remote_rwlock protecting the Inode Tree must be taken by the caller.
     526 *
     527 * TODO the access rights are not checked yet.
     528 ******************************************************************************************
     529 * @ root_xp     : [in]  extended pointer on root inode (can be root of a subtree).
     530 * @ pathname    : [in]  path (can be relative or absolute).
     531 * @ lookup_mode : [in]  flags defining the searching mode.
    530532 * @ inode_xp    : [out] buffer for extended pointer on searched inode.
     533 * @ last_name   : [out] pointer on buffer for last name in path.
    531534 * @ return 0 if success / ENOENT if inode not found , EACCES if permisson denied,
    532  *                         EAGAIN if a new complete lookup must be made
    533  *****************************************************************************************/
    534 error_t vfs_lookup( xptr_t             cwd_xp,
     535 *****************************************************************************************/
     536error_t vfs_lookup( xptr_t             root_xp,
    535537                    char             * pathname,
    536538                    uint32_t           lookup_mode,
    537                                         xptr_t           * inode_xp );
     539                                        xptr_t           * inode_xp,
     540                    char             * last_name );
    538541
    539542/******************************************************************************************
    540543 * This function creates a new couple dentry/inode, and insert it in the Inode-Tree.
     544 * Only the distributed Inode Tree is modified: it does NOT modify the parent mapper,
     545 * and does NOT update the FS on IOC device.
    541546 * It can be executed by any thread running in any cluster (can be different from both
    542  * the child cluster and the parent cluster), as it uses RPCs if required.
    543  * Only the distributed Inode Tree is modified: Even for a new file, this function
    544  * does NOT modify the parent mapper, and does NOT update the FS on IOC device.
     547 * the child cluster and the parent cluster).
    545548 *
    546549 * [Implementation]
     
    563566 * @ return 0 if success / -1 if dentry or inode cannot be created.
    564567 *****************************************************************************************/
    565 error_t vfs_add_child_in_parent( cxy_t              child_inodecxy,
    566                                  vfs_inode_type_t   chilg_inode_type,
     568error_t vfs_add_child_in_parent( cxy_t              child_inode_cxy,
     569                                 vfs_inode_type_t   child_inode_type,
    567570                                 vfs_fs_type_t      fs_type,
    568571                                 xptr_t             parent_inode_xp,
     
    572575
    573576/******************************************************************************************
    574  * This function removes a couple dentry/inode from the Inode-Tree.
    575  * Both the inode and dentry references counters must be 1.
     577 * This function removes a remote dentry from the Inode-Tree.
     578 * - It removes the dentry from the parent inode xhtab ("children" field), and from the
     579 *   child inode xlist ("parents" field).
     580 * - It releases the memory allocated to the dentry descriptor.
     581 * - If the number of parents of the child inode is one, it also releases the memory
     582 *   allocated to the child inode.
     583 * Only the Inode Tree is modified: it does NOT modify the parent mapper,
     584 * and does NOT update the FS on IOC device.
    576585 * It can be executed by any thread running in any cluster (can be different from both
    577  * the inode cluster and the dentry cluster), as it uses RPCs if required.
    578  ******************************************************************************************
    579  * @ child_xp   : extended pointer on removed inode.
    580  *****************************************************************************************/
    581 void vfs_remove_child_from_parent( xptr_t inode_xp );
     586 * the inode cluster and the dentry cluster).
     587 ******************************************************************************************
     588 * @ dentry_xp   : extended pointer on removed dentry.
     589 *****************************************************************************************/
     590void vfs_remove_child_from_parent( xptr_t dentry_xp );
    582591
    583592/******************************************************************************************
     
    599608 *****************************************************************************************/
    600609error_t vfs_new_child_init( xptr_t   parent_xp,
    601                          xptr_t   dentry_xp,
    602                          xptr_t   child_xp );
     610                            xptr_t   dentry_xp,
     611                            xptr_t   child_xp );
    603612
    604613/******************************************************************************************
     
    661670/******************************************************************************************
    662671 * This function allocates a vfs_file_t structure in the cluster containing the inode
    663  * associated to the file identified by the <cwd_xp> & <path> arguments.
     672 * identified by the <root_xp> & <path> arguments.
    664673 * It initializes it, register it in the reference process fd_array identified by the
    665  * <process> argument, and returns both the extended pointer on the file descriptor,
    666  * and the allocated index in the fd_array.
     674 * <process_xp> argument, and returns both the extended pointer on the file descriptor,
     675 * and the allocated index in the <file_xp> and <file_id> buffers.
    667676 * The pathname can be relative to current directory or absolute.
    668  * If the inode does not exist in the inode cache, it try to find the file on the mounted
     677 * If the inode does not exist in the inode cache, it try to find the file on the IOC
    669678 * device, and creates an inode on a pseudo randomly selected cluster if found.
    670679 * It the requested file does not exist on device, it creates a new inode if the
    671680 * O_CREAT flag is set, and return an error otherwise.
     681 *
     682 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
    672683 ******************************************************************************************
    673  * @ process     : local pointer on local process descriptor copy.
     684 * @ root_xp     : extended pointer on path root inode.
    674685 * @ path        : file pathname (absolute or relative to current directory).
     686 * @ process_xp  : extended pointer on client reference process.
    675687 * @ flags       : defined in vfs_file_t structure.
    676688 * @ mode        : access rights (as defined by chmod).
     
    679691 * @ return 0 if success / return non-zero if error.
    680692 *****************************************************************************************/
    681 error_t vfs_open( struct process_s * process,
     693error_t vfs_open( xptr_t             root_xp,
    682694                          char             * path,
     695                  xptr_t             process_xp,
    683696                          uint32_t           flags,
    684697                  uint32_t           mode,
     
    721734/******************************************************************************************
    722735 * This function is called by the kernel to create in the file system a new directory
    723  * entry identified by the <cwd_xp> & <path_1>, linked to the node identified by the
    724  * <cwd_xp> & <path_2> arguments.  It can be any type of node.
    725  * If the link is successful, the link count of the target node is incremented.
    726  * <path_1> and <path_2> share equal access rights to the underlying object.
     736 * identified by the <root_xp> & <path> arguments, with the access permission defined
     737 * by the <rights> argument. All nodes in the path - but the last -  must exist.
     738 *
     739 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     740 ******************************************************************************************
     741 * @ root_xp : extended pointer on path root inode (any inode in Inode Tree).
     742 * @ path    : pathname (absolute or relative to current directory).
     743 * @ rights  : access rights.
     744 * @ returns 0 if success / -1 if error.
     745 *****************************************************************************************/
     746error_t vfs_mkdir( xptr_t   root_xp,
     747                   char   * path,
     748                   uint32_t rights );
     749
     750/******************************************************************************************
     751 * This function is called by the kernel to create in the file system a new directory
     752 * entry identified by the <new_root_xp> & <new_path> arguments, to be linked to an
     753 * existing inode, identified by the  <old_root_xp> & <old_path> arguments.
     754 * If the link is successful, the link count of the target inode is incremented.
     755 * The <new_path> and <old_path> share equal access rights to the underlying inode.
    727756 * Both the IOC device and the Inode Tree are modified.
    728  ******************************************************************************************
    729  * @ cwd_xp   : extended pointer on current working directory file descriptor.
    730  * @ path_1   : new pathname (absolute or relative to current directory).
    731  * @ path_1   : existing pathname (absolute or relative to current directory).
     757 $
     758 * TODO This function should handle any type of node, but the current implementation
     759 * handles only the FILE and DIR types.
     760 *
     761 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     762 ******************************************************************************************
     763 * @ old_root_xp : extended pointer on old path root inode (any inode in Inode Tree).
     764 * @ old_path    : old pathname (absolute or relative to current directory).
     765 * @ nld_root_xp : extended pointer on new path root inode (any inode in Inode Tree).
     766 * @ new_path    : new pathname (absolute or relative to current directory).
    732767 * @ returns 0 if success / -1 if error.
    733768 *****************************************************************************************/
    734 error_t vfs_link( xptr_t   cwd_xp,
    735                   char   * path_1,
    736                   char   * path_2 );
     769error_t vfs_link( xptr_t   old_root_xp,
     770                  char   * old_path,
     771                  xptr_t   new_root_xp,
     772                  char   * new_path );
    737773
    738774/******************************************************************************************
    739775 * This function is called by the kernel to remove from the file system a directory entry
    740  * identified by the  <cwd_xp> & <path> arguments. The target node can be any type of node.
    741  * The link count of the target node is decremented. If the removed link is the last,
    742  * the target node is deleted.
     776 * identified by the  <root_xp> & <path> arguments.
     777 * The link count of the target node is decremented.
     778 * If the removed link is the last, the target inode is deleted.
    743779 * Both the IOC device and the Inode Tree are modified.
    744  ******************************************************************************************
    745  * @ cwd_xp   : extended pointer on the current working directory file descriptor.
     780 *
     781 * TODO This function should handle any type of node, but the current implementation
     782 * handles only only the FILE and DIR types.
     783 *
     784 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     785 ******************************************************************************************
     786 * @ root_xp  : extended pointer on root inode (can be any inode in Inode Tree).
    746787 * @ path     : pathname (absolute or relative to current directory).
    747788 * @ returns 0 if success / -1 if error.
    748789 *****************************************************************************************/
    749 error_t vfs_unlink( xptr_t   cwd_xp,
     790error_t vfs_unlink( xptr_t   root_xp,
    750791                    char   * path );
    751792
    752793/******************************************************************************************
    753  * This function returns, in the structure pointed by the <st> pointer,
    754  * various informations on the inode identified by the <inode_xp> argument.
    755  * TODO : only partially implemented yet...
    756  ******************************************************************************************
    757  * @ inode_xp   : extended pointer on the remote inode.
     794 * This function returns, in the structure pointed by the <st> pointer, various
     795 * informations on the inode identified by the <root_inode_xp> and <patname> arguments.
     796 *
     797 * TODO : only partially implemented yet (only size and inum fields).
     798 *
     799 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     800 ******************************************************************************************
     801 * @ root_xp    : extended pointer on path root inode (any inode in Inode Tree)
     802 * @ pathname   : pathname to target inode.
    758803 * @ st         : local pointer on the stat structure in kernel space.
    759804 * @ returns 0 if success / -1 if error.
    760805 *****************************************************************************************/
    761 error_t vfs_stat( xptr_t        inode_xp,
     806error_t vfs_stat( xptr_t        root_xp,
     807                  char        * pathname,
    762808                  struct stat * st );
    763809
     
    775821
    776822/******************************************************************************************
    777  * This function  creates a new inode and associated dentry  for the directory defined
    778  * by the <cwd_xp> & <path> arguments.
     823 * This function  creates a new directory as defined by the <root_xp> & <path> arguments.
    779824 * TODO not implemented yet...
    780825 ******************************************************************************************
    781  * @ cwd_xp   : extended pointer on the current working directory file descriptor.
    782  * @ path     : pathname (absolute or relative to current directory).                     
     826 * @ root_xp  : extended pointer on the path root directory.
     827 * @ path     : pathname (absolute or relative to CWD).                     
    783828 * @ mode     : access rights (as defined by chmod)
    784829 * @ returns 0 if success / -1 if error.
    785830 *****************************************************************************************/
    786 error_t vfs_mkdir( xptr_t     cwd_xp,
     831error_t vfs_mkdir( xptr_t     root_xp,
    787832                   char     * path,
    788833                   uint32_t   mode );
    789834
    790835/******************************************************************************************
    791  * This function makes the directory identified by <cwd_xp / path> arguments to become
    792  * the working directory for the calling process.
     836 * This function makes the directory identified by the <root_xp and <path> arguments
     837 * to become the working directory for the calling process.
    793838 ******************************************************************************************
    794  * @ cwd_xp      : extended pointer on current directory file descriptor (relative path).
    795  * @ path        : file pathname (absolute or relative to current directory).
     839 * @ root_xp  : extended pointer on the path root directory.
     840 * @ path     : pathname (absolute or relative to CWD).
    796841 * return 0 if success / -1 if error.
    797842 *****************************************************************************************/
    798 error_t vfs_chdir( xptr_t   cwd_xp,
     843error_t vfs_chdir( xptr_t   root_xp,
    799844                   char   * path );
    800845
    801846/******************************************************************************************
    802  * This function change the access rigths for the file identified by the <cwd_xp / path>
    803  * arguments. The new access rights are defined by the <mode> argument value.
     847 * This function change the access rigths for the file/directory identified by the
     848 * <root_xp> and <path> arguments as defined by the <mode> argument value.
    804849 ******************************************************************************************
    805  * @ cwd_xp      : extended pointer on current directory file descriptor (relative path).
    806  * @ path        : file pathname (absolute or relative to current directory).
    807  * @ mode        : access rights new value.
     850 * @ root_xp  : extended pointer on the path root directory.
     851 * @ path     : pathname (absolute or relative to CWD).
     852 * @ mode     : access rights
    808853 * return 0 if success / -1 if error.
    809854 *****************************************************************************************/
    810 error_t vfs_chmod( xptr_t        cwd_xp,
     855error_t vfs_chmod( xptr_t        root_xp,
    811856                   char        * path,
    812857                   uint32_t      mode );
     
    816861 * TODO not implemented yet                                                         
    817862 ******************************************************************************************
    818  * @ path        : FIFO pathname (absolute or relative to current directory).
    819  * @ cwd_xp      : extended pointer on the current working directory file descriptor.
    820  * @ mode        : access rights new value.
    821  *****************************************************************************************/
    822 error_t vfs_mkfifo( xptr_t       cwd_xp,
     863 * @ root_xp  : extended pointer on the path root directory.
     864 * @ path     : pathname (absolute or relative to CWD).
     865 * @ mode     : access rights new value.
     866 *****************************************************************************************/
     867error_t vfs_mkfifo( xptr_t       root_xp,
    823868                    char       * path,
    824869                    uint32_t     mode );
     
    905950
    906951/*****************************************************************************************
    907  * This function updates the FS on the IOC device for the FAT itself.
    908  * It scan all clusters registered in the FAT mapper, and copies to device
    909  * each page marked as dirty.
     952 * This function updates the FS defined by the <fs_type> argument on the IOC device
     953 * for the FAT itself. It scan all clusters registered in the FAT mapper, and copies
     954 * to device each page marked as dirty.
    910955 *
    911956 * Depending on the file system type, it calls the relevant, FS specific function.
    912957 * It can be called by a thread running in any cluster.
    913958 *****************************************************************************************
     959 * @ fs_type   : specific file system type.
    914960 * @ return 0 if success / return EIO if failure during device access.
    915961 ****************************************************************************************/
    916 error_t vfs_fs_sync_fat( void );
     962error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type );
    917963
    918964/*****************************************************************************************
    919  * This function updates the free clusters info on the IOC device.
     965 * This function updates the free clusters info on the IOC device for the FS defined
     966 * by the <fs_type> argument.
    920967 *
    921968 * Depending on the file system type, it calls the relevant, FS specific function.
    922969 * It can be called by a thread running in any cluster.
    923970 *****************************************************************************************
     971 * @ fs_type   : specific file system type.
    924972 * @ return 0 if success / return EIO if failure during device access.
    925973 ****************************************************************************************/
    926 error_t vfs_fs_sync_free_info( void );
     974error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type );
    927975
    928976/******************************************************************************************
Note: See TracChangeset for help on using the changeset viewer.