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

Last change on this file since 508 was 492, checked in by viala@…, 6 years ago

Refactoring assert calling to conform with new assert macro.

Made with this command for the general case.
find ./kernel/ hal/ -name "*.c" | xargs sed -i -e '/assert(/ s/,[ ]*FUNCTION[ ]*,/,/'

And some done by hand.

File size: 68.9 KB
RevLine 
[1]1/*
2 * vfs.c - Virtual File System implementation.
3 *
4 * Author  Mohamed Lamine Karaoui (2015)
[437]5 *         Alain Greiner (2016,2017,2018)
[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
25
[14]26#include <kernel_config.h>
[457]27#include <hal_kernel_types.h>
[1]28#include <hal_atomic.h>
29#include <hal_special.h>
30#include <readlock.h>
31#include <spinlock.h>
32#include <printk.h>
33#include <list.h>
34#include <xlist.h>
35#include <slist.h>
36#include <xhtab.h>
[430]37#include <string.h>
[23]38#include <rpc.h>
[1]39#include <errno.h>
40#include <kmem.h>
41#include <mapper.h>
42#include <thread.h>
[337]43#include <chdev.h>
[1]44#include <process.h>
[23]45#include <vfs.h>
[1]46#include <fatfs.h>
47#include <ramfs.h>
[23]48#include <devfs.h>
49#include <syscalls.h>
[1]50
51
52//////////////////////////////////////////////////////////////////////////////////////////
[50]53//           Extern variables         
[1]54//////////////////////////////////////////////////////////////////////////////////////////
55
[337]56extern vfs_ctx_t          fs_context[FS_TYPES_NR];    // allocated in kernel_init.c
[188]57
[337]58extern chdev_directory_t  chdev_dir;                  // allocated in kernel_init.c 
[50]59 
[1]60//////////////////////////////////////////////////////////////////////////////////////////
61//           Context related functions
62//////////////////////////////////////////////////////////////////////////////////////////
63
[188]64////////////////////////////////////////
65void vfs_ctx_init( vfs_fs_type_t   type,
66                   uint32_t        attr,
67                       uint32_t        total_clusters,
68                       uint32_t        cluster_size,
69                       xptr_t          vfs_root_xp,
70                   void          * extend )
71{
72    vfs_ctx_t * vfs_ctx = &fs_context[type];
73
74    vfs_ctx->type           = type;
75    vfs_ctx->attr           = attr;
76    vfs_ctx->total_clusters = total_clusters;
77    vfs_ctx->cluster_size   = cluster_size;
78    vfs_ctx->vfs_root_xp    = vfs_root_xp;
79    vfs_ctx->extend         = extend;
80
81    spinlock_init( &vfs_ctx->lock );
82
83    bitmap_init( vfs_ctx->bitmap , BITMAP_SIZE(CONFIG_VFS_MAX_INODES) ); 
84}
85
[23]86////////////////////////////////////////////
[1]87error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx,
88                            uint32_t  * inum )
89{
90    // get lock on inum allocator
91    spinlock_lock( &ctx->lock );
92
93    // get lid from local inum allocator
[23]94    uint32_t lid = bitmap_ffc( ctx->bitmap , CONFIG_VFS_MAX_INODES );
[1]95
[473]96    if( lid == 0xFFFFFFFF )   // no more free slot => error
[1]97    {
98        // release lock
99        spinlock_unlock( &ctx->lock );
100
101        // return error
102        return 1;
103    }
104    else              // found => return inum
105    {
106        // set slot allocated
[23]107        bitmap_set( ctx->bitmap , lid );
[1]108
109        // release lock
110        spinlock_unlock( &ctx->lock );
111
112        // return inum
113        *inum = (((uint32_t)local_cxy) << 16) | (lid & 0xFFFF);
114        return 0;
115    }
116}
117
118////////////////////////////////////////////
119void vfs_ctx_inum_release( vfs_ctx_t * ctx,
120                           uint32_t    inum )
121{
[23]122    bitmap_clear( ctx->bitmap , inum & 0xFFFF ); 
[1]123}
124
125//////////////////////////////////////////////////////////////////////////////////////////
126//           Inode related functions
127//////////////////////////////////////////////////////////////////////////////////////////
128
[188]129char * vfs_inode_type_str( uint32_t type )
130{
131    if     ( type == INODE_TYPE_FILE ) return "FILE";
132    else if( type == INODE_TYPE_DIR  ) return "DIR ";
133    else if( type == INODE_TYPE_FIFO ) return "FIFO";
134    else if( type == INODE_TYPE_PIPE ) return "PIPE";
135    else if( type == INODE_TYPE_SOCK ) return "SOCK";
136    else if( type == INODE_TYPE_DEV  ) return "DEV ";
137    else if( type == INODE_TYPE_SYML ) return "SYML";
138    else                               return "undefined";
139}
140
[23]141//////////////////////////////////////////////////////
142error_t vfs_inode_create( xptr_t            dentry_xp,
143                          vfs_fs_type_t     fs_type,
144                          vfs_inode_type_t  inode_type,
[188]145                          void            * extend,
[23]146                          uint32_t          attr,
147                          uint32_t          rights,
148                          uid_t             uid,
149                          gid_t             gid,
150                          xptr_t          * inode_xp )
[1]151{
152    mapper_t         * mapper;     // associated mapper( to be allocated)
153    vfs_inode_t      * inode;      // inode descriptor (to be allocated)
154    uint32_t           inum;       // inode identifier (to be allocated)
155    vfs_ctx_t        * ctx;        // file system context
156        kmem_req_t         req;        // request to kernel memory allocator
157    error_t            error;
158
[438]159#if DEBUG_VFS_INODE_CREATE
[433]160uint32_t cycle = (uint32_t)hal_get_cycles();
[438]161if( DEBUG_VFS_INODE_CREATE < cycle )
[433]162printk("\n[DBG] %s : thread %x enter / dentry = %x in cluster %x / cycle %d\n",
163__FUNCTION__, CURRENT_THREAD, GET_PTR(dentry_xp), GET_CXY(dentry_xp), cycle );
164#endif
[279]165 
[23]166    // check fs type and get pointer on context
167    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
168    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
169    else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS];
[1]170    else
171    {
172        ctx = NULL;
[492]173                assert( false , "illegal file system type = %d\n" , fs_type );
[1]174    }
175
176    // allocate inum
177    error = vfs_ctx_inum_alloc( ctx , &inum );
178
179    if( error )
180    {
181        printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ );
182        return ENOMEM;
183    }
184
185    // allocate memory for mapper
[246]186    mapper = mapper_create( fs_type );
[1]187
188    if( mapper == NULL )
189    {
190        printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ );
191        vfs_ctx_inum_release( ctx , inum );
192        return ENOMEM;
193    }
194
[23]195    // allocate memory for VFS inode descriptor
[1]196        req.type  = KMEM_VFS_INODE;
197        req.size  = sizeof(vfs_inode_t);
198    req.flags = AF_KERNEL | AF_ZERO;
199        inode     = (vfs_inode_t *)kmem_alloc( &req );
200
201    if( inode == NULL )
202    {
203        printk("\n[ERROR] in %s : cannot allocate inode descriptor\n", __FUNCTION__ );
204        vfs_ctx_inum_release( ctx , inum );
205        mapper_destroy( mapper );
206        return ENOMEM;
207    }
208
209    // initialize inode descriptor
210    inode->gc         = 0;
[23]211    inode->type       = inode_type;
[1]212    inode->inum       = inum;
213    inode->attr       = attr;
[23]214    inode->rights     = rights;
[1]215    inode->uid        = uid;
216    inode->gid        = gid;
217    inode->refcount   = 0;
218    inode->parent_xp  = dentry_xp;
219    inode->ctx        = ctx;
[246]220    inode->mapper     = mapper;
[188]221    inode->extend     = extend;
[1]222
[246]223    // initialise inode field in mapper
224    mapper->inode     = inode;
225 
[1]226    // initialise threads waiting queue
227    xlist_root_init( XPTR( local_cxy , &inode->wait_root ) );
228
[204]229    // initialize dentries hash table
230    xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
[1]231
232    // initialize inode locks
[10]233    remote_rwlock_init( XPTR( local_cxy , &inode->data_lock ) );
[1]234    remote_spinlock_init( XPTR( local_cxy , &inode->main_lock ) );
235
[438]236#if DEBUG_VFS_INODE_CREATE
[436]237cycle = (uint32_t)hal_get_cycles();
[438]238if( DEBUG_VFS_INODE_CREATE < cycle )
[433]239printk("\n[DBG] %s : thread %x exit / inode = %x in cluster %x / cycle %d\n",
240__FUNCTION__, CURRENT_THREAD, inode, local_cxy, cycle );
241#endif
[401]242 
[1]243    // return extended pointer on inode
244    *inode_xp = XPTR( local_cxy , inode );
245    return 0;
246
247}  // end vfs_inode_create() 
248
[459]249////////////////////////////////////////////////
250error_t vfs_inode_destroy( vfs_inode_t * inode )
[1]251{
[492]252    assert( (inode->refcount == 0) , "inode refcount non zero\n" );
[1]253
254    // release memory allocated for mapper
255    mapper_destroy( inode->mapper );
256
257    // release memory allocate for inode descriptor
258        kmem_req_t req;
259        req.ptr   = inode;
260        req.type  = KMEM_VFS_INODE;
261        kmem_free( &req );
262
[459]263    return 0;
264
[1]265}  // end vfs_inode_destroy()
266
[238]267/////////////////////////////////////////////
268error_t vfs_inode_load( vfs_inode_t * parent,
269                        char        * name,
270                        xptr_t        child_xp )
271{
[246]272
[438]273#if DEBUG_VFS_INODE_LOAD
[433]274uint32_t cycle = (uint32_t)hal_get_cycles();
[438]275if( DEBUG_VFS_INODE_LOAD < cycle )
[433]276printk("\n[DBG] %s : thread %x enter for <%s> / cycle %d\n",
277__FUNCTION__, CURRENT_THREAD , name , cycle );
278#endif
279
[238]280    error_t error = 0;
281
[492]282    assert( (parent != NULL) , "parent pointer is NULL\n");
[238]283
[492]284    assert( (child_xp != XPTR_NULL) , "child pointer is NULL\n");
[238]285
286    // get parent inode FS type
287    vfs_fs_type_t fs_type = parent->ctx->type;
288
289    // call relevant FS function
290    if( fs_type == FS_TYPE_FATFS )
291    {
292        error = fatfs_inode_load( parent , name , child_xp );
293    }
294    else if( fs_type == FS_TYPE_RAMFS )
295    {
[492]296        assert( false , "should not be called for RAMFS\n" );
[238]297    }
298    else if( fs_type == FS_TYPE_DEVFS )
299    {
[492]300        assert( false , "should not be called for DEVFS\n" );
[238]301    }
302    else
303    {
[492]304        assert( false , "undefined file system type\n" );
[238]305    }
306
[438]307#if DEBUG_VFS_INODE_LOAD
[433]308cycle = (uint32_t)hal_get_cycles();
[438]309if( DEBUG_VFS_INODE_LOAD < cycle )
[433]310printk("\n[DBG] %s : thread %x exit for <%s> / cycle %d\n",
311__FUNCTION__, CURRENT_THREAD , name , cycle );
312#endif
[246]313
[238]314    return error;
315
[459]316} // end vfs_inode_load()
[238]317
[1]318////////////////////////////////////////////
319void vfs_inode_remote_up( xptr_t  inode_xp )
320{
321    // get inode cluster and local pointer
322    cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]323    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[1]324
325    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , 1 );   
326}
327
328//////////////////////////////////////////////
329void vfs_inode_remote_down( xptr_t  inode_xp )
330{
331    // get inode cluster and local pointer
332    cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]333    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[1]334
335    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , -1 );   
336}
337
338//////////////////////////////////////////////
339uint32_t vfs_inode_get_size( xptr_t inode_xp )
340{
341    // get inode cluster and local pointer
342    cxy_t         cxy = GET_CXY( inode_xp );
[473]343    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]344
345    // get size
[10]346    remote_rwlock_rd_lock( XPTR( cxy , &ptr->data_lock ) );
[1]347    uint32_t size = hal_remote_lw( XPTR( cxy , &ptr->size ) );
[10]348    remote_rwlock_rd_unlock( XPTR( cxy , &ptr->data_lock ) );
[1]349    return size;
350}
351
[101]352////////////////////////////////////////////
353void vfs_inode_set_size( xptr_t    inode_xp,
[409]354                         uint32_t  size )
[1]355{
356    // get inode cluster and local pointer
357    cxy_t         cxy = GET_CXY( inode_xp );
[473]358    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]359
360    // set size
[10]361    remote_rwlock_wr_unlock( XPTR( cxy , &ptr->data_lock ) );
[1]362    hal_remote_sw( XPTR( cxy , &ptr->size ) , size );
[10]363    remote_rwlock_wr_unlock( XPTR( cxy , &ptr->data_lock ) );
[1]364}
365
[101]366////////////////////////////////////////
367void vfs_inode_unlock( xptr_t inode_xp )
[1]368{
369    // get inode cluster and local pointer
370    cxy_t         cxy = GET_CXY( inode_xp );
[473]371    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]372
373    // release the main lock
374    remote_spinlock_unlock( XPTR( cxy , &ptr->main_lock ) );
375}
376
[101]377//////////////////////////////////////
378void vfs_inode_lock( xptr_t inode_xp )
[1]379{
380    // get inode cluster and local pointer
381    cxy_t         cxy = GET_CXY( inode_xp );
[473]382    vfs_inode_t * ptr = GET_PTR( inode_xp );
[1]383
384    // get the main lock
385    remote_spinlock_lock( XPTR( cxy , &ptr->main_lock ) );
386}
387
[101]388/////////////////////////////////////////
[409]389void vfs_inode_get_name( xptr_t inode_xp,
390                         char * name )
[101]391{
[204]392    cxy_t          inode_cxy;
393    vfs_inode_t  * inode_ptr;
394    xptr_t         dentry_xp;
395    cxy_t          dentry_cxy;
396    vfs_dentry_t * dentry_ptr;
397   
398    // get inode cluster and local pointer
399    inode_cxy = GET_CXY( inode_xp );
[473]400    inode_ptr = GET_PTR( inode_xp );
[204]401
402    // get parent dentry
403    dentry_xp  = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
404
405    // get local copy of name
406    if( dentry_xp == XPTR_NULL )  // it is the VFS root
407    {
408        strcpy( name , "/" );
409    }
410    else                          // not the VFS root
411    {
412        dentry_cxy = GET_CXY( dentry_xp );
[473]413        dentry_ptr = GET_PTR( dentry_xp );
[204]414
415        hal_remote_strcpy( XPTR( local_cxy  , name ) , 
416                           XPTR( dentry_cxy , &dentry_ptr->name ) );
417    }
[409]418}  // end vfs_inode_get_name()
[204]419
420////////////////////////////////////////////////////////////////////////////////////////////
[1]421//           Dentry related functions
422//////////////////////////////////////////////////////////////////////////////////////////
423
[23]424///////////////////////////////////////////////////
425error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
426                           char          * name,
427                           vfs_inode_t   * parent,
428                           xptr_t        * dentry_xp )
[1]429{
430    vfs_ctx_t      * ctx;        // context descriptor
431    vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated)
432        kmem_req_t       req;        // request to kernel memory allocator
[459]433    error_t          error;
[1]434
[438]435#if DEBUG_VFS_DENTRY_CREATE
[433]436uint32_t cycle = (uint32_t)hal_get_cycles();
[438]437if( DEBUG_VFS_DENTRY_CREATE < cycle )
[459]438printk("\n[DBG] %s : thread %x in process %x enter for <%s> / parent_inode %x / cycle %d\n",
439__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, name, parent, cycle );
[433]440#endif
[296]441
[188]442    // get pointer on context
[23]443    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
444    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
445    else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS];
[459]446    else 
[1]447    {
448        ctx = NULL;
[459]449        return EINVAL;
[1]450    }
451
452    // get name length
453    uint32_t length = strlen( name );
454
[459]455    if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return EINVAL;
[437]456
[1]457    // allocate memory for dentry descriptor
458        req.type  = KMEM_VFS_DENTRY;
459        req.size  = sizeof(vfs_dentry_t);
460    req.flags = AF_KERNEL | AF_ZERO;
461        dentry     = (vfs_dentry_t *)kmem_alloc( &req );
462
[459]463    if( dentry == NULL ) return ENOMEM;
[437]464
[1]465    // initialize dentry descriptor
[23]466
[1]467    dentry->ctx     = ctx;
468    dentry->length  = length;
469    dentry->parent  = parent;
470    strcpy( dentry->name , name );
471
[438]472#if( DEBUG_VFS_DENTRY_CREATE & 1 )
[437]473cycle = (uint32_t)hal_get_cycles();
[438]474if( DEBUG_VFS_DENTRY_CREATE < cycle )
[437]475printk("\n[DBG] %s : dentry initialised\n", __FUNCTION__ );
476#endif
477
[23]478    // register dentry in hash table rooted in parent inode
[459]479    error = xhtab_insert( XPTR( local_cxy , &parent->children ),
480                          name, 
481                          XPTR( local_cxy , &dentry->list ) );
[23]482
[459]483    if( error ) return EINVAL;
484
[438]485#if( DEBUG_VFS_DENTRY_CREATE & 1 )
[437]486cycle = (uint32_t)hal_get_cycles();
[438]487if( DEBUG_VFS_DENTRY_CREATE < cycle )
[437]488printk("\n[DBG] %s : dentry registerd in htab\n", __FUNCTION__ );
489#endif
490
[23]491    // return extended pointer on dentry
[1]492    *dentry_xp = XPTR( local_cxy , dentry );
493
[438]494#if DEBUG_VFS_DENTRY_CREATE
[433]495cycle = (uint32_t)hal_get_cycles();
[438]496if( DEBUG_VFS_DENTRY_CREATE < cycle )
[459]497printk("\n[DBG] %s : thread %x in process %x exit for <%s> / dentry %x / cycle %d\n",
498__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, name, dentry, cycle );
[433]499#endif
[296]500
[1]501    return 0;
502
503}  // end vfs_dentry_create()
504
[459]505///////////////////////////////////////////////////
506error_t vfs_dentry_destroy( vfs_dentry_t * dentry )
[1]507{
[459]508    error_t error;
[1]509
[459]510    assert( (dentry->refcount == 0) , __FUNCTION__ , "dentry refcount non zero\n" );
511
512    // get pointer on parent inode
513    vfs_inode_t * parent = dentry->parent;
514
515    // remove this dentry from parent inode htab
516    error = xhtab_remove( XPTR( local_cxy , &parent->children ),
517                          dentry->name,
518                          XPTR( local_cxy , &dentry->list ) ); 
519
520    if( error ) return EINVAL;     
521
522    // release memory allocated to dentry
[1]523        kmem_req_t req;
524        req.ptr   = dentry;
525        req.type  = KMEM_VFS_DENTRY;
526        kmem_free( &req );
[459]527
528    return 0;
[1]529}
530
531
[188]532
[1]533//////////////////////////////////////////////////////////////////////////////////////////
534//           File descriptor related functions
535//////////////////////////////////////////////////////////////////////////////////////////
536
[23]537/////////////////////////////////////////////
538error_t vfs_file_create( vfs_inode_t * inode,
539                         uint32_t      attr,
540                         xptr_t      * file_xp )
541{
542    vfs_file_t  * file;
543        kmem_req_t    req;
544
545    // allocate memory for new file descriptor
546        req.type  = KMEM_VFS_FILE;
547        req.size  = sizeof(vfs_file_t);
548    req.flags = AF_KERNEL | AF_ZERO;
549        file      = (vfs_file_t *)kmem_alloc( &req );
550
551    if( file == NULL ) return ENOMEM;
552
553    // initializes new file descriptor
554    file->gc       = 0;
555    file->type     = inode->type;
556    file->attr     = attr;
557    file->offset   = 0;
[337]558    file->refcount = 1;
[23]559    file->inode    = inode;
560    file->ctx      = inode->ctx;
561    file->mapper   = inode->mapper;
562
563    remote_rwlock_init( XPTR( local_cxy , &file->lock ) );
564
565    *file_xp = XPTR( local_cxy , file );
[459]566
567#if DEBUG_VFS_OPEN
568uint32_t cycle = (uint32_t)hal_get_cycles();
569if( DEBUG_VFS_OPEN < cycle )
570printk("\n[DBG] %s : thread %x in process %x created file %x in cluster %x / cycle %d\n",
571__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, file, local_cxy, cycle );
572#endif
573
[23]574    return 0;
575
576}  // end vfs_file_create()
577
578///////////////////////////////////////////
579void vfs_file_destroy( vfs_file_t *  file )
580{
581    if( file->refcount )
582    {
[492]583        assert( false , "refcount non zero\n" );
[23]584    }       
585
586        kmem_req_t req;
587        req.ptr   = file;
588        req.type  = KMEM_VFS_FILE;
589        kmem_free( &req );
590
[459]591#if DEBUG_VFS_CLOSE
592uint32_t cycle = (uint32_t)hal_get_cycles();
593if( DEBUG_VFS_CLOSE < cycle )
594printk("\n[DBG] %s : thread %x in process %x deleted file %x in cluster %x / cycle %d\n",
595__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, file, local_cxy, cycle );
596#endif
597
[23]598}  // end vfs_file_destroy()
599
600
[1]601////////////////////////////////////////
602void vfs_file_count_up( xptr_t file_xp )
603{
604    // get file cluster and local pointer
605    cxy_t        file_cxy = GET_CXY( file_xp );
[459]606    vfs_file_t * file_ptr = GET_PTR( file_xp ); 
[1]607
608    // atomically increment count
609    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 
610}
611
612//////////////////////////////////////////
613void vfs_file_count_down( xptr_t file_xp )
614{
615    // get file cluster and local pointer
616    cxy_t        file_cxy = GET_CXY( file_xp );
[459]617    vfs_file_t * file_ptr = GET_PTR( file_xp ); 
[1]618
619    // atomically decrement count
620    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 
621}
622
[23]623//////////////////////////////////////////////////////////////////////////////////////////
624//           File access related functions
625//////////////////////////////////////////////////////////////////////////////////////////
626
[407]627//////////////////////////////////////
628error_t vfs_open( process_t * process,
629                          char      * path,
630                          uint32_t    flags,
631                  uint32_t    mode, 
632                          xptr_t    * new_file_xp,
633                  uint32_t  * new_file_id )
[1]634{
[23]635    error_t       error;
636    xptr_t        inode_xp;     // extended pointer on target inode
637    cxy_t         inode_cxy;    // inode cluster identifier       
638    vfs_inode_t * inode_ptr;    // inode local pointer
639    uint32_t      file_attr;    // file descriptor attributes
640    uint32_t      lookup_mode;  // lookup working mode       
641    xptr_t        file_xp;      // extended pointer on created file descriptor
642    uint32_t      file_id;      // created file descriptor index in reference fd_array
[1]643
[473]644    assert( (mode == 0), __FUNCTION__,
645    "the mode parameter is not supported yet\n" );
646
[438]647#if DEBUG_VFS_OPEN
[433]648uint32_t cycle = (uint32_t)hal_get_cycles();
[438]649if( DEBUG_VFS_OPEN < cycle )
[459]650printk("\n[DBG] %s :  thread %x in process %x enter for <%s> / cycle %d\n",
651__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, path, cycle );
[433]652#endif
[101]653
[23]654    // compute lookup working mode
655    lookup_mode = VFS_LOOKUP_OPEN;
656    if( (flags & O_DIR    )      )  lookup_mode |= VFS_LOOKUP_DIR;
657    if( (flags & O_CREAT  )      )  lookup_mode |= VFS_LOOKUP_CREATE;
658    if( (flags & O_EXCL   )      )  lookup_mode |= VFS_LOOKUP_EXCL;
659 
660    // compute attributes for the created file
661    file_attr = 0;
[407]662    if( (flags & O_RDONLY ) == 0 )  file_attr |= FD_ATTR_WRITE_ENABLE;
663    if( (flags & O_WRONLY ) == 0 )  file_attr |= FD_ATTR_READ_ENABLE;
[23]664    if( (flags & O_SYNC   )      )  file_attr |= FD_ATTR_SYNC;
665    if( (flags & O_APPEND )      )  file_attr |= FD_ATTR_APPEND;
666    if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC;
[1]667
[23]668    // get extended pointer on target inode
[407]669    error = vfs_lookup( process->vfs_cwd_xp , path , lookup_mode , &inode_xp );
[23]670
671    if( error ) return error;
672
673    // get target inode cluster and local pointer
674    inode_cxy = GET_CXY( inode_xp );
[473]675    inode_ptr = GET_PTR( inode_xp );
[23]676   
677    // create a new file descriptor in cluster containing inode
678    if( inode_cxy == local_cxy )      // target cluster is local
[1]679    {
[23]680        error = vfs_file_create( inode_ptr , file_attr , &file_xp );
[1]681    }
[23]682    else                              // target cluster is remote
683    {
684        rpc_vfs_file_create_client( inode_cxy , inode_ptr , file_attr , &file_xp , &error );
685    }
[1]686
[23]687    if( error )  return error;
[1]688
[407]689    // allocate and register a new file descriptor index in reference process
690    error = process_fd_register( process , file_xp , &file_id );
[1]691
[23]692    if( error ) return error;
[1]693
[438]694#if DEBUG_VFS_OPEN
[433]695cycle = (uint32_t)hal_get_cycles();
[438]696if( DEBUG_VFS_OPEN < cycle )
[459]697printk("\n[DBG] %s :  thread %x in process %x exit for <%s> / fdid %d / cluster %x / cycle %d\n",
698__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, path,
699file_id, GET_CXY( file_xp ), cycle );
[433]700#endif
[238]701
[23]702    // success
703    *new_file_xp = file_xp;
704    *new_file_id = file_id;
705    return 0;
[1]706
[23]707}  // end vfs_open()
708
[407]709//////////////////////////////////////
710int vfs_user_move( bool_t   to_buffer,
711                   xptr_t   file_xp,
712                   void   * buffer,
713                   uint32_t size )
[23]714{
[492]715    assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
[23]716
717    cxy_t              file_cxy;     // remote file descriptor cluster
718    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
719    vfs_inode_type_t   inode_type;
720    uint32_t           file_offset;  // current offset in file
721    mapper_t         * mapper;
722    error_t            error;
723
724    // get cluster and local pointer on remote file descriptor
725    file_cxy  = GET_CXY( file_xp );
[473]726    file_ptr  = GET_PTR( file_xp );
[23]727
728    // get inode type from remote file descriptor
729    inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type   ) );
730   
[492]731    assert( (inode_type == INODE_TYPE_FILE) ,
[407]732    "inode type is not INODE_TYPE_FILE" );
[23]733
[407]734    // get mapper pointer and file offset from file descriptor
735    file_offset = hal_remote_lw( XPTR( file_cxy , &file_ptr->offset ) );
736    mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
[23]737
[407]738    // move data between mapper and buffer
739    if( file_cxy == local_cxy )
740    {
741        error = mapper_move_user( mapper,
742                                  to_buffer,
743                                  file_offset,
744                                  buffer,
745                                  size );
[23]746    }
[407]747    else
[23]748    {
[407]749        rpc_mapper_move_buffer_client( file_cxy,
750                                       mapper,
751                                       to_buffer,
752                                       true,          // user buffer
753                                       file_offset,
754                                       (uint64_t)(intptr_t)buffer,
755                                       size,
756                                       &error );
757    } 
758
759    if( error ) return -1;
760    else        return size;
761
[313]762}  // end vfs_user_move()
[23]763
[317]764////////////////////////////////////////////
765error_t vfs_kernel_move( bool_t   to_buffer,
766                         xptr_t   file_xp,
767                         xptr_t   buffer_xp,
768                         uint32_t size )
769{
[492]770    assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
[317]771
772    cxy_t              file_cxy;     // remote file descriptor cluster
773    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
774    vfs_inode_type_t   inode_type;
775    uint32_t           file_offset;  // current offset in file
776    mapper_t         * mapper;
777    error_t            error;
778
779    // get cluster and local pointer on remote file descriptor
780    file_cxy  = GET_CXY( file_xp );
[473]781    file_ptr  = GET_PTR( file_xp );
[317]782
783    // get inode type from remote file descriptor
784    inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type   ) );
785   
786    // action depends on inode type
787    if( inode_type == INODE_TYPE_FILE )
788    {
789        // get mapper pointer and file offset from file descriptor
790        file_offset = hal_remote_lw( XPTR( file_cxy , &file_ptr->offset ) );
791        mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
792
793        // move data between mapper and buffer
794        if( file_cxy == local_cxy )
795        {
796            error = mapper_move_kernel( mapper,
797                                        to_buffer,
798                                        file_offset,
799                                        buffer_xp,
800                                        size );
801        }
802        else
803        {
804            rpc_mapper_move_buffer_client( file_cxy,
805                                           mapper,
806                                           to_buffer,
807                                           false,          // kernel buffer
808                                           file_offset,
809                                           buffer_xp,
810                                           size,
811                                           &error );
812        } 
813
814        if( error ) return -1;
815        else        return 0;
816    }
817    else 
818    {
819        printk("\n[ERROR] in %s : inode is not a file", __FUNCTION__ );
820        return -1;
821    }
822}  // end vfs_kernel_move()
823
[23]824//////////////////////////////////////
825error_t vfs_lseek( xptr_t     file_xp,
826                   uint32_t   offset,
827                   uint32_t   whence, 
828                   uint32_t * new_offset )
829{
[266]830    xptr_t         offset_xp;
831    xptr_t         lock_xp;
832    cxy_t          file_cxy;
833    vfs_file_t  *  file_ptr;
834    vfs_inode_t *  inode_ptr;
835    uint32_t       new;
836
[492]837    assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
[266]838
839    // get cluster and local pointer on remote file descriptor
840    file_cxy = GET_CXY( file_xp );
[473]841    file_ptr = GET_PTR( file_xp );
[266]842
843    // build extended pointers on lock and offset
844    offset_xp = XPTR( file_cxy , &file_ptr->offset );
845    lock_xp   = XPTR( file_cxy , &file_ptr->lock );
846
847    // take file descriptor lock
848    remote_rwlock_wr_lock( lock_xp );
849
850    if      ( whence == SEEK_CUR )   // new = current + offset
851    {
852        new = hal_remote_lw( offset_xp ) + offset;
853    }
854    else if ( whence == SEEK_SET )   // new = offset
855    {
856        new = offset;
857    }
858    else if ( whence == SEEK_END )   // new = size + offset
859    { 
860        // get local pointer on remote inode
861        inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
862
863        new = hal_remote_lw( XPTR( file_cxy , &inode_ptr->size ) ) + offset;
864    }
865    else
866    {
867        printk("\n[ERROR] in %s : illegal whence value\n", __FUNCTION__ );
868        remote_rwlock_wr_unlock( lock_xp );
869        return -1;
870    }
871
872    // set new offset
873    hal_remote_sw( offset_xp , new );
874
875    // release file descriptor lock
876    remote_rwlock_wr_unlock( lock_xp );
877
878    // success
[271]879    if ( new_offset != NULL )
880        *new_offset = new;
[1]881    return 0;
882
[23]883}  // vfs_lseek()
884
885///////////////////////////////////
886error_t vfs_close( xptr_t   file_xp,
887                   uint32_t file_id )
[1]888{
[459]889    cluster_t  * cluster;          // local pointer on local cluster
890    cxy_t        file_cxy;         // cluster containing the file descriptor.
891    vfs_file_t * file_ptr;         // local ponter on file descriptor
892    cxy_t        owner_cxy;        // process owner cluster
893    lpid_t       lpid;             // process local index
894    xptr_t       root_xp;          // root of list of process copies
895    xptr_t       lock_xp;          // lock protecting the list of copies
896    xptr_t       iter_xp;          // iterator on list of process copies
897    xptr_t       process_xp;       // extended pointer on one process copy
898    cxy_t        process_cxy;      // process copy cluster
899    process_t  * process_ptr;      // process copy local pointer
900
[492]901    assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
[23]902
[492]903    assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , "illegal file_id" );
[23]904
905    thread_t  * this    = CURRENT_THREAD;
906    process_t * process = this->process;
907
[459]908#if DEBUG_VFS_CLOSE
909uint32_t cycle = (uint32_t)hal_get_cycles();
910if( DEBUG_VFS_CLOSE < cycle )
911printk("\n[DBG] %s : thread %x in process %x enter / fdid %d / cycle %d\n",
912__FUNCTION__, this->trdid, process->pid, file_id, cycle );
913#endif
[1]914
[23]915    // get local pointer on local cluster manager
[459]916    cluster = LOCAL_CLUSTER;
[23]917
918    // get owner process cluster and lpid
[459]919    owner_cxy  = CXY_FROM_PID( process->pid );
920    lpid       = LPID_FROM_PID( process->pid );
[23]921
922    // get extended pointers on copies root and lock
[459]923    root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
924    lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
[23]925
[459]926    // 1) loop on the process descriptor copies to reset all fd_array[file_id] entries
927
928    // take the lock protecting the list of copies
[23]929    remote_spinlock_lock( lock_xp );
930
931    XLIST_FOREACH( root_xp , iter_xp )
[1]932    {
[459]933        process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
934        process_cxy = GET_CXY( process_xp );
935        process_ptr = GET_PTR( process_xp );
[1]936
[459]937#if (DEBUG_VFS_CLOSE & 1 )
938if( DEBUG_VFS_CLOSE < cycle )
939printk("\n[DBG] %s : reset fd_array[%d] for process %x in cluster %x\n",
940__FUNCTION__, file_id, process_ptr, process_cxy );
941#endif
[23]942
[459]943// fd_array lock is required for atomic write of a 64 bits word
944// xptr_t fd_array_lock_xp = XPTR( process_cxy , &process_ptr->fd_array.lock );
945
946        xptr_t entry_xp         = XPTR( process_cxy , &process_ptr->fd_array.array[file_id] );
947
948// remote_rwlock_wr_lock( fd_array_lock_xp );
949
[23]950        hal_remote_swd( entry_xp , XPTR_NULL );
[459]951       
952// remote_rwlock_wr_unlock( fd_array_lock_xp );
[23]953
[459]954        vfs_file_count_down( file_xp );
955
[124]956        hal_fence();
[23]957    }   
958
[459]959    // release the lock protecting the list of copies
960    remote_spinlock_unlock( lock_xp );
961
962#if (DEBUG_VFS_CLOSE & 1)
963if( DEBUG_VFS_CLOSE < cycle )
964printk("\n[DBG] %s : thread %x in process %x reset all fd-array copies\n",
965__FUNCTION__, this->trdid, process->pid );
966#endif
967
[23]968    // 2) release memory allocated to file descriptor in remote cluster
[459]969
970    // get cluster and local pointer on remote file descriptor
971    file_cxy = GET_CXY( file_xp );
972    file_ptr = GET_PTR( file_xp );
973
[23]974    if( file_cxy == local_cxy )             // file cluster is local
[1]975    {
[23]976        vfs_file_destroy( file_ptr );
977    }
978    else                                    // file cluster is local
979    {
980        rpc_vfs_file_destroy_client( file_cxy , file_ptr );
981    }
[1]982
[459]983#if DEBUG_VFS_CLOSE
984cycle = (uint32_t)hal_get_cycles();
985if( DEBUG_VFS_CLOSE < cycle )
986printk("\n[DBG] %s : thread %x in process %x exit / fdid %d closed / cycle %d\n",
987__FUNCTION__, this->trdid, process->pid, file_id, cycle );
988#endif
989
[23]990    return 0;
[1]991
[23]992}  // end vfs_close()
[1]993
994////////////////////////////////////
[23]995error_t vfs_unlink( xptr_t   cwd_xp,
996                    char   * path )
[1]997{
[492]998    assert( false , "not implemented cwd_xp %x, path <%s> \n",
999      cwd_xp, path );   
[1]1000    return 0;
[407]1001} 
[1]1002
[407]1003////////////////////////////////////////
1004error_t vfs_stat( xptr_t        file_xp,
1005                  struct stat * k_stat )
[1]1006{
[492]1007    assert( false , "not implemented file_xp: %x, k_stat ptr %x\n",
1008      file_xp, k_stat );
[1]1009    return 0;
1010}
1011
[407]1012/////////////////////////////////////////////
1013error_t vfs_readdir( xptr_t          file_xp,
1014                     struct dirent * k_dirent )
[1]1015{
[492]1016    assert( false , "not implemented file_xp: %x, k_dirent ptr %x\n",
1017      file_xp, k_dirent );
[1]1018    return 0;
1019}
1020
1021//////////////////////////////////////
[23]1022error_t vfs_mkdir( xptr_t     file_xp,
1023                   char     * path,
1024                   uint32_t   mode )
[1]1025{
[492]1026    assert( false , "not implemented file_xp: %x, path <%s>, mode: %x\n",
1027      file_xp, path, mode );
[1]1028    return 0;
1029}
1030
[23]1031////////////////////////////////////
1032error_t vfs_rmdir( xptr_t   file_xp,
1033                   char   * path )
[1]1034{
[492]1035    assert( false , "not implemented file_xp: %x, path <%s>\n",
1036      file_xp, path );
[1]1037    return 0;
1038}
1039
[23]1040///////////////////////////////////
1041error_t vfs_chdir( xptr_t   cwd_xp,
1042                   char   * path )
[1]1043{
[23]1044    error_t           error;
1045    xptr_t            inode_xp;     // extended pointer on target inode
1046    cxy_t             inode_cxy;    // target inode cluster identifier       
1047    vfs_inode_t     * inode_ptr;    // target inode local pointer
1048    uint32_t          mode;         // lookup working mode       
1049    vfs_inode_type_t  inode_type;   // target inode type
1050
1051    // set lookup working mode
1052    mode = 0;
1053
1054    // get extended pointer on target inode
1055    error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
1056
1057    if( error ) return error;
1058
1059    // get inode cluster and local pointer
1060    inode_cxy = GET_CXY( inode_xp );
[473]1061    inode_ptr = GET_PTR( inode_xp );
[23]1062
1063    // get inode type from remote file
1064    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
1065
1066    if( inode_type != INODE_TYPE_DIR )
1067    {
1068        CURRENT_THREAD->errno = ENOTDIR;
1069        return -1;
1070    }
1071
[492]1072    assert( false , "not implemented\n" );
[1]1073    return 0;
1074}
1075
[23]1076///////////////////////////////////
1077error_t vfs_chmod( xptr_t   cwd_xp,
1078                   char   * path,
1079                   uint32_t rights )
[1]1080{
[23]1081    error_t           error;
1082    xptr_t            inode_xp;     // extended pointer on target inode
1083    cxy_t             inode_cxy;    // inode cluster identifier       
1084    vfs_inode_t     * inode_ptr;    // inode local pointer
1085    vfs_inode_type_t  inode_type;   // target inode type
1086
1087    // set lookup working mode
[473]1088    assert( (rights == 0), __FUNCTION__,
1089    "access rights non implemented yet\n" );
[23]1090 
1091    // get extended pointer on target inode
[473]1092    error = vfs_lookup( cwd_xp , path , 0 , &inode_xp );
[23]1093
1094    if( error ) return error;
1095
1096    // get inode cluster and local pointer
1097    inode_cxy = GET_CXY( inode_xp );
[473]1098    inode_ptr = GET_PTR( inode_xp );
[23]1099   
1100    // get inode type from remote inode
1101    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
1102
1103   
[492]1104    assert( false , "not implemented\n" );
[1]1105    return 0;
1106}
1107
[23]1108///////////////////////////////////
1109error_t vfs_mkfifo( xptr_t   cwd_xp,
1110                    char   * path,
1111                    uint32_t rights )
1112{
[492]1113    assert( false , "not implemented cwd_xp: %x, path <%s>, rights %x\n",
1114      cwd_xp, path, rights );
[23]1115    return 0;
1116}
[1]1117
1118
1119
[188]1120//////////////////////////////////////////////////////////////////////////////////////////
[1]1121//            Inode Tree functions
1122//////////////////////////////////////////////////////////////////////////////////////////
1123
[188]1124/////////////////////////////////
[484]1125cxy_t vfs_cluster_random_select( void )
[188]1126{
1127    uint32_t  x_size    = LOCAL_CLUSTER->x_size;
1128    uint32_t  y_size    = LOCAL_CLUSTER->y_size;
1129    uint32_t  y_width   = LOCAL_CLUSTER->y_width;
1130    uint32_t  index     = ( hal_get_cycles() + hal_get_gid() ) % (x_size * y_size);
1131    uint32_t  x         = index / y_size;   
1132    uint32_t  y         = index % y_size;
1133
1134    return (x<<y_width) + y;
1135}
1136
1137
1138//////////////////////////////////////////////////////////////////////////
1139// This static function is called by the vfs_display() function.
[337]1140// that is supposed to take the TXT0 lock.
[188]1141//////////////////////////////////////////////////////////////////////////
1142static void vfs_recursive_display( xptr_t   inode_xp,
1143                                   xptr_t   name_xp,
1144                                   uint32_t indent )
1145{
1146    cxy_t              inode_cxy;
1147    vfs_inode_t      * inode_ptr;
1148    vfs_inode_type_t   inode_type;
[204]1149    xptr_t             children_xp;    // extended pointer on children xhtab
[188]1150
[204]1151    xptr_t             child_dentry_xp;
1152    cxy_t              child_dentry_cxy;
1153    vfs_dentry_t     * child_dentry_ptr;
1154    xptr_t             child_inode_xp;
1155    xptr_t             child_dentry_name_xp;
[188]1156
1157    char               name[CONFIG_VFS_MAX_NAME_LENGTH];
1158
1159    char *             indent_str[] = { "",                                  // level 0
1160                                        "  ",                                // level 1
1161                                        "    ",                              // level 2
1162                                        "      ",                            // level 3
1163                                        "        ",                          // level 4
1164                                        "          ",                        // level 5
1165                                        "            ",                      // level 6
1166                                        "              ",                    // level 7
1167                                        "                ",                  // level 8
1168                                        "                  ",                // level 9
1169                                        "                    ",              // level 10
1170                                        "                      ",            // level 11
1171                                        "                        ",          // level 12
1172                                        "                          ",        // level 13
1173                                        "                            ",      // level 14
1174                                        "                              " };  // level 15
1175
[492]1176    assert( (inode_xp != XPTR_NULL) , "inode_xp cannot be NULL\n" );
1177    assert( (name_xp  != XPTR_NULL) , "name_xp cannot be NULL\n" );
1178    assert( (indent < 16)           , "depth cannot be larger than 15\n" );
[188]1179   
1180    // get inode cluster and local pointer
1181    inode_cxy = GET_CXY( inode_xp );
[473]1182    inode_ptr = GET_PTR( inode_xp );
[188]1183
1184    // get inode type
1185    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
1186
[367]1187    // get local pointer on associated mapper
1188    mapper_t * mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
1189
[188]1190    // make a local copy of node name
1191    hal_remote_strcpy( XPTR( local_cxy , name ) , name_xp );
1192
1193    // display inode
[407]1194    nolock_printk("%s%s <%s> : inode = %x / mapper = %x / cluster %x\n",
[367]1195                  indent_str[indent], vfs_inode_type_str( inode_type ), name,
[407]1196                  inode_ptr , mapper_ptr , inode_cxy );
[188]1197
1198    // scan directory entries 
1199    if( inode_type == INODE_TYPE_DIR )
1200    {
1201        // get extended pointer on directory entries xhtab
[204]1202        children_xp =  XPTR( inode_cxy , &inode_ptr->children );
[188]1203
1204        // get xhtab lock
[204]1205        xhtab_read_lock( children_xp );
[188]1206
1207        // get first dentry from xhtab
[204]1208        child_dentry_xp = xhtab_get_first( children_xp );
[188]1209
[204]1210        while( child_dentry_xp != XPTR_NULL )
[188]1211        {
1212            // get dentry cluster and local pointer
[204]1213            child_dentry_cxy = GET_CXY( child_dentry_xp );
[473]1214            child_dentry_ptr = GET_PTR( child_dentry_xp );
[188]1215
1216            // get extended pointer on child inode
[204]1217            child_inode_xp = hal_remote_lwd( XPTR( child_dentry_cxy,
1218                                                   &child_dentry_ptr->child_xp ) );
[188]1219
1220            // get extended pointer on dentry name
[204]1221            child_dentry_name_xp = XPTR( child_dentry_cxy , &child_dentry_ptr->name );
[188]1222
1223            // recursive call on child inode
[204]1224            vfs_recursive_display( child_inode_xp,
1225                                   child_dentry_name_xp,
1226                                   indent+1 );
[188]1227
1228            // get next dentry
[204]1229            child_dentry_xp = xhtab_get_next( children_xp );
[188]1230        }
1231
1232        // release xhtab lock
[204]1233        xhtab_read_unlock( children_xp );
[188]1234    }
1235}  // end vfs_recursive_display()
1236
1237///////////////////////////////////
1238void vfs_display( xptr_t inode_xp )
1239{
[204]1240    xptr_t         name_xp;
[188]1241    xptr_t         dentry_xp; 
1242    cxy_t          dentry_cxy;
1243    vfs_dentry_t * dentry_ptr;
[337]1244    uint32_t       save_sr;
[188]1245
1246    // get target inode cluster and local pointer
1247    cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]1248    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[188]1249
1250    // get extended pointer on associated dentry
[367]1251    dentry_xp   = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
[188]1252
1253    // check if target inode is the File System root
1254    if( dentry_xp == XPTR_NULL )
1255    {
1256        // build extended pointer on root name
1257        name_xp = XPTR( local_cxy , "/" );
1258    }
1259    else
1260    {
1261        // get dentry cluster and local pointer
1262        dentry_cxy = GET_CXY( dentry_xp );
[473]1263        dentry_ptr = GET_PTR( dentry_xp );
[188]1264
1265        // get extended pointer on dentry name
1266        name_xp = XPTR( dentry_cxy , &dentry_ptr->name );
1267    }
1268
[337]1269    // get pointers on TXT0 chdev
[407]1270    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
[337]1271    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
1272    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
1273
1274    // get extended pointer on remote TXT0 chdev lock
1275    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
1276
1277    // get TXT0 lock in busy waiting mode
1278    remote_spinlock_lock_busy( lock_xp , &save_sr );
1279
[188]1280    // print header
[401]1281    nolock_printk("\n***** file system state\n\n");
[188]1282
1283    // call recursive function
[473]1284    vfs_recursive_display( inode_xp , name_xp , 0 );
[188]1285
[337]1286    // release lock
1287    remote_spinlock_unlock_busy( lock_xp , save_sr );
1288
[204]1289}  // end vfs_display()
[188]1290
[1]1291//////////////////////////////////////////////////////////////////////////////////////////
[23]1292// This function is used by the vfs_lookup() function.
[1]1293// It takes an extended pointer on a remote inode (parent directory inode),
1294// and check access_rights violation for the calling thread.
1295// It can be used by any thread running in any cluster.
1296//////////////////////////////////////////////////////////////////////////////////////////
1297// @ inode_xp    : extended pointer on inode.
1298// @ client_uid  : client thread user ID
1299// @ client_gid  : client thread group ID
1300// @ return true if access rights are violated.
1301//////////////////////////////////////////////////////////////////////////////////////////
1302bool_t vfs_access_denied( xptr_t   inode_xp,
1303                          uint32_t client_uid,
1304                          uint32_t client_gid )
1305{
1306    // get found inode cluster and local pointer
1307    cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]1308    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[1]1309
1310    // get inode access mode, UID, and GID
1311    // TODO uint32_t  mode = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->mode ) );
1312    uid_t     uid  = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->uid  ) );
1313    gid_t     gid  = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->gid  ) );
1314
1315    // FIXME : me must use mode
1316    if( (uid == client_uid) || (gid == client_gid) ) return false;
1317    else                                             return true;
1318}
1319
1320//////////////////////////////////////////////////////////////////////////////////////////
1321// This static function is used by the vfs_lookup() function.
[204]1322// It takes an extended pointer on a remote parent directory inode, a directory
[1]1323// entry name, and returns an extended pointer on the child inode.
1324// It can be used by any thread running in any cluster.
1325//////////////////////////////////////////////////////////////////////////////////////////
1326// @ parent_xp   : extended pointer on parent inode in remote cluster.
1327// @ name        : dentry name
1328// @ child_xp    : [out] buffer for extended pointer on child inode.
1329// @ return true if success / return false if not found.
1330//////////////////////////////////////////////////////////////////////////////////////////
1331static bool_t vfs_get_child( xptr_t   parent_xp,
1332                             char   * name,
1333                             xptr_t * child_xp )
1334{
1335    xptr_t  xhtab_xp;    // extended pointer on hash table containing children dentries
1336    xptr_t  dentry_xp;   // extended pointer on children dentry
1337
1338    // get parent inode cluster and local pointer
1339    cxy_t         parent_cxy = GET_CXY( parent_xp );
[473]1340    vfs_inode_t * parent_ptr = GET_PTR( parent_xp );
[1]1341
1342    // get extended pointer on hash table of children directory entries
1343    xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
1344
1345    // search extended pointer on matching dentry
1346    dentry_xp = xhtab_lookup( xhtab_xp , name );
1347
1348    if( dentry_xp == XPTR_NULL ) return false;
1349
1350    // get dentry cluster and local pointer
1351    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
[473]1352    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
[1]1353
1354    // return child inode
[101]1355    *child_xp = (xptr_t)hal_remote_lwd( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
[1]1356    return true;
1357
[204]1358}  // end vfs_get_child()
1359
[1]1360//////////////////////////////////////////////////////////////////////////////////////////
1361// This static function is used by the vfs_lookup() function.
1362// It takes the <current> pointer on a buffer containing a complete pathname, and return
1363// in the <name> buffer, allocated by the caller, a single name in the path.
1364// It return also in the <next> pointer the next character to analyse in the path.
1365// Finally it returns a <last> boolean, that is true when the returned <name> is the
1366// last name in the path. The names are supposed to be separated by one or several '/'
1367// characters, that are not written in  the <name> buffer.
1368//////////////////////////////////////////////////////////////////////////////////////////
1369// @ current   : pointer on first character to analyse in buffer containing the path.
1370// @ name      : [out] pointer on buffer allocated by the caller for the returned name.
1371// @ next      : [out] pointer on next character to analyse in buffer containing the path.
1372// @ last      : [out] true if the returned name is the last (NUL character found).
1373// @ return 0 if success / return EINVAL if string empty (first chracter is NUL).
1374//////////////////////////////////////////////////////////////////////////////////////////
1375static error_t vfs_get_name_from_path( char     * current,
1376                                       char     * name,
1377                                       char    ** next,
1378                                       bool_t   * last )
1379{
1380    char * ptr = current;
1381
1382    // skip leading '/' characters
1383    while( *ptr == '/' ) ptr++;
1384
1385    // return EINVAL if string empty
1386    if( *ptr == 0 ) return EINVAL;
1387
1388    // copy all characters in name until NUL or '/'
1389    while( (*ptr != 0) && (*ptr !='/') )  *(name++) = *(ptr++);
1390
[204]1391    // set NUL terminating character in name buffer
1392    *(name++) = 0;
1393
[1]1394    // return last an next
1395    if( *ptr == 0 )             // last found character is NUL => last name in path
1396    {
1397        *last = true;
1398    }
1399    else                        // last found character is '/' => skip it
1400    {
1401        *last = false;
1402        *next = ptr + 1;
1403    }
1404
1405    return 0;
[204]1406
1407}  // end vfs_get name_from_path()
[188]1408   
[23]1409//////////////////////////////////////////////
1410error_t vfs_lookup( xptr_t             cwd_xp,
1411                    char             * pathname,
1412                    uint32_t           mode,
1413                                        xptr_t           * inode_xp )
[1]1414{
[101]1415    char               name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path
[1]1416
[23]1417    xptr_t             parent_xp;    // extended pointer on parent inode
1418    cxy_t              parent_cxy;   // cluster for parent inode
1419    vfs_inode_t      * parent_ptr;   // local pointer on parent inode 
1420    xptr_t             child_xp;     // extended pointer on child inode
1421    cxy_t              child_cxy;    // cluster for child inode
1422    vfs_inode_t      * child_ptr;    // local pointer on child inode 
1423    vfs_fs_type_t      fs_type;      // File system type
1424    vfs_ctx_t        * ctx_ptr;      // local pointer on FS context
1425    char             * current;      // current pointer on path
1426    char             * next;         // next value for current pointer   
1427    bool_t             last;         // true when the name is the last in path
1428    bool_t             found;        // true when a child has been found
[459]1429    bool_t             dir;          // searched inode is a directory
1430    bool_t             create;       // searched inode must be created if not found
1431    bool_t             excl;         // searched inode must not exist
[23]1432    thread_t         * this;         // pointer on calling thread descriptor
1433    process_t        * process;      // pointer on calling process descriptor
1434    error_t            error;
[1]1435
1436    this    = CURRENT_THREAD;
1437    process = this->process;
1438
[438]1439#if DEBUG_VFS_LOOKUP
[433]1440uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1441if( DEBUG_VFS_LOOKUP < cycle )
[459]1442printk("\n[DBG] %s : thread %x in process %x enter for <%s> / cycle %d\n",
1443__FUNCTION__, this->trdid, process->pid, pathname, cycle );
[433]1444#endif
[380]1445
[459]1446    // compute lookup flags
1447    dir    = mode & VFS_LOOKUP_DIR;
1448    create = mode & VFS_LOOKUP_CREATE;
1449    excl   = mode & VFS_LOOKUP_EXCL;
1450   
[1]1451    // get extended pointer on first inode to search
1452    if( pathname[0] == '/' ) parent_xp = process->vfs_root_xp;
1453    else                     parent_xp = cwd_xp;
1454
[101]1455    // initialise other loop variables
[1]1456    current  = pathname;
1457    next     = NULL;
1458    last     = false;
1459    child_xp = XPTR_NULL;
1460
1461    // take lock on parent inode
[101]1462    vfs_inode_lock( parent_xp );
[1]1463
[401]1464    // sequencially loop on nodes in pathname
[459]1465    // load from device if one node in path not found in inode tree
[401]1466    // exit loop when last name found (i.e. last == true)
[1]1467    do
1468    {
[401]1469        // get one name from path, and "last" flag
[1]1470        vfs_get_name_from_path( current , name , &next , &last );
1471
[438]1472#if (DEBUG_VFS_LOOKUP & 1)
1473if( DEBUG_VFS_LOOKUP < cycle )
[459]1474printk("\n[DBG] %s : look for <%s> / last = %d\n",
1475__FUNCTION__ , name , last );
[433]1476#endif
[101]1477
[204]1478        // search a child dentry matching name in parent inode
[1]1479        found = vfs_get_child( parent_xp,
1480                               name,
1481                               &child_xp );
1482
[459]1483        if (found == false )  // child not found in inode tree
[1]1484        {
[101]1485
[438]1486#if (DEBUG_VFS_LOOKUP & 1)
1487if( DEBUG_VFS_LOOKUP < cycle )
[459]1488printk("\n[DBG] %s : miss <%s> node => try to create it\n",
1489__FUNCTION__ , name );
[433]1490#endif
[459]1491            // if a child node is not found in the inode tree,
1492            // we introduce a new (dentry/inode) in inode tree,
1493            // and try to find it by scanning the parent directory mapper.
1494            // . if it is found in parent mapper:
1495            //   - if the child is a directory, the child mapper is loaded from device
1496            //   - if the child is not a directory, the search is completed
1497            // . if it is not found in the parent mapper:
1498            //   - if ( not last or not create ) an error is reported
1499            //   - if (last and create and dir) a new directory is created
1500            //   - if (last and create and not dir) a new file is created
[407]1501
[1]1502            // release lock on parent inode
[101]1503            vfs_inode_unlock( parent_xp );
[459]1504 
[238]1505            // get parent inode FS type
[23]1506            parent_cxy = GET_CXY( parent_xp );
[459]1507            parent_ptr = GET_PTR( parent_xp );
1508            ctx_ptr    = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
[238]1509            fs_type    = hal_remote_lw( XPTR( parent_cxy , &ctx_ptr->type ) );
[23]1510
[238]1511            // select a cluster for missing inode
1512            child_cxy = vfs_cluster_random_select();
[401]1513 
[459]1514            // insert a new child dentry/inode in inode tree
[188]1515            error = vfs_add_child_in_parent( child_cxy,
[459]1516                                             0,           // type will be updated later
[23]1517                                             fs_type, 
1518                                             parent_xp, 
[222]1519                                             name, 
[459]1520                                             NULL,        // fs_type_specific inode extend
[23]1521                                             &child_xp );
[1]1522            if( error )
1523            {
[459]1524                printk("\n[ERROR] in %s : cannot create node %s for path <%s>\n",
1525                __FUNCTION__ , name, pathname );
[238]1526                return ENOMEM;
1527            }
1528
[459]1529            // get child inode cluster and local pointer
1530            child_cxy = GET_CXY( child_xp );
1531            child_ptr = GET_PTR( child_xp );
1532
1533#if (DEBUG_VFS_LOOKUP & 1)
1534if( DEBUG_VFS_LOOKUP < cycle )
1535printk("\n[DBG] %s : missing <%s> inode speculatively created / cxy %x / ptr %x\n",
1536__FUNCTION__ , name , child_cxy, child_ptr );
1537#endif
1538             // scan parent mapper to complete the missing inode
[238]1539            if( parent_cxy == local_cxy )
1540            {
1541                error = vfs_inode_load( parent_ptr,
1542                                        name,
1543                                        child_xp );
1544            }
1545            else
1546            {
1547                rpc_vfs_inode_load_client( parent_cxy,
1548                                           parent_ptr,
1549                                           name,
1550                                           child_xp,
1551                                           &error );
1552            }
1553
[459]1554            if ( error )   // child not found in parent mapper
[238]1555            {
[459]1556                if( last && create && dir )  // new directory  => update inode type
1557                {
1558                     hal_remote_sw( XPTR( child_cxy, &child_ptr->type ), INODE_TYPE_DIR );
[1]1559
[459]1560#if (DEBUG_VFS_LOOKUP & 1)
1561if( DEBUG_VFS_LOOKUP < cycle )
1562printk("\n[DBG] %s : created node <%s> in path %s / type DIR\n",
1563__FUNCTION__ , name, pathname );
1564#endif
[238]1565                }
[459]1566                else if ( last && create )   // new file => update inode type
[238]1567                {
[459]1568                     hal_remote_sw( XPTR( child_cxy, &child_ptr->type ), INODE_TYPE_FILE );
[238]1569
[459]1570#if (DEBUG_VFS_LOOKUP & 1)
1571if( DEBUG_VFS_LOOKUP < cycle )
1572printk("\n[DBG] %s : created node <%s> in path %s / type FILE\n",
1573__FUNCTION__ , name, pathname );
1574#endif
[238]1575                }
[459]1576                else                         // not last or not create => remove created node
1577                {                       
1578                     printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
1579                     __FUNCTION__ , name , pathname );
1580                     vfs_remove_child_from_parent( child_xp );
1581                     return ENOENT;
1582                }
[238]1583            }
[459]1584            else          // child found in parent
1585            {
1586                // load child mapper from device if child is a directory (prefetch)
1587                if( hal_remote_lw( XPTR( child_cxy , &child_ptr->type ) ) == INODE_TYPE_DIR ) 
1588                {
1589                    if( child_cxy == local_cxy )
1590                    {
1591                        error = vfs_mapper_load_all( child_ptr );
1592                    }
1593                    else
1594                    {
1595                        rpc_vfs_mapper_load_all_client( child_cxy,
1596                                                        child_ptr,
1597                                                        &error );
1598                    }
1599                    if ( error )
1600                    {
1601                        printk("\n[ERROR] in %s : cannot load <%s> from device\n",
1602                        __FUNCTION__ , name );
1603                        vfs_remove_child_from_parent( child_xp );
1604                        return EIO;
1605                    }
[238]1606
[438]1607#if (DEBUG_VFS_LOOKUP & 1)
1608if( DEBUG_VFS_LOOKUP < cycle )
[459]1609printk("\n[DBG] %s : load mapper from device for node <%s> in path %s\n",
1610__FUNCTION__ , name, pathname );
[433]1611#endif
[459]1612                }
1613            }
[407]1614
[459]1615            // take lock on parent inode
1616            vfs_inode_lock( parent_xp );
[1]1617        }
[459]1618        else   // child found in inode tree
1619        {
1620       
[438]1621#if (DEBUG_VFS_LOOKUP & 1)
1622if( DEBUG_VFS_LOOKUP < cycle )
[433]1623printk("\n[DBG] %s : found <%s> / inode %x in cluster %x\n",
1624__FUNCTION__ , name , GET_PTR(child_xp) , GET_CXY(child_xp) );
1625#endif
[459]1626            child_ptr  = GET_PTR( child_xp );
1627            child_cxy  = GET_CXY( child_xp );
1628            parent_cxy = GET_CXY( parent_xp );
1629            parent_ptr = GET_PTR( parent_xp );
[101]1630
[459]1631            if( last && (mode & VFS_LOOKUP_CREATE) && (mode & VFS_LOOKUP_EXCL) )
1632            {
1633                printk("\n[ERROR] in %s : node already exist <%s>\n", __FUNCTION__, name );
1634                return EINVAL;
1635            }
1636        }
1637
[380]1638        // TODO check access rights here [AG]
[23]1639        // error = vfs_access_denied( child_xp,
1640        //                            client_uid,
1641        //                            client_gid );
1642        // if( error )
1643        // {
[441]1644        //     printk("\n[ERROR] in %s : thread %x / permission denied for %s\n",
1645        //     __FUNCTION__ , this , name );
[23]1646        //     return EACCES;
1647        // }
[1]1648
[238]1649        // take lock on child inode and release lock on parent
1650        vfs_inode_lock( child_xp );
[101]1651        vfs_inode_unlock( parent_xp );
[1]1652
1653        // update loop variables
1654        parent_xp = child_xp;
1655        current   = next;
1656    }
1657    while( last == false );
1658
[238]1659    // release lock
1660    vfs_inode_unlock( parent_xp );
[1]1661
[438]1662#if DEBUG_VFS_LOOKUP
[433]1663cycle = (uint32_t)hal_get_cycles();
[438]1664if( DEBUG_VFS_LOOKUP < cycle )
[459]1665printk("\n[DBG] %s : thread %x in process %x exit for <%s>\n" 
1666"     parent %x in cluster %x / child %x in cluster %x / cycle %d\n",
1667__FUNCTION__ , this->trdid, process->pid, pathname, 
1668parent_ptr, parent_cxy, child_ptr, child_cxy, cycle );
[433]1669#endif
[1]1670
[238]1671    // return searched pointer
[459]1672    if( mode & VFS_LOOKUP_PARENT ) *inode_xp = parent_xp;
1673    else                           *inode_xp = child_xp;
[1]1674
1675    return 0;
1676
1677}  // end vfs_lookup()
1678
1679////////////////////////////////////////////
1680error_t vfs_get_path( xptr_t    searched_xp,
1681                      char    * buffer,
1682                      uint32_t  max_size )
1683{
1684        xptr_t       dentry_xp;   // extended pointer on current dentry
1685    char       * name;        // local pointer on current dentry name
1686        uint32_t     length;      // length of current dentry name
1687        uint32_t     count;       // number of characters written in buffer
1688        uint32_t     index;       // slot index in buffer
[23]1689    xptr_t       inode_xp;    // extended pointer on   
[1]1690
1691    // implementation note:
1692    // we use two variables "index" and "count" because the buffer
[401]1693    // is written in decreasing index order (from leaf to root)
[433]1694    // TODO  : handle conflict with a concurrent rename [AG]
1695    // FIXME : handle synchro in the loop  [AG]
[1]1696
1697        // set the NUL character in buffer / initialise buffer index and count
1698        buffer[max_size - 1] = 0;
1699        count    = 1;
1700    index    = max_size - 2;
1701
1702    // initialize current inode
1703    inode_xp  = searched_xp;
1704
1705    // exit when root inode found (i.e. dentry_xp == XPTR_NULL)
1706        do
1707    {
1708        // get inode cluster and local pointer
1709        cxy_t         inode_cxy = GET_CXY( inode_xp );
[473]1710        vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
[1]1711
1712        // get extended pointer on parent dentry               
1713        dentry_xp = (xptr_t)hal_remote_lwd( XPTR( inode_cxy , inode_ptr->parent_xp ) );
1714
1715        // get dentry cluster and local pointer
1716        cxy_t          dentry_cxy = GET_CXY( dentry_xp );
[473]1717        vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
[1]1718
1719        // get dentry name length and pointer
1720        length =  hal_remote_lw( XPTR( dentry_cxy , &dentry_ptr->length ) );
1721        name   = (char *)hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->name ) );
1722
1723        // update index and count
1724        index -= (length + 1); 
1725        count += (length + 1);
1726
1727        // check buffer overflow
1728        if( count >= max_size )
1729        {
1730            printk("\n[ERROR] in %s : kernel buffer too small\n", __FUNCTION__ );
1731            return EINVAL;
1732        }
1733
1734        // update pathname
1735        hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
1736                           XPTR( dentry_cxy , name ) , length );
1737                buffer[index] = '/';
1738
1739                // get extended pointer on next inode
1740        inode_xp = (xptr_t)hal_remote_lwd( XPTR( dentry_cxy , dentry_ptr->parent ) );
1741    }
1742    while( (dentry_xp != XPTR_NULL) );
1743
1744        return 0;
1745
1746}  // end vfs_get_path()
1747
[188]1748     
1749//////////////////////////////////////////////////////////////
1750error_t vfs_add_child_in_parent( cxy_t              child_cxy,
1751                                 vfs_inode_type_t   inode_type,
[23]1752                                 vfs_fs_type_t      fs_type,
1753                                 xptr_t             parent_xp,
1754                                 char             * name,
[188]1755                                 void             * extend,
[23]1756                                 xptr_t           * child_xp )
[1]1757{
[23]1758    error_t         error;
1759    xptr_t          dentry_xp;   // extended pointer on created dentry
1760    xptr_t          inode_xp;    // extended pointer on created inode
1761    cxy_t           parent_cxy;  // parent inode cluster identifier
1762    vfs_inode_t   * parent_ptr;  // parent inode local pointer
[1]1763
1764    // get parent inode cluster and local pointer
[23]1765    parent_cxy = GET_CXY( parent_xp );
[459]1766    parent_ptr = GET_PTR( parent_xp );
[1]1767
[438]1768#if DEBUG_VFS_ADD_CHILD
[433]1769uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1770if( DEBUG_VFS_ADD_CHILD < cycle )
[459]1771printk("\n[DBG] %s : thread %x enter for <%s> / child_cxy = %x / parent_cxy = %x / cycle %d\n",
1772__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, name,
1773child_cxy, parent_cxy, (uint32_t)hal_get_cycles() );
[433]1774#endif
[279]1775
[204]1776    // 1. create dentry
[1]1777    if( parent_cxy == local_cxy )      // parent cluster is the local cluster
1778    {
[23]1779        error = vfs_dentry_create( fs_type,
[1]1780                                   name,
1781                                   parent_ptr,
1782                                   &dentry_xp );
[279]1783
[438]1784#if (DEBUG_VFS_ADD_CHILD & 1)
1785if( (DEBUG_VFS_ADD_CHILD < cycle) && (error == 0) )
[433]1786printk("\n[DBG] %s : dentry <%s> created in cluster %x\n", __FUNCTION__, name, local_cxy );
1787#endif
[407]1788
[1]1789    }
1790    else                               // parent cluster is remote
1791    {
1792        rpc_vfs_dentry_create_client( parent_cxy,
[23]1793                                      fs_type,
[1]1794                                      name,
1795                                      parent_ptr,
1796                                      &dentry_xp,
1797                                      &error );
[279]1798
[438]1799#if (DEBUG_VFS_ADD_CHILD & 1)
1800if( (DEBUG_VFS_ADD_CHILD < cycle) && (error == 0) )
[433]1801printk("\n[DBG] %s : dentry <%s> created in cluster %x\n", __FUNCTION__, name, parent_cxy );
1802#endif
[407]1803
[1]1804    }
1805                                     
1806    if( error )
1807    {
[437]1808        printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n",
1809        __FUNCTION__ , name , parent_cxy );
[204]1810        return ENOMEM;
[1]1811    }
1812
[204]1813    // 2. create child inode TODO : define attr / mode / uid / gid
[1]1814    uint32_t attr = 0;
1815    uint32_t mode = 0;
1816    uint32_t uid  = 0;
1817    uint32_t gid  = 0;
1818   
1819    if( child_cxy == local_cxy )      // child cluster is the local cluster
1820    {
1821        error = vfs_inode_create( dentry_xp,
[23]1822                                  fs_type,
1823                                  inode_type,
[188]1824                                  extend,
[1]1825                                  attr,
1826                                  mode,
1827                                  uid,
1828                                  gid,
1829                                  &inode_xp );
[279]1830
[438]1831#if (DEBUG_VFS_ADD_CHILD & 1)
1832if( DEBUG_VFS_ADD_CHILD < cycle )
[433]1833printk("\n[DBG] %s : inode <%x> created in cluster %x\n",
1834__FUNCTION__ , GET_PTR(inode_xp) , local_cxy );
1835#endif
1836
[1]1837    }
1838    else                              // child cluster is remote
1839    {
1840        rpc_vfs_inode_create_client( child_cxy,
1841                                     dentry_xp,
[23]1842                                     fs_type,
1843                                     inode_type,
[188]1844                                     extend,
[1]1845                                     attr,
1846                                     mode,
1847                                     uid,
1848                                     gid,
1849                                     &inode_xp,
1850                                     &error );
[279]1851
[438]1852#if (DEBUG_VFS_ADD_CHILD & 1)
1853if( DEBUG_VFS_ADD_CHILD < cycle )
[433]1854printk("\n[DBG] %s : inode <%s> created in cluster %x\n",
[407]1855__FUNCTION__ , GET_PTR(inode_xp) , child_cxy );
[433]1856#endif
[407]1857
[1]1858    }
1859                                     
1860    if( error )
1861    {
1862        printk("\n[ERROR] in %s : cannot create inode in cluster %x\n",
1863               __FUNCTION__ , child_cxy );
1864 
[459]1865        vfs_dentry_t * dentry = GET_PTR( dentry_xp );
[1]1866        if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry );
[459]1867        else rpc_vfs_dentry_destroy_client( parent_cxy , dentry , &error );
[204]1868        return ENOMEM;
[1]1869    }
1870
[204]1871    // 3. update extended pointer on inode in dentry
1872    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
[473]1873    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
[204]1874    hal_remote_swd( XPTR( dentry_cxy , &dentry_ptr->child_xp ) , inode_xp );
1875
[438]1876#if DEBUG_VFS_ADD_CHILD
[433]1877cycle = (uint32_t)hal_get_cycles();
[438]1878if( DEBUG_VFS_ADD_CHILD < cycle )
[459]1879printk("\n[DBG] %s : thread %x in process %x exit for <%s>\n",
1880__FUNCTION__, CURRENT_THREAD, CURRENT_THREAD->process->pid, name );
[433]1881#endif
[296]1882
[1]1883    // success : return extended pointer on child inode
1884    *child_xp = inode_xp;
1885    return 0;
1886
[459]1887    // FIXME update the refcount fields in both inode and dentry
1888
[1]1889}  // end vfs_add_child_in_parent()
1890
[459]1891///////////////////////////////////////////////////////
1892error_t vfs_remove_child_from_parent( xptr_t inode_xp )
1893{
1894    cxy_t          inode_cxy;
1895    vfs_inode_t  * inode_ptr;
1896    xptr_t         dentry_xp;
1897    cxy_t          dentry_cxy;
1898    vfs_dentry_t * dentry_ptr;
1899    error_t        error;
1900   
1901    // get inode cluster and local pointer
1902    inode_cxy = GET_CXY( inode_xp );
1903    inode_ptr = GET_PTR( inode_xp );
1904
1905    // get cluster and pointers of associated dentry
1906    dentry_xp  = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
1907    dentry_cxy = GET_CXY( dentry_xp ); 
1908    dentry_ptr = GET_PTR( dentry_xp );
1909
1910    // FIXME update the refcount fields in both inode and dentry
1911
1912    // delete dentry
1913    if( dentry_cxy == local_cxy )
1914    {
1915         error = vfs_dentry_destroy( dentry_ptr );
1916    }
1917    else
1918    {
1919         rpc_vfs_dentry_destroy_client( dentry_cxy,
1920                                        dentry_ptr,
1921                                        &error );
1922    }
1923    if( error ) return EINVAL;
1924
1925    // delete inode
1926    if( inode_cxy == local_cxy )
1927    {
1928         vfs_inode_destroy( inode_ptr );
1929    }
1930    else
1931    {
1932         rpc_vfs_inode_destroy_client( inode_cxy,
1933                                       inode_ptr,
1934                                       &error );
1935    }
1936    if( error ) return EINVAL;
1937
1938    return 0;
1939
1940}  // end vfs_remove_child_from_parent()
1941
[23]1942//////////////////////////////////////////////////////////////////////////////////////////
1943//            Mapper related functions
1944//////////////////////////////////////////////////////////////////////////////////////////
1945
[238]1946////////////////////////////////////////////
1947error_t vfs_mapper_move_page( page_t * page,
1948                              bool_t   to_mapper )
[23]1949{
[204]1950    error_t error = 0;
[23]1951
[492]1952    assert( (page != NULL) , "page pointer is NULL\n" );
[23]1953
[246]1954    mapper_t    * mapper = page->mapper;
[23]1955
[492]1956    assert( (mapper != NULL) , "no mapper for page\n" );
[23]1957
[438]1958#if DEBUG_VFS_MAPPER_MOVE
[433]1959uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1960if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]1961printk("\n[DBG] %s : thread %x enter for page %d / mapper %x / inode %x / cycle %d\n",
1962__FUNCTION__, CURRENT_THREAD, page->index, mapper, mapper->inode, cycle );
1963#endif
[246]1964
[23]1965    // get FS type
[246]1966    vfs_fs_type_t fs_type = mapper->type;
[23]1967
[238]1968    // call relevant FS function
[23]1969    if( fs_type == FS_TYPE_FATFS )
1970    {
1971        rwlock_wr_lock( &mapper->lock );
[246]1972        error = fatfs_mapper_move_page( page , to_mapper ); 
[23]1973        rwlock_wr_unlock( &mapper->lock );
1974    }
1975    else if( fs_type == FS_TYPE_RAMFS )
1976    {
[492]1977        assert( false , "should not be called for RAMFS\n" );
[23]1978    }
1979    else if( fs_type == FS_TYPE_DEVFS )
1980    {
[492]1981        assert( false , "should not be called for DEVFS\n" );
[23]1982    }
1983    else
1984    {
[492]1985        assert( false , "undefined file system type\n" );
[23]1986    }
1987
[438]1988#if DEBUG_VFS_MAPPER_MOVE
[433]1989cycle = (uint32_t)hal_get_cycles();
[438]1990if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]1991printk("\n[DBG] %s : thread %x exit for page %d / mapper %x / inode %x / cycle %d\n",
1992__FUNCTION__, CURRENT_THREAD, page->index, mapper, mapper->inode, cycle );
1993#endif
[246]1994
[23]1995    return error;
1996
[238]1997}  // end vfs_move_page()
[23]1998
1999//////////////////////////////////////////////////
[238]2000error_t vfs_mapper_load_all( vfs_inode_t * inode )
[23]2001{
[492]2002    assert( (inode != NULL) , "inode pointer is NULL\n" );
[23]2003
[238]2004    uint32_t   index;
2005    page_t   * page;
[23]2006
[238]2007    mapper_t * mapper = inode->mapper;
2008    uint32_t   size   = inode->size;
[23]2009
[492]2010    assert( (mapper != NULL) , "mapper pointer is NULL\n" );
[23]2011
[438]2012#if DEBUG_VFS_MAPPER_LOAD
[433]2013uint32_t cycle = (uint32_t)hal_get_cycles();
[438]2014if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]2015printk("\n[DBG] %s : thread %x enter for inode %x in cluster %x / cycle %d\n",
2016__FUNCTION__, CURRENT_THREAD, inode, local_cxy, cycle );
2017#endif
[401]2018
2019    // compute number of pages
[238]2020    uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
[265]2021    if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++;
[238]2022
[265]2023    // loop on pages
[238]2024    for( index = 0 ; index < npages ; index ++ )
[23]2025    {
[238]2026        // this function allocates the missing page in mapper,
2027        // and call the vfs_mapper_move_page() to load the page from device
2028        page = mapper_get_page( mapper , index );
[23]2029
[238]2030        if( page == NULL ) return EIO;
[23]2031    }
2032
[438]2033#if DEBUG_VFS_MAPPER_LOAD
[433]2034cycle = (uint32_t)hal_get_cycles();
[438]2035if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]2036printk("\n[DBG] %s : thread %x exit for inode %x in cluster %x / cycle %d\n",
2037__FUNCTION__, CURRENT_THREAD, inode, local_cxy, cycle );
2038#endif
[401]2039
[238]2040    return 0;
[23]2041
[238]2042}  // end vfs_mapper_load_all()
[23]2043
Note: See TracBrowser for help on using the repository browser.