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

Last change on this file since 535 was 530, checked in by nicolas.van.phan@…, 6 years ago

Hack to compile on both IOB and LETI for now

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