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

Last change on this file since 450 was 441, checked in by alain, 7 years ago

Fix a bug in rpc_vmm_get_pte_client() function (bad RPC index).

File size: 62.8 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>
[1]27#include <hal_types.h>
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
96    if( lid == -1 )   // no more free slot => error
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;
[430]173                assert( false , __FUNCTION__ , "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
249/////////////////////////////////////////////
250void vfs_inode_destroy( vfs_inode_t * inode )
251{
252    if( inode->refcount )
253    {
[430]254        assert( false , __FUNCTION__ , "inode refcount non zero\n" );
[1]255    }       
256
257    // release memory allocated for mapper
258    mapper_destroy( inode->mapper );
259
260    // release memory allocate for inode descriptor
261        kmem_req_t req;
262        req.ptr   = inode;
263        req.type  = KMEM_VFS_INODE;
264        kmem_free( &req );
265
266}  // end vfs_inode_destroy()
267
[238]268/////////////////////////////////////////////
269error_t vfs_inode_load( vfs_inode_t * parent,
270                        char        * name,
271                        xptr_t        child_xp )
272{
[246]273
[438]274#if DEBUG_VFS_INODE_LOAD
[433]275uint32_t cycle = (uint32_t)hal_get_cycles();
[438]276if( DEBUG_VFS_INODE_LOAD < cycle )
[433]277printk("\n[DBG] %s : thread %x enter for <%s> / cycle %d\n",
278__FUNCTION__, CURRENT_THREAD , name , cycle );
279#endif
280
[238]281    error_t error = 0;
282
283    assert( (parent != NULL) , __FUNCTION__ , "parent pointer is NULL\n");
284
285    assert( (child_xp != XPTR_NULL) , __FUNCTION__ , "child pointer is NULL\n");
286
287    // get parent inode FS type
288    vfs_fs_type_t fs_type = parent->ctx->type;
289
290    // call relevant FS function
291    if( fs_type == FS_TYPE_FATFS )
292    {
293        error = fatfs_inode_load( parent , name , child_xp );
294    }
295    else if( fs_type == FS_TYPE_RAMFS )
296    {
297        assert( false , __FUNCTION__ , "should not be called for RAMFS\n" );
298    }
299    else if( fs_type == FS_TYPE_DEVFS )
300    {
301        assert( false , __FUNCTION__ , "should not be called for DEVFS\n" );
302    }
303    else
304    {
305        assert( false , __FUNCTION__ , "undefined file system type\n" );
306    }
307
[438]308#if DEBUG_VFS_INODE_LOAD
[433]309cycle = (uint32_t)hal_get_cycles();
[438]310if( DEBUG_VFS_INODE_LOAD < cycle )
[433]311printk("\n[DBG] %s : thread %x exit for <%s> / cycle %d\n",
312__FUNCTION__, CURRENT_THREAD , name , cycle );
313#endif
[246]314
[238]315    return error;
316
317} // end vfs_load_inode()
318
[1]319////////////////////////////////////////////
320void vfs_inode_remote_up( xptr_t  inode_xp )
321{
322    // get inode cluster and local pointer
323    cxy_t         inode_cxy = GET_CXY( inode_xp );
324    vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
325
326    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , 1 );   
327}
328
329//////////////////////////////////////////////
330void vfs_inode_remote_down( xptr_t  inode_xp )
331{
332    // get inode cluster and local pointer
333    cxy_t         inode_cxy = GET_CXY( inode_xp );
334    vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
335
336    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , -1 );   
337}
338
339//////////////////////////////////////////////
340uint32_t vfs_inode_get_size( xptr_t inode_xp )
341{
342    // get inode cluster and local pointer
343    cxy_t         cxy = GET_CXY( inode_xp );
344    vfs_inode_t * ptr = (vfs_inode_t *)GET_PTR( inode_xp );
345
346    // get size
[10]347    remote_rwlock_rd_lock( XPTR( cxy , &ptr->data_lock ) );
[1]348    uint32_t size = hal_remote_lw( XPTR( cxy , &ptr->size ) );
[10]349    remote_rwlock_rd_unlock( XPTR( cxy , &ptr->data_lock ) );
[1]350    return size;
351}
352
[101]353////////////////////////////////////////////
354void vfs_inode_set_size( xptr_t    inode_xp,
[409]355                         uint32_t  size )
[1]356{
357    // get inode cluster and local pointer
358    cxy_t         cxy = GET_CXY( inode_xp );
359    vfs_inode_t * ptr = (vfs_inode_t *)GET_PTR( inode_xp );
360
361    // set size
[10]362    remote_rwlock_wr_unlock( XPTR( cxy , &ptr->data_lock ) );
[1]363    hal_remote_sw( XPTR( cxy , &ptr->size ) , size );
[10]364    remote_rwlock_wr_unlock( XPTR( cxy , &ptr->data_lock ) );
[1]365}
366
[101]367////////////////////////////////////////
368void vfs_inode_unlock( xptr_t inode_xp )
[1]369{
370    // get inode cluster and local pointer
371    cxy_t         cxy = GET_CXY( inode_xp );
372    vfs_inode_t * ptr = (vfs_inode_t *)GET_PTR( inode_xp );
373
374    // release the main lock
375    remote_spinlock_unlock( XPTR( cxy , &ptr->main_lock ) );
376}
377
[101]378//////////////////////////////////////
379void vfs_inode_lock( xptr_t inode_xp )
[1]380{
381    // get inode cluster and local pointer
382    cxy_t         cxy = GET_CXY( inode_xp );
383    vfs_inode_t * ptr = (vfs_inode_t *)GET_PTR( inode_xp );
384
385    // get the main lock
386    remote_spinlock_lock( XPTR( cxy , &ptr->main_lock ) );
387}
388
[101]389/////////////////////////////////////////
[409]390void vfs_inode_get_name( xptr_t inode_xp,
391                         char * name )
[101]392{
[204]393    cxy_t          inode_cxy;
394    vfs_inode_t  * inode_ptr;
395    xptr_t         dentry_xp;
396    cxy_t          dentry_cxy;
397    vfs_dentry_t * dentry_ptr;
398   
399    // get inode cluster and local pointer
400    inode_cxy = GET_CXY( inode_xp );
401    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
402
403    // get parent dentry
404    dentry_xp  = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
405
406    // get local copy of name
407    if( dentry_xp == XPTR_NULL )  // it is the VFS root
408    {
409        strcpy( name , "/" );
410    }
411    else                          // not the VFS root
412    {
413        dentry_cxy = GET_CXY( dentry_xp );
414        dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
415
416        hal_remote_strcpy( XPTR( local_cxy  , name ) , 
417                           XPTR( dentry_cxy , &dentry_ptr->name ) );
418    }
[409]419}  // end vfs_inode_get_name()
[204]420
421////////////////////////////////////////////////////////////////////////////////////////////
[1]422//           Dentry related functions
423//////////////////////////////////////////////////////////////////////////////////////////
424
[23]425///////////////////////////////////////////////////
426error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
427                           char          * name,
428                           vfs_inode_t   * parent,
429                           xptr_t        * dentry_xp )
[1]430{
431    vfs_ctx_t      * ctx;        // context descriptor
432    vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated)
433        kmem_req_t       req;        // request to kernel memory allocator
434
[438]435#if DEBUG_VFS_DENTRY_CREATE
[433]436uint32_t cycle = (uint32_t)hal_get_cycles();
[438]437if( DEBUG_VFS_DENTRY_CREATE < cycle )
[433]438printk("\n[DBG] %s : thread %x enter for <%s> / parent_inode %x / cycle %d\n",
439__FUNCTION__, CURRENT_THREAD , name , parent , cycle );
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];
[1]446    else
447    {
448        ctx = NULL;
[430]449        assert( false , __FUNCTION__ , "undefined file system type\n" );
[1]450    }
451
452    // get name length
453    uint32_t length = strlen( name );
454
[23]455    if( length >= CONFIG_VFS_MAX_NAME_LENGTH )
[1]456    {
[437]457
[438]458#if DEBUG_SYSCALLS_ERROR
[437]459printk("\n[ERROR] in %s : name <name> too long\n", __FUNCTION__ , name );
460#endif
[1]461        return EINVAL;
462    }
463
464    // allocate memory for dentry descriptor
465        req.type  = KMEM_VFS_DENTRY;
466        req.size  = sizeof(vfs_dentry_t);
467    req.flags = AF_KERNEL | AF_ZERO;
468        dentry     = (vfs_dentry_t *)kmem_alloc( &req );
469
470    if( dentry == NULL )
471    {
[437]472
[438]473#if DEBUG_SYSCALLS_ERROR
[437]474printk("\n[ERROR] in %s : cannot allocate dentry\n", __FUNCTION__ );
475#endif
[1]476        return ENOMEM;
477    }
478
479    // initialize dentry descriptor
[23]480
[1]481    dentry->ctx     = ctx;
482    dentry->length  = length;
483    dentry->parent  = parent;
484    strcpy( dentry->name , name );
485
[438]486#if( DEBUG_VFS_DENTRY_CREATE & 1 )
[437]487cycle = (uint32_t)hal_get_cycles();
[438]488if( DEBUG_VFS_DENTRY_CREATE < cycle )
[437]489printk("\n[DBG] %s : dentry initialised\n", __FUNCTION__ );
490#endif
491
[23]492    // register dentry in hash table rooted in parent inode
493    xhtab_insert( XPTR( local_cxy , &parent->children ),
494                  name, 
[188]495                  XPTR( local_cxy , &dentry->list ) );
[23]496
[438]497#if( DEBUG_VFS_DENTRY_CREATE & 1 )
[437]498cycle = (uint32_t)hal_get_cycles();
[438]499if( DEBUG_VFS_DENTRY_CREATE < cycle )
[437]500printk("\n[DBG] %s : dentry registerd in htab\n", __FUNCTION__ );
501#endif
502
[23]503    // return extended pointer on dentry
[1]504    *dentry_xp = XPTR( local_cxy , dentry );
505
[438]506#if DEBUG_VFS_DENTRY_CREATE
[433]507cycle = (uint32_t)hal_get_cycles();
[438]508if( DEBUG_VFS_DENTRY_CREATE < cycle )
[433]509printk("\n[DBG] %s : thread %x exit for <%s> / dentry %x / cycle %d\n",
510__FUNCTION__, CURRENT_THREAD , name , dentry , cycle );
511#endif
[296]512
[1]513    return 0;
514
515}  // end vfs_dentry_create()
516
517////////////////////////////////////////////////
518void vfs_dentry_destroy( vfs_dentry_t * dentry )
519{
520    if( dentry->refcount )
521    {
[430]522        assert( false , __FUNCTION__ , "dentry refcount non zero\n" );
[1]523    }       
524
525        kmem_req_t req;
526        req.ptr   = dentry;
527        req.type  = KMEM_VFS_DENTRY;
528        kmem_free( &req );
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 );
566    return 0;
567
568}  // end vfs_file_create()
569
570///////////////////////////////////////////
571void vfs_file_destroy( vfs_file_t *  file )
572{
573    if( file->refcount )
574    {
[430]575        assert( false , __FUNCTION__ , "refcount non zero\n" );
[23]576    }       
577
578        kmem_req_t req;
579        req.ptr   = file;
580        req.type  = KMEM_VFS_FILE;
581        kmem_free( &req );
582
583}  // end vfs_file_destroy()
584
585
[1]586////////////////////////////////////////
587void vfs_file_count_up( xptr_t file_xp )
588{
589    // get file cluster and local pointer
590    cxy_t        file_cxy = GET_CXY( file_xp );
591    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 
592
593    // atomically increment count
594    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 
595}
596
597//////////////////////////////////////////
598void vfs_file_count_down( xptr_t file_xp )
599{
600    // get file cluster and local pointer
601    cxy_t        file_cxy = GET_CXY( file_xp );
602    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 
603
604    // atomically decrement count
605    hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 
606}
607
[23]608//////////////////////////////////////////////////////////////////////////////////////////
609//           File access related functions
610//////////////////////////////////////////////////////////////////////////////////////////
611
[407]612//////////////////////////////////////
613error_t vfs_open( process_t * process,
614                          char      * path,
615                          uint32_t    flags,
616                  uint32_t    mode, 
617                          xptr_t    * new_file_xp,
618                  uint32_t  * new_file_id )
[1]619{
[23]620    error_t       error;
621    xptr_t        inode_xp;     // extended pointer on target inode
622    cxy_t         inode_cxy;    // inode cluster identifier       
623    vfs_inode_t * inode_ptr;    // inode local pointer
624    uint32_t      file_attr;    // file descriptor attributes
625    uint32_t      lookup_mode;  // lookup working mode       
626    xptr_t        file_xp;      // extended pointer on created file descriptor
627    uint32_t      file_id;      // created file descriptor index in reference fd_array
[1]628
[438]629#if DEBUG_VFS_OPEN
[433]630uint32_t cycle = (uint32_t)hal_get_cycles();
[438]631if( DEBUG_VFS_OPEN < cycle )
[433]632printk("\n[DBG] %s :  thread %x enter for <%s> / cycle %d\n",
633__FUNCTION__, CURRENT_THREAD, path, cycle );
634#endif
[101]635
[23]636    // compute lookup working mode
637    lookup_mode = VFS_LOOKUP_OPEN;
638    if( (flags & O_DIR    )      )  lookup_mode |= VFS_LOOKUP_DIR;
639    if( (flags & O_CREAT  )      )  lookup_mode |= VFS_LOOKUP_CREATE;
640    if( (flags & O_EXCL   )      )  lookup_mode |= VFS_LOOKUP_EXCL;
641 
642    // compute attributes for the created file
643    file_attr = 0;
[407]644    if( (flags & O_RDONLY ) == 0 )  file_attr |= FD_ATTR_WRITE_ENABLE;
645    if( (flags & O_WRONLY ) == 0 )  file_attr |= FD_ATTR_READ_ENABLE;
[23]646    if( (flags & O_SYNC   )      )  file_attr |= FD_ATTR_SYNC;
647    if( (flags & O_APPEND )      )  file_attr |= FD_ATTR_APPEND;
648    if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC;
[1]649
[23]650    // get extended pointer on target inode
[407]651    error = vfs_lookup( process->vfs_cwd_xp , path , lookup_mode , &inode_xp );
[23]652
653    if( error ) return error;
654
655    // get target inode cluster and local pointer
656    inode_cxy = GET_CXY( inode_xp );
657    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
658   
659    // create a new file descriptor in cluster containing inode
660    if( inode_cxy == local_cxy )      // target cluster is local
[1]661    {
[23]662        error = vfs_file_create( inode_ptr , file_attr , &file_xp );
[1]663    }
[23]664    else                              // target cluster is remote
665    {
666        rpc_vfs_file_create_client( inode_cxy , inode_ptr , file_attr , &file_xp , &error );
667    }
[1]668
[23]669    if( error )  return error;
[1]670
[407]671    // allocate and register a new file descriptor index in reference process
672    error = process_fd_register( process , file_xp , &file_id );
[1]673
[23]674    if( error ) return error;
[1]675
[438]676#if DEBUG_VFS_OPEN
[433]677cycle = (uint32_t)hal_get_cycles();
[438]678if( DEBUG_VFS_OPEN < cycle )
[433]679printk("\n[DBG] %s : thread %x exit for <%s> / file %x in cluster %x / cycle %d\n",
680__FUNCTION__, CURRENT_THREAD, path, GET_PTR(file_xp), GET_CXY(file_xp), cycle );
681#endif
[238]682
[23]683    // success
684    *new_file_xp = file_xp;
685    *new_file_id = file_id;
686    return 0;
[1]687
[23]688}  // end vfs_open()
689
[407]690//////////////////////////////////////
691int vfs_user_move( bool_t   to_buffer,
692                   xptr_t   file_xp,
693                   void   * buffer,
694                   uint32_t size )
[23]695{
[433]696    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
[23]697
698    cxy_t              file_cxy;     // remote file descriptor cluster
699    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
700    vfs_inode_type_t   inode_type;
701    uint32_t           file_offset;  // current offset in file
702    mapper_t         * mapper;
703    error_t            error;
704
705    // get cluster and local pointer on remote file descriptor
706    file_cxy  = GET_CXY( file_xp );
707    file_ptr  = (vfs_file_t *)GET_PTR( file_xp );
708
709    // get inode type from remote file descriptor
710    inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type   ) );
711   
[407]712    assert( (inode_type == INODE_TYPE_FILE) , __FUNCTION__ ,
713    "inode type is not INODE_TYPE_FILE" );
[23]714
[407]715    // get mapper pointer and file offset from file descriptor
716    file_offset = hal_remote_lw( XPTR( file_cxy , &file_ptr->offset ) );
717    mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
[23]718
[407]719    // move data between mapper and buffer
720    if( file_cxy == local_cxy )
721    {
722        error = mapper_move_user( mapper,
723                                  to_buffer,
724                                  file_offset,
725                                  buffer,
726                                  size );
[23]727    }
[407]728    else
[23]729    {
[407]730        rpc_mapper_move_buffer_client( file_cxy,
731                                       mapper,
732                                       to_buffer,
733                                       true,          // user buffer
734                                       file_offset,
735                                       (uint64_t)(intptr_t)buffer,
736                                       size,
737                                       &error );
738    } 
739
740    if( error ) return -1;
741    else        return size;
742
[313]743}  // end vfs_user_move()
[23]744
[317]745////////////////////////////////////////////
746error_t vfs_kernel_move( bool_t   to_buffer,
747                         xptr_t   file_xp,
748                         xptr_t   buffer_xp,
749                         uint32_t size )
750{
751    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
752
753    cxy_t              file_cxy;     // remote file descriptor cluster
754    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
755    vfs_inode_type_t   inode_type;
756    uint32_t           file_offset;  // current offset in file
757    mapper_t         * mapper;
758    error_t            error;
759
760    // get cluster and local pointer on remote file descriptor
761    file_cxy  = GET_CXY( file_xp );
762    file_ptr  = (vfs_file_t *)GET_PTR( file_xp );
763
764    // get inode type from remote file descriptor
765    inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type   ) );
766   
767    // action depends on inode type
768    if( inode_type == INODE_TYPE_FILE )
769    {
770        // get mapper pointer and file offset from file descriptor
771        file_offset = hal_remote_lw( XPTR( file_cxy , &file_ptr->offset ) );
772        mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
773
774        // move data between mapper and buffer
775        if( file_cxy == local_cxy )
776        {
777            error = mapper_move_kernel( mapper,
778                                        to_buffer,
779                                        file_offset,
780                                        buffer_xp,
781                                        size );
782        }
783        else
784        {
785            rpc_mapper_move_buffer_client( file_cxy,
786                                           mapper,
787                                           to_buffer,
788                                           false,          // kernel buffer
789                                           file_offset,
790                                           buffer_xp,
791                                           size,
792                                           &error );
793        } 
794
795        if( error ) return -1;
796        else        return 0;
797    }
798    else 
799    {
800        printk("\n[ERROR] in %s : inode is not a file", __FUNCTION__ );
801        return -1;
802    }
803}  // end vfs_kernel_move()
804
[23]805//////////////////////////////////////
806error_t vfs_lseek( xptr_t     file_xp,
807                   uint32_t   offset,
808                   uint32_t   whence, 
809                   uint32_t * new_offset )
810{
[266]811    xptr_t         offset_xp;
812    xptr_t         lock_xp;
813    cxy_t          file_cxy;
814    vfs_file_t  *  file_ptr;
815    vfs_inode_t *  inode_ptr;
816    uint32_t       new;
817
818    assert( (file_xp != XPTR_NULL) , __FUNCTION__ , "file_xp == XPTR_NULL" );
819
820    // get cluster and local pointer on remote file descriptor
821    file_cxy = GET_CXY( file_xp );
822    file_ptr = (vfs_file_t *)GET_PTR( file_xp );
823
824    // build extended pointers on lock and offset
825    offset_xp = XPTR( file_cxy , &file_ptr->offset );
826    lock_xp   = XPTR( file_cxy , &file_ptr->lock );
827
828    // take file descriptor lock
829    remote_rwlock_wr_lock( lock_xp );
830
831    if      ( whence == SEEK_CUR )   // new = current + offset
832    {
833        new = hal_remote_lw( offset_xp ) + offset;
834    }
835    else if ( whence == SEEK_SET )   // new = offset
836    {
837        new = offset;
838    }
839    else if ( whence == SEEK_END )   // new = size + offset
840    { 
841        // get local pointer on remote inode
842        inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
843
844        new = hal_remote_lw( XPTR( file_cxy , &inode_ptr->size ) ) + offset;
845    }
846    else
847    {
848        printk("\n[ERROR] in %s : illegal whence value\n", __FUNCTION__ );
849        remote_rwlock_wr_unlock( lock_xp );
850        return -1;
851    }
852
853    // set new offset
854    hal_remote_sw( offset_xp , new );
855
856    // release file descriptor lock
857    remote_rwlock_wr_unlock( lock_xp );
858
859    // success
[271]860    if ( new_offset != NULL )
861        *new_offset = new;
[1]862    return 0;
863
[23]864}  // vfs_lseek()
865
866///////////////////////////////////
867error_t vfs_close( xptr_t   file_xp,
868                   uint32_t file_id )
[1]869{
[23]870    assert( (file_xp != XPTR_NULL) , __FUNCTION__ , "file_xp == XPTR_NULL" );
871
872    assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , __FUNCTION__ , "illegal file_id" );
873
874    thread_t  * this    = CURRENT_THREAD;
875    process_t * process = this->process;
876
877    // get cluster and local pointer on remote file descriptor
[1]878    cxy_t        file_cxy = GET_CXY( file_xp );
879    vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp );
880
[23]881    // get local pointer on local cluster manager
882    cluster_t * cluster = LOCAL_CLUSTER;
883
884    // get owner process cluster and lpid
885    cxy_t   owner_cxy  = CXY_FROM_PID( process->pid );
886    lpid_t  lpid       = LPID_FROM_PID( process->pid );
887
888    // get extended pointers on copies root and lock
889    xptr_t root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
890    xptr_t lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
891
892    // take the lock protecting the copies
893    remote_spinlock_lock( lock_xp );
894
895    // 1) loop on the process descriptor copies to cancel all fd_array[file_id] entries
896    xptr_t  iter_xp;
897    XLIST_FOREACH( root_xp , iter_xp )
[1]898    {
[23]899        xptr_t      process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
900        cxy_t       process_cxy = GET_CXY( process_xp );
901        process_t * process_ptr = (process_t *)GET_PTR( process_xp );
[1]902
[23]903        xptr_t lock_xp  = XPTR( process_cxy , &process_ptr->fd_array.lock );
904        xptr_t entry_xp = XPTR( process_cxy , &process_ptr->fd_array.array[file_id] );
905
906        // lock is required for atomic write of a 64 bits word
907        remote_rwlock_wr_lock( lock_xp );
908        hal_remote_swd( entry_xp , XPTR_NULL );
909        remote_rwlock_wr_unlock( lock_xp );
910
[124]911        hal_fence();
[23]912    }   
913
914    // 2) release memory allocated to file descriptor in remote cluster
915    if( file_cxy == local_cxy )             // file cluster is local
[1]916    {
[23]917        vfs_file_destroy( file_ptr );
918    }
919    else                                    // file cluster is local
920    {
921        rpc_vfs_file_destroy_client( file_cxy , file_ptr );
922    }
[1]923
[23]924    return 0;
[1]925
[23]926}  // end vfs_close()
[1]927
928////////////////////////////////////
[23]929error_t vfs_unlink( xptr_t   cwd_xp,
930                    char   * path )
[1]931{
[430]932    assert( false , __FUNCTION__ , "not implemented\n" );
[1]933    return 0;
[407]934} 
[1]935
[407]936////////////////////////////////////////
937error_t vfs_stat( xptr_t        file_xp,
938                  struct stat * k_stat )
[1]939{
[430]940    assert( false , __FUNCTION__ , "not implemented\n" );
[1]941    return 0;
942}
943
[407]944/////////////////////////////////////////////
945error_t vfs_readdir( xptr_t          file_xp,
946                     struct dirent * k_dirent )
[1]947{
[430]948    assert( false , __FUNCTION__ , "not implemented\n" );
[1]949    return 0;
950}
951
952//////////////////////////////////////
[23]953error_t vfs_mkdir( xptr_t     file_xp,
954                   char     * path,
955                   uint32_t   mode )
[1]956{
[430]957    assert( false , __FUNCTION__ , "not implemented\n" );
[1]958    return 0;
959}
960
[23]961////////////////////////////////////
962error_t vfs_rmdir( xptr_t   file_xp,
963                   char   * path )
[1]964{
[430]965    assert( false , __FUNCTION__ , "not implemented\n" );
[1]966    return 0;
967}
968
[23]969///////////////////////////////////
970error_t vfs_chdir( xptr_t   cwd_xp,
971                   char   * path )
[1]972{
[23]973    error_t           error;
974    xptr_t            inode_xp;     // extended pointer on target inode
975    cxy_t             inode_cxy;    // target inode cluster identifier       
976    vfs_inode_t     * inode_ptr;    // target inode local pointer
977    uint32_t          mode;         // lookup working mode       
978    vfs_inode_type_t  inode_type;   // target inode type
979
980    // set lookup working mode
981    mode = 0;
982
983    // get extended pointer on target inode
984    error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
985
986    if( error ) return error;
987
988    // get inode cluster and local pointer
989    inode_cxy = GET_CXY( inode_xp );
990    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
991
992    // get inode type from remote file
993    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
994
995    if( inode_type != INODE_TYPE_DIR )
996    {
997        CURRENT_THREAD->errno = ENOTDIR;
998        return -1;
999    }
1000
[430]1001    assert( false , __FUNCTION__ , "not implemented\n" );
[1]1002    return 0;
1003}
1004
[23]1005///////////////////////////////////
1006error_t vfs_chmod( xptr_t   cwd_xp,
1007                   char   * path,
1008                   uint32_t rights )
[1]1009{
[23]1010    error_t           error;
1011    xptr_t            inode_xp;     // extended pointer on target inode
1012    cxy_t             inode_cxy;    // inode cluster identifier       
1013    vfs_inode_t     * inode_ptr;    // inode local pointer
1014    uint32_t          mode;         // lookup working mode
1015    vfs_inode_type_t  inode_type;   // target inode type
1016
1017    // set lookup working mode
1018    mode = 0;
1019 
1020    // get extended pointer on target inode
1021    error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
1022
1023    if( error ) return error;
1024
1025    // get inode cluster and local pointer
1026    inode_cxy = GET_CXY( inode_xp );
1027    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
1028   
1029    // get inode type from remote inode
1030    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
1031
1032   
[430]1033    assert( false , __FUNCTION__ , "not implemented\n" );
[1]1034    return 0;
1035}
1036
[23]1037///////////////////////////////////
1038error_t vfs_mkfifo( xptr_t   cwd_xp,
1039                    char   * path,
1040                    uint32_t rights )
1041{
[430]1042    assert( false , __FUNCTION__ , "not implemented\n" );
[23]1043    return 0;
1044}
[1]1045
1046
1047
[188]1048//////////////////////////////////////////////////////////////////////////////////////////
[1]1049//            Inode Tree functions
1050//////////////////////////////////////////////////////////////////////////////////////////
1051
[188]1052/////////////////////////////////
1053cxy_t vfs_cluster_random_select()
1054{
1055    uint32_t  x_size    = LOCAL_CLUSTER->x_size;
1056    uint32_t  y_size    = LOCAL_CLUSTER->y_size;
1057    uint32_t  y_width   = LOCAL_CLUSTER->y_width;
1058    uint32_t  index     = ( hal_get_cycles() + hal_get_gid() ) % (x_size * y_size);
1059    uint32_t  x         = index / y_size;   
1060    uint32_t  y         = index % y_size;
1061
1062    return (x<<y_width) + y;
1063}
1064
1065
1066//////////////////////////////////////////////////////////////////////////
1067// This static function is called by the vfs_display() function.
[337]1068// that is supposed to take the TXT0 lock.
[188]1069//////////////////////////////////////////////////////////////////////////
1070static void vfs_recursive_display( xptr_t   inode_xp,
1071                                   xptr_t   name_xp,
[204]1072                                   xptr_t   dentry_xp,
[188]1073                                   uint32_t indent )
1074{
1075    cxy_t              inode_cxy;
1076    vfs_inode_t      * inode_ptr;
1077    vfs_inode_type_t   inode_type;
[204]1078    xptr_t             children_xp;    // extended pointer on children xhtab
[188]1079
[204]1080    xptr_t             child_dentry_xp;
1081    cxy_t              child_dentry_cxy;
1082    vfs_dentry_t     * child_dentry_ptr;
1083    xptr_t             child_inode_xp;
1084    xptr_t             child_dentry_name_xp;
[188]1085
1086    char               name[CONFIG_VFS_MAX_NAME_LENGTH];
1087
1088    char *             indent_str[] = { "",                                  // level 0
1089                                        "  ",                                // level 1
1090                                        "    ",                              // level 2
1091                                        "      ",                            // level 3
1092                                        "        ",                          // level 4
1093                                        "          ",                        // level 5
1094                                        "            ",                      // level 6
1095                                        "              ",                    // level 7
1096                                        "                ",                  // level 8
1097                                        "                  ",                // level 9
1098                                        "                    ",              // level 10
1099                                        "                      ",            // level 11
1100                                        "                        ",          // level 12
1101                                        "                          ",        // level 13
1102                                        "                            ",      // level 14
1103                                        "                              " };  // level 15
1104
1105    assert( (inode_xp != XPTR_NULL) , __FUNCTION__ , "inode_xp cannot be NULL\n" );
1106    assert( (name_xp  != XPTR_NULL) , __FUNCTION__ , "name_xp cannot be NULL\n" );
1107    assert( (indent < 16)           , __FUNCTION__ , "depth cannot be larger than 15\n" );
1108   
1109    // get inode cluster and local pointer
1110    inode_cxy = GET_CXY( inode_xp );
1111    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
1112
1113    // get inode type
1114    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
1115
[367]1116    // get local pointer on associated mapper
1117    mapper_t * mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
1118
[188]1119    // make a local copy of node name
1120    hal_remote_strcpy( XPTR( local_cxy , name ) , name_xp );
1121
1122    // display inode
[407]1123    nolock_printk("%s%s <%s> : inode = %x / mapper = %x / cluster %x\n",
[367]1124                  indent_str[indent], vfs_inode_type_str( inode_type ), name,
[407]1125                  inode_ptr , mapper_ptr , inode_cxy );
[188]1126
1127    // scan directory entries 
1128    if( inode_type == INODE_TYPE_DIR )
1129    {
1130        // get extended pointer on directory entries xhtab
[204]1131        children_xp =  XPTR( inode_cxy , &inode_ptr->children );
[188]1132
1133        // get xhtab lock
[204]1134        xhtab_read_lock( children_xp );
[188]1135
1136        // get first dentry from xhtab
[204]1137        child_dentry_xp = xhtab_get_first( children_xp );
[188]1138
[204]1139        while( child_dentry_xp != XPTR_NULL )
[188]1140        {
1141            // get dentry cluster and local pointer
[204]1142            child_dentry_cxy = GET_CXY( child_dentry_xp );
1143            child_dentry_ptr = (vfs_dentry_t *)GET_PTR( child_dentry_xp );
[188]1144
1145            // get extended pointer on child inode
[204]1146            child_inode_xp = hal_remote_lwd( XPTR( child_dentry_cxy,
1147                                                   &child_dentry_ptr->child_xp ) );
[188]1148
1149            // get extended pointer on dentry name
[204]1150            child_dentry_name_xp = XPTR( child_dentry_cxy , &child_dentry_ptr->name );
[188]1151
1152            // recursive call on child inode
[204]1153            vfs_recursive_display( child_inode_xp,
1154                                   child_dentry_name_xp,
1155                                   child_dentry_xp,
1156                                   indent+1 );
[188]1157
1158            // get next dentry
[204]1159            child_dentry_xp = xhtab_get_next( children_xp );
[188]1160        }
1161
1162        // release xhtab lock
[204]1163        xhtab_read_unlock( children_xp );
[188]1164    }
1165}  // end vfs_recursive_display()
1166
1167///////////////////////////////////
1168void vfs_display( xptr_t inode_xp )
1169{
[204]1170    xptr_t         name_xp;
[188]1171    xptr_t         dentry_xp; 
1172    cxy_t          dentry_cxy;
1173    vfs_dentry_t * dentry_ptr;
[337]1174    uint32_t       save_sr;
[188]1175
1176    // get target inode cluster and local pointer
1177    cxy_t         inode_cxy = GET_CXY( inode_xp );
1178    vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
1179
1180    // get extended pointer on associated dentry
[367]1181    dentry_xp   = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
[188]1182
1183    // check if target inode is the File System root
1184    if( dentry_xp == XPTR_NULL )
1185    {
1186        // build extended pointer on root name
1187        name_xp = XPTR( local_cxy , "/" );
1188    }
1189    else
1190    {
1191        // get dentry cluster and local pointer
1192        dentry_cxy = GET_CXY( dentry_xp );
1193        dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
1194
1195        // get extended pointer on dentry name
1196        name_xp = XPTR( dentry_cxy , &dentry_ptr->name );
1197    }
1198
[337]1199    // get pointers on TXT0 chdev
[407]1200    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
[337]1201    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
1202    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
1203
1204    // get extended pointer on remote TXT0 chdev lock
1205    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
1206
1207    // get TXT0 lock in busy waiting mode
1208    remote_spinlock_lock_busy( lock_xp , &save_sr );
1209
[188]1210    // print header
[401]1211    nolock_printk("\n***** file system state\n\n");
[188]1212
1213    // call recursive function
[204]1214    vfs_recursive_display( inode_xp , name_xp , dentry_xp , 0 );
[188]1215
[337]1216    // release lock
1217    remote_spinlock_unlock_busy( lock_xp , save_sr );
1218
[204]1219}  // end vfs_display()
[188]1220
[1]1221//////////////////////////////////////////////////////////////////////////////////////////
[23]1222// This function is used by the vfs_lookup() function.
[1]1223// It takes an extended pointer on a remote inode (parent directory inode),
1224// and check access_rights violation for the calling thread.
1225// It can be used by any thread running in any cluster.
1226//////////////////////////////////////////////////////////////////////////////////////////
1227// @ inode_xp    : extended pointer on inode.
1228// @ client_uid  : client thread user ID
1229// @ client_gid  : client thread group ID
1230// @ return true if access rights are violated.
1231//////////////////////////////////////////////////////////////////////////////////////////
1232bool_t vfs_access_denied( xptr_t   inode_xp,
1233                          uint32_t client_uid,
1234                          uint32_t client_gid )
1235{
1236    // get found inode cluster and local pointer
1237    cxy_t         inode_cxy = GET_CXY( inode_xp );
1238    vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
1239
1240    // get inode access mode, UID, and GID
1241    // TODO uint32_t  mode = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->mode ) );
1242    uid_t     uid  = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->uid  ) );
1243    gid_t     gid  = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->gid  ) );
1244
1245    // FIXME : me must use mode
1246    if( (uid == client_uid) || (gid == client_gid) ) return false;
1247    else                                             return true;
1248}
1249
1250//////////////////////////////////////////////////////////////////////////////////////////
1251// This static function is used by the vfs_lookup() function.
[204]1252// It takes an extended pointer on a remote parent directory inode, a directory
[1]1253// entry name, and returns an extended pointer on the child inode.
1254// It can be used by any thread running in any cluster.
1255//////////////////////////////////////////////////////////////////////////////////////////
1256// @ parent_xp   : extended pointer on parent inode in remote cluster.
1257// @ name        : dentry name
1258// @ child_xp    : [out] buffer for extended pointer on child inode.
1259// @ return true if success / return false if not found.
1260//////////////////////////////////////////////////////////////////////////////////////////
1261static bool_t vfs_get_child( xptr_t   parent_xp,
1262                             char   * name,
1263                             xptr_t * child_xp )
1264{
1265    xptr_t  xhtab_xp;    // extended pointer on hash table containing children dentries
1266    xptr_t  dentry_xp;   // extended pointer on children dentry
1267
1268    // get parent inode cluster and local pointer
1269    cxy_t         parent_cxy = GET_CXY( parent_xp );
1270    vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
1271
1272    // get extended pointer on hash table of children directory entries
1273    xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
1274
1275    // search extended pointer on matching dentry
1276    dentry_xp = xhtab_lookup( xhtab_xp , name );
1277
1278    if( dentry_xp == XPTR_NULL ) return false;
1279
1280    // get dentry cluster and local pointer
1281    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
1282    vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
1283
1284    // return child inode
[101]1285    *child_xp = (xptr_t)hal_remote_lwd( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
[1]1286    return true;
1287
[204]1288}  // end vfs_get_child()
1289
[1]1290//////////////////////////////////////////////////////////////////////////////////////////
1291// This static function is used by the vfs_lookup() function.
1292// It takes the <current> pointer on a buffer containing a complete pathname, and return
1293// in the <name> buffer, allocated by the caller, a single name in the path.
1294// It return also in the <next> pointer the next character to analyse in the path.
1295// Finally it returns a <last> boolean, that is true when the returned <name> is the
1296// last name in the path. The names are supposed to be separated by one or several '/'
1297// characters, that are not written in  the <name> buffer.
1298//////////////////////////////////////////////////////////////////////////////////////////
1299// @ current   : pointer on first character to analyse in buffer containing the path.
1300// @ name      : [out] pointer on buffer allocated by the caller for the returned name.
1301// @ next      : [out] pointer on next character to analyse in buffer containing the path.
1302// @ last      : [out] true if the returned name is the last (NUL character found).
1303// @ return 0 if success / return EINVAL if string empty (first chracter is NUL).
1304//////////////////////////////////////////////////////////////////////////////////////////
1305static error_t vfs_get_name_from_path( char     * current,
1306                                       char     * name,
1307                                       char    ** next,
1308                                       bool_t   * last )
1309{
1310    char * ptr = current;
1311
1312    // skip leading '/' characters
1313    while( *ptr == '/' ) ptr++;
1314
1315    // return EINVAL if string empty
1316    if( *ptr == 0 ) return EINVAL;
1317
1318    // copy all characters in name until NUL or '/'
1319    while( (*ptr != 0) && (*ptr !='/') )  *(name++) = *(ptr++);
1320
[204]1321    // set NUL terminating character in name buffer
1322    *(name++) = 0;
1323
[1]1324    // return last an next
1325    if( *ptr == 0 )             // last found character is NUL => last name in path
1326    {
1327        *last = true;
1328    }
1329    else                        // last found character is '/' => skip it
1330    {
1331        *last = false;
1332        *next = ptr + 1;
1333    }
1334
1335    return 0;
[204]1336
1337}  // end vfs_get name_from_path()
[188]1338   
[23]1339//////////////////////////////////////////////
1340error_t vfs_lookup( xptr_t             cwd_xp,
1341                    char             * pathname,
1342                    uint32_t           mode,
1343                                        xptr_t           * inode_xp )
[1]1344{
[101]1345    char               name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path
[1]1346
[23]1347    xptr_t             parent_xp;    // extended pointer on parent inode
1348    cxy_t              parent_cxy;   // cluster for parent inode
1349    vfs_inode_t      * parent_ptr;   // local pointer on parent inode 
1350    xptr_t             child_xp;     // extended pointer on child inode
1351    cxy_t              child_cxy;    // cluster for child inode
1352    vfs_inode_t      * child_ptr;    // local pointer on child inode 
[238]1353    vfs_inode_type_t   child_type;   // child inode type
[23]1354    vfs_fs_type_t      fs_type;      // File system type
1355    vfs_ctx_t        * ctx_ptr;      // local pointer on FS context
1356    char             * current;      // current pointer on path
1357    char             * next;         // next value for current pointer   
1358    bool_t             last;         // true when the name is the last in path
1359    bool_t             found;        // true when a child has been found
1360    thread_t         * this;         // pointer on calling thread descriptor
1361    process_t        * process;      // pointer on calling process descriptor
1362    error_t            error;
[1]1363
1364    this    = CURRENT_THREAD;
1365    process = this->process;
1366
[438]1367#if DEBUG_VFS_LOOKUP
[433]1368uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1369if( DEBUG_VFS_LOOKUP < cycle )
[433]1370printk("\n[DBG] %s : thread %x enter for <%s> / cycle %d\n",
[436]1371__FUNCTION__, CURRENT_THREAD, pathname, cycle );
[433]1372#endif
[380]1373
[1]1374    // get extended pointer on first inode to search
1375    if( pathname[0] == '/' ) parent_xp = process->vfs_root_xp;
1376    else                     parent_xp = cwd_xp;
1377
[101]1378    // initialise other loop variables
[1]1379    current  = pathname;
1380    next     = NULL;
1381    last     = false;
1382    child_xp = XPTR_NULL;
1383
1384    // take lock on parent inode
[101]1385    vfs_inode_lock( parent_xp );
[1]1386
[401]1387    // sequencially loop on nodes in pathname
1388    // load from device if one node not found in inode tree
1389    // exit loop when last name found (i.e. last == true)
[1]1390    do
1391    {
[401]1392        // get one name from path, and "last" flag
[1]1393        vfs_get_name_from_path( current , name , &next , &last );
1394
[438]1395#if (DEBUG_VFS_LOOKUP & 1)
1396if( DEBUG_VFS_LOOKUP < cycle )
[433]1397printk("\n[DBG] %s : look for <%s> / last = %d\n", __FUNCTION__ , name , last );
1398#endif
[101]1399
[204]1400        // search a child dentry matching name in parent inode
[1]1401        found = vfs_get_child( parent_xp,
1402                               name,
1403                               &child_xp );
1404
[238]1405        // if a child inode is not found in the inode tree:
1406        // - we create the missing inode/dentry couple in the inode tree,
1407        // - we scan the parent mapper to complete the child inode (type and extension),
1408        // - we return an error if child not found on device.
1409        // - if the missing child is a directory, we load the child mapper from device
1410
1411        // for the last name, the behaviour depends on the "mode" argument:
1412
[246]1413        if (found == false ) // child node not found in inode tree
[1]1414        {
[101]1415
[438]1416#if (DEBUG_VFS_LOOKUP & 1)
1417if( DEBUG_VFS_LOOKUP < cycle )
[433]1418printk("\n[DBG] %s : miss <%s> => load it\n", __FUNCTION__ , name );
1419#endif
[407]1420
[1]1421            // release lock on parent inode
[101]1422            vfs_inode_unlock( parent_xp );
[1]1423
[238]1424            // get parent inode FS type
[23]1425            parent_cxy = GET_CXY( parent_xp );
1426            parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
[401]1427            ctx_ptr    = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
[238]1428            fs_type    = hal_remote_lw( XPTR( parent_cxy , &ctx_ptr->type ) );
[23]1429
[238]1430            // select a cluster for missing inode
1431            child_cxy = vfs_cluster_random_select();
[401]1432 
[188]1433            // insert a new child dentry/inode in parent inode
1434            error = vfs_add_child_in_parent( child_cxy,
[238]1435                                             INODE_TYPE_DIR,
[23]1436                                             fs_type, 
1437                                             parent_xp, 
[222]1438                                             name, 
[238]1439                                             NULL,     // fs_type_specific inode extend
[23]1440                                             &child_xp );
[1]1441            if( error )
1442            {
[441]1443                printk("\n[ERROR] in %s : thread %x cannot allocate inode for path <%s>\n",
1444                __FUNCTION__ , this , pathname );
[238]1445                return ENOMEM;
1446            }
1447
1448            // scan parent mapper to complete the missing inode
1449            if( parent_cxy == local_cxy )
1450            {
1451                error = vfs_inode_load( parent_ptr,
1452                                        name,
1453                                        child_xp );
1454            }
1455            else
1456            {
1457                rpc_vfs_inode_load_client( parent_cxy,
1458                                           parent_ptr,
1459                                           name,
1460                                           child_xp,
1461                                           &error );
1462            }
1463
1464            if ( error )
1465            {
[441]1466                printk("\n[ERROR] in %s : thread %x / <%s> node not found in <%s>\n",
1467                __FUNCTION__ , this , name , pathname );
[1]1468                return ENOENT;
1469            }
1470
[238]1471            // get child inode type
1472            child_ptr  = (vfs_inode_t *)GET_PTR( child_xp );
1473            child_type = hal_remote_lw( XPTR( child_cxy , &child_ptr->type ) );
1474
1475            // load child mapper from device if it is a directory
1476            if( child_type == INODE_TYPE_DIR )
1477            {
1478                if( child_cxy == local_cxy )
1479                {
1480                    error = vfs_mapper_load_all( child_ptr );
1481                }
1482                else
1483                {
1484                    rpc_vfs_mapper_load_all_client( child_cxy,
1485                                                    child_ptr,
1486                                                    &error );
1487                }
1488
1489                if ( error )
1490                {
[441]1491                    printk("\n[ERROR] in %s : thread %x / cannot access device for <%s>\n",
1492                    __FUNCTION__ , this , name );
[238]1493                    return EIO;
1494                }
1495            }
1496
1497            // TODO handle lookup mode here [AG]
1498
[1]1499            // take lock on parent inode
[101]1500            vfs_inode_lock( parent_xp );
[401]1501
[438]1502#if (DEBUG_VFS_LOOKUP & 1)
1503if( DEBUG_VFS_LOOKUP < cycle )
[433]1504printk("\n[DBG] %s : created node <%s>\n", __FUNCTION__ , name );
1505#endif
[407]1506
[1]1507        }
1508
[438]1509#if (DEBUG_VFS_LOOKUP & 1)
1510if( DEBUG_VFS_LOOKUP < cycle )
[433]1511printk("\n[DBG] %s : found <%s> / inode %x in cluster %x\n",
1512__FUNCTION__ , name , GET_PTR(child_xp) , GET_CXY(child_xp) );
1513#endif
[101]1514
[380]1515        // TODO check access rights here [AG]
[23]1516        // error = vfs_access_denied( child_xp,
1517        //                            client_uid,
1518        //                            client_gid );
1519        // if( error )
1520        // {
[441]1521        //     printk("\n[ERROR] in %s : thread %x / permission denied for %s\n",
1522        //     __FUNCTION__ , this , name );
[23]1523        //     return EACCES;
1524        // }
[1]1525
[238]1526        // take lock on child inode and release lock on parent
1527        vfs_inode_lock( child_xp );
[101]1528        vfs_inode_unlock( parent_xp );
[1]1529
1530        // update loop variables
1531        parent_xp = child_xp;
1532        current   = next;
1533    }
1534    while( last == false );
1535
[238]1536    // release lock
1537    vfs_inode_unlock( parent_xp );
[1]1538
[438]1539#if DEBUG_VFS_LOOKUP
[433]1540cycle = (uint32_t)hal_get_cycles();
[438]1541if( DEBUG_VFS_LOOKUP < cycle )
[433]1542printk("\n[DBG] %s : thread %x exit for <%s> / inode %x in cluster %x / cycle %d\n",
[436]1543__FUNCTION__, CURRENT_THREAD, pathname, GET_PTR(child_xp), GET_CXY(child_xp), cycle );
[433]1544#endif
[1]1545
[238]1546    // return searched pointer
[1]1547    *inode_xp = child_xp;
1548
1549    return 0;
1550
1551}  // end vfs_lookup()
1552
1553////////////////////////////////////////////
1554error_t vfs_get_path( xptr_t    searched_xp,
1555                      char    * buffer,
1556                      uint32_t  max_size )
1557{
1558        xptr_t       dentry_xp;   // extended pointer on current dentry
1559    char       * name;        // local pointer on current dentry name
1560        uint32_t     length;      // length of current dentry name
1561        uint32_t     count;       // number of characters written in buffer
1562        uint32_t     index;       // slot index in buffer
[23]1563    xptr_t       inode_xp;    // extended pointer on   
[1]1564
1565    // implementation note:
1566    // we use two variables "index" and "count" because the buffer
[401]1567    // is written in decreasing index order (from leaf to root)
[433]1568    // TODO  : handle conflict with a concurrent rename [AG]
1569    // FIXME : handle synchro in the loop  [AG]
[1]1570
1571        // set the NUL character in buffer / initialise buffer index and count
1572        buffer[max_size - 1] = 0;
1573        count    = 1;
1574    index    = max_size - 2;
1575
1576    // initialize current inode
1577    inode_xp  = searched_xp;
1578
1579    // exit when root inode found (i.e. dentry_xp == XPTR_NULL)
1580        do
1581    {
1582        // get inode cluster and local pointer
1583        cxy_t         inode_cxy = GET_CXY( inode_xp );
1584        vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
1585
1586        // get extended pointer on parent dentry               
1587        dentry_xp = (xptr_t)hal_remote_lwd( XPTR( inode_cxy , inode_ptr->parent_xp ) );
1588
1589        // get dentry cluster and local pointer
1590        cxy_t          dentry_cxy = GET_CXY( dentry_xp );
1591        vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
1592
1593        // get dentry name length and pointer
1594        length =  hal_remote_lw( XPTR( dentry_cxy , &dentry_ptr->length ) );
1595        name   = (char *)hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->name ) );
1596
1597        // update index and count
1598        index -= (length + 1); 
1599        count += (length + 1);
1600
1601        // check buffer overflow
1602        if( count >= max_size )
1603        {
1604            printk("\n[ERROR] in %s : kernel buffer too small\n", __FUNCTION__ );
1605            return EINVAL;
1606        }
1607
1608        // update pathname
1609        hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
1610                           XPTR( dentry_cxy , name ) , length );
1611                buffer[index] = '/';
1612
1613                // get extended pointer on next inode
1614        inode_xp = (xptr_t)hal_remote_lwd( XPTR( dentry_cxy , dentry_ptr->parent ) );
1615    }
1616    while( (dentry_xp != XPTR_NULL) );
1617
1618        return 0;
1619
1620}  // end vfs_get_path()
1621
[188]1622     
1623//////////////////////////////////////////////////////////////
1624error_t vfs_add_child_in_parent( cxy_t              child_cxy,
1625                                 vfs_inode_type_t   inode_type,
[23]1626                                 vfs_fs_type_t      fs_type,
1627                                 xptr_t             parent_xp,
1628                                 char             * name,
[188]1629                                 void             * extend,
[23]1630                                 xptr_t           * child_xp )
[1]1631{
[23]1632    error_t         error;
1633    xptr_t          dentry_xp;   // extended pointer on created dentry
1634    xptr_t          inode_xp;    // extended pointer on created inode
1635    cxy_t           parent_cxy;  // parent inode cluster identifier
1636    vfs_inode_t   * parent_ptr;  // parent inode local pointer
[1]1637
1638    // get parent inode cluster and local pointer
[23]1639    parent_cxy = GET_CXY( parent_xp );
1640    parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
[1]1641
[438]1642#if DEBUG_VFS_ADD_CHILD
[433]1643uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1644if( DEBUG_VFS_ADD_CHILD < cycle )
[433]1645printk("\n[DBG] %s : thread %x enter for <%s> / child_cxy = %x / parent_cxy = %x\n",
1646__FUNCTION__ , CURRENT_THREAD , name , child_cxy , parent_cxy );
1647#endif
[279]1648
[204]1649    // 1. create dentry
[1]1650    if( parent_cxy == local_cxy )      // parent cluster is the local cluster
1651    {
[23]1652        error = vfs_dentry_create( fs_type,
[1]1653                                   name,
1654                                   parent_ptr,
1655                                   &dentry_xp );
[279]1656
[438]1657#if (DEBUG_VFS_ADD_CHILD & 1)
1658if( (DEBUG_VFS_ADD_CHILD < cycle) && (error == 0) )
[433]1659printk("\n[DBG] %s : dentry <%s> created in cluster %x\n", __FUNCTION__, name, local_cxy );
1660#endif
[407]1661
[1]1662    }
1663    else                               // parent cluster is remote
1664    {
1665        rpc_vfs_dentry_create_client( parent_cxy,
[23]1666                                      fs_type,
[1]1667                                      name,
1668                                      parent_ptr,
1669                                      &dentry_xp,
1670                                      &error );
[279]1671
[438]1672#if (DEBUG_VFS_ADD_CHILD & 1)
1673if( (DEBUG_VFS_ADD_CHILD < cycle) && (error == 0) )
[433]1674printk("\n[DBG] %s : dentry <%s> created in cluster %x\n", __FUNCTION__, name, parent_cxy );
1675#endif
[407]1676
[1]1677    }
1678                                     
1679    if( error )
1680    {
[437]1681        printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n",
1682        __FUNCTION__ , name , parent_cxy );
[204]1683        return ENOMEM;
[1]1684    }
1685
[204]1686    // 2. create child inode TODO : define attr / mode / uid / gid
[1]1687    uint32_t attr = 0;
1688    uint32_t mode = 0;
1689    uint32_t uid  = 0;
1690    uint32_t gid  = 0;
1691   
1692    if( child_cxy == local_cxy )      // child cluster is the local cluster
1693    {
1694        error = vfs_inode_create( dentry_xp,
[23]1695                                  fs_type,
1696                                  inode_type,
[188]1697                                  extend,
[1]1698                                  attr,
1699                                  mode,
1700                                  uid,
1701                                  gid,
1702                                  &inode_xp );
[279]1703
[438]1704#if (DEBUG_VFS_ADD_CHILD & 1)
1705if( DEBUG_VFS_ADD_CHILD < cycle )
[433]1706printk("\n[DBG] %s : inode <%x> created in cluster %x\n",
1707__FUNCTION__ , GET_PTR(inode_xp) , local_cxy );
1708#endif
1709
[1]1710    }
1711    else                              // child cluster is remote
1712    {
1713        rpc_vfs_inode_create_client( child_cxy,
1714                                     dentry_xp,
[23]1715                                     fs_type,
1716                                     inode_type,
[188]1717                                     extend,
[1]1718                                     attr,
1719                                     mode,
1720                                     uid,
1721                                     gid,
1722                                     &inode_xp,
1723                                     &error );
[279]1724
[438]1725#if (DEBUG_VFS_ADD_CHILD & 1)
1726if( DEBUG_VFS_ADD_CHILD < cycle )
[433]1727printk("\n[DBG] %s : inode <%s> created in cluster %x\n",
[407]1728__FUNCTION__ , GET_PTR(inode_xp) , child_cxy );
[433]1729#endif
[407]1730
[1]1731    }
1732                                     
1733    if( error )
1734    {
1735        printk("\n[ERROR] in %s : cannot create inode in cluster %x\n",
1736               __FUNCTION__ , child_cxy );
1737 
1738        vfs_dentry_t * dentry = (vfs_dentry_t *)GET_PTR( dentry_xp );
1739        if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry );
1740        else rpc_vfs_dentry_destroy_client( parent_cxy , dentry );
[204]1741        return ENOMEM;
[1]1742    }
1743
[204]1744    // 3. update extended pointer on inode in dentry
1745    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
1746    vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
1747    hal_remote_swd( XPTR( dentry_cxy , &dentry_ptr->child_xp ) , inode_xp );
1748
[438]1749#if DEBUG_VFS_ADD_CHILD
[433]1750cycle = (uint32_t)hal_get_cycles();
[438]1751if( DEBUG_VFS_ADD_CHILD < cycle )
[433]1752printk("\n[DBG] %s : thread %x exit for <%s>\n",
1753__FUNCTION__ , CURRENT_THREAD , name );
1754#endif
[296]1755
[1]1756    // success : return extended pointer on child inode
1757    *child_xp = inode_xp;
1758    return 0;
1759
1760}  // end vfs_add_child_in_parent()
1761
[23]1762//////////////////////////////////////////////////////////////////////////////////////////
1763//            Mapper related functions
1764//////////////////////////////////////////////////////////////////////////////////////////
1765
[238]1766////////////////////////////////////////////
1767error_t vfs_mapper_move_page( page_t * page,
1768                              bool_t   to_mapper )
[23]1769{
[204]1770    error_t error = 0;
[23]1771
1772    assert( (page != NULL) , __FUNCTION__ , "page pointer is NULL\n" );
1773
[246]1774    mapper_t    * mapper = page->mapper;
[23]1775
1776    assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" );
1777
[438]1778#if DEBUG_VFS_MAPPER_MOVE
[433]1779uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1780if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]1781printk("\n[DBG] %s : thread %x enter for page %d / mapper %x / inode %x / cycle %d\n",
1782__FUNCTION__, CURRENT_THREAD, page->index, mapper, mapper->inode, cycle );
1783#endif
[246]1784
[23]1785    // get FS type
[246]1786    vfs_fs_type_t fs_type = mapper->type;
[23]1787
[238]1788    // call relevant FS function
[23]1789    if( fs_type == FS_TYPE_FATFS )
1790    {
1791        rwlock_wr_lock( &mapper->lock );
[246]1792        error = fatfs_mapper_move_page( page , to_mapper ); 
[23]1793        rwlock_wr_unlock( &mapper->lock );
1794    }
1795    else if( fs_type == FS_TYPE_RAMFS )
1796    {
1797        assert( false , __FUNCTION__ , "should not be called for RAMFS\n" );
1798    }
1799    else if( fs_type == FS_TYPE_DEVFS )
1800    {
1801        assert( false , __FUNCTION__ , "should not be called for DEVFS\n" );
1802    }
1803    else
1804    {
1805        assert( false , __FUNCTION__ , "undefined file system type\n" );
1806    }
1807
[438]1808#if DEBUG_VFS_MAPPER_MOVE
[433]1809cycle = (uint32_t)hal_get_cycles();
[438]1810if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]1811printk("\n[DBG] %s : thread %x exit for page %d / mapper %x / inode %x / cycle %d\n",
1812__FUNCTION__, CURRENT_THREAD, page->index, mapper, mapper->inode, cycle );
1813#endif
[246]1814
[23]1815    return error;
1816
[238]1817}  // end vfs_move_page()
[23]1818
1819//////////////////////////////////////////////////
[238]1820error_t vfs_mapper_load_all( vfs_inode_t * inode )
[23]1821{
[265]1822    assert( (inode != NULL) , __FUNCTION__ , "inode pointer is NULL\n" );
[23]1823
[238]1824    uint32_t   index;
1825    page_t   * page;
[23]1826
[238]1827    mapper_t * mapper = inode->mapper;
1828    uint32_t   size   = inode->size;
[23]1829
[265]1830    assert( (mapper != NULL) , __FUNCTION__ , "mapper pointer is NULL\n" );
[23]1831
[438]1832#if DEBUG_VFS_MAPPER_LOAD
[433]1833uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1834if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]1835printk("\n[DBG] %s : thread %x enter for inode %x in cluster %x / cycle %d\n",
1836__FUNCTION__, CURRENT_THREAD, inode, local_cxy, cycle );
1837#endif
[401]1838
1839    // compute number of pages
[238]1840    uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
[265]1841    if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++;
[238]1842
[265]1843    // loop on pages
[238]1844    for( index = 0 ; index < npages ; index ++ )
[23]1845    {
[238]1846        // this function allocates the missing page in mapper,
1847        // and call the vfs_mapper_move_page() to load the page from device
1848        page = mapper_get_page( mapper , index );
[23]1849
[238]1850        if( page == NULL ) return EIO;
[23]1851    }
1852
[438]1853#if DEBUG_VFS_MAPPER_LOAD
[433]1854cycle = (uint32_t)hal_get_cycles();
[438]1855if( DEBUG_VFS_MAPPER_MOVE < cycle )
[433]1856printk("\n[DBG] %s : thread %x exit for inode %x in cluster %x / cycle %d\n",
1857__FUNCTION__, CURRENT_THREAD, inode, local_cxy, cycle );
1858#endif
[401]1859
[238]1860    return 0;
[23]1861
[238]1862}  // end vfs_mapper_load_all()
[23]1863
Note: See TracBrowser for help on using the repository browser.