source: trunk/kernel/fs/vfs.c @ 668

Last change on this file since 668 was 657, checked in by alain, 5 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 129.8 KB
RevLine 
[1]1/*
2 * vfs.c - Virtual File System implementation.
3 *
4 * Author  Mohamed Lamine Karaoui (2015)
[657]5 *         Alain Greiner (2016,2017,2018,2019,2020)
[1]6 *
7 * Copyright (c) UPMC Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-MKH is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
[14]25#include <kernel_config.h>
[457]26#include <hal_kernel_types.h>
[1]27#include <hal_atomic.h>
28#include <hal_special.h>
29#include <printk.h>
30#include <list.h>
31#include <xlist.h>
32#include <slist.h>
33#include <xhtab.h>
[430]34#include <string.h>
[1]35#include <errno.h>
36#include <kmem.h>
37#include <mapper.h>
38#include <thread.h>
[337]39#include <chdev.h>
[1]40#include <process.h>
[568]41#include <cluster.h>
[23]42#include <vfs.h>
[1]43#include <fatfs.h>
44#include <ramfs.h>
[23]45#include <devfs.h>
46#include <syscalls.h>
[1]47
48//////////////////////////////////////////////////////////////////////////////////////////
[50]49//           Extern variables         
[1]50//////////////////////////////////////////////////////////////////////////////////////////
51
[337]52extern vfs_ctx_t          fs_context[FS_TYPES_NR];    // allocated in kernel_init.c
53extern chdev_directory_t  chdev_dir;                  // allocated in kernel_init.c 
[568]54extern char *             lock_type_str[];            // allocated in kernel_init.c
[50]55 
[602]56///////////////////////////////////////////////////////////////////////////////////////////
57//           VFS Context related functions
[1]58//////////////////////////////////////////////////////////////////////////////////////////
59
[657]60///////////////////////////////////////
61void vfs_ctx_init( cxy_t           cxy,
62                   vfs_fs_type_t   fs_type,
[188]63                       uint32_t        total_clusters,
64                       uint32_t        cluster_size,
65                       xptr_t          vfs_root_xp,
66                   void          * extend )
67{
[657]68    // get pointer on relevant VFS context (same in all clusters)
69    vfs_ctx_t * vfs_ctx_ptr = &fs_context[fs_type];
[188]70
[657]71    // initialise VFS context fields
72    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->type           ) , fs_type );
73    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->total_clusters ) , total_clusters );
74    hal_remote_s32( XPTR( cxy , &vfs_ctx_ptr->cluster_size   ) , cluster_size );
75    hal_remote_s64( XPTR( cxy , &vfs_ctx_ptr->vfs_root_xp    ) , vfs_root_xp );
76    hal_remote_spt( XPTR( cxy , &vfs_ctx_ptr->extend         ) , extend );
[188]77
[657]78    // initialize VFS context lock
79    remote_busylock_init( XPTR( cxy , &vfs_ctx_ptr->lock ) , LOCK_VFS_CTX );
[188]80
[657]81    // initialize inum allocator
82    bitmap_remote_init( XPTR( cxy , &vfs_ctx_ptr->bitmap ),
83                        BITMAP_SIZE(CONFIG_VFS_MAX_INODES) ); 
[188]84
[657]85} // end vfs_ctx_init()
86
87///////////////////////////////////////////////
88error_t vfs_ctx_inum_alloc( xptr_t      ctx_xp,
[1]89                            uint32_t  * inum )
90{
[657]91    // get context cluster and local pointer
92    cxy_t       ctx_cxy = GET_CXY( ctx_xp );
93    vfs_ctx_t * ctx_ptr = GET_PTR( ctx_xp );
94
95    // build extended pointer on lock protecting the inum allocator
96    xptr_t lock_xp = XPTR( ctx_cxy , &ctx_ptr->lock );
97
98    // build extended pointer on inum bitmap
99    xptr_t bitmap_xp = XPTR( ctx_cxy , &ctx_ptr->bitmap );
100
[1]101    // get lock on inum allocator
[657]102    remote_busylock_acquire( lock_xp );
[1]103
104    // get lid from local inum allocator
[657]105    uint32_t lid = bitmap_remote_ffc( bitmap_xp , CONFIG_VFS_MAX_INODES );
[1]106
[473]107    if( lid == 0xFFFFFFFF )   // no more free slot => error
[1]108    {
109        // release lock
[657]110        remote_busylock_release( lock_xp );
[1]111
112        // return error
[657]113        return -1;
[1]114    }
115    else              // found => return inum
116    {
117        // set slot allocated
[657]118        bitmap_remote_set( bitmap_xp , lid );
[1]119
120        // release lock
[657]121        remote_busylock_release( lock_xp );
[1]122
123        // return inum
124        *inum = (((uint32_t)local_cxy) << 16) | (lid & 0xFFFF);
125        return 0;
126    }
[657]127}  // end vfs_ctx_inum_alloc()
[1]128
[657]129/////////////////////////////////////////////
130void vfs_ctx_inum_release( xptr_t     ctx_xp,
131                           uint32_t   inum )
[1]132{
[657]133    // get context cluster and local pointer
134    cxy_t       ctx_cxy = GET_CXY( ctx_xp );
135    vfs_ctx_t * ctx_ptr = GET_PTR( ctx_xp );
[1]136
[657]137    // build extended pointer on inum bitmap
138    xptr_t bitmap_xp = XPTR( ctx_cxy , &ctx_ptr->bitmap );
139
140    // build extended pointer on lock
141    xptr_t lock_xp = XPTR( ctx_cxy , &ctx_ptr->lock );
142
143    // get lock
144    remote_busylock_acquire( lock_xp );
145
146    bitmap_remote_clear( bitmap_xp , inum & 0xFFFF ); 
147
148    // release lock
149    remote_busylock_release( lock_xp );
150
151}  // end vfs_ctx_inum_release()
152
[1]153//////////////////////////////////////////////////////////////////////////////////////////
[602]154//           VFS inode descriptor related functions
[1]155//////////////////////////////////////////////////////////////////////////////////////////
156
[598]157const char * vfs_inode_type_str( vfs_inode_type_t type )
[188]158{
[598]159    switch ( type ) 
160    {
161        case INODE_TYPE_FILE: return "FILE";
162        case INODE_TYPE_DIR:  return "DIR ";
163        case INODE_TYPE_FIFO: return "FIFO";
164        case INODE_TYPE_PIPE: return "PIPE";
165        case INODE_TYPE_SOCK: return "SOCK";
166        case INODE_TYPE_DEV:  return "DEV ";
[611]167        case INODE_TYPE_BLK:  return "BLK ";
[598]168        case INODE_TYPE_SYML: return "SYML";
169        default:              return "undefined";
[527]170    }
[188]171}
172
[657]173////////////////////////////////////////////////
174error_t vfs_inode_create( cxy_t             cxy,
175                          vfs_fs_type_t     fs_type,
[23]176                          uint32_t          attr,
177                          uint32_t          rights,
178                          uid_t             uid,
179                          gid_t             gid,
180                          xptr_t          * inode_xp )
[1]181{
[657]182    xptr_t             mapper_xp;    // extended pointer on associated mapper
183    mapper_t         * mapper_ptr;   // local pointer on associated mapper
184    vfs_inode_t      * inode_ptr;    // local pointer on allocated inode
185    uint32_t           inum;         // inode identifier (to be allocated)
186    vfs_ctx_t        * ctx;          // file system context
187        kmem_req_t         req;          // request to kernel memory allocator
[1]188    error_t            error;
189
[23]190    // check fs type and get pointer on context
191    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
192    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
193    else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS];
[1]194    else
195    {
[625]196        printk("\n[ERROR] in %s : illegal FS type\n", __FUNCTION__ );
197        return -1;
[1]198    }
199
[657]200// check inode descriptor contained in one page
201assert( (sizeof(vfs_inode_t) <= CONFIG_PPM_PAGE_SIZE),
202"inode descriptor must fit in one page" );
203
[1]204    // allocate inum
[657]205    error = vfs_ctx_inum_alloc( XPTR( cxy , ctx ) , &inum );
[1]206
207    if( error )
208    {
209        printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ );
[625]210        return -1;
[1]211    }
212
[657]213    // allocate memory for mapper in cluster cxy
214    mapper_xp = mapper_create( cxy , fs_type );
[1]215
[657]216    if( mapper_xp == XPTR_NULL )
[1]217    {
218        printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ );
[657]219        vfs_ctx_inum_release( XPTR( cxy , ctx ) , inum );
220        return -1;
[1]221    }
222
[657]223    mapper_ptr = GET_PTR( mapper_xp );
[635]224
225    // allocate one page for VFS inode descriptor
[657]226    // because the embedded "children" xhtab footprint
227        req.type   = KMEM_PPM;
228        req.order  = 0;
229    req.flags  = AF_KERNEL | AF_ZERO;
230        inode_ptr  = kmem_remote_alloc( cxy , &req );
[1]231
[657]232    if( inode_ptr == NULL )
[1]233    {
234        printk("\n[ERROR] in %s : cannot allocate inode descriptor\n", __FUNCTION__ );
[657]235        vfs_ctx_inum_release( XPTR( cxy , ctx ) , inum );
236        mapper_destroy( mapper_xp );
[610]237        return -1;
[1]238    }
239
[657]240    // initialise inode field in mapper
241    hal_remote_spt( XPTR( cxy , &mapper_ptr->inode ) , inode_ptr );
242 
[1]243    // initialize inode descriptor
[657]244    hal_remote_s32( XPTR( cxy , &inode_ptr->type   ) , INODE_TYPE_FILE );  // default value
245    hal_remote_s32( XPTR( cxy , &inode_ptr->inum   ) , inum ); 
246    hal_remote_s32( XPTR( cxy , &inode_ptr->attr   ) , attr ); 
247    hal_remote_s32( XPTR( cxy , &inode_ptr->rights ) , rights ); 
248    hal_remote_s32( XPTR( cxy , &inode_ptr->links  ) , 0 );
249    hal_remote_s32( XPTR( cxy , &inode_ptr->uid    ) , uid ); 
250    hal_remote_s32( XPTR( cxy , &inode_ptr->gid    ) , gid ); 
251    hal_remote_spt( XPTR( cxy , &inode_ptr->ctx    ) , ctx ); 
252    hal_remote_spt( XPTR( cxy , &inode_ptr->mapper ) , mapper_ptr ); 
253    hal_remote_spt( XPTR( cxy , &inode_ptr->extend ) , NULL ); 
[1]254
[610]255    // initialize chidren dentries xhtab
[657]256    xhtab_init( XPTR( cxy , &inode_ptr->children ) , XHTAB_DENTRY_TYPE );
[1]257
[610]258    // initialize parents dentries xlist
[657]259    xlist_root_init( XPTR( cxy , &inode_ptr->parents ) );
[610]260 
261    // initialize lock protecting size
[657]262    remote_rwlock_init( XPTR( cxy , &inode_ptr->size_lock ), LOCK_VFS_SIZE );
[1]263
[610]264    // initialise lock protecting inode tree traversal
[657]265    remote_rwlock_init( XPTR( cxy , &inode_ptr->main_lock ), LOCK_VFS_MAIN );
[568]266
[610]267    // return extended pointer on inode
[657]268    *inode_xp = XPTR( cxy , inode_ptr );
[610]269
[438]270#if DEBUG_VFS_INODE_CREATE
[635]271uint32_t       cycle      = (uint32_t)hal_get_cycles();
272thread_t *     this       = CURRENT_THREAD;
[438]273if( DEBUG_VFS_INODE_CREATE < cycle )
[657]274printk("\n[%s] thread[%x,%x] created inode (%x,%x) / ctx %x / fs_type %d / cycle %d\n",
275__FUNCTION__, this->process->pid, this->trdid, cxy, inode_ptr, ctx, ctx->type, cycle );
[433]276#endif
[401]277 
[1]278    return 0;
279
280}  // end vfs_inode_create() 
281
[657]282//////////////////////////////////////////
283void vfs_inode_destroy( xptr_t  inode_xp )
[1]284{
[657]285    // get cluster and local pointer
286    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
287    cxy_t         inode_cxy = GET_CXY( inode_xp );
288
[1]289    // release memory allocated for mapper
[657]290    mapper_destroy( XPTR( inode_cxy , &inode_ptr->mapper ) );
[1]291
[657]292    // release memory allocated for inode descriptor
[1]293        kmem_req_t req;
[635]294        req.type  = KMEM_PPM;
[657]295        req.ptr   = inode_ptr;
296        kmem_remote_free( inode_cxy , &req );
[1]297
298}  // end vfs_inode_destroy()
299
300//////////////////////////////////////////////
301uint32_t vfs_inode_get_size( xptr_t inode_xp )
302{
303    // get inode cluster and local pointer
304    cxy_t         cxy = GET_CXY( inode_xp );
[473]305    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]306
[623]307    // build extended pointers on lock & size
308    xptr_t   lock_xp = XPTR( cxy , &ptr->size_lock );
309    xptr_t   size_xp = XPTR( cxy , &ptr->size );
310
311    // take lock in read mode
312    remote_rwlock_rd_acquire( lock_xp );
313
[1]314    // get size
[623]315    uint32_t size = hal_remote_l32( size_xp );
316
317    // release lock from read mode
318    remote_rwlock_rd_release( lock_xp );
319
[1]320    return size;
321}
322
[623]323///////////////////////////////////////////////
324void vfs_inode_update_size( xptr_t    inode_xp,
325                            uint32_t  size )
[1]326{
327    // get inode cluster and local pointer
328    cxy_t         cxy = GET_CXY( inode_xp );
[473]329    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]330
[623]331    // build extended pointers on lock & size
332    xptr_t   lock_xp = XPTR( cxy , &ptr->size_lock );
333    xptr_t   size_xp = XPTR( cxy , &ptr->size );
334
335    // take lock in write mode
336    remote_rwlock_wr_acquire( lock_xp );
337
338    // get current size
339    uint32_t current_size = hal_remote_l32( size_xp );
340
341    // set size if required
342    if( current_size < size ) hal_remote_s32( size_xp , size );
343
344    // release lock from write mode
345    remote_rwlock_wr_release( lock_xp );
[1]346}
347
[101]348////////////////////////////////////////
349void vfs_inode_unlock( xptr_t inode_xp )
[1]350{
351    // get inode cluster and local pointer
352    cxy_t         cxy = GET_CXY( inode_xp );
[473]353    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]354
355    // release the main lock
[568]356    remote_busylock_release( XPTR( cxy , &ptr->main_lock ) );
[1]357}
358
[101]359//////////////////////////////////////
360void vfs_inode_lock( xptr_t inode_xp )
[1]361{
362    // get inode cluster and local pointer
363    cxy_t         cxy = GET_CXY( inode_xp );
[473]364    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]365
366    // get the main lock
[568]367    remote_busylock_acquire( XPTR( cxy , &ptr->main_lock ) );
[1]368}
369
[610]370///////////////////////////////////////////
371void vfs_inode_get_name( xptr_t   inode_xp,
372                         char   * name )
[101]373{
[610]374    cxy_t          inode_cxy;          // inode cluster identifier
375    vfs_inode_t  * inode_ptr;          // local pointer on inode
376    xptr_t         parents_root_xp;    // extended pointer on inode parents root
[204]377   
378    // get inode cluster and local pointer
[657]379    inode_ptr = GET_PTR( inode_xp );
[204]380    inode_cxy = GET_CXY( inode_xp );
381
[610]382    // build extended pointer on parents dentries root
383    parents_root_xp  = XPTR( inode_cxy , &inode_ptr->parents );
[204]384
[610]385    // check VFS root
386    if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root
[204]387    {
388        strcpy( name , "/" );
389    }
[610]390    else                                     // not the VFS root
[204]391    {
[610]392        xptr_t         dentry_xp;
393        cxy_t          dentry_cxy;
394        vfs_dentry_t * dentry_ptr;
395
396        // get first name in list of parents
397        dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
[204]398        dentry_cxy = GET_CXY( dentry_xp );
[473]399        dentry_ptr = GET_PTR( dentry_xp );
[204]400
401        hal_remote_strcpy( XPTR( local_cxy  , name ) , 
[610]402                           XPTR( dentry_cxy , dentry_ptr->name ) );
[204]403    }
[610]404
[409]405}  // end vfs_inode_get_name()
[204]406
[657]407////////////////////////////////////////////////////
408error_t vfs_inode_load_all_pages( xptr_t  inode_xp )
[602]409{
410    uint32_t   page_id;
411    xptr_t     page_xp;
412
413
[657]414    // get inode cluster and local pointer
415    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
416    cxy_t         inode_cxy = GET_CXY( inode_xp );
[602]417
[657]418    // get pointer on mapper and size
419    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
420    uint32_t   size   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size ) );
421
[602]422#if DEBUG_VFS_INODE_LOAD_ALL
[657]423char       name[CONFIG_VFS_MAX_NAME_LENGTH];
[602]424uint32_t   cycle = (uint32_t)hal_get_cycles();
425thread_t * this  = CURRENT_THREAD;
[657]426vfs_inode_get_name( inode_xp , name );
[602]427if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
428printk("\n[%s] thread[%x,%x] enter for <%s> in cluster %x / cycle %d\n",
[657]429__FUNCTION__, this->process->pid, this->trdid, name, inode_cxy, cycle );
[602]430#endif
431
432    // compute number of pages
433    uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
434    if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++;
435
436    // loop on pages
437    for( page_id = 0 ; page_id < npages ; page_id ++ )
438    {
439        // If the mage is missing, this function allocates the missing page,
440        // and load the page from IOC device into mapper
[657]441        page_xp = mapper_get_page( XPTR( inode_cxy , mapper ), page_id );
[602]442
443        if( page_xp == XPTR_NULL ) return -1;
444    }
445
446#if DEBUG_VFS_INODE_LOAD_ALL
447cycle = (uint32_t)hal_get_cycles();
448if( DEBUG_VFS_INODE_LOAD_ALL < cycle )
[657]449printk("\n[%s] thread[%x,%x] exit for <%s> in cluster %x\n",
450__FUNCTION__, this->process->pid, this->trdid, name, inode_cxy );
[602]451#endif
452
453    return 0;
454
455}  // end vfs_inode_load_all_pages()
456
[626]457/////////////////////////////////////////
458void vfs_inode_display( xptr_t inode_xp )
459{
460    assert( (inode_xp != XPTR_NULL), "inode pointer is NULL");
461
462    char  name[CONFIG_VFS_MAX_NAME_LENGTH];
463
464    vfs_inode_get_name( inode_xp , name );
465
[657]466    // get inode cluster and local pointer
[626]467    cxy_t         inode_cxy = GET_CXY( inode_xp );
468    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
469
470    vfs_inode_type_t type    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
471    uint32_t         attr    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->attr ) );
472    uint32_t         size    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size ) );
473    uint32_t         parents = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->links ) );
474    mapper_t       * mapper  = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
475    void           * extend  = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->extend ) );
476
477    printk("\n**** inode <%s>\n"
478           " - type    = %s\n"
479           " - attr    = %x\n"
480           " - size    = %d\n"
481           " - parents = %d\n"
482           " - cxy     = %x\n"
483           " - inode   = %x\n"
484           " - mapper  = %x\n"
485           " - extend  = %x\n",
486           name,
487           vfs_inode_type_str( type ),
488           attr,
489           size,
490           parents,
491           inode_cxy,
492           inode_ptr,
493           mapper,
494           extend );
495
496}  // end vfs_inode_display()
497
498
[204]499////////////////////////////////////////////////////////////////////////////////////////////
[602]500//          VFS dentry descriptor related functions
[1]501//////////////////////////////////////////////////////////////////////////////////////////
502
[657]503///////////////////////////////////////////////
504error_t vfs_dentry_create( cxy_t           cxy,
505                           vfs_fs_type_t   fs_type,
[23]506                           char          * name,
507                           xptr_t        * dentry_xp )
[1]508{
[657]509        kmem_req_t       req;            // request to kernel memory allocator
510    vfs_ctx_t      * ctx = NULL;     // context descriptor
511    vfs_dentry_t   * dentry_ptr;     // dentry descriptor (to be allocated)
[1]512
[657]513#if DEBUG_VFS_DENTRY_CREATE
514thread_t * this  = CURRENT_THREAD;
515uint32_t   cycle = (uint32_t)hal_get_cycles();
516if( DEBUG_VFS_DENTRY_CREATE < cycle )
517printk("\n[%s] thread[%x,%x] enters for <%s> /  fs_type %x / cycle %d\n",
518__FUNCTION__, this->process->pid, this->trdid, name, fs_type, cycle );
519#endif
520
[188]521    // get pointer on context
[23]522    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
523    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
524    else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS];
[459]525    else 
[1]526    {
[657]527        printk("\n[ERROR] in %s undefined fs_type %d\n", __FUNCTION__, fs_type );
[610]528        return -1;
[1]529    }
530
531    // get name length
532    uint32_t length = strlen( name );
533
[657]534    if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return -1;
[437]535
[1]536    // allocate memory for dentry descriptor
[657]537        req.type   = KMEM_KCM;
538        req.order  = bits_log2( sizeof(vfs_dentry_t) );
539    req.flags  = AF_KERNEL | AF_ZERO;
540        dentry_ptr = kmem_remote_alloc( cxy , &req );
[1]541
[657]542    if( dentry_ptr == NULL ) 
[610]543    {
544        printk("\n[ERROR] in %s : cannot allocate dentry descriptor\n",
545        __FUNCTION__ );
546        return -1;
547    }
[437]548
[1]549    // initialize dentry descriptor
[657]550    hal_remote_spt( XPTR( cxy , &dentry_ptr->ctx    ) , ctx );
551    hal_remote_s32( XPTR( cxy , &dentry_ptr->length ) , length );
552    hal_remote_spt( XPTR( cxy , &dentry_ptr->extend ) , NULL );
[1]553
[657]554    // register name
555    hal_remote_strcpy( XPTR( cxy, dentry_ptr->name ),
556                       XPTR( local_cxy, name ) );
557
[23]558    // return extended pointer on dentry
[657]559    *dentry_xp = XPTR( cxy , dentry_ptr );
[1]560
[438]561#if DEBUG_VFS_DENTRY_CREATE
562if( DEBUG_VFS_DENTRY_CREATE < cycle )
[657]563printk("\n[%s] thread[%x,%x] exit for <%s> / dentry (%x,%x)\n",
564__FUNCTION__, this->process->pid, this->trdid, name, cxy, dentry_ptr );
[433]565#endif
[296]566
[1]567    return 0;
568
569}  // end vfs_dentry_create()
570
[657]571////////////////////////////////////////////
572void vfs_dentry_destroy( xptr_t  dentry_xp )
[1]573{
[657]574    // get cluster and local pointer
575    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
576    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
577 
[459]578    // release memory allocated to dentry
[1]579        kmem_req_t req;
[635]580        req.type  = KMEM_KCM;
[657]581        req.ptr   = dentry_ptr;
582        kmem_remote_free( dentry_cxy , &req );
[459]583
[602]584}  // end vfs_dentry_destroy()
585
586
[1]587//////////////////////////////////////////////////////////////////////////////////////////
[602]588//       VFS file descriptor related functions
[1]589//////////////////////////////////////////////////////////////////////////////////////////
590
[23]591/////////////////////////////////////////////
[657]592error_t vfs_file_create( xptr_t     inode_xp,
593                         uint32_t   attr,
594                         xptr_t   * file_xp )
[23]595{
[657]596    vfs_file_t  * file_ptr;
[23]597        kmem_req_t    req;
[657]598    uint32_t      type;
599    mapper_t    * mapper;
600    vfs_ctx_t   * ctx;
[23]601
[657]602    // get inode cluster and local pointer
603    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
604    cxy_t         inode_cxy = GET_CXY( inode_xp );
605
[568]606#if DEBUG_VFS_FILE_CREATE
[598]607thread_t * this = CURRENT_THREAD;
[568]608uint32_t cycle = (uint32_t)hal_get_cycles();
609if( DEBUG_VFS_OPEN < cycle )
[657]610printk("\n[%s] thread[%x,%x] enter for inode (%x,%x) / cycle %d\n",
611__FUNCTION__, this->process->pid, this->trdid, inode_cxy, inode_ptr, cycle );
[568]612#endif
613
[23]614    // allocate memory for new file descriptor
[635]615        req.type  = KMEM_KCM;
616        req.order = bits_log2( sizeof(vfs_file_t) );
[23]617    req.flags = AF_KERNEL | AF_ZERO;
[657]618        file_ptr  = kmem_remote_alloc( inode_cxy , &req );
[23]619
[657]620    if( file_ptr == NULL ) return -1;
[23]621
[657]622    // get type, ctx and mapper from inode descriptor
623    type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
624    ctx    = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) );
625    mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
626
[23]627    // initializes new file descriptor
[657]628    hal_remote_s32( XPTR( inode_cxy , &file_ptr->type     ) , type );
629    hal_remote_s32( XPTR( inode_cxy , &file_ptr->attr     ) , attr );
630    hal_remote_s32( XPTR( inode_cxy , &file_ptr->offset   ) , 0 );
631    hal_remote_s32( XPTR( inode_cxy , &file_ptr->refcount ) , 1 );
632    hal_remote_spt( XPTR( inode_cxy , &file_ptr->inode    ) , inode_ptr );
633    hal_remote_spt( XPTR( inode_cxy , &file_ptr->ctx      ) , ctx );
634    hal_remote_spt( XPTR( inode_cxy , &file_ptr->mapper   ) , mapper );
[23]635
[657]636    remote_rwlock_init( XPTR( inode_cxy , &file_ptr->lock ), LOCK_VFS_FILE );
[23]637
[657]638    *file_xp = XPTR( inode_cxy , file_ptr );
[459]639
[568]640#if DEBUG_VFS_FILE_CREATE
641cycle = (uint32_t)hal_get_cycles();
[459]642if( DEBUG_VFS_OPEN < cycle )
[657]643printk("\n[%s] thread[%x,%x] created file (%x,%x) %x\n",
644__FUNCTION__, this->process->pid, this->trdid, inode_cxy, file_ptr, cycle );
[459]645#endif
646
[23]647    return 0;
648
649}  // end vfs_file_create()
650
[657]651////////////////////////////////////////
652void vfs_file_destroy( xptr_t  file_xp )
[23]653{
[657]654    // get file cluster and local pointer
655    vfs_file_t * file_ptr = GET_PTR( file_xp );
656    cxy_t        file_cxy = GET_CXY( file_xp );
657
658    // release file descriptor
[23]659        kmem_req_t req;
[635]660        req.type  = KMEM_KCM;
[657]661        req.ptr   = file_ptr;
662        kmem_remote_free( file_cxy , &req );
[23]663
[459]664#if DEBUG_VFS_CLOSE
[623]665char name[CONFIG_VFS_MAX_NAME_LENGTH];
[657]666vfs_file_get_name( file_xp , name );
[598]667thread_t * this = CURRENT_THREAD;
[459]668uint32_t cycle = (uint32_t)hal_get_cycles();
669if( DEBUG_VFS_CLOSE < cycle )
[623]670printk("\n[%s] thread[%x,%x] deleted file <%s> in cluster %x / cycle %d\n",
[657]671__FUNCTION__, this->process->pid, this->trdid, name, file_cxy, cycle );
[459]672#endif
673
[23]674}  // end vfs_file_destroy()
675
676
[1]677////////////////////////////////////////
678void vfs_file_count_up( xptr_t file_xp )
679{
680    // get file cluster and local pointer
681    cxy_t        file_cxy = GET_CXY( file_xp );
[459]682    vfs_file_t * file_ptr = GET_PTR( file_xp ); 
[1]683
684    // atomically increment count
685    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 
686}
687
688//////////////////////////////////////////
689void vfs_file_count_down( xptr_t file_xp )
690{
691    // get file cluster and local pointer
692    cxy_t        file_cxy = GET_CXY( file_xp );
[459]693    vfs_file_t * file_ptr = GET_PTR( file_xp ); 
[1]694
695    // atomically decrement count
696    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 
697}
698
[623]699///////////////////////////////////////
700void vfs_file_get_name( xptr_t file_xp,
701                        char * name )
702{
703    // get cluster and local pointer on remote file
704    vfs_file_t * file_ptr = GET_PTR( file_xp );
705    cxy_t        file_cxy = GET_CXY( file_xp );
706
707    // get pointers on remote inode
708    vfs_inode_t * inode_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) ); 
709    xptr_t        inode_xp  = XPTR( file_cxy , inode_ptr );
710
711    // call the relevant function
712    vfs_inode_get_name( inode_xp , name );
713}
714
715
[23]716//////////////////////////////////////////////////////////////////////////////////////////
[602]717//           "syscalls" API related functions
[23]718//////////////////////////////////////////////////////////////////////////////////////////
719
[407]720//////////////////////////////////////
[610]721error_t vfs_open( xptr_t      root_xp,
[407]722                          char      * path,
[610]723                  xptr_t      process_xp,
[407]724                          uint32_t    flags,
725                  uint32_t    mode, 
726                          xptr_t    * new_file_xp,
727                  uint32_t  * new_file_id )
[1]728{
[610]729    error_t        error;
730    xptr_t         inode_xp;       // extended pointer on target inode
731    cxy_t          inode_cxy;      // inode cluster identifier       
732    vfs_inode_t  * inode_ptr;      // inode local pointer
733    uint32_t       file_attr;      // file descriptor attributes
734    uint32_t       lookup_mode;    // lookup working mode       
735    xptr_t         file_xp;        // extended pointer on created file descriptor
736    uint32_t       file_id;        // created file descriptor index in reference fd_array
737    xptr_t         vfs_root_xp;    // extended pointer on VFS root inode
738    vfs_inode_t  * vfs_root_ptr;   // local pointer on VFS root inode
739    cxy_t          vfs_root_cxy;   // VFS root inode cluster identifier
740    xptr_t         lock_xp;        // extended pointer on Inode Tree lock
[1]741
[602]742    if( mode != 0 )
743    {
744        printk("\n[ERROR] in %s : the mode parameter is not supported yet\n" );
745        return -1;
746    }
747
[610]748    thread_t  * this    = CURRENT_THREAD;
749    process_t * process = this->process;
750
[647]751    // compute lookup working mode
752    lookup_mode = VFS_LOOKUP_OPEN;
753    if( (flags & O_DIR    )      )  lookup_mode |= VFS_LOOKUP_DIR;
754    if( (flags & O_CREAT  )      )  lookup_mode |= VFS_LOOKUP_CREATE;
755    if( (flags & O_EXCL   )      )  lookup_mode |= VFS_LOOKUP_EXCL;
756 
[438]757#if DEBUG_VFS_OPEN
[433]758uint32_t cycle = (uint32_t)hal_get_cycles();
[438]759if( DEBUG_VFS_OPEN < cycle )
[610]760printk("\n[%s] thread[%x,%x] enter for <%s> / root_inode (%x,%x) / cycle %d\n",
761__FUNCTION__, process->pid, this->trdid, path, GET_CXY(root_xp), GET_PTR(root_xp), cycle );
[433]762#endif
[101]763
[23]764    // compute attributes for the created file
765    file_attr = 0;
[407]766    if( (flags & O_RDONLY ) == 0 )  file_attr |= FD_ATTR_WRITE_ENABLE;
767    if( (flags & O_WRONLY ) == 0 )  file_attr |= FD_ATTR_READ_ENABLE;
[23]768    if( (flags & O_SYNC   )      )  file_attr |= FD_ATTR_SYNC;
769    if( (flags & O_APPEND )      )  file_attr |= FD_ATTR_APPEND;
770    if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC;
[1]771
[610]772    // build extended pointer on lock protecting Inode Tree
773    vfs_root_xp  = process->vfs_root_xp;
774    vfs_root_ptr = GET_PTR( vfs_root_xp );
775    vfs_root_cxy = GET_CXY( vfs_root_xp );
776    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
777
778    // take lock protecting Inode Tree in read mode
779    remote_rwlock_rd_acquire( lock_xp );
780
[23]781    // get extended pointer on target inode
[610]782    error = vfs_lookup( root_xp,
783                        path,
784                        lookup_mode,
785                        &inode_xp,
786                        NULL );
[23]787
[610]788    // release lock protecting Inode Tree
789    remote_rwlock_rd_release( lock_xp );
[23]790
[610]791    if( error )
792    {
793        printk("\n[ERROR] in %s : cannot get inode <%s>\n",
794        __FUNCTION__ , path );
795        return -1;
796    }
797
[23]798    // get target inode cluster and local pointer
799    inode_cxy = GET_CXY( inode_xp );
[473]800    inode_ptr = GET_PTR( inode_xp );
[23]801   
[610]802#if (DEBUG_VFS_OPEN & 1)
803cycle = (uint32_t)hal_get_cycles();
804if( DEBUG_VFS_OPEN < cycle )
805printk("\n[%s] thread[%x,%x] found inode(%x,%x) for <%s>\n",
806__FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr, path );
807#endif
808
[23]809    // create a new file descriptor in cluster containing inode
[657]810    error = vfs_file_create( inode_xp , file_attr , &file_xp );
[1]811
[23]812    if( error )  return error;
[1]813
[610]814#if (DEBUG_VFS_OPEN & 1)
815cycle = (uint32_t)hal_get_cycles();
816if( DEBUG_VFS_OPEN < cycle )
817printk("\n[%s] thread[%x,%x] created file descriptor (%x,%x) for <%s>\n",
818__FUNCTION__, process->pid, this->trdid, GET_CXY(file_xp), GET_PTR(file_xp), path );
819#endif
820
[407]821    // allocate and register a new file descriptor index in reference process
[610]822    error = process_fd_register( process_xp , file_xp , &file_id );
[1]823
[23]824    if( error ) return error;
[1]825
[438]826#if DEBUG_VFS_OPEN
[433]827cycle = (uint32_t)hal_get_cycles();
[438]828if( DEBUG_VFS_OPEN < cycle )
[657]829printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / file(%x,%x) / cycle %d\n",
830__FUNCTION__, process->pid, this->trdid, path, file_id,
831GET_CXY( file_xp ), GET_PTR( file_xp ), cycle );
[433]832#endif
[238]833
[23]834    // success
835    *new_file_xp = file_xp;
836    *new_file_id = file_id;
837    return 0;
[1]838
[23]839}  // end vfs_open()
840
[656]841///////////////////////////////////////////
842uint32_t vfs_user_move( bool_t   to_buffer,
843                        xptr_t   file_xp,
844                        void   * buffer,
845                        uint32_t count )
[23]846{
[656]847    cxy_t              file_cxy;       // remote file descriptor cluster
848    vfs_file_t       * file_ptr;       // remote file descriptor local pointer
849    mapper_t         * mapper;         // local pointer on file mapper
850    vfs_inode_t      * inode;          // local pointer on file inode
851    vfs_inode_type_t   type;           // inode type
852    uint32_t           offset;         // current offset in file
853    uint32_t           size;           // current file size
854    uint32_t           nbytes;         // number of bytes actually transfered
[23]855    error_t            error;
856
[602]857// check argument
[625]858assert( (file_xp != XPTR_NULL), "file_xp == XPTR_NULL" );
[602]859
[23]860    // get cluster and local pointer on remote file descriptor
861    file_cxy  = GET_CXY( file_xp );
[473]862    file_ptr  = GET_PTR( file_xp );
[23]863
[656]864    // get various infos from remote file descriptor
865    type   = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) );
866    offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
867    mapper = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
868    inode  = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode  ) );
869    size   = hal_remote_l32( XPTR( file_cxy , &inode->size      ) );
[23]870   
[602]871// check inode type
[656]872assert( (type == INODE_TYPE_FILE), "bad inode type" );
[23]873
[626]874#if DEBUG_VFS_USER_MOVE
875char          name[CONFIG_VFS_MAX_NAME_LENGTH];
876uint32_t      cycle      = (uint32_t)hal_get_cycles();
877thread_t    * this       = CURRENT_THREAD;
878vfs_inode_get_name( XPTR( file_cxy , inode ) , name );
879if( cycle > DEBUG_VFS_USER_MOVE )
880{
881    if( to_buffer ) 
[628]882    printk("\n[%s] thread[%x,%x] enter / %d bytes / map(%s) -> buf(%x) / offset %d / cycle %d\n",
[656]883    __FUNCTION__ , this->process->pid, this->trdid, count, name, buffer, offset, cycle );
[626]884    else           
[628]885    printk("\n[%s] thread[%x,%x] enter / %d bytes / buf(%x) -> map(%s) / offset %d / cycle %d\n",
[656]886    __FUNCTION__ , this->process->pid, this->trdid, count, buffer, name, offset, cycle );
[626]887}
888#endif
889
[656]890    if( to_buffer ) // => compute the number of bytes to move and make the move
891    {
892        // compute number of bytes to move
893        if     ( size <= offset )         nbytes = 0; 
894        else if( size < offset + count )  nbytes = size - offset;
895        else                              nbytes = count;
896
897        // move data from mapper to buffer when required
898        if( nbytes > 0 )
899        {     
900            error = mapper_move_user( XPTR( file_cxy , mapper ),
901                                      to_buffer,
902                                      offset,
903                                      buffer,
904                                      nbytes );
905        }
906        else
907        {
908            error = 0;
909        }
910    }
911    else // to mapper => make the move and update the file size if required
912    {
913        nbytes = count;
914
915        // move data from buffer to mapper
916        error = mapper_move_user( XPTR( file_cxy , mapper ),
917                                  to_buffer,
918                                  offset,
919                                  buffer,
920                                  count );
921
922        // update file size in inode if required
923        if( offset + count > size ) 
924        {
925            vfs_inode_update_size( XPTR( file_cxy , inode ) , offset + count );
926        }
927    }
928       
[602]929    if( error ) 
930    {
[625]931        printk("\n[ERROR] in %s : cannot move data", __FUNCTION__ );
[602]932        return -1;
933    }
934
[625]935    // update file offset in file descriptor
[656]936    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->offset ) , nbytes );
[625]937
938#if DEBUG_VFS_USER_MOVE
[626]939cycle = (uint32_t)hal_get_cycles();
[625]940if( cycle > DEBUG_VFS_USER_MOVE )
941{
942    if( to_buffer ) 
[656]943    printk("\n[%s] thread[%x,%x] exit / %d bytes moved from mapper to buffer\n",
944    __FUNCTION__ , this->process->pid, nbytes );
[625]945    else           
[657]946    printk("\n[%s] thread[%x,%x] exit / %d bytes moved from buffer to mapper\n",
947    __FUNCTION__ , this->process->pid, nbytes );
[625]948}
949#endif
950
[656]951    return nbytes;
[602]952
[313]953}  // end vfs_user_move()
[23]954
[317]955////////////////////////////////////////////
956error_t vfs_kernel_move( bool_t   to_buffer,
957                         xptr_t   file_xp,
958                         xptr_t   buffer_xp,
959                         uint32_t size )
960{
961    cxy_t              file_cxy;     // remote file descriptor cluster
962    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
[602]963    vfs_inode_type_t   inode_type;   // remote file type
[317]964    uint32_t           file_offset;  // current offset in file
[602]965    mapper_t         * mapper_ptr;   // remote mapper local pointer
966    xptr_t             mapper_xp;    // remote mapper extended pointer
[317]967    error_t            error;
968
[602]969// check argument
[625]970assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
[602]971
[317]972    // get cluster and local pointer on remote file descriptor
973    file_cxy  = GET_CXY( file_xp );
[473]974    file_ptr  = GET_PTR( file_xp );
[317]975
976    // get inode type from remote file descriptor
[568]977    inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) );
[610]978
[625]979// check inode type
980assert( (inode_type == INODE_TYPE_FILE), "bad file type" );
[317]981
[625]982    // get mapper pointers and file offset from file descriptor
983    file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
984    mapper_ptr  = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
985    mapper_xp   = XPTR( file_cxy , mapper_ptr );
986
987    // move data between mapper and buffer
988    error = mapper_move_kernel( mapper_xp,
989                                to_buffer,
990                                file_offset,
991                                buffer_xp,
992                                size );
993    if( error ) 
[317]994    {
[625]995        printk("\n[ERROR] in %s : cannot move data", __FUNCTION__ );
[317]996        return -1;
997    }
[602]998
[625]999#if DEBUG_VFS_KERNEL_MOVE
1000char          name[CONFIG_VFS_MAX_NAME_LENGTH];
1001uint32_t      cycle      = (uint32_t)hal_get_cycles();
1002thread_t    * this       = CURRENT_THREAD;
1003cxy_t         buffer_cxy = GET_CXY( buffer_xp );
1004void        * buffer_ptr = GET_PTR( buffer_xp );
1005vfs_inode_t * inode      = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
1006vfs_inode_get_name( XPTR( file_cxy , inode ) , name );
1007if( cycle > DEBUG_VFS_KERNEL_MOVE )
1008{
1009    if( to_buffer ) 
1010    printk("\n[%s] thread[%x,%x] moves %d bytes from <%s> mapper to buffer(%x,%x) / cycle %d\n",
1011    __FUNCTION__ , this->process->pid, this->trdid, size, name, buffer_cxy, buffer_ptr );
1012    else           
1013    printk("\n[%s] thread[%x,%x] moves %d bytes from buffer(%x,%x) to <%s> mapper / cycle %d\n",
1014    __FUNCTION__ , this->process->pid, this->trdid, size, buffer_cxy, buffer_ptr, name );
1015}
1016#endif
1017
[602]1018    return 0;
1019
[317]1020}  // end vfs_kernel_move()
1021
[23]1022//////////////////////////////////////
1023error_t vfs_lseek( xptr_t     file_xp,
1024                   uint32_t   offset,
1025                   uint32_t   whence, 
1026                   uint32_t * new_offset )
1027{
[266]1028    xptr_t         offset_xp;
1029    xptr_t         lock_xp;
[602]1030    xptr_t         size_xp;
[266]1031    cxy_t          file_cxy;
1032    vfs_file_t  *  file_ptr;
1033    vfs_inode_t *  inode_ptr;
1034    uint32_t       new;
1035
[651]1036// check arguments
[625]1037assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
[651]1038assert( (new_offset != NULL )  , "new_offset == NULL" );
[266]1039
1040    // get cluster and local pointer on remote file descriptor
1041    file_cxy = GET_CXY( file_xp );
[473]1042    file_ptr = GET_PTR( file_xp );
[266]1043
[602]1044    // get local pointer on remote inode
1045    inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
1046
1047    // build extended pointers on lock, offset and size
[266]1048    offset_xp = XPTR( file_cxy , &file_ptr->offset );
1049    lock_xp   = XPTR( file_cxy , &file_ptr->lock );
[602]1050    size_xp   = XPTR( file_cxy , &inode_ptr->size );
[266]1051
1052    // take file descriptor lock
[568]1053    remote_rwlock_wr_acquire( lock_xp );
[266]1054
1055    if      ( whence == SEEK_CUR )   // new = current + offset
1056    {
[568]1057        new = hal_remote_l32( offset_xp ) + offset;
[266]1058    }
1059    else if ( whence == SEEK_SET )   // new = offset
1060    {
1061        new = offset;
1062    }
1063    else if ( whence == SEEK_END )   // new = size + offset
1064    { 
[602]1065        new = hal_remote_l32( size_xp ) + offset;
[266]1066    }
1067    else
1068    {
1069        printk("\n[ERROR] in %s : illegal whence value\n", __FUNCTION__ );
[568]1070        remote_rwlock_wr_release( lock_xp );
[266]1071        return -1;
1072    }
1073
[602]1074#if DEBUG_VFS_LSEEK
1075uint32_t   cycle = (uint32_t)hal_get_cycles();
1076thread_t * this  = CURRENT_THREAD;
1077char       name[CONFIG_VFS_MAX_NAME_LENGTH];
1078vfs_inode_get_name( XPTR( file_cxy , inode_ptr ) , name );
1079if( cycle > DEBUG_VFS_LSEEK )
1080printk("\n[%s] thread[%x,%x] for <%s> / new offset %d / cycle %d\n",
1081__FUNCTION__ , this->process->pid, this->trdid, name, new, cycle );
1082#endif
1083
[266]1084    // set new offset
[568]1085    hal_remote_s32( offset_xp , new );
[266]1086
1087    // release file descriptor lock
[568]1088    remote_rwlock_wr_release( lock_xp );
[266]1089
1090    // success
[651]1091    *new_offset = new;
[1]1092    return 0;
1093
[23]1094}  // vfs_lseek()
1095
[623]1096////////////////////////////////////
[23]1097error_t vfs_close( xptr_t   file_xp,
1098                   uint32_t file_id )
[1]1099{
[623]1100    cxy_t         file_cxy;         // cluster containing the file descriptor.
[657]1101    vfs_file_t  * file_ptr;         // local pointer on file descriptor
[623]1102    cxy_t         owner_cxy;        // process owner cluster
1103    pid_t         pid;              // process identifier
1104    lpid_t        lpid;             // process local index
1105    xptr_t        root_xp;          // root of xlist (processes , or dentries)
1106    xptr_t        lock_xp;          // lock protecting the xlist
1107    xptr_t        iter_xp;          // iterator on xlist
1108    mapper_t    * mapper_ptr;       // local pointer on associated mapper
1109    vfs_inode_t * inode_ptr;        // local pointer on associated inode
1110    uint32_t      size;             // current file size (from inode descriptor)
1111    error_t       error;
[459]1112
[623]1113    char          name[CONFIG_VFS_MAX_NAME_LENGTH];  // file name
[23]1114
[623]1115// check argument
[625]1116assert( (file_xp != XPTR_NULL) , "file_xp is XPTR_NULL" );
[623]1117
[23]1118    thread_t  * this    = CURRENT_THREAD;
1119    process_t * process = this->process;
[623]1120    cluster_t * cluster = LOCAL_CLUSTER;
[23]1121
[623]1122    // get file name
1123    vfs_file_get_name( file_xp , name );
1124   
[459]1125#if DEBUG_VFS_CLOSE
1126uint32_t cycle = (uint32_t)hal_get_cycles();
1127if( DEBUG_VFS_CLOSE < cycle )
[623]1128printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
1129__FUNCTION__, process->pid, this->trdid, name, cycle );
[459]1130#endif
[1]1131
[623]1132    // get cluster and local pointer on remote file descriptor
1133    file_cxy = GET_CXY( file_xp );
1134    file_ptr = GET_PTR( file_xp );
[23]1135
[623]1136    //////// 1) update all dirty pages from mapper to device
[23]1137
[633]1138    // get local pointer on mapper associated to file
[623]1139    mapper_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
[23]1140
[623]1141    // copy all dirty pages from mapper to device
[657]1142    error = mapper_sync( XPTR( file_cxy , mapper_ptr ) );
[459]1143
[623]1144    if( error )
1145    {
1146        printk("\n[ERROR] in %s : cannot synchronise dirty pages for <%s>\n",
1147        __FUNCTION__, name ); 
1148        return -1;
1149    }
[23]1150
[623]1151#if DEBUG_VFS_CLOSE
1152if( DEBUG_VFS_CLOSE < cycle )
1153printk("\n[%s] thread[%x,%x] synchronised mapper of <%s> to device\n",
1154__FUNCTION__, process->pid, this->trdid, name );
1155#endif
1156
[625]1157    //////// 2) update file size in all parent directory mapper(s) and update device
[623]1158
[633]1159    // get local pointer on remote inode
[623]1160    inode_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
1161
1162    // get file size from remote inode
1163    size = hal_remote_l32( XPTR( file_cxy , &inode_ptr->size ) );
1164
1165    // get root of list of parents dentry
1166    root_xp = XPTR( file_cxy , &inode_ptr->parents );
1167
1168    // loop on all parents
[23]1169    XLIST_FOREACH( root_xp , iter_xp )
[1]1170    {
[623]1171        // get pointers on parent directory dentry
1172        xptr_t         parent_dentry_xp  = XLIST_ELEMENT( iter_xp , vfs_dentry_t , parents );
1173        cxy_t          parent_cxy        = GET_CXY( parent_dentry_xp );
1174        vfs_dentry_t * parent_dentry_ptr = GET_PTR( parent_dentry_xp );
[1]1175
[623]1176        // get local pointer on parent directory inode
1177        vfs_inode_t * parent_inode_ptr = hal_remote_lpt( XPTR( parent_cxy, 
1178                                                         &parent_dentry_ptr->parent ) );
1179
1180        // get local pointer on parent directory mapper
1181        mapper_t * parent_mapper_ptr = hal_remote_lpt( XPTR( parent_cxy,
1182                                                       &parent_inode_ptr->mapper ) );
1183 
1184        // update dentry size in parent directory mapper
[657]1185        error = vfs_fs_update_dentry( XPTR( parent_cxy , parent_inode_ptr ),
1186                                      parent_dentry_ptr );
[623]1187
1188        if( error )
1189        {
1190            printk("\n[ERROR] in %s : cannot update size in parent\n",
1191            __FUNCTION__ ); 
1192            return -1;
1193        }
1194
1195#if DEBUG_VFS_CLOSE
1196char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
1197vfs_inode_get_name( XPTR( parent_cxy , parent_inode_ptr ) , parent_name );
[459]1198if( DEBUG_VFS_CLOSE < cycle )
[625]1199printk("\n[%s] thread[%x,%x] updated <%s> in <%s> / size = %d bytes\n",
1200__FUNCTION__, process->pid, this->trdid, name, parent_name, size );
[459]1201#endif
[23]1202
[623]1203        // copy all dirty pages from parent mapper to device
[657]1204        error = mapper_sync( XPTR( parent_cxy , parent_mapper_ptr ) );
[459]1205
[623]1206        if( error )
1207        {
1208            printk("\n[ERROR] in %s : cannot synchronise parent mapper to device\n",
1209            __FUNCTION__ ); 
1210            return -1;
1211        }
[459]1212
[623]1213#if DEBUG_VFS_CLOSE
1214if( DEBUG_VFS_CLOSE < cycle )
1215printk("\n[%s] thread[%x,%x] synchonized mapper of parent <%s> to device\n",
1216__FUNCTION__, process->pid, this->trdid, parent_name );
1217#endif
[459]1218
[623]1219    }
1220
1221    //////// 3) loop on the process copies to reset all fd_array[file_id] entries
1222
1223    // get owner process cluster and lpid
1224    pid        = process->pid;
1225    owner_cxy  = CXY_FROM_PID( pid );
1226    lpid       = LPID_FROM_PID( pid );
1227
1228    // get extended pointers on copies root and lock
1229    root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
1230    lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
1231
1232    // take the lock protecting the list of copies
1233    remote_queuelock_acquire( lock_xp );
1234
1235    XLIST_FOREACH( root_xp , iter_xp )
1236    {
1237        xptr_t      process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
1238        cxy_t       process_cxy = GET_CXY( process_xp );
1239        process_t * process_ptr = GET_PTR( process_xp );
1240
1241        xptr_t entry_xp = XPTR( process_cxy , &process_ptr->fd_array.array[file_id] );
[568]1242        hal_remote_s64( entry_xp , XPTR_NULL );
[459]1243        vfs_file_count_down( file_xp );
[124]1244        hal_fence();
[23]1245    }   
1246
[459]1247    // release the lock protecting the list of copies
[568]1248    remote_queuelock_release( lock_xp );
[459]1249
[623]1250#if DEBUG_VFS_CLOSE
[459]1251if( DEBUG_VFS_CLOSE < cycle )
[625]1252printk("\n[%s] thread[%x,%x] reset all fd-array copies for <%s>\n",
[623]1253__FUNCTION__, process->pid, this->trdid, name );
[459]1254#endif
1255
[623]1256    //////// 4) release memory allocated to file descriptor in remote cluster
[459]1257
[657]1258    vfs_file_destroy( file_xp );
[1]1259
[459]1260#if DEBUG_VFS_CLOSE
1261cycle = (uint32_t)hal_get_cycles();
1262if( DEBUG_VFS_CLOSE < cycle )
[625]1263printk("\n[%s] thread[%x,%x] exit / closed <%s> in process %x / cycle %d\n",
1264__FUNCTION__, process->pid, this->trdid, name, process->pid, cycle );
[459]1265#endif
1266
[23]1267    return 0;
[1]1268
[23]1269}  // end vfs_close()
[1]1270
1271////////////////////////////////////
[610]1272error_t vfs_mkdir( xptr_t   root_xp,
1273                   char   * path,
1274                   uint32_t rights )
1275{
1276    error_t        error;
1277    xptr_t         vfs_root_xp;        // extended pointer on VFS root inode
1278    vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode
1279    cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier
1280    xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree
[611]1281    xptr_t         inode_xp;           // extended pointer on new directory inode
1282    vfs_inode_t  * inode_ptr;          // local pointer on new directory inode
1283    cxy_t          inode_cxy;          // new directory inode cluster identifier
[610]1284    xptr_t         dentry_xp;          // extended pointer on new dentry
[611]1285    vfs_dentry_t * dentry_ptr;         // new dentry local pointer
1286    xptr_t         parent_xp;          // extended pointer on parent inode
1287    vfs_inode_t  * parent_ptr;         // local pointer on parent inode 
1288    cxy_t          parent_cxy;         // parent inode cluster identifier
1289    vfs_ctx_t    * parent_ctx_ptr;     // local pointer on parent inode context
1290    uint32_t       parent_fs_type;     // parent inode file system type
[610]1291
1292    xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root)
1293    xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry
1294    xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root)
1295    xptr_t         children_entry_xp;  // extended pointer on children field in dentry
1296
1297    char           last_name[CONFIG_VFS_MAX_NAME_LENGTH];
1298
1299    thread_t  * this    = CURRENT_THREAD;
1300    process_t * process = this->process;
1301
1302#if DEBUG_VFS_MKDIR
1303char root_name[CONFIG_VFS_MAX_NAME_LENGTH];
1304vfs_inode_get_name( root_xp , root_name );
1305uint32_t   cycle = (uint32_t)hal_get_cycles();
1306if( DEBUG_VFS_MKDIR < cycle )
1307printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n",
1308__FUNCTION__, process->pid, this->trdid, root_name, path, cycle );
1309#endif
1310
1311    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
1312    vfs_root_xp  = process->vfs_root_xp;
1313    vfs_root_ptr = GET_PTR( vfs_root_xp );
1314    vfs_root_cxy = GET_CXY( vfs_root_xp );
1315    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
1316
1317    // take the lock protecting Inode Tree in write mode
1318    remote_rwlock_wr_acquire( lock_xp );
1319
1320    // 1. get pointers on parent inode
1321    error = vfs_lookup( root_xp,
1322                        path,
1323                        VFS_LOOKUP_DIR | VFS_LOOKUP_PARENT,
1324                        &parent_xp,
1325                        last_name );
1326    if( error )
1327    {
1328        remote_rwlock_wr_release( lock_xp );
1329        printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n",
1330        __FUNCTION__, path );
1331        return -1;
1332    }
1333
1334    // get parent inode cluster and local pointer
1335    parent_cxy = GET_CXY( parent_xp );
1336    parent_ptr = GET_PTR( parent_xp );
1337
1338#if( DEBUG_VFS_MKDIR & 1 )
1339if( DEBUG_VFS_MKDIR < cycle )
1340printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n",
1341__FUNCTION__, process->pid, this->trdid, parent_cxy, parent_ptr, path );
1342#endif
1343
1344    // get parent inode context, and FS type
1345    parent_ctx_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
1346    parent_fs_type = hal_remote_l32( XPTR( parent_cxy , &parent_ctx_ptr->type ) );
1347
1348    // 2. create one new dentry in parent cluster
[657]1349    error = vfs_dentry_create( parent_cxy,
1350                               parent_fs_type,
1351                               last_name,
1352                               &dentry_xp );
[610]1353    if( error )
1354    {
1355        remote_rwlock_wr_release( lock_xp );
1356        printk("\n[ERROR] in %s : cannot create new dentry in cluster %x for <%s>\n",
1357        __FUNCTION__, parent_cxy, path );
1358        return -1;
1359    }
1360
1361    // get local pointer on dentry
1362    dentry_ptr = GET_PTR( dentry_xp );
1363
1364#if( DEBUG_VFS_MKDIR & 1 )
1365if( DEBUG_VFS_MKDIR < cycle )
1366printk("\n[%s] thread[%x,%x] created new dentry (%x,%x) for <%s>\n",
1367__FUNCTION__, process->pid, this->trdid, parent_cxy, dentry_ptr, path );
1368#endif
1369
[611]1370    // 3. create new directory inode
[610]1371    // TODO : define attr / uid / gid
1372    uint32_t attr = 0;
1373    uint32_t uid  = 0;
1374    uint32_t gid  = 0;
1375
1376    // select a target cluster for new inode
1377    inode_cxy = cluster_random_select();
1378   
[657]1379    // create inode
1380    error = vfs_inode_create( inode_cxy,
1381                              parent_fs_type,
1382                              attr,
1383                              rights,
1384                              uid,
1385                              gid,
1386                              &inode_xp );
[610]1387    if( error )
1388    {
[611]1389        remote_rwlock_wr_release( lock_xp );
[610]1390        printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
[657]1391         __FUNCTION__ , inode_cxy , path );
1392        vfs_dentry_destroy( dentry_xp );
[610]1393        return -1;
1394    }
1395
1396    // get new inode local pointer
1397    inode_ptr = GET_PTR( inode_xp );
[623]1398
1399    // update inode "type" field
1400    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->type ) , INODE_TYPE_DIR ); 
[610]1401   
1402#if(DEBUG_VFS_MKDIR & 1)
1403if( DEBUG_VFS_MKDIR < cycle )
1404printk("\n[%s] thread[%x,%x] created new inode (%x,%x) for <%s>\n",
1405__FUNCTION__ , process->pid, this->trdid, inode_cxy, inode_ptr, path );
1406#endif
1407
1408    // 4. register dentry in new inode list of parents
1409    parents_root_xp  = XPTR( inode_cxy  , &inode_ptr->parents );
1410    parents_entry_xp = XPTR( parent_cxy , &dentry_ptr->parents );
1411    xlist_add_first( parents_root_xp , parents_entry_xp );
1412    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 );
1413
1414    // 5. register dentry in parent inode
1415    children_xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
1416    children_entry_xp = XPTR( parent_cxy , &dentry_ptr->children );
1417    xhtab_insert( children_xhtab_xp , last_name , children_entry_xp );
1418
1419    // 6. update "parent" and "child_xp" fields in dentry
1420    hal_remote_s64( XPTR( parent_cxy , &dentry_ptr->child_xp ) , inode_xp );
1421    hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->parent ) , parent_ptr );
1422
1423#if(DEBUG_VFS_MKDIR & 1)
1424if( DEBUG_VFS_MKDIR < cycle )
1425printk("\n[%s] thread[%x,%x] updated Inode Tree for <%s>\n",
1426__FUNCTION__, process->pid, this->trdid, path );
1427#endif
1428
[611]1429    // 7. create the two special dentries <.> and <..> in new directory
1430    // both the new directory mapper, and the Inode Tree are updated
1431    error = vfs_add_special_dentries( inode_xp,
1432                                      parent_xp );
1433
1434    if( error )
1435    {
1436        remote_rwlock_wr_release( lock_xp );
1437        printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
[657]1438        __FUNCTION__ , inode_cxy , path );
1439        vfs_dentry_destroy( dentry_xp );
[611]1440        return -1;
1441    }
1442
[610]1443    // release the lock protecting Inode Tree
1444    remote_rwlock_wr_release( lock_xp );
1445
[611]1446    // 8. update parent directory mapper
[610]1447    //    and synchronize the parent directory on IOC device
[657]1448    error = vfs_fs_add_dentry( parent_xp,
1449                               dentry_ptr );
[610]1450    if( error )
1451    {
1452        printk("\n[ERROR] in %s : cannot update parent directory for <%s>\n",
1453        __FUNCTION__, path );
1454        return -1;
1455    }
1456
1457#if(DEBUG_VFS_MKDIR & 1)
1458if( DEBUG_VFS_MKDIR < cycle )
1459printk("\n[%s] thread[%x,%x] updated parent dir (mapper and IOC) for <%s>\n",
1460__FUNCTION__, process->pid, this->trdid, path );
1461#endif
1462
1463    return 0;
1464
1465}  // end vfs_mkdir()
1466
1467///////////////////////////////////////
1468error_t vfs_link( xptr_t   old_root_xp,
1469                  char   * old_path,
1470                  xptr_t   new_root_xp,
1471                  char   * new_path )
1472{
1473    error_t        error;
1474    xptr_t         vfs_root_xp;        // extended pointer on VFS root inode
1475    vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode
1476    cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier
1477    xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree
1478    xptr_t         inode_xp;           // extended pointer on target inode
1479    vfs_inode_t  * inode_ptr;          // local pointer on target inode
1480    cxy_t          inode_cxy;          // target inode cluster identifier
1481    uint32_t       inode_type;         // target inode type
1482    vfs_ctx_t    * inode_ctx_ptr;      // local pointer on target inode context
1483    uint32_t       inode_fs_type;      // target inode file system type
1484    xptr_t         dentry_xp;          // extended pointer on new dentry
1485    vfs_dentry_t * dentry_ptr;         // target dentry local pointer
1486    xptr_t         new_parent_xp;      // extended pointer on new parent inode
1487    vfs_inode_t  * new_parent_ptr;     // local pointer on new parent inode 
1488    cxy_t          new_parent_cxy;     // new parent inode cluster identifier
1489
1490    xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root)
1491    xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry
1492    xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root)
1493    xptr_t         children_entry_xp;  // extended pointer on children field in dentry
1494
1495    char           new_name[CONFIG_VFS_MAX_NAME_LENGTH];
1496
1497    thread_t  * this    = CURRENT_THREAD;
1498    process_t * process = this->process;
1499
1500#if DEBUG_VFS_LINK
1501char old_root_name[CONFIG_VFS_MAX_NAME_LENGTH];
1502char new_root_name[CONFIG_VFS_MAX_NAME_LENGTH];
1503vfs_inode_get_name( old_root_xp , old_root_name );
1504vfs_inode_get_name( new_root_xp , new_root_name );
1505uint32_t   cycle = (uint32_t)hal_get_cycles();
1506if( DEBUG_VFS_LINK < cycle )
1507printk("\n[%s] thread[%x,%x] enter / old_root <%s> / old_path <%s> / "
1508"new_root <%s> / new_path <%s> / cycle %d\n",
1509__FUNCTION__, process->pid, this->trdid,
1510old_root_name, old_path, new_root_name, new_path, cycle );
1511#endif
1512
1513    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
1514    vfs_root_xp  = process->vfs_root_xp;
1515    vfs_root_ptr = GET_PTR( vfs_root_xp );
1516    vfs_root_cxy = GET_CXY( vfs_root_xp );
1517    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
1518
1519    // take the lock protecting Inode Tree in write mode
1520    remote_rwlock_wr_acquire( lock_xp );
1521
1522    // get extended pointer on target inode
1523    error = vfs_lookup( old_root_xp,
1524                        old_path,
1525                        0,
1526                        &inode_xp,
1527                        NULL );
1528    if( error )
1529    {
1530        remote_rwlock_wr_release( lock_xp );
1531        printk("\n[ERROR] in %s : cannot get target inode for <%s>\n",
1532        __FUNCTION__, old_path );
1533        return -1;
1534    }
1535
1536#if( DEBUG_VFS_LINK & 1 )
1537if( DEBUG_VFS_LINK < cycle )
1538printk("\n[%s] thread[%x,%x] get child inode (%x,%x) for <%s>\n",
1539__FUNCTION__, process->pid, this->trdid,
1540GET_CXY(inode_xp), GET_PTR(inode_xp), old_path, cycle );
1541#endif
1542
1543    // get extended pointer on parent inode in new path
1544    error = vfs_lookup( new_root_xp,
1545                        new_path,
1546                        VFS_LOOKUP_PARENT,
1547                        &new_parent_xp,
1548                        new_name );
1549    if( error )
1550    {
1551        remote_rwlock_wr_release( lock_xp );
1552        printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n",
1553        __FUNCTION__, new_path );
1554        return -1;
1555    }
1556
1557#if( DEBUG_VFS_LINK & 1 )
1558if( DEBUG_VFS_LINK < cycle )
1559printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n",
1560__FUNCTION__, process->pid, this->trdid,
1561GET_CXY(new_parent_xp), GET_PTR(new_parent_xp), new_path );
1562#endif
1563
1564    // get target inode cluster and local pointer
1565    inode_cxy = GET_CXY( inode_xp );
1566    inode_ptr = GET_PTR( inode_xp );
1567
1568    // get target inode type, context, and FS type
1569    inode_type        = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
1570    inode_ctx_ptr     = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) );
1571    inode_fs_type     = hal_remote_l32( XPTR( inode_cxy , &inode_ctx_ptr->type ) );
1572
1573    // get new parent inode cluster an local pointer
1574    new_parent_ptr = GET_PTR( new_parent_xp );
1575    new_parent_cxy = GET_CXY( new_parent_xp );
1576
1577    ///////////////////////////////////////////////////////////////////////
1578    if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) )
1579    {
1580        // 1. create one new dentry
[657]1581        error = vfs_dentry_create( new_parent_cxy,
1582                                   inode_fs_type,
1583                                   new_name,
1584                                   &dentry_xp );
[610]1585        if( error )
1586        {
1587            remote_rwlock_wr_release( lock_xp );
1588            printk("\n[ERROR] in %s : cannot create new dentry for <%s>\n",
1589            __FUNCTION__, new_path );
1590            return -1;
1591        }
1592
1593        // get local pointer on dentry
1594        dentry_ptr = GET_PTR( dentry_xp );
1595
1596        // 2. register dentry in target inode
1597        parents_root_xp  = XPTR( inode_cxy      , &inode_ptr->parents );
1598        parents_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->parents );
1599        xlist_add_first( parents_root_xp , parents_entry_xp );
1600        hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 );
1601
1602        // 3. register dentry in parent inode
1603        children_xhtab_xp = XPTR( new_parent_cxy , &new_parent_ptr->children );
1604        children_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->children );
1605        xhtab_insert( children_xhtab_xp , new_name , children_entry_xp );
1606
1607        // 4. update "parent" and "child_xp" fields in dentry
1608        hal_remote_s64( XPTR( new_parent_cxy , &dentry_ptr->child_xp ) , inode_xp );
1609        hal_remote_spt( XPTR( new_parent_cxy , &dentry_ptr->parent ) , new_parent_ptr );
1610
1611#if(DEBUG_VFS_LINK & 1)
1612if( DEBUG_VFS_LINK < cycle )
1613printk("\n[%s] thread[%x,%x] updated Inode Tree / old <%s> / new <%s>\n",
1614__FUNCTION__, process->pid, this->trdid, old_path, new_path );
1615vfs_display( new_parent_xp ); 
1616#endif
1617
1618        // release the lock protecting Inode Tree
1619        remote_rwlock_wr_release( lock_xp );
1620
1621        // 5. update new parent directory mapper in Inode Tree
1622        //    and synchronize the parent directory on IOC device
1623        if (new_parent_cxy == local_cxy)
[657]1624        error = vfs_fs_add_dentry( new_parent_xp,
1625                                   dentry_ptr );
[610]1626        if( error )
1627        {
1628            printk("\n[ERROR] in %s : cannot update new parent directory for <%s>\n",
1629            __FUNCTION__, new_path );
1630            return -1;
1631        }
1632
1633#if(DEBUG_VFS_LINK & 1)
1634if( DEBUG_VFS_LINK < cycle )
1635printk("\n[%s] thread[%x,%x] updated new parent dir (mapper and IOC) / old <%s> / new <%s>\n",
1636__FUNCTION__, process->pid, this->trdid, old_path, new_path );
1637#endif
1638        return 0;
1639    }
1640    else
1641    {
1642        // release the lock protecting Inode Tree
1643        remote_rwlock_wr_release( lock_xp );
1644
1645        printk("\n[ERROR] in %s : unsupported inode type %s\n",
1646        __FUNCTION__ , vfs_inode_type_str( inode_type ) );
1647        return -1;
1648    }
1649
1650}  // end vfs_link()
1651
1652/////////////////////////////////////
1653error_t vfs_unlink( xptr_t   root_xp,
[23]1654                    char   * path )
[1]1655{
[602]1656    error_t           error;
[610]1657    xptr_t            vfs_root_xp;        // extended pointer on VFS root inode
1658    vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode
1659    cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier
1660    xptr_t            lock_xp;            // extended pointer on lock protecting Inode Tree
1661    xptr_t            parent_xp;          // extended pointer on target inode
1662    cxy_t             parent_cxy;         // target inode cluster identifier       
1663    vfs_inode_t     * parent_ptr;         // target inode local pointer
[602]1664    xptr_t            inode_xp;           // extended pointer on target inode
1665    cxy_t             inode_cxy;          // target inode cluster identifier       
1666    vfs_inode_t     * inode_ptr;          // target inode local pointer
[610]1667    uint32_t          inode_links;        // target inode links count
1668    vfs_inode_type_t  inode_type;         // target inode type
1669    uint32_t          inode_children;     // target inode number of children
1670    xptr_t            dentry_xp;          // extended pointer on dentry to unlink
1671    vfs_dentry_t    * dentry_ptr;         // local pointer on dentry to unlink
[623]1672    vfs_ctx_t       * ctx_ptr;            // local pointer on FS context
1673    vfs_fs_type_t     fs_type;            // File system type
[1]1674
[657]1675    char              child_name[CONFIG_VFS_MAX_NAME_LENGTH];   // name of link to remove
1676    char              parent_name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of parent directory
[610]1677
1678    thread_t  * this    = CURRENT_THREAD;
1679    process_t * process = this->process;
1680
[602]1681#if DEBUG_VFS_UNLINK
1682uint32_t   cycle = (uint32_t)hal_get_cycles();
[610]1683char root_name[CONFIG_VFS_MAX_NAME_LENGTH];
1684vfs_inode_get_name( root_xp , root_name );
[602]1685if( DEBUG_VFS_UNLINK < cycle )
[623]1686printk("\n[%s] thread[%x,%x] : enter for root <%s> / path <%s> / cycle %d\n",
[610]1687__FUNCTION__, process->pid, this->trdid, root_name, path, cycle );
[602]1688#endif
1689
[610]1690    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
1691    vfs_root_xp  = process->vfs_root_xp;
[633]1692    vfs_root_ptr = GET_PTR( vfs_root_xp );
1693    vfs_root_cxy = GET_CXY( vfs_root_xp );
[610]1694    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
[602]1695
[610]1696    // take the lock protecting Inode Tree
1697    remote_rwlock_wr_acquire( lock_xp );
[602]1698
[610]1699    // get extended pointer on parent inode
1700    error = vfs_lookup( root_xp,
1701                        path,
1702                        VFS_LOOKUP_PARENT,
1703                        &parent_xp,
[657]1704                        child_name );
[610]1705    if( error ) 
1706    {
1707        remote_rwlock_wr_release( lock_xp );
1708        printk("\n[ERROR] in %s : cannot get parent inode for <%s> in <%s>\n",
[657]1709        __FUNCTION__, child_name, path );
[610]1710        return -1;
1711    }
[657]1712   
1713    // get parent inode name, cluster and local pointer
1714    vfs_inode_get_name( parent_xp , parent_name );
[610]1715    parent_cxy = GET_CXY( parent_xp );
1716    parent_ptr = GET_PTR( parent_xp );
1717 
1718#if( DEBUG_VFS_UNLINK & 1 )
1719if( DEBUG_VFS_UNLINK < cycle )
[623]1720printk("\n[%s] thread[%x,%x] : parent inode <%s> is (%x,%x)\n",
[610]1721__FUNCTION__, process->pid, this->trdid, parent_name, parent_cxy, parent_ptr );
1722#endif
1723
1724    // build extended pointer on parent inode "children" xhtab
1725    xptr_t children_xp = XPTR( parent_cxy , &parent_ptr->children );
1726
[623]1727    // try to get extended pointer on dentry from Inode Tree
[657]1728    dentry_xp = xhtab_lookup( children_xp , child_name );
[610]1729   
[657]1730    // when dentry not found in Inode Tree, try to get it from mapper
[623]1731
1732    if( dentry_xp == XPTR_NULL )           // miss target dentry in Inode Tree
[610]1733    {
1734
1735#if( DEBUG_VFS_UNLINK & 1 )
1736if( DEBUG_VFS_UNLINK < cycle )
[657]1737printk("\n[%s] thread[%x,%x] : inode <%s> not found => scan parent mapper <%s>\n",
1738__FUNCTION__, process->pid, this->trdid, child_name , parent_name );
[610]1739#endif
[623]1740        // get parent inode FS type
1741        ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
1742        fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
[610]1743
[623]1744        // select a cluster for new inode
1745        inode_cxy = cluster_random_select();
1746
1747        // speculatively insert a new child dentry/inode couple in inode tree
1748        error = vfs_add_child_in_parent( inode_cxy,
1749                                         fs_type, 
1750                                         parent_xp, 
[657]1751                                         child_name, 
[623]1752                                         &dentry_xp,
1753                                         &inode_xp );
1754        if( error )
1755        {
[657]1756            printk("\n[ERROR] in %s : cannot create inode <%s> in Inode Tree\n",
1757            __FUNCTION__ , child_name );
[623]1758            return -1;
1759        }
1760
1761        // get local pointers on new dentry and new inode descriptors
1762        inode_ptr  = GET_PTR( inode_xp );
1763        dentry_ptr = GET_PTR( dentry_xp );
1764
1765        // scan parent mapper to find the missing dentry, and complete
1766        // initialisation of new dentry and new inode descriptors In Inode Tree
[657]1767        error = vfs_fs_new_dentry_from_mapper( parent_xp,
1768                                               dentry_ptr );
1769        if ( error ) 
[623]1770        {
[657]1771            printk("\n[ERROR] in %s : cannot get entry <%s> in parent <%s> mapper\n",
1772            __FUNCTION__ , child_name, parent_name );
[623]1773            return -1;
1774        }
1775
1776#if (DEBUG_VFS_UNLINK & 1)
1777if( DEBUG_VFS_UNLINK < cycle )
1778printk("\n[%s] thread[%x,%x] : created missing inode & dentry <%s> in cluster %x\n",
[657]1779__FUNCTION__, process->pid, this->trdid, child_name, inode_cxy );
[623]1780#endif
1781
1782    }
1783    else                                  // found target dentry in Inode Tree
1784    {
1785        dentry_ptr = GET_PTR( dentry_xp );
1786       
1787        // get pointer on target inode from dentry
1788        inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
1789        inode_cxy = GET_CXY( inode_xp );
1790        inode_ptr = GET_PTR( inode_xp );
1791    }
1792
1793    // At this point the Inode Tree contains the target dentry and child inode
1794    // we can safely remove this dentry from both the parent mapper, and the Inode Tree.
1795
[610]1796#if( DEBUG_VFS_UNLINK & 1 )
1797if( DEBUG_VFS_UNLINK < cycle )
[623]1798printk("\n[%s] thread[%x,%x] : dentry (%x,%x) / inode (%x,%x)\n",
1799__FUNCTION__, process->pid, this->trdid, parent_cxy, dentry_ptr, inode_cxy, inode_ptr );
[610]1800#endif
[602]1801
[610]1802    // get target inode "type" and "links"
1803    inode_type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
1804    inode_links  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->links ) );
[602]1805
[610]1806    ///////////////////////////////////////////////////////////////////////
1807    if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) )
[602]1808    {
[623]1809
1810#if( DEBUG_VFS_UNLINK & 1 )
1811if( DEBUG_VFS_UNLINK < cycle )
1812printk("\n[%s] thread[%x,%x] : unlink inode <%s> / type %s / %d links\n",
[657]1813__FUNCTION__, process->pid, this->trdid, child_name, 
1814vfs_inode_type_str(inode_type), inode_links );
[623]1815#endif
1816
[610]1817        // 1. Release clusters allocated to target inode
1818        //    and synchronize the FAT on IOC device if last link.
1819        if( inode_links == 1 ) 
[602]1820        {
[610]1821            // build extended pointer on target inode "children" number
1822            xptr_t inode_children_xp = XPTR( inode_cxy , &inode_ptr->children.items );
[602]1823
[610]1824            // get target inode number of children
1825            inode_children = hal_remote_l32( inode_children_xp );
1826
1827            // check no children
1828            if( inode_children != 0 )
1829            {
1830                remote_rwlock_wr_release( lock_xp );
1831                printk("\n[ERROR] in %s : cannot remove <%s> inode that has children\n",
1832                __FUNCTION__, path );
1833                return -1;
1834            }
1835
1836            // release clusters on IOC device
1837            error = vfs_fs_release_inode( inode_xp ); 
1838
1839            if( error )
1840            {
1841                remote_rwlock_wr_release( lock_xp );
1842                printk("\n[ERROR] in %s : cannot update FAT mapper to remove <%s> inode\n",
1843                __FUNCTION__ , path );
1844                return -1;
1845            }
1846
[602]1847#if(DEBUG_VFS_UNLINK & 1)
1848if( DEBUG_VFS_UNLINK < cycle )
1849printk("\n[%s] thread[%x,%x] removed <%s> inode from FAT (mapper and IOC device)\n",
[610]1850__FUNCTION__, process->pid, this->trdid, path );
[602]1851#endif
[610]1852        }
[602]1853
[610]1854        // 2. update parent directory mapper
1855        //    and synchronize the parent directory on IOC device
[657]1856        error = vfs_fs_remove_dentry( parent_xp,
1857                                      dentry_ptr );
[602]1858        if( error )
1859        {
[610]1860            remote_rwlock_wr_release( lock_xp );
1861            printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n",
1862            __FUNCTION__ , path );
[602]1863            return -1;
1864        }
1865
1866#if(DEBUG_VFS_UNLINK & 1)
1867if( DEBUG_VFS_UNLINK < cycle )
1868printk("\n[%s] thread[%x,%x] removed <%s> inode from parent dir (mapper and IOC device)\n",
[610]1869__FUNCTION__, process->pid, this->trdid, path );
[602]1870#endif
[610]1871        // 3. remove dentry from Inode Tree (and associated chils inode when last link)
1872        vfs_remove_child_from_parent( dentry_xp );
[602]1873
[610]1874        // release the lock protecting Inode Tree
1875        remote_rwlock_wr_release( lock_xp );
1876
[602]1877#if DEBUG_VFS_UNLINK
1878if( DEBUG_VFS_UNLINK < cycle )
1879printk("\n[%s] thread[%x,%x] exit / removed <%s> inode from Inode Tree / cycle %d\n",
[610]1880__FUNCTION__, process->pid, this->trdid, path, cycle );
[602]1881#endif
1882        return 0;
1883    }
1884    else
1885    {
[610]1886        remote_rwlock_wr_release( lock_xp );
1887        printk("\n[ERROR] in %s : unsupported inode type %s\n",
1888        __FUNCTION__ , vfs_inode_type_str( inode_type ) );
[602]1889        return -1;
1890    }
1891
1892}  // end vfs_unlink()
1893
[611]1894////////////////////////////////////////////////
1895error_t vfs_stat( xptr_t         root_inode_xp,
1896                  char         * path,
1897                  struct stat  * st )
[1]1898{
[610]1899    error_t       error;
1900    xptr_t        inode_xp;           // extended pointer on target inode
1901    vfs_inode_t * inode_ptr;          // local pointer on target inode
1902    cxy_t         inode_cxy;          // target inode cluster identifier
1903    xptr_t        vfs_root_xp;        // extended pointer on VFS root inode
1904    vfs_inode_t * vfs_root_ptr;       // local_pointer on VFS root inode
1905    cxy_t         vfs_root_cxy;       // VFS root inode cluster identifier
1906    xptr_t        lock_xp;            // extended pointer on lock protecting Inode Tree
1907
1908    thread_t  * this    = CURRENT_THREAD;
1909    process_t * process = this->process;
1910
1911    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
1912    vfs_root_xp  = process->vfs_root_xp;
1913    vfs_root_ptr = GET_PTR( vfs_root_xp );
1914    vfs_root_cxy = GET_CXY( vfs_root_xp );
1915    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
1916
1917    // get the lock protecting Inode Tree in read mode
1918    remote_rwlock_rd_acquire( lock_xp );
1919
1920    // get extended pointer on target inode
1921    error = vfs_lookup( root_inode_xp,
1922                        path,
1923                        0,
1924                        &inode_xp,
1925                        NULL );
1926
1927    // release the lock protecting Inode Tree
1928    remote_rwlock_rd_release( lock_xp );
1929
1930    if( error )
1931    {
1932        printk("\n[ERROR] in %s : cannot found inode <%s>\n",
1933        __FUNCTION__ , path );
1934        return -1;
1935    }
1936
[598]1937    // get cluster and local pointer on inode descriptor
[610]1938    inode_ptr = GET_PTR( inode_xp );
1939    inode_cxy = GET_CXY( inode_xp );
[598]1940
1941    // get relevant infos from inode descriptor
1942    uint32_t inum   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->inum   ) );
1943    uint32_t size   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size   ) );
1944    uint32_t uid    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->uid    ) );
1945    uint32_t gid    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->gid    ) );
1946    uint32_t type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type   ) );
1947    uint32_t rights = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->rights ) );
1948
1949    // set stat structure fields
1950    st->st_ino  = inum;
1951    st->st_gid  = gid;
1952    st->st_uid  = uid;
1953    st->st_size = size;
1954    st->st_mode = (type << 16) | rights;
1955
1956#if DEBUG_VFS_STAT
1957uint32_t cycle  = (uint32_t)hal_get_cycles();
1958if( DEBUG_VFS_STAT < cycle )
1959printk("\n[%s] thread[%x,%x] set stat %x for inode %x in cluster %x / cycle %d\n"
1960       " %s / inum %d / size %d\n",
[610]1961__FUNCTION__, process->pid, this->trdid, st, inode_ptr, inode_cxy, cycle,
[598]1962vfs_inode_type_str( type ), inum, size );
1963#endif
1964
[1]1965    return 0;
1966
[602]1967}  // end vfs_stat()
1968
[23]1969////////////////////////////////////
[610]1970error_t vfs_chdir( xptr_t   root_xp,
[23]1971                   char   * path )
[1]1972{
[23]1973    error_t           error;
[610]1974    xptr_t            inode_xp;           // extended pointer on target inode
1975    cxy_t             inode_cxy;          // target inode cluster identifier       
1976    vfs_inode_t     * inode_ptr;          // target inode local pointer
1977    vfs_inode_type_t  inode_type;         // target inode type
1978    xptr_t            vfs_root_xp;        // extended pointer on VFS root inode
1979    vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode
1980    cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier
1981    xptr_t            main_lock_xp;       // extended pointer on lock protecting Inode Tree
1982    xptr_t            ref_xp;             // extended pointer on reference process
1983    process_t       * ref_ptr;            // local pointer on reference process
1984    cxy_t             ref_cxy;            // reference process cluster
1985    xptr_t            cwd_lock_xp;        // extended pointer on lock protecting CWD change
1986    xptr_t            cwd_xp_xp;          // extended pointer on cwd_xp in reference process
[23]1987
[610]1988    thread_t  * this    = CURRENT_THREAD;
1989    process_t * process = this->process;
[23]1990
[610]1991#if DEBUG_VFS_CHDIR
1992uint32_t cycle = (uint32_t)hal_get_cycles();
1993if( DEBUG_VFS_CHDIR < cycle )
1994printk("\n[%s] thread[%x,%x] enter for path <%s> / cycle %d\n",
1995__FUNCTION__, process->pid, this->trdid, path, cycle );
1996#endif
1997
1998    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
1999    vfs_root_xp  = process->vfs_root_xp;
2000    vfs_root_ptr = GET_PTR( vfs_root_xp );
2001    vfs_root_cxy = GET_CXY( vfs_root_xp );
2002    main_lock_xp = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
2003
2004    // take lock protecting Inode Tree in read mode
2005    remote_rwlock_rd_acquire( main_lock_xp );
2006
[23]2007    // get extended pointer on target inode
[610]2008    error = vfs_lookup( root_xp,
2009                        path,
2010                        VFS_LOOKUP_DIR,
2011                        &inode_xp,
2012                        NULL );
[23]2013
[610]2014    // release lock protecting Inode Tree in read mode
2015    remote_rwlock_rd_release( main_lock_xp );
[23]2016
[610]2017    if( error ) 
2018    {
2019        printk("\n[ERROR] in %s : <%s> not found\n",
2020        __FUNCTION__, path );
2021        return -1;
2022    }
2023
2024    // get inode type from remote file
[23]2025    inode_cxy = GET_CXY( inode_xp );
[473]2026    inode_ptr = GET_PTR( inode_xp );
[568]2027    inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
[23]2028
2029    if( inode_type != INODE_TYPE_DIR )
2030    {
[610]2031        printk("\n[ERROR] in %s : <%s> is not a directory\n",
2032        __FUNCTION__, path );
[23]2033        return -1;
2034    }
2035
[610]2036    // build extended pointer on cwd_lock and cwd_xp
2037    ref_xp       = process->ref_xp;
2038    ref_ptr      = GET_PTR( ref_xp );
2039    ref_cxy      = GET_CXY( ref_xp );
2040    cwd_lock_xp  = XPTR( ref_cxy , &ref_ptr->cwd_lock );
2041    cwd_xp_xp    = XPTR( ref_cxy , &ref_ptr->cwd_xp );
[568]2042
[610]2043    // take lock protecting CWD changes
2044    remote_busylock_acquire( cwd_lock_xp );
[568]2045
[610]2046    // update cwd_xp field in reference process descriptor
2047    hal_remote_s64( cwd_xp_xp , inode_xp );
2048
2049    // release lock protecting CWD changes
2050    remote_busylock_release( cwd_lock_xp );
2051
2052#if DEBUG_VFS_CHDIR
2053cycle = (uint32_t)hal_get_cycles();
2054if( DEBUG_VFS_CHDIR < cycle )
2055printk("\n[%s] thread[%x,%x] exit : inode (%x,%x) / &cwd_xp (%x,%x) / cycle %d\n",
2056__FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr, 
2057GET_CXY(cwd_xp_xp), GET_PTR(cwd_xp_xp), cycle );
2058#endif
2059
[1]2060    return 0;
2061
[610]2062}  // end vfs_chdir()
2063
[23]2064///////////////////////////////////
2065error_t vfs_chmod( xptr_t   cwd_xp,
2066                   char   * path,
2067                   uint32_t rights )
[1]2068{
[23]2069    error_t           error;
2070    xptr_t            inode_xp;     // extended pointer on target inode
2071    cxy_t             inode_cxy;    // inode cluster identifier       
2072    vfs_inode_t     * inode_ptr;    // inode local pointer
2073
[625]2074// check lookup working mode
2075assert( (rights == 0), "access rights non implemented yet" );
[23]2076 
2077    // get extended pointer on target inode
[610]2078    error = vfs_lookup( cwd_xp,
2079                        path,
2080                        0,
2081                        &inode_xp,
2082                        NULL );
[23]2083
2084    if( error ) return error;
2085
2086    // get inode cluster and local pointer
2087    inode_cxy = GET_CXY( inode_xp );
[473]2088    inode_ptr = GET_PTR( inode_xp );
[23]2089   
2090    // get inode type from remote inode
[633]2091    // inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
[23]2092
[633]2093    // TODO finalize implementation
[610]2094
[625]2095assert( false , "not implemented" );
[610]2096
[633]2097    // set inode rights in remote inode
2098    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->rights ) , rights );
2099
[1]2100    return 0;
2101}
2102
[23]2103///////////////////////////////////
2104error_t vfs_mkfifo( xptr_t   cwd_xp,
2105                    char   * path,
2106                    uint32_t rights )
2107{
[625]2108    assert( false , "not implemented %l %x %x", cwd_xp, path, rights );
[23]2109    return 0;
2110}
[1]2111
2112
2113
[188]2114//////////////////////////////////////////////////////////////////////////////////////////
[602]2115//       Distributed Inode Tree access related functions
[1]2116//////////////////////////////////////////////////////////////////////////////////////////
2117
[188]2118//////////////////////////////////////////////////////////////////////////
[657]2119// This recursive function is called by the vfs_display() function.
[337]2120// that is supposed to take the TXT0 lock.
[188]2121//////////////////////////////////////////////////////////////////////////
2122static void vfs_recursive_display( xptr_t   inode_xp,
2123                                   xptr_t   name_xp,
2124                                   uint32_t indent )
2125{
2126    cxy_t              inode_cxy;
2127    vfs_inode_t      * inode_ptr;
2128    vfs_inode_type_t   inode_type;
[598]2129    uint32_t           inode_size;
2130    uint32_t           inode_attr;
[625]2131    void             * inode_extd;
2132
[204]2133    xptr_t             children_xp;    // extended pointer on children xhtab
[188]2134
[204]2135    xptr_t             child_dentry_xp;
2136    cxy_t              child_dentry_cxy;
2137    vfs_dentry_t     * child_dentry_ptr;
2138    xptr_t             child_inode_xp;
2139    xptr_t             child_dentry_name_xp;
[598]2140    mapper_t         * mapper_ptr;
[188]2141
2142    char               name[CONFIG_VFS_MAX_NAME_LENGTH];
2143
2144    char *             indent_str[] = { "",                                  // level 0
2145                                        "  ",                                // level 1
2146                                        "    ",                              // level 2
2147                                        "      ",                            // level 3
2148                                        "        ",                          // level 4
2149                                        "          ",                        // level 5
2150                                        "            ",                      // level 6
2151                                        "              ",                    // level 7
2152                                        "                ",                  // level 8
2153                                        "                  ",                // level 9
2154                                        "                    ",              // level 10
2155                                        "                      ",            // level 11
2156                                        "                        ",          // level 12
2157                                        "                          ",        // level 13
2158                                        "                            ",      // level 14
2159                                        "                              " };  // level 15
2160
[625]2161assert( (inode_xp != XPTR_NULL) , "inode_xp cannot be NULL" );
2162assert( (name_xp  != XPTR_NULL) , "name_xp cannot be NULL" );
2163assert( (indent < 16)           , "depth cannot be larger than 15" );
[188]2164   
[610]2165    // get current inode cluster and local pointer
[188]2166    inode_cxy = GET_CXY( inode_xp );
[473]2167    inode_ptr = GET_PTR( inode_xp );
[188]2168
[598]2169    // get inode type, size, attr, mapper, and inum
2170    inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type   ) );
2171    inode_size = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size   ) );
2172    inode_attr = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->attr   ) );
[625]2173    inode_extd = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->extend ) );
[598]2174    mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
[188]2175
2176    // make a local copy of node name
2177    hal_remote_strcpy( XPTR( local_cxy , name ) , name_xp );
2178
[598]2179    // compute dirty
[657]2180    // inode_dirty = ((inode_attr & INODE_ATTR_DIRTY) != 0); unused [AG] dec 2019
[598]2181
[188]2182    // display inode
[657]2183    nolock_printk("%s<%s> : %s / extd %x / %d bytes / cxy %x / inode %x / mapper %x\n",
[625]2184    indent_str[indent], name, vfs_inode_type_str( inode_type ), (uint32_t)inode_extd,
[657]2185    inode_size, inode_cxy, inode_ptr, mapper_ptr );
[188]2186
[611]2187    // scan directory entries when current inode is a directory
2188    // don't scan the the "." and ".." directories to break loops
2189    if( (inode_type == INODE_TYPE_DIR) && 
2190        (strcmp( name , "." ) != 0)    &&
2191        (strcmp( name , ".." ) != 0) )
[188]2192    {
2193        // get extended pointer on directory entries xhtab
[204]2194        children_xp =  XPTR( inode_cxy , &inode_ptr->children );
[188]2195
2196        // get xhtab lock
[568]2197        xhtab_lock( children_xp );
[188]2198
2199        // get first dentry from xhtab
[204]2200        child_dentry_xp = xhtab_get_first( children_xp );
[188]2201
[204]2202        while( child_dentry_xp != XPTR_NULL )
[188]2203        {
2204            // get dentry cluster and local pointer
[204]2205            child_dentry_cxy = GET_CXY( child_dentry_xp );
[473]2206            child_dentry_ptr = GET_PTR( child_dentry_xp );
[188]2207
2208            // get extended pointer on child inode
[568]2209            child_inode_xp = hal_remote_l64( XPTR( child_dentry_cxy,
[204]2210                                                   &child_dentry_ptr->child_xp ) );
[188]2211
2212            // get extended pointer on dentry name
[204]2213            child_dentry_name_xp = XPTR( child_dentry_cxy , &child_dentry_ptr->name );
[188]2214
[568]2215            // recursive call on inode display
[204]2216            vfs_recursive_display( child_inode_xp,
2217                                   child_dentry_name_xp,
2218                                   indent+1 );
[188]2219
2220            // get next dentry
[204]2221            child_dentry_xp = xhtab_get_next( children_xp );
[188]2222        }
2223
2224        // release xhtab lock
[568]2225        xhtab_unlock( children_xp );
[188]2226    }
2227}  // end vfs_recursive_display()
2228
2229///////////////////////////////////
2230void vfs_display( xptr_t inode_xp )
2231{
[204]2232    xptr_t         name_xp;
[188]2233    xptr_t         dentry_xp; 
2234    cxy_t          dentry_cxy;
2235    vfs_dentry_t * dentry_ptr;
[610]2236    xptr_t         parents_root_xp;   // root of parent dentries xlist
[188]2237
2238    // get target inode cluster and local pointer
2239    cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]2240    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[188]2241
[610]2242    // build extended pointer on parents dentries root
2243    parents_root_xp = XPTR( inode_cxy , &inode_ptr->parents );
[188]2244
[610]2245    // check VFS root     
2246    if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root
[188]2247    {
2248        // build extended pointer on root name
2249        name_xp = XPTR( local_cxy , "/" );
2250    }
2251    else
2252    {
[610]2253        // get first parent dentry cluster and pointers
2254        dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
[188]2255        dentry_cxy = GET_CXY( dentry_xp );
[473]2256        dentry_ptr = GET_PTR( dentry_xp );
[188]2257
2258        // get extended pointer on dentry name
2259        name_xp = XPTR( dentry_cxy , &dentry_ptr->name );
2260    }
2261
[337]2262    // get pointers on TXT0 chdev
[407]2263    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
[337]2264    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
2265    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
2266
2267    // get extended pointer on remote TXT0 chdev lock
2268    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
2269
2270    // get TXT0 lock in busy waiting mode
[568]2271    remote_busylock_acquire( lock_xp );
[337]2272
[188]2273    // print header
[657]2274    nolock_printk("\n***** current VFS state\n\n");
[188]2275
2276    // call recursive function
[473]2277    vfs_recursive_display( inode_xp , name_xp , 0 );
[188]2278
[337]2279    // release lock
[568]2280    remote_busylock_release( lock_xp );
[337]2281
[204]2282}  // end vfs_display()
[188]2283
[602]2284/*
[1]2285//////////////////////////////////////////////////////////////////////////////////////////
[602]2286// This static function is used by the vfs_lookup() function.
[1]2287// It takes an extended pointer on a remote inode (parent directory inode),
2288// and check access_rights violation for the calling thread.
2289// It can be used by any thread running in any cluster.
2290//////////////////////////////////////////////////////////////////////////////////////////
2291// @ inode_xp    : extended pointer on inode.
2292// @ client_uid  : client thread user ID
2293// @ client_gid  : client thread group ID
2294// @ return true if access rights are violated.
2295//////////////////////////////////////////////////////////////////////////////////////////
[602]2296static bool_t vfs_access_denied( xptr_t   inode_xp,
[1]2297                          uint32_t client_uid,
2298                          uint32_t client_gid )
2299{
2300    // get found inode cluster and local pointer
2301    cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]2302    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[1]2303
2304    // get inode access mode, UID, and GID
[568]2305    // TODO uint32_t  mode = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->mode ) );
2306    uid_t     uid  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->uid  ) );
2307    gid_t     gid  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->gid  ) );
[1]2308
[634]2309    // TODO : me must use mode
[1]2310    if( (uid == client_uid) || (gid == client_gid) ) return false;
2311    else                                             return true;
2312}
[602]2313*/
[1]2314
2315//////////////////////////////////////////////////////////////////////////////////////////
2316// This static function is used by the vfs_lookup() function.
[204]2317// It takes an extended pointer on a remote parent directory inode, a directory
[626]2318// entry name, and and scan the XHTAB associated to the parent inode to find the
2319// searched dentry. It does NOT modify the inode tree in case of miss.
[1]2320// It can be used by any thread running in any cluster.
2321//////////////////////////////////////////////////////////////////////////////////////////
2322// @ parent_xp   : extended pointer on parent inode in remote cluster.
2323// @ name        : dentry name
2324// @ child_xp    : [out] buffer for extended pointer on child inode.
2325// @ return true if success / return false if not found.
2326//////////////////////////////////////////////////////////////////////////////////////////
2327static bool_t vfs_get_child( xptr_t   parent_xp,
2328                             char   * name,
2329                             xptr_t * child_xp )
2330{
[610]2331    xptr_t         xhtab_xp;    // extended pointer on hash table for children dentries
2332    xptr_t         dentry_xp;   // extended pointer on children dentry
2333    cxy_t          dentry_cxy;
2334    vfs_dentry_t * dentry_ptr;
[1]2335
2336    // get parent inode cluster and local pointer
2337    cxy_t         parent_cxy = GET_CXY( parent_xp );
[473]2338    vfs_inode_t * parent_ptr = GET_PTR( parent_xp );
[1]2339
2340    // get extended pointer on hash table of children directory entries
2341    xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
2342
[610]2343    // get pointers on matching dentry
2344    dentry_xp  = xhtab_lookup( xhtab_xp , name );
2345    dentry_cxy = GET_CXY( dentry_xp );
2346    dentry_ptr = GET_PTR( dentry_xp );
[1]2347
[610]2348    if( dentry_xp == XPTR_NULL ) 
2349    {
2350        return false;
2351    }
2352    else
2353    {
2354        *child_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
2355        return true;
2356    }
[1]2357
[204]2358}  // end vfs_get_child()
2359
[1]2360//////////////////////////////////////////////////////////////////////////////////////////
2361// This static function is used by the vfs_lookup() function.
2362// It takes the <current> pointer on a buffer containing a complete pathname, and return
2363// in the <name> buffer, allocated by the caller, a single name in the path.
2364// It return also in the <next> pointer the next character to analyse in the path.
2365// Finally it returns a <last> boolean, that is true when the returned <name> is the
2366// last name in the path. The names are supposed to be separated by one or several '/'
2367// characters, that are not written in  the <name> buffer.
[610]2368//
2369// WARNING: the leading characters '/' in the path are skiped before analysis.
2370//          The path "/" identifies the VFS root, and is therefore anaysed as an empty
2371//          string. This empty string is dignaled by the (-1) return value. 
[1]2372//////////////////////////////////////////////////////////////////////////////////////////
2373// @ current   : pointer on first character to analyse in buffer containing the path.
2374// @ name      : [out] pointer on buffer allocated by the caller for the returned name.
2375// @ next      : [out] pointer on next character to analyse in buffer containing the path.
2376// @ last      : [out] true if the returned name is the last (NUL character found).
[610]2377// @ return 0 if success / return -1 if string empty (first chracter is NUL).
[1]2378//////////////////////////////////////////////////////////////////////////////////////////
2379static error_t vfs_get_name_from_path( char     * current,
2380                                       char     * name,
2381                                       char    ** next,
2382                                       bool_t   * last )
2383{
2384    char * ptr = current;
2385
2386    // skip leading '/' characters
2387    while( *ptr == '/' ) ptr++;
2388
[610]2389    // signal empty string
2390    if( *ptr == 0 )
2391    {
2392        *last = true;
2393        return -1;
2394    }
[1]2395
2396    // copy all characters in name until NUL or '/'
2397    while( (*ptr != 0) && (*ptr !='/') )  *(name++) = *(ptr++);
2398
[204]2399    // set NUL terminating character in name buffer
2400    *(name++) = 0;
2401
[1]2402    // return last an next
2403    if( *ptr == 0 )             // last found character is NUL => last name in path
2404    {
2405        *last = true;
2406    }
2407    else                        // last found character is '/' => skip it
2408    {
2409        *last = false;
2410        *next = ptr + 1;
2411    }
2412
2413    return 0;
[204]2414
2415}  // end vfs_get name_from_path()
[188]2416   
[610]2417///////////////////////////////////////////////
2418error_t vfs_lookup( xptr_t             root_xp,
[23]2419                    char             * pathname,
[610]2420                    uint32_t           lookup_mode,
2421                                        xptr_t           * inode_xp,
2422                                        char             * last_name )
[1]2423{
[101]2424    char               name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path
[1]2425
[23]2426    xptr_t             parent_xp;    // extended pointer on parent inode
2427    cxy_t              parent_cxy;   // cluster for parent inode
2428    vfs_inode_t      * parent_ptr;   // local pointer on parent inode 
[602]2429    xptr_t             dentry_xp;    // extended pointer on dentry       
[657]2430    vfs_dentry_t     * dentry_ptr;   // local pointer on dentry
[23]2431    xptr_t             child_xp;     // extended pointer on child inode
2432    cxy_t              child_cxy;    // cluster for child inode
[602]2433    vfs_inode_t      * child_ptr;    // local pointer on child inode
[23]2434    vfs_fs_type_t      fs_type;      // File system type
2435    vfs_ctx_t        * ctx_ptr;      // local pointer on FS context
2436    char             * current;      // current pointer on path
2437    char             * next;         // next value for current pointer   
2438    bool_t             last;         // true when the name is the last in path
2439    bool_t             found;        // true when a child has been found
[459]2440    bool_t             create;       // searched inode must be created if not found
2441    bool_t             excl;         // searched inode must not exist
[626]2442    bool_t             parent;       // searched inode is the parent
[23]2443    thread_t         * this;         // pointer on calling thread descriptor
2444    process_t        * process;      // pointer on calling process descriptor
2445    error_t            error;
[1]2446
2447    this    = CURRENT_THREAD;
2448    process = this->process;
2449
[610]2450// check pathname / root_xp consistency
2451assert( ((pathname[0] != '/') || (root_xp == process->vfs_root_xp)), 
[625]2452"root inode must be VFS root for path <%s>", pathname );
[610]2453
[438]2454#if DEBUG_VFS_LOOKUP
[433]2455uint32_t cycle = (uint32_t)hal_get_cycles();
[610]2456char     root_name[CONFIG_VFS_MAX_NAME_LENGTH];
2457vfs_inode_get_name( root_xp , root_name );
[438]2458if( DEBUG_VFS_LOOKUP < cycle )
[610]2459printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / mode %x / cycle %d\n",
2460__FUNCTION__, process->pid, this->trdid, root_name, pathname, lookup_mode, cycle );
[433]2461#endif
[380]2462
[656]2463#if ( DEBUG_VFS_LOOKUP & 1 )
2464if( DEBUG_VFS_LOOKUP < cycle )
2465vfs_display( root_xp );
2466#endif
2467
[459]2468    // compute lookup flags
[610]2469    create = (lookup_mode & VFS_LOOKUP_CREATE) == VFS_LOOKUP_CREATE;
2470    excl   = (lookup_mode & VFS_LOOKUP_EXCL)   == VFS_LOOKUP_EXCL;
[626]2471    parent = (lookup_mode & VFS_LOOKUP_PARENT) == VFS_LOOKUP_PARENT;
[1]2472
[610]2473    // initialise loop variables
2474    parent_xp = root_xp;
2475    current   = pathname;
2476    next      = NULL;
2477    last      = false;
2478    child_xp  = XPTR_NULL;
[657]2479    child_cxy = 0;
2480    child_ptr = NULL;
[1]2481
[610]2482    // loop on nodes in pathname
2483    // load from device if one node in path not found in Inode Tree
[401]2484    // exit loop when last name found (i.e. last == true)
[610]2485    while( 1 )
[1]2486    {
[610]2487        // get parent inode cluster and local pointer
2488        parent_cxy = GET_CXY( parent_xp );
2489        parent_ptr = GET_PTR( parent_xp );
[1]2490
[610]2491        // get one "name" from path, and "last" flag
2492        error = vfs_get_name_from_path( current , name , &next , &last );
2493
[611]2494        // handle VFS root case
[610]2495        if ( error )
2496        {
2497
2498#if DEBUG_VFS_LOOKUP
2499cycle = (uint32_t)hal_get_cycles();
2500if( DEBUG_VFS_LOOKUP < cycle )
2501printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n",
2502__FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle );
2503#endif
2504            *inode_xp = process->vfs_root_xp;
2505            break;
2506        }
2507
[438]2508#if (DEBUG_VFS_LOOKUP & 1)
2509if( DEBUG_VFS_LOOKUP < cycle )
[628]2510printk("\n[%s] thread[%x,%x] search <%s> in <%s> / last = %d\n",
[602]2511__FUNCTION__, process->pid, this->trdid, name, pathname, last );
[433]2512#endif
[101]2513
[656]2514        // search the child dentry matching name in parent inode XHTAB
[1]2515        found = vfs_get_child( parent_xp,
2516                               name,
2517                               &child_xp );
2518
[657]2519        if( found == false )                          // child not found in Inode Tree
[1]2520        {
[610]2521            // when a inode is not found in the Inode Tree:
[626]2522            // - if (last and parent) the Inode Tree is not modified
[610]2523            // - else we speculatively introduce a new (dentry/inode) in inode tree,
2524            //        and scan the parent directory mapper to initialise it.
2525            //     . if it is not found in the parent mapper:
2526            //         - if(last and create), a brand new file or directory is created
2527            //         - else, an error is reported
2528            //     . if it is found in parent mapper:
2529            //         - if( last and excl ), an error is reported
2530            //         - else the new child (inode & dentry) is initialised in Inode Tree
2531            //         - if the child is a directory, the child mapper is loaded from device
[101]2532
[626]2533            if( last && parent )   //  does nothing
[610]2534            {
2535
[438]2536#if (DEBUG_VFS_LOOKUP & 1)
2537if( DEBUG_VFS_LOOKUP < cycle )
[610]2538printk("\n[%s] thread[%x,%x] child not found but only parent requested in <%s>\n",
2539__FUNCTION__, process->pid, this->trdid, pathname );
2540#endif
2541            }
2542            else                                    // try to get it from parent mapper
2543            {
2544
2545#if (DEBUG_VFS_LOOKUP & 1)
2546if( DEBUG_VFS_LOOKUP < cycle )
2547printk("\n[%s] thread[%x,%x] miss <%s> inode in Inode Tree => build from parent mapper\n",
[602]2548__FUNCTION__, process->pid, this->trdid, name );
[433]2549#endif
[610]2550                // get parent inode FS type
[657]2551                ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
[610]2552                fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
[407]2553
[610]2554                // select a cluster for new inode
2555                child_cxy = cluster_random_select();
[602]2556
[611]2557                // insert a new child dentry/inode couple in inode tree
[610]2558                error = vfs_add_child_in_parent( child_cxy,
2559                                                 fs_type, 
2560                                                 parent_xp, 
2561                                                 name, 
2562                                                 &dentry_xp,
2563                                                 &child_xp );
2564                if( error )
2565                {
2566                    printk("\n[ERROR] in %s : cannot create inode <%s> in path <%s>\n",
2567                    __FUNCTION__ , name, pathname );
2568                    return -1;
2569                }
[238]2570
[657]2571                // get child inode and dentry local pointers
2572                child_ptr  = GET_PTR( child_xp );
2573                dentry_ptr = GET_PTR( dentry_xp );
[459]2574
2575#if (DEBUG_VFS_LOOKUP & 1)
2576if( DEBUG_VFS_LOOKUP < cycle )
[656]2577printk("\n[%s] thread[%x,%x] created missing inode <%s> in cluster %x\n",
[602]2578__FUNCTION__, process->pid, this->trdid, name, child_cxy );
[459]2579#endif
[610]2580                // scan parent mapper to find the missing dentry, and complete
[611]2581                // the initialisation of dentry and child inode descriptors
[657]2582                error = vfs_fs_new_dentry_from_mapper( parent_xp,
2583                                                       dentry_ptr );
[238]2584
[657]2585                if ( error )  // an error can be fatal or non-fatal :
[459]2586                {
[625]2587                    if ( last && create )  // add a brand new dentry in parent directory
[602]2588                    {
[657]2589                        error = vfs_fs_new_dentry_to_mapper( parent_xp,               
2590                                                             dentry_ptr );
[610]2591                        if ( error )
2592                        {
[657]2593                            printk("\n[ERROR] in %s : cannot add dentry <%s> in parent dir\n",
2594                            __FUNCTION__, name );
[610]2595                            vfs_remove_child_from_parent( dentry_xp );
2596                            return -1;
2597                        }
[1]2598
[459]2599#if (DEBUG_VFS_LOOKUP & 1)
2600if( DEBUG_VFS_LOOKUP < cycle )
[626]2601printk("\n[%s] thread[%x,%x] child <%s> not found in parent mapper => created it\n",
[602]2602__FUNCTION__, process->pid, this->trdid, name );
[626]2603vfs_inode_display( child_xp );
[459]2604#endif
[610]2605                    }
2606                    else                   // not last or not create => error
2607                    {                       
2608                        printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
2609                        __FUNCTION__ , name , pathname );
2610                        vfs_remove_child_from_parent( dentry_xp );
2611                        return -1;
2612                    }
[238]2613                }
[610]2614                else          // child has been found in parent mapper
[459]2615                {
[610]2616                    // check the excl
2617                    if( last && create && excl )
[459]2618                    {
[610]2619                        printk("\n[ERROR] in %s : node already exist <%s>\n",
2620                        __FUNCTION__, name );
2621                       return -1;
[459]2622                    }
[610]2623
2624#if (DEBUG_VFS_LOOKUP & 1)
2625if( DEBUG_VFS_LOOKUP < cycle )
2626printk("\n[%s] thread[%x,%x] initialised inode <%s> from parent mapper\n",
2627__FUNCTION__, process->pid, this->trdid, name );
2628#endif
2629                    // load child mapper from device if child is a directory (prefetch)
2630                    uint32_t type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
2631                    if( type == INODE_TYPE_DIR ) 
[459]2632                    {
[657]2633                        error = vfs_inode_load_all_pages( child_xp );
2634
[610]2635                        if ( error )
2636                        {
2637                            printk("\n[ERROR] in %s : cannot load <%s> from device\n",
2638                            __FUNCTION__ , name );
2639                            vfs_remove_child_from_parent( dentry_xp );
2640                            return -1;
2641                        }
[238]2642
[438]2643#if (DEBUG_VFS_LOOKUP & 1)
2644if( DEBUG_VFS_LOOKUP < cycle )
[610]2645printk("\n[%s] thread[%x,%x] loaded directory mapper for <%s> from IOC\n",
2646__FUNCTION__ , process->pid, this->trdid, name );
[433]2647#endif
[610]2648                    }
[459]2649                }
2650            }
[1]2651        }
[657]2652        else                                    // child found in Inode Tree
[459]2653        {
[657]2654            // get child inode local pointer and cluster
2655            child_ptr  = GET_PTR( child_xp );
2656            child_cxy  = GET_CXY( child_xp );
[459]2657       
[438]2658#if (DEBUG_VFS_LOOKUP & 1)
2659if( DEBUG_VFS_LOOKUP < cycle )
[610]2660printk("\n[%s] thread[%x,%x] found <%s> in Inode Tree / inode (%x,%x)\n",
[611]2661__FUNCTION__, process->pid, this->trdid, name, child_cxy, child_ptr );
[433]2662#endif
[610]2663            // check the excl flag
2664            if( last && create && excl )
[459]2665            {
[610]2666                printk("\n[ERROR] in %s : node <%s> already exist\n",
2667                __FUNCTION__, name );
2668                return -1;
[459]2669            }
2670        }
2671
[380]2672        // TODO check access rights here [AG]
[23]2673        // error = vfs_access_denied( child_xp,
2674        //                            client_uid,
2675        //                            client_gid );
2676        // if( error )
2677        // {
[441]2678        //     printk("\n[ERROR] in %s : thread %x / permission denied for %s\n",
2679        //     __FUNCTION__ , this , name );
[23]2680        //     return EACCES;
2681        // }
[1]2682
[610]2683        // exit when last
2684        if ( last )           // last inode in path  => return relevant info
2685        {
[626]2686            if ( parent )  // return parent inode and child name
[610]2687            {
[1]2688
[610]2689#if DEBUG_VFS_LOOKUP
2690cycle = (uint32_t)hal_get_cycles();
2691if( DEBUG_VFS_LOOKUP < cycle )
2692printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n",
2693__FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle );
2694#endif
2695                *inode_xp = parent_xp;
2696                strcpy( last_name , name );
2697                break; 
2698            }
2699            else        // return child inode name     
2700            {
[1]2701
[438]2702#if DEBUG_VFS_LOOKUP
[433]2703cycle = (uint32_t)hal_get_cycles();
[438]2704if( DEBUG_VFS_LOOKUP < cycle )
[610]2705printk("\n[%s] thread[%x,%x] exit / child inode (%x,%x) / <%s> / cycle %d\n",
2706__FUNCTION__ , process->pid, this->trdid, child_cxy, child_ptr, pathname, cycle );
[433]2707#endif
[610]2708                *inode_xp = child_xp;
2709                break;
2710            }
2711        }
[657]2712        else                     // not the last node in path => update loop variables
[610]2713        {
2714            parent_xp = child_xp;
2715            current   = next;
2716        }
[657]2717    }  // end while loop on nodes in pathname
[1]2718
[657]2719#if ( DEBUG_VFS_LOOKUP & 1 )
2720if( DEBUG_VFS_LOOKUP < cycle )
2721vfs_display( root_xp );
[602]2722#endif
2723
2724    return 0;
2725
[657]2726}  // end vfs_lookup()
[602]2727
[611]2728///////////////////////////////////////////////////
2729error_t vfs_add_special_dentries( xptr_t  child_xp,
2730                                  xptr_t  parent_xp )
2731{
2732    error_t         error;
2733    vfs_inode_t   * child_ptr;         // local pointer on child inode directory
2734    cxy_t           child_cxy;         // child inode directory cluster identifier
2735    vfs_ctx_t     * ctx_ptr;           // local pointer on child inode FS context
2736    vfs_fs_type_t   fs_type;           // FS type of child inode
2737    xptr_t          dentry_xp;         // extended pointer on dentry (used for . and ..)
2738    vfs_dentry_t  * dentry_ptr;        // local pointer on dentry (used for . and ..)
2739    xptr_t          children_xhtab_xp; // extended pointer on inode "children" field
2740    xptr_t          children_entry_xp; // extended pointer on dentry "children" field
2741
2742#if DEBUG_VFS_ADD_SPECIAL
2743uint32_t   cycle = (uint32_t)hal_get_cycles();
2744thread_t * this  = CURRENT_THREAD;
2745char child_name[CONFIG_VFS_MAX_NAME_LENGTH];
2746char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
2747vfs_inode_get_name( child_xp  , child_name );
2748vfs_inode_get_name( parent_xp , parent_name );
2749if( DEBUG_VFS_ADD_SPECIAL < cycle )
[612]2750printk("\n[%s] thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
[611]2751__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle );
2752#endif
2753
[657]2754    // get child directory cluster and local pointer
[611]2755    child_cxy  = GET_CXY( child_xp );
2756    child_ptr  = GET_PTR( child_xp );
2757
2758    // get child inode FS type
2759    ctx_ptr    = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) );
2760    fs_type    = hal_remote_l32( XPTR( child_cxy , &ctx_ptr->type ) );
2761
[630]2762    //////////////////////////// create <.> dentry //////////////////////
[657]2763    error = vfs_dentry_create( child_cxy,
2764                               fs_type,
2765                               ".",
2766                               &dentry_xp );
[611]2767    if( error )
2768    {
2769        printk("\n[ERROR] in %s : cannot create dentry <.> in cluster %x\n",
2770        __FUNCTION__ , child_cxy );
2771        return -1;
2772    }
2773
2774    // get <.> dentry local pointer
2775    dentry_ptr = GET_PTR( dentry_xp );
2776
2777#if(DEBUG_VFS_ADD_SPECIAL & 1)
[630]2778cycle = (uint32_t)hal_get_cycles();
[611]2779if( DEBUG_VFS_ADD_SPECIAL < cycle )
[630]2780printk("\n[%s] thread[%x,%x] created dentry <.> (%x,%x) / cycle %d\n",
2781__FUNCTION__, this->process->pid, this->trdid, child_cxy, dentry_ptr, cycle );
[611]2782#endif
2783
2784    // register <.> dentry in child inode xhtab of children
2785    children_xhtab_xp = XPTR( child_cxy , &child_ptr->children );
2786    children_entry_xp = XPTR( child_cxy , &dentry_ptr->children );
[657]2787
[611]2788    error = xhtab_insert( children_xhtab_xp , "." , children_entry_xp );
[657]2789
[611]2790    if( error )
2791    {
2792        printk("\n[ERROR] in %s : cannot register dentry <.> in xhtab\n",
2793        __FUNCTION__ );
2794        return -1;
2795    }
[612]2796   
[611]2797    // update "parent" and "child_xp" fields in <.> dentry
2798    hal_remote_s64( XPTR( child_cxy , &dentry_ptr->child_xp ) , child_xp );
2799    hal_remote_spt( XPTR( child_cxy , &dentry_ptr->parent ) , child_ptr );
2800
2801#if(DEBUG_VFS_ADD_SPECIAL & 1)
[630]2802cycle = (uint32_t)hal_get_cycles();
[611]2803if( DEBUG_VFS_ADD_SPECIAL < cycle )
[630]2804printk("\n[%s] thread[%x,%x] linked dentry <.> to parent and child inodes / cycle %d\n", 
2805__FUNCTION__, this->process->pid, this->trdid, cycle ); 
[611]2806#endif
2807
2808    // introduce <.> dentry into child directory mapper
[630]2809    // only if the target directory is not the root VFS
2810    if( child_xp != parent_xp )
[611]2811    {
[657]2812        error = vfs_fs_add_dentry( child_xp,
2813                                   dentry_ptr );
[630]2814        if( error )
2815        {
2816            printk("\n[ERROR] in %s : cannot introduce dentry <..> in mapper %x\n",
2817            __FUNCTION__ );
2818            return -1;
2819        }
[611]2820
2821#if(DEBUG_VFS_ADD_SPECIAL & 1)
[630]2822cycle = (uint32_t)hal_get_cycles();
[611]2823if( DEBUG_VFS_ADD_SPECIAL < cycle )
[630]2824printk("\n[%s] thread[%x,%x] registered dentry <.> in child mapper / cycle %d\n", 
2825__FUNCTION__, this->process->pid, this->trdid, cycle ); 
[611]2826#endif
2827
[630]2828    }
2829
2830    ///////////////////////////// create <..> dentry ///////////////////////
[657]2831    error = vfs_dentry_create( child_cxy,
2832                               fs_type,
2833                               "..",
2834                               &dentry_xp );
[611]2835    if( error )
2836    {
2837        printk("\n[ERROR] in %s : cannot create dentry <..> in cluster %x\n",
2838        __FUNCTION__ , child_cxy );
2839        return -1;
2840    }
2841
2842    // get <..> dentry local pointer
2843    dentry_ptr = GET_PTR( dentry_xp );
2844
2845#if(DEBUG_VFS_ADD_SPECIAL & 1)
[630]2846cycle = (uint32_t)hal_get_cycles();
[611]2847if( DEBUG_VFS_ADD_SPECIAL < cycle )
[630]2848printk("\n[%s] thread[%x,%x] created dentry <..> (%x,%x) / cycle %d\n",
2849__FUNCTION__, this->process->pid, this->trdid, child_cxy, dentry_ptr, cycle );
[611]2850#endif
2851
2852    // register <..> dentry in child_inode xhtab of children
2853    children_xhtab_xp = XPTR( child_cxy , &child_ptr->children );
2854    children_entry_xp = XPTR( child_cxy , &dentry_ptr->children );
2855    error = xhtab_insert( children_xhtab_xp , ".." , children_entry_xp );
2856    if( error )
2857    {
2858        printk("\n[ERROR] in %s : cannot register dentry <..> in xhtab\n",
2859        __FUNCTION__ );
2860        return -1;
2861    }
2862
[612]2863    // don't register <..> dentry in parent_inode xlist of parents
[611]2864
2865    // update "parent" and "child_xp" fields in <..> dentry
2866    hal_remote_s64( XPTR( child_cxy , &dentry_ptr->child_xp ) , parent_xp );
2867    hal_remote_spt( XPTR( child_cxy , &dentry_ptr->parent ) , child_ptr );
2868
2869#if(DEBUG_VFS_ADD_SPECIAL & 1)
[630]2870cycle = (uint32_t)hal_get_cycles();
[611]2871if( DEBUG_VFS_ADD_SPECIAL < cycle )
[630]2872printk("\n[%s] thread[%x,%x] linked dentry <..> to parent and child inodes / cycle %d\n", 
2873__FUNCTION__, this->process->pid, this->trdid, cycle ); 
[611]2874#endif
2875
2876    // introduce <..> dentry into child directory mapper
[630]2877    // only if the target directory is not the root VFS
2878    if( child_xp != parent_xp )
[611]2879    {
[657]2880        error = vfs_fs_add_dentry( child_xp,
2881                                   dentry_ptr );
[630]2882        if( error )
2883        {
2884            printk("\n[ERROR] in %s : cannot introduce dentry <..> in mapper %x\n",
2885            __FUNCTION__ );
2886            return -1;
2887        }
[611]2888
2889#if(DEBUG_VFS_ADD_SPECIAL & 1)
[630]2890cycle = (uint32_t)hal_get_cycles();
[611]2891if( DEBUG_VFS_ADD_SPECIAL < cycle )
[630]2892printk("\n[%s] thread[%x,%x] registered dentry <..> in child mapper / cycle %d\n", 
2893__FUNCTION__, this->process->pid, this->trdid, cycle ); 
[611]2894#endif
2895
[630]2896    }
2897
[611]2898#if DEBUG_VFS_ADD_SPECIAL
2899cycle = (uint32_t)hal_get_cycles();
2900if( DEBUG_VFS_ADD_SPECIAL < cycle )
[612]2901printk("\n[%s] thread[%x,%x] exit for child <%s> in parent <%s> / cycle %d\n",
2902__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle );
[611]2903#endif
2904
2905    return 0;
2906
2907}  // end vfs_add_special_dentries()
2908
[610]2909//////////////////////////////////////////
2910error_t vfs_get_path( xptr_t     inode_xp,
2911                      char     * buffer,
2912                      char    ** first,
2913                      uint32_t   max_size )
[1]2914{
[610]2915        xptr_t         dentry_xp;        // extended pointer on current dentry
2916    vfs_dentry_t * dentry_ptr;       // local pointer on current dentry
2917    cxy_t          dentry_cxy;       // current dentry cluster identifier
2918    xptr_t         name_xp;          // extended pointer on current dentry name
2919        uint32_t       length;           // length of current dentry name
2920        int32_t        index;            // slot index in buffer
2921    xptr_t         current_xp;       // extended pointer on current inode
2922    vfs_inode_t  * current_ptr;      // local pointer on current inode
2923    cxy_t          current_cxy;      // current inode cluster identifier
2924    xptr_t         vfs_root_xp;      // extended pointer on VFS root inode
2925    vfs_inode_t  * vfs_root_ptr;     // local pointer on VFS root inode
2926    cxy_t          vfs_root_cxy;     // VFS root inode cluster identifier
2927    xptr_t         lock_xp;          // extended pointer on Inode Tree lock
2928    xptr_t         parents_root_xp;  // extended pointer on current inode parents root
2929    bool_t         found;            // condition to exit the while loop
[1]2930
[610]2931    thread_t  * this    = CURRENT_THREAD;
2932    process_t * process = this->process;
[1]2933
[610]2934#if DEBUG_VFS_GET_PATH
2935uint32_t cycle = (uint32_t)hal_get_cycles();
2936if( DEBUG_VFS_GET_PATH < cycle )
2937printk("\n[%s] thread[%x,%x] enter : inode (%x,%x) / cycle %d\n",
2938__FUNCTION__ , process->pid, this->trdid,
2939GET_CXY( inode_xp ), GET_PTR( inode_xp ), cycle );
2940#endif
2941
2942        // set the NUL character in buffer / initialise buffer index
[1]2943        buffer[max_size - 1] = 0;
[610]2944    index    = (int32_t)(max_size - 1);
[1]2945
2946    // initialize current inode
[610]2947    current_xp  = inode_xp;
[1]2948
[610]2949    // build extended pointer on lock protecting Inode Tree
2950    vfs_root_xp  = process->vfs_root_xp;
2951    vfs_root_ptr = GET_PTR( vfs_root_xp );
2952    vfs_root_cxy = GET_CXY( vfs_root_xp );
2953    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
2954
2955    // take lock protecting Inode Tree in read mode
2956    remote_rwlock_rd_acquire( lock_xp );
2957
2958    // traverse Inode Tree from target inode to VFS root
2959    // selecting always the first parent dentry
2960    // the buffer is written in "reverse order" (from target inode to root)
2961    // exit the while loop when the VFS root has been found
[1]2962        do
2963    {
[610]2964        // get current inode cluster and local pointer
2965        current_cxy = GET_CXY( current_xp );
2966        current_ptr = GET_PTR( current_xp );
[1]2967
[610]2968        // build extended pointer on parents dentries root
2969        parents_root_xp = XPTR( current_cxy , &current_ptr->parents );
[1]2970
[610]2971        // compute exit condition <=> current inode is VFS root   
2972        found = xlist_is_empty( parents_root_xp );
[1]2973
[610]2974        if( found )                              // parent is the VFS root
2975        {
2976            if( index == (int32_t)(max_size - 1) )
2977            {
2978                // update index
2979                index--;
2980                 
2981                // set separator 
2982                        buffer[index] = '/';
[1]2983
[610]2984// check buffer overflow
[625]2985assert( (index >= 0) , "kernel buffer too small" );
[1]2986
[610]2987            }
2988        }
2989        else                                     // not the VFS root
[1]2990        {
[610]2991            // get first parent dentry cluster and pointers
2992            dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
2993            dentry_cxy = GET_CXY( dentry_xp );
2994            dentry_ptr = GET_PTR( dentry_xp );
[1]2995
[610]2996            // get extended pointer on dentry name and name length
2997            name_xp = XPTR( dentry_cxy , dentry_ptr->name );
2998            length  = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->length ) );
[1]2999
[610]3000#if (DEBUG_VFS_GET_PATH & 1)
3001char debug_name[CONFIG_VFS_MAX_NAME_LENGTH];
3002hal_remote_strcpy( XPTR( local_cxy , debug_name ) , name_xp );
3003if( DEBUG_VFS_GET_PATH < cycle )
3004printk("\n[%s] thread(%x,%s) get current dentry <%s> in cluster %x\n",
3005__FUNCTION__ , process->pid, this->trdid, debug_name, current_cxy );
3006#endif
3007            // update index
3008            index -= (length + 1); 
3009
3010// check buffer overflow
[625]3011assert( (index >= 0) , "kernel buffer too small" );
[610]3012
3013            // update pathname
3014            hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
3015                               name_xp , length );
3016
3017            // set separator 
3018                    buffer[index] = '/';
3019
3020            // get extended pointer on parent inode
3021            current_xp = XPTR( dentry_cxy , 
3022                               hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) ) );
3023        }
[1]3024    }
[610]3025    while( found == false );
[1]3026
[610]3027    // release lock protecting Inode Tree in read mode
3028    remote_rwlock_rd_release( lock_xp );
3029
3030#if DEBUG_VFS_GET_PATH
3031cycle = (uint32_t)hal_get_cycles();
3032if( DEBUG_VFS_GET_PATH < cycle )
3033printk("\n[%s] thread[%x,%x] exit : path <%s> / cycle %d\n",
3034__FUNCTION__ , process->pid, this->trdid, &buffer[index], cycle );
3035#endif
3036
3037    // return pointer on first character in buffer
3038    *first = &buffer[index];
[1]3039        return 0;
3040
3041}  // end vfs_get_path()
3042
[188]3043     
[657]3044//////////////////////////////////////////////////////////////
[610]3045error_t vfs_add_child_in_parent( cxy_t              child_cxy,
[23]3046                                 vfs_fs_type_t      fs_type,
[602]3047                                 xptr_t             parent_inode_xp,
[23]3048                                 char             * name,
[610]3049                                 xptr_t           * child_dentry_xp,
[602]3050                                 xptr_t           * child_inode_xp )
[1]3051{
[610]3052    error_t        error;
3053    cxy_t          parent_cxy;          // parent inode cluster identifier
3054    vfs_inode_t  * parent_inode_ptr;    // parent inode local pointer
3055    xptr_t         new_dentry_xp;       // extended pointer on created dentry
3056    vfs_dentry_t * new_dentry_ptr;      // created dentry local pointer
3057    xptr_t         new_inode_xp;        // extended pointer on created child inode
3058    vfs_inode_t  * new_inode_ptr;       // local pointer on created child inode
[1]3059
[610]3060    xptr_t         parents_root_xp;     // extended pointer on child inode  "parents" field
3061    xptr_t         parents_entry_xp;    // extended pointer on child dentry "parents" field
3062    xptr_t         children_xhtab_xp;   // extended pointer on parent inode "children" field
3063    xptr_t         children_entry_xp;   // extended pointer on child dentry "children" field
3064   
3065    // get parent inode cluster and pointer
3066    parent_cxy       = GET_CXY( parent_inode_xp );
[602]3067    parent_inode_ptr = GET_PTR( parent_inode_xp );
[1]3068
[438]3069#if DEBUG_VFS_ADD_CHILD
[602]3070char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
3071vfs_inode_get_name( parent_inode_xp , parent_name );
[433]3072uint32_t cycle = (uint32_t)hal_get_cycles();
[568]3073thread_t * this = CURRENT_THREAD; 
[438]3074if( DEBUG_VFS_ADD_CHILD < cycle )
[610]3075printk("\n[%s] thread[%x,%x] enter / child <%s> / parent <%s> / cycle %d\n",
3076__FUNCTION__, this->process->pid, this->trdid, name,
3077parent_name, (uint32_t)hal_get_cycles() );
[433]3078#endif
[279]3079
[610]3080    // 1. create dentry in parent cluster
[657]3081    error = vfs_dentry_create( parent_cxy,
3082                               fs_type,
3083                               name,
3084                               &new_dentry_xp );
[1]3085    if( error )
3086    {
[437]3087        printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n",
[610]3088        __FUNCTION__ , name , parent_cxy );
[602]3089        return -1;
[1]3090    }
3091
[602]3092    // get dentry local pointer
3093    new_dentry_ptr = GET_PTR( new_dentry_xp );
3094
[568]3095#if(DEBUG_VFS_ADD_CHILD & 1)
3096if( DEBUG_VFS_ADD_CHILD < cycle )
[656]3097printk("\n[%s] thread[%x,%x] created dentry <%s> : (%x,%x)\n",
[610]3098__FUNCTION__, this->process->pid, this->trdid, name, parent_cxy, new_dentry_ptr );
[568]3099#endif
3100
[610]3101    // 2. create child inode in child cluster
3102    // TODO : define attr / mode / uid / gid
[1]3103    uint32_t attr = 0;
3104    uint32_t mode = 0;
3105    uint32_t uid  = 0;
3106    uint32_t gid  = 0;
3107   
[657]3108    error = vfs_inode_create( child_cxy,
3109                              fs_type,
3110                              attr,
3111                              mode,
3112                              uid,
3113                              gid,
3114                              &new_inode_xp );
[1]3115    if( error )
3116    {
3117        printk("\n[ERROR] in %s : cannot create inode in cluster %x\n",
[610]3118               __FUNCTION__ , child_cxy );
[1]3119 
[657]3120        vfs_dentry_destroy( new_dentry_xp );
[602]3121        return -1;
[1]3122    }
3123
[610]3124    // get new inode local pointer
3125    new_inode_ptr = GET_PTR( new_inode_xp );
3126   
[568]3127#if(DEBUG_VFS_ADD_CHILD & 1)
3128if( DEBUG_VFS_ADD_CHILD < cycle )
[656]3129printk("\n[%s] thread[%x,%x] created inode <%s> : (%x,%x)\n",
[610]3130__FUNCTION__ , this->process->pid, this->trdid, name , child_cxy, new_inode_ptr );
[568]3131#endif
3132
[610]3133    // 3. register new_dentry in new_inode xlist of parents
3134    parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents );
3135    parents_entry_xp = XPTR( parent_cxy, &new_dentry_ptr->parents );
3136    xlist_add_first( parents_root_xp , parents_entry_xp );
3137    hal_remote_atomic_add( XPTR( child_cxy , &new_inode_ptr->links ) , 1 );
[204]3138
[610]3139#if(DEBUG_VFS_ADD_CHILD & 1)
[611]3140if( DEBUG_VFS_ADD_CHILD < cycle )
[656]3141printk("\n[%s] thread[%x,%x] linked dentry(%x,%x) to child inode(%x,%x)\n",
[610]3142__FUNCTION__, this->process->pid, this->trdid, 
3143parent_cxy, new_dentry_ptr, child_cxy, new_inode_ptr );
3144#endif
3145
[626]3146    // 4. register new_dentry in parent_inode xhtab of children
[610]3147    children_xhtab_xp = XPTR( parent_cxy , &parent_inode_ptr->children );
3148    children_entry_xp = XPTR( parent_cxy , &new_dentry_ptr->children );
3149    xhtab_insert( children_xhtab_xp , name , children_entry_xp );
3150
3151#if(DEBUG_VFS_ADD_CHILD & 1)
3152if( DEBUG_VFS_ADD_CHILD < cycle )
[656]3153printk("\n[%s] thread[%x,%x] linked dentry(%x,%x) to parent inode(%x,%x)\n",
[610]3154__FUNCTION__, this->process->pid, this->trdid, 
3155parent_cxy, new_dentry_ptr, parent_cxy, parent_inode_ptr );
3156#endif
3157
[626]3158    // 5. update "parent" and "child_xp" fields in new_dentry
[610]3159    hal_remote_s64( XPTR( parent_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp );
3160    hal_remote_spt( XPTR( parent_cxy , &new_dentry_ptr->parent ) , parent_inode_ptr );
3161
[438]3162#if DEBUG_VFS_ADD_CHILD
[433]3163cycle = (uint32_t)hal_get_cycles();
[438]3164if( DEBUG_VFS_ADD_CHILD < cycle )
[598]3165printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n",
[633]3166__FUNCTION__, this->process->pid, this->trdid, name, cycle );
[433]3167#endif
[296]3168
[602]3169    // return extended pointer on dentry & child inode
[610]3170    *child_dentry_xp = new_dentry_xp;
3171    *child_inode_xp  = new_inode_xp;
[1]3172    return 0;
3173
3174}  // end vfs_add_child_in_parent()
3175
[610]3176/////////////////////////////////////////////////////
3177void vfs_remove_child_from_parent( xptr_t dentry_xp )
[459]3178{
[610]3179    cxy_t          parent_cxy;         // parent inode cluster identifier
3180    cxy_t          child_cxy;          // child inode cluster identifier
3181    vfs_dentry_t * dentry_ptr;         // local pointer on dentry
3182    xptr_t         child_inode_xp;     // extended pointer on child inode
3183    vfs_inode_t  * child_inode_ptr;    // local pointer on child inode
3184    vfs_inode_t  * parent_inode_ptr;   // local pointer on parent inode
3185    uint32_t       links;              // number of child inode parents
3186
3187    char dentry_name[CONFIG_VFS_MAX_NAME_LENGTH];
[459]3188   
[610]3189    // get parent cluster and dentry local pointer
3190    parent_cxy = GET_CXY( dentry_xp );
[459]3191    dentry_ptr = GET_PTR( dentry_xp );
3192
[610]3193    // get a local copy of dentry name
3194    hal_remote_strcpy( XPTR( local_cxy  , dentry_name ),
3195                       XPTR( parent_cxy , &dentry_ptr->name ) );
[459]3196
[610]3197    // get parent_inode local pointer
3198    parent_inode_ptr = hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->parent ) );
3199 
3200    // get child cluster and child_inode pointers
3201    child_inode_xp   = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
3202    child_cxy        = GET_CXY( child_inode_xp ); 
3203    child_inode_ptr  = GET_PTR( child_inode_xp );
[602]3204
[610]3205    // remove dentry from parent_inode
3206    xhtab_remove( XPTR( parent_cxy , &parent_inode_ptr->children ),
3207                  dentry_name,
3208                  XPTR( parent_cxy , &dentry_ptr->children ) );
[602]3209
[610]3210    // remove dentry from child_inode
3211    xlist_unlink( XPTR( parent_cxy , &dentry_ptr->parents ) );
3212    links = hal_remote_atomic_add( XPTR( child_cxy , &child_inode_ptr->links ) , -1 );
3213
3214    // delete dentry descriptor
[657]3215    vfs_dentry_destroy( dentry_xp );
[459]3216
[610]3217    // delete child_inode descriptor if last link
[657]3218    if( links == 1 )  vfs_inode_destroy( child_inode_xp );
[459]3219
3220}  // end vfs_remove_child_from_parent()
3221
[612]3222
3223
3224
[23]3225//////////////////////////////////////////////////////////////////////////////////////////
[602]3226//    API used by VFS to access a specific FS 
[23]3227//////////////////////////////////////////////////////////////////////////////////////////
3228
[657]3229///////////////////////////////////////////////////
3230error_t vfs_fs_add_dentry( xptr_t         inode_xp,
3231                           vfs_dentry_t * dentry_ptr )
[23]3232{
[204]3233    error_t error = 0;
[23]3234
[657]3235assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
3236assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
[23]3237
[657]3238    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3239    cxy_t         inode_cxy = GET_CXY( inode_xp );
[23]3240
[657]3241    // get inode mapper
3242    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
[23]3243
[657]3244assert( (mapper != NULL) , "mapper pointer is NULL")       
[246]3245
[23]3246    // get FS type
[657]3247    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
[23]3248
[238]3249    // call relevant FS function
[23]3250    if( fs_type == FS_TYPE_FATFS )
3251    {
[657]3252        error = fatfs_add_dentry( inode_xp , dentry_ptr ); 
[602]3253    }
3254    else if( fs_type == FS_TYPE_RAMFS )
3255    {
[657]3256        error = 0;     // does nothing for RAMFS
[602]3257    }
3258    else if( fs_type == FS_TYPE_DEVFS )
3259    {
[657]3260        error = 0;     // does nothing for DEVFS
[602]3261    }
3262    else
3263    {
[625]3264        assert( false , "undefined file system type" );
[602]3265    }
[568]3266
[602]3267    return error;
[568]3268
[657]3269}  // end vfs_fs_add_dentry()
[602]3270
[657]3271//////////////////////////////////////////////////////
3272error_t vfs_fs_remove_dentry( xptr_t         inode_xp,
3273                              vfs_dentry_t * dentry_ptr )
[602]3274{
3275    error_t error = 0;
3276
[657]3277assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
3278assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
[602]3279
[657]3280    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3281    cxy_t         inode_cxy = GET_CXY( inode_xp );
[602]3282
[657]3283    // get inode mapper
3284    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
[602]3285
[657]3286assert( (mapper != NULL) , "mapper pointer is NULL")       
3287
[602]3288    // get FS type
[657]3289    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
[602]3290
3291    // call relevant FS function
3292    if( fs_type == FS_TYPE_FATFS )
3293    {
[657]3294        error = fatfs_remove_dentry( inode_xp , dentry_ptr ); 
3295
[23]3296    }
3297    else if( fs_type == FS_TYPE_RAMFS )
3298    {
[612]3299        error = 0;     // does nothing for RAMFS
[23]3300    }
3301    else if( fs_type == FS_TYPE_DEVFS )
3302    {
[612]3303        error = 0;     // does nothing for DEVFS
[23]3304    }
3305    else
3306    {
[625]3307        assert( false , "undefined file system type" );
[23]3308    }
3309
3310    return error;
3311
[657]3312}  // end vfs_fs_remove_dentry()
[23]3313
[657]3314///////////////////////////////////////////////////////////////
3315error_t vfs_fs_new_dentry_from_mapper( xptr_t         inode_xp,
3316                                       vfs_dentry_t * dentry_ptr )
[23]3317{
[602]3318    error_t error = 0;
[23]3319
[657]3320assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
3321assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
[23]3322
[657]3323    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3324    cxy_t         inode_cxy = GET_CXY( inode_xp );
[23]3325
[657]3326    // get inode mapper
3327    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
[23]3328
[657]3329assert( (mapper != NULL) , "mapper pointer is NULL")       
3330
[602]3331    // get FS type
[657]3332    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
[401]3333
[602]3334    // call relevant FS function
3335    if( fs_type == FS_TYPE_FATFS )
3336    {
[657]3337        error = fatfs_new_dentry_from_mapper( inode_xp , dentry_ptr );
[602]3338    }
3339    else if( fs_type == FS_TYPE_RAMFS )
3340    {
[657]3341        assert( false , "should not be called for RAMFS" );
[602]3342    }
3343    else if( fs_type == FS_TYPE_DEVFS )
3344    {
[657]3345        assert( false , "should not be called for DEVFS" );
[602]3346    }
3347    else
3348    {
[625]3349        assert( false , "undefined file system type" );
[602]3350    }
[238]3351
[602]3352    return error;
3353
[657]3354} // end vfs_fs_new_dentry_from_mapper()
[602]3355
[657]3356///////////////////////////////////////////////////////////////
3357error_t vfs_fs_new_dentry_to_mapper( xptr_t         inode_xp,
3358                                     vfs_dentry_t * dentry_ptr )
[602]3359{
3360    error_t error = 0;
3361
[657]3362assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
3363assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
[602]3364
[657]3365    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3366    cxy_t         inode_cxy = GET_CXY( inode_xp );
[602]3367
[657]3368    // get inode mapper
3369    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
3370
3371assert( (mapper != NULL) , "mapper pointer is NULL")       
3372
3373    // get FS type
3374    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
3375
[602]3376    // call relevant FS function
3377    if( fs_type == FS_TYPE_FATFS )
[23]3378    {
[657]3379        error = fatfs_new_dentry_to_mapper( inode_xp , dentry_ptr );
[602]3380    }
3381    else if( fs_type == FS_TYPE_RAMFS )
3382    {
[625]3383        assert( false , "should not be called for RAMFS" );
[602]3384    }
3385    else if( fs_type == FS_TYPE_DEVFS )
3386    {
[625]3387        assert( false , "should not be called for DEVFS" );
[602]3388    }
3389    else
3390    {
[625]3391        assert( false , "undefined file system type" );
[602]3392    }
[23]3393
[602]3394    return error;
3395
[657]3396} // end vfs_fs_new_dentry_to_mapper()
[602]3397
[657]3398//////////////////////////////////////////////////////
3399error_t vfs_fs_update_dentry( xptr_t         inode_xp,
3400                              vfs_dentry_t * dentry_ptr )
[623]3401{
3402    error_t error = 0;
3403
[657]3404assert( (inode_xp   != XPTR_NULL) , "inode_xp argument is NULL" );
3405assert( (dentry_ptr != NULL     ) , "dentry_ptr argument is NULL" );
[623]3406
[657]3407    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3408    cxy_t         inode_cxy = GET_CXY( inode_xp );
[623]3409
[657]3410    // get inode mapper
3411    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
3412
3413assert( (mapper != NULL) , "mapper pointer is NULL")       
3414
3415    // get FS type
3416    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
3417
[623]3418    // call relevant FS function
3419    if( fs_type == FS_TYPE_FATFS )
3420    {
[657]3421        error = fatfs_update_dentry( inode_xp , dentry_ptr );
[623]3422    }
3423    else if( fs_type == FS_TYPE_RAMFS )
3424    {
[625]3425        assert( false , "should not be called for RAMFS" );
[623]3426    }
3427    else if( fs_type == FS_TYPE_DEVFS )
3428    {
[625]3429        assert( false , "should not be called for DEVFS" );
[623]3430    }
3431    else
3432    {
[625]3433        assert( false , "undefined file system type" );
[623]3434    }
3435
3436    return error;
3437
3438} // end vfs_fs_update_dentry()
3439
3440///////////////////////////////////////////////////
[612]3441error_t vfs_fs_get_user_dir( vfs_inode_t   * inode,
3442                             struct dirent * array,
3443                             uint32_t        max_dirent,
3444                             uint32_t        min_dentry,
3445                             bool_t          detailed,
3446                             uint32_t      * entries,
3447                             bool_t        * done )
3448{
3449    error_t error = 0;
3450
3451// check arguments
[625]3452assert( (inode != NULL) , "parent pointer is NULL");
3453assert( (array != NULL) , "child pointer is NULL");
[612]3454assert( (detailed == false) , "detailed argument not supported\n");
3455
3456    // check inode type
3457    if( inode->type != INODE_TYPE_DIR )
3458    {
3459        printk("\n[ERROR] in %s : target inode is not a directory\n",
3460        __FUNCTION__ );
3461        return -1;
3462    }
3463
3464    // get parent inode FS type
3465    vfs_fs_type_t fs_type = inode->ctx->type;
3466
3467    // call relevant FS function
3468    if( fs_type == FS_TYPE_FATFS )
3469    {
3470        error = fatfs_get_user_dir( inode, 
3471                                    array,
3472                                    max_dirent,
3473                                    min_dentry,
3474                                    detailed,
3475                                    entries,
3476                                    done );
3477    }
3478    else if( fs_type == FS_TYPE_RAMFS )
3479    {
[625]3480        assert( false , "should not be called for RAMFS" );
[612]3481    }
3482    else if( fs_type == FS_TYPE_DEVFS )
3483    {
3484        error = devfs_get_user_dir( inode,
3485                                    array,
3486                                    max_dirent,
3487                                    min_dentry,
3488                                    detailed,
3489                                    entries,
3490                                    done );
3491    }
3492    else
3493    {
[625]3494        assert( false , "undefined file system type" );
[612]3495    }
3496
3497    return error;
3498
3499}  // end vfs_fs_get_user_dir()
3500 
[657]3501/////////////////////////////////////////////
3502error_t vfs_fs_sync_inode( xptr_t  inode_xp )
[610]3503{
3504    error_t error = 0;
3505
[657]3506assert( (inode_xp != XPTR_NULL) , "inode_xp argument is NULL");
[610]3507
[657]3508    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3509    cxy_t         inode_cxy = GET_CXY( inode_xp );
[610]3510
[657]3511    // get inode mapper
3512    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
3513
3514assert( (mapper != NULL) , "mapper pointer is NULL")       
3515
3516    // get FS type
3517    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
3518
[610]3519    // call relevant FS function
3520    if( fs_type == FS_TYPE_FATFS )
3521    {
[657]3522        error = fatfs_sync_inode( inode_xp );
[610]3523    }
3524    else if( fs_type == FS_TYPE_RAMFS )
3525    {
[625]3526        assert( false , "should not be called for RAMFS" );
[610]3527    }
3528    else if( fs_type == FS_TYPE_DEVFS )
3529    {
[625]3530        assert( false , "should not be called for DEVFS" );
[610]3531    }
3532    else
3533    {
[625]3534        assert( false , "undefined file system type" );
[610]3535    }
3536
3537    return error;
3538
3539}  // end vfs_fs_sync_inode()
3540
3541////////////////////////////////////////////////
3542error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type )
3543{
3544    error_t error = 0;
3545
3546    // call relevant FS function
3547    if( fs_type == FS_TYPE_FATFS )
3548    {
3549        error = fatfs_sync_fat();
3550    }
3551    else if( fs_type == FS_TYPE_RAMFS )
3552    {
[625]3553        assert( false , "should not be called for RAMFS" );
[610]3554    }
3555    else if( fs_type == FS_TYPE_DEVFS )
3556    {
[625]3557        assert( false , "should not be called for DEVFS" );
[610]3558    }
3559    else
3560    {
[625]3561        assert( false , "undefined file system type" );
[610]3562    }
3563
3564    return error;
3565
3566}  // end vfs_fs_sync_fat()
3567
[657]3568////////////////////////////////////////////////
3569error_t vfs_fs_release_inode( xptr_t  inode_xp )
[610]3570{
3571    error_t error = 0;
3572
[657]3573assert( (inode_xp  != XPTR_NULL) , "inode_xp argument is NULL")       
[610]3574
[657]3575    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
3576    cxy_t         inode_cxy = GET_CXY( inode_xp );
[610]3577
[657]3578    // get local pointer on mapper
3579    mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
[610]3580
[657]3581assert( (mapper != NULL) , "mapper pointer is NULL")       
[602]3582
[657]3583    // get FS type from mapper
3584    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->fs_type ) );
3585
[602]3586    // call relevant FS function
3587    if( fs_type == FS_TYPE_FATFS )
3588    {
[657]3589        error = fatfs_release_inode( inode_xp ); 
[23]3590    }
[602]3591    else if( fs_type == FS_TYPE_RAMFS )
3592    {
[625]3593        assert( false , "should not be called for RAMFS" );
[602]3594    }
3595    else if( fs_type == FS_TYPE_DEVFS )
3596    {
[625]3597        assert( false , "should not be called for DEVFS" );
[602]3598    }
3599    else
3600    {
[625]3601        assert( false , "undefined file system type" );
[602]3602    }
[23]3603
[602]3604    return error;
[657]3605   
3606}  // end vfs_fs_release_inode()
[401]3607
[657]3608//////////////////////////////////////////////////
3609error_t vfs_fs_move_page( xptr_t          page_xp,
3610                          ioc_cmd_type_t  cmd_type )
[602]3611{
3612    error_t error = 0;
[23]3613
[657]3614assert( (page_xp != XPTR_NULL) , "page pointer is NULL" );
[602]3615
[657]3616    page_t * page_ptr = GET_PTR( page_xp );
3617    cxy_t    page_cxy = GET_CXY( page_xp );
[602]3618
[657]3619    // get local pointer on  mapper
3620    mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
[602]3621
[657]3622assert( (mapper != NULL) , "no mapper for page" );
[602]3623
[657]3624    // get FS type
3625    vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->fs_type ) );
[602]3626
3627    // call relevant FS function
3628    if( fs_type == FS_TYPE_FATFS )
3629    {
[657]3630        error = fatfs_move_page( page_xp , cmd_type ); 
[602]3631    }
3632    else if( fs_type == FS_TYPE_RAMFS )
3633    {
[657]3634        assert( false , "should not be called for RAMFS\n" );
[602]3635    }
3636    else if( fs_type == FS_TYPE_DEVFS )
3637    {
[657]3638        assert( false , "should not be called for DEVFS\n" );
[602]3639    }
3640    else
3641    {
[625]3642        assert( false , "undefined file system type" );
[602]3643    }
3644
3645    return error;
3646
[657]3647}  // end vfs_fs_move_page()
[602]3648
[657]3649
Note: See TracBrowser for help on using the repository browser.