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

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

1) introduce a dev_ioc_sync_write() function in IOC API,

to improve the DEVFS synchronous update.

2) fix a big bug in both the user_dir_create() and user_dir_destroy()

functions: add an extended pointer on the reference client process
in the function's arguments.

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