Changeset 610 for trunk


Ignore:
Timestamp:
Dec 27, 2018, 7:38:58 PM (3 years ago)
Author:
alain
Message:

Fix several bugs in VFS to support the following
ksh commandis : cp, mv, rm, mkdir, cd, pwd

Location:
trunk
Files:
58 edited

Legend:

Unmodified
Added
Removed
  • trunk/Makefile

    r590 r610  
    119119        mmd                     -o -i $(DISK_IMAGE) ::/bin/user    || true
    120120        mmd                     -o -i $(DISK_IMAGE) ::/home        || true
     121        mcopy           -o -i $(DISK_IMAGE) Makefile ::/home
    121122        mdir             -/ -b -i $(DISK_IMAGE) ::/
    122        
     123
    123124##############################################################
    124125# Rules to generate hardware description files (hard_config.h,
  • trunk/boot/tsar_mips32/boot.ld

    r572 r610  
    1 /**********************************************************************************************
    2  * This is the linker script for the ALMOS-MK boot-loader used for the TSAR architecture.
    3  * It describes the memory layout for the 'boot.elf' binary file.
    4  *********************************************************************************************/
     1/*******************************************************************
     2 * This is the linker script for the ALMOS-MKH boot-loader,
     3 * to generate the 'boot.elf' file used for the TSAR architecture.
     4 *******************************************************************/
    55
    66/* define the boot code base address */
     
    88boot_code_base = 0x100000;
    99
    10 /* Set the entry point of the boot-loader (e_entry field in the "boot.elf" file header) */
     10/* Set the entry point of the boot-loader */
     11/* (e_entry field in the "boot.elf" file header) */
    1112
    1213ENTRY(boot_entry)
  • trunk/hal/tsar_mips32/core/hal_exception.c

    r587 r610  
    158158// This function is called when an MMU exception has been detected (IBE / DBE).
    159159// It get the relevant exception arguments from the MMU.
    160 // It signal a fatal error in case of illegal access. In case of page unmapped
    161 // it checks that the faulty address belongs to a registered vseg. It update the local
     160// It signal a fatal error in case of illegal access. In case of page unmapped,
     161// it get the client process to access the relevant VMM: for a RPC thread, the client
     162// process is NOT the calling thread process.
     163// Then, it checks that the faulty address belongs to a registered vseg, update the local
    162164// vseg list from the reference cluster if required, and signal a fatal user error
    163165// in case of illegal virtual address. Finally, it updates the local page table from the
     
    183185    uint32_t         bad_vaddr;
    184186    uint32_t         excp_code;
    185        
     187
     188    // check thread type
     189    if( CURRENT_THREAD->type != THREAD_USER )
     190    {
     191        printk("\n[KERNEL PANIC] in %s : illegal thread type %s\n",
     192        __FUNCTION__, thread_type_str(CURRENT_THREAD->type) );
     193
     194        return EXCP_KERNEL_PANIC;
     195    }
     196
     197    // get faulty thread process 
    186198    process = this->process;
    187199
     
    207219uint32_t cycle = (uint32_t)hal_get_cycles();
    208220if( DEBUG_HAL_EXCEPTIONS < cycle )
    209 printk("\n[DBG] %s : thread[%x,%x] enter / is_ins %d / %s / vaddr %x / cycle %d\n",
    210 __FUNCTION__, process->pid, this->trdid,
     221printk("\n[%s] thread[%x,%x] on core [%x,%x] enter / is_ins %d / %s / vaddr %x / cycle %d\n",
     222__FUNCTION__, process->pid, this->trdid, local_cxy, this->core->lid,
    211223is_ins, hal_mmu_exception_str(excp_code), bad_vaddr, cycle);
    212224#endif
     
    215227    switch( excp_code )
    216228    {
    217         case MMU_WRITE_PT1_UNMAPPED:      // non fatal
    218         case MMU_WRITE_PT2_UNMAPPED:
    219         case MMU_READ_PT1_UNMAPPED:
    220         case MMU_READ_PT2_UNMAPPED:
     229        case MMU_WRITE_PT1_UNMAPPED:      // can be non fatal
     230        case MMU_WRITE_PT2_UNMAPPED:      // can be non fatal
     231        case MMU_READ_PT1_UNMAPPED:       // can be non fatal
     232        case MMU_READ_PT2_UNMAPPED:       // can be non fatal
    221233        {
    222234            // try to map the unmapped PTE
     
    230242cycle = (uint32_t)hal_get_cycles();
    231243if( DEBUG_HAL_EXCEPTIONS < cycle )
    232 printk("\n[DBG] %s : thread[%x,%x] exit / page-fault handled for vaddr = %x\n",
    233 __FUNCTION__, process->pid, this->trdid, bad_vaddr );
     244printk("\n[%s] thread[%x,%x] on core [%x,%x] exit / page-fault handled for vaddr = %x\n",
     245__FUNCTION__, process->pid, this->trdid, local_cxy, this->core->lid, bad_vaddr );
    234246#endif
    235247 
     
    238250            else if( error == EXCP_USER_ERROR )      // illegal vaddr
    239251            {
    240                 printk("\n[USER ERROR] in %s for thread %x in process %x\n"
    241                 "   illegal vaddr = %x / is_ins %d / epc %x\n",
    242                 __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
     252                printk("\n[USER ERROR] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     253                "  %s : epc %x / badvaddr %x / is_ins %d\n",
     254                __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     255                this->core->lid, (uint32_t)hal_get_cycles(),
     256                hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
    243257
    244258                        return EXCP_USER_ERROR;
     
    246260            else  // error == EXCP_KERNEL_PANIC 
    247261            {
    248                 printk("\n[KERNEL ERROR] in %s for thread %x in process %x\n"
    249                 "   no memory to map vaddr = %x / is_ins %d / epc %x\n",
    250                 __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
     262                printk("\n[KERNEL PANIC] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     263                "  %s : epc %x / badvaddr %x / is_ins %d\n",
     264                __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     265                this->core->lid, (uint32_t)hal_get_cycles(),
     266                hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
    251267
    252268                        return EXCP_KERNEL_PANIC;
    253269            }
    254270        }
    255         case MMU_WRITE_PRIVILEGE_VIOLATION:  // illegal access user error
    256         case MMU_READ_PRIVILEGE_VIOLATION:
    257         {
    258             printk("\n[USER ERROR] in %s : thread %x in process %x\n"
    259             "   illegal user access to vaddr = %x / is_ins %d / epc %x\n",
    260             __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
     271        case MMU_WRITE_PRIVILEGE_VIOLATION:  // illegal user error
     272        case MMU_READ_PRIVILEGE_VIOLATION:   // illegal
     273        {
     274            printk("\n[USER ERROR] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     275            "  %s : epc %x / badvaddr %x / is_ins %d\n",
     276            __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     277            this->core->lid, (uint32_t)hal_get_cycles(),
     278            hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
    261279
    262280            return EXCP_USER_ERROR;
    263281        }
    264         case MMU_WRITE_ACCESS_VIOLATION:     // user error, or Copy-on-Write
    265         {
    266             // access page table to get GPT_COW flag
    267             bool_t cow = hal_gpt_pte_is_cow( &(process->vmm.gpt),
    268                                              bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );
    269 
    270             if( cow )                        // Copy-on-Write
    271             {
    272                 // try to allocate and copy the page
    273                 error = vmm_handle_cow( process,
    274                                         bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );
    275 
    276                 if( error == EXCP_NON_FATAL )        // Copy on write successfull
    277                 {
     282        case MMU_WRITE_ACCESS_VIOLATION:    // can be non fatal if COW
     283        {
     284            // try to handle a possible COW
     285            error = vmm_handle_cow( process,
     286                                    bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );
     287
     288            if( error == EXCP_NON_FATAL )        // COW successfully handled
     289            {
    278290
    279291#if DEBUG_HAL_EXCEPTIONS
    280292cycle = (uint32_t)hal_get_cycles();
    281293if( DEBUG_HAL_EXCEPTIONS < cycle )
    282 printk("\n[DBG] %s : thread[%x,%x] exit / copy-on-write handled for vaddr = %x\n",
     294printk("\n[%s] thread[%x,%x] exit / copy-on-write handled for vaddr = %x\n",
    283295__FUNCTION__, process->pid, this->trdid, bad_vaddr );
    284296#endif
    285 
    286                     return EXCP_NON_FATAL;
    287                 }
    288                 else if( error == EXCP_USER_ERROR )  // illegal user access
    289                 {
    290                     printk("\n[USER ERROR] in %s : thread %x in process %x\n"
    291                     "   cannot cow vaddr = %x / is_ins %d / epc %x\n",
    292                     __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
     297                return EXCP_NON_FATAL;
     298            }
     299            else if( error == EXCP_USER_ERROR )  // illegal write access
     300            {
     301                    printk("\n[USER ERROR] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     302                    "  %s : epc %x / badvaddr %x / is_ins %d\n",
     303                    __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     304                    this->core->lid, (uint32_t)hal_get_cycles(),
     305                    hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
    293306
    294307                            return EXCP_USER_ERROR;
    295                 }
    296                 else   // error == EXCP_KERNEL_PANIC
    297                 {
    298                     printk("\n[KERNEL ERROR] in %s : thread %x in process %x\n"
    299                     "   no memoty to cow vaddr = %x / is_ins %d / epc %x\n",
    300                     __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
    301 
    302                             return EXCP_USER_ERROR;
    303                 }
    304308            }
    305             else                             // non writable user error
    306             {
    307                 printk("\n[USER ERROR] in %s : thread %x in process %x\n"
    308                 "   non-writable vaddr = %x / is_ins %d / epc %x\n",
    309                 __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
    310 
    311                 return EXCP_USER_ERROR;
     309            else   // error == EXCP_KERNEL_PANIC
     310            {
     311                printk("\n[KERNEL PANIC] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     312                "  %s : epc %x / badvaddr %x / is_ins %d\n",
     313                __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     314                this->core->lid, (uint32_t)hal_get_cycles(),
     315                hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
     316
     317                        return EXCP_USER_ERROR;
    312318            }
    313319        }
    314320        case MMU_READ_EXEC_VIOLATION:        // user error
    315321        {
    316             printk("\n[USER_ERROR] in %s : thread %x in process %x\n"
    317             "   non-executable vaddr = %x / is_ins %d / epc %x\n",
    318             __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
     322            printk("\n[USER ERROR] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     323            "  %s : epc %x / badvaddr %x / is_ins %d\n",
     324            __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     325            this->core->lid, (uint32_t)hal_get_cycles(),
     326            hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
    319327
    320328            return EXCP_USER_ERROR;
     
    322330        default:                             // this is a kernel error   
    323331        {
    324             printk("\n[KERNEL ERROR] in %s : thread %x in process %x\n"
    325             "  epc %x / badvaddr %x / is_ins %d\n",
    326             __FUNCTION__, this->trdid, this->process->pid, excPC, bad_vaddr, is_ins );
     332            printk("\n[KERNEL PANIC] in %s : thread[%x,%x] on core[%x,%x] / cycle %d\n"
     333            "  %s : epc %x / badvaddr %x / is_ins %d\n",
     334            __FUNCTION__, this->process->pid, this->trdid, local_cxy,
     335            this->core->lid, (uint32_t)hal_get_cycles(),
     336            hal_mmu_exception_str(excp_code), excPC, bad_vaddr, is_ins );
    327337
    328338            return EXCP_KERNEL_PANIC;
     
    359369    if( error == EXCP_USER_ERROR )
    360370    {
    361         nolock_printk("\n=== USER ERROR / trdid %x / pid %x / core[%x,%d] / cycle %d ===\n",
    362         this->trdid, process->pid, local_cxy, core->lid , (uint32_t)hal_get_cycles() );
     371        nolock_printk("\n=== USER ERROR / thread(%x,%x) / core[%d] / cycle %d ===\n",
     372        process->pid, this->trdid, core->lid, (uint32_t)hal_get_cycles() );
    363373    }
    364374    else
    365375    {
    366         nolock_printk("\n=== KERNEL ERROR / trdid %x / pid %x / core[%x,%d] / cycle %d ===\n",
    367         this->trdid, process->pid, local_cxy, core->lid , (uint32_t)hal_get_cycles() );
     376        nolock_printk("\n=== KERNEL PANIC / thread(%x,%x) / core[%d] / cycle %d ===\n",
     377        process->pid, this->trdid, core->lid, (uint32_t)hal_get_cycles() );
    368378    }
    369379
     
    400410}  // end hal_exception_dump()
    401411
    402 ///////////////////////
     412/////////////////////////////
    403413void hal_do_exception( void )
    404414{
     
    420430uint32_t cycle = (uint32_t)hal_get_cycles();
    421431if( DEBUG_HAL_EXCEPTIONS < cycle )
    422 printk("\n[DBG] %s : thread %x in process %x enter / core[%x,%d] / epc %x / xcode %x / cycle %d\n",
    423 __FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid, excPC, excCode, cycle );
     432printk("\n[%s] thread[%x,%x] enter / core[%x,%d] / epc %x / xcode %x / cycle %d\n",
     433__FUNCTION__, this->process->pid, this->trdid,
     434local_cxy, this->core->lid, excPC, excCode, cycle );
    424435#endif
    425436
     
    473484        {
    474485            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
    475             "   illegal data load address / epc %x\n",
    476             __FUNCTION__, this->trdid, this->process->pid, excPC );
     486            "   illegal data load address / epc %x / bad_address %x\n",
     487            __FUNCTION__, this->trdid, this->process->pid, excPC, hal_get_bad_vaddr() );
    477488
    478489                    error = EXCP_USER_ERROR;
     
    482493        {
    483494            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
    484             "   illegal data store address / epc %x\n",
    485             __FUNCTION__, this->trdid, this->process->pid, excPC );
     495            "   illegal data store address / epc %x / bad_address %x\n",
     496            __FUNCTION__, this->trdid, this->process->pid, excPC, hal_get_bad_vaddr() );
    486497
    487498                    error = EXCP_USER_ERROR;
     
    505516        hal_exception_dump( this , uzone , error );
    506517
    507         assert( false , "Exception raised kernel panic see information below.\n" );
     518        hal_core_sleep();
    508519    }
    509520
     
    511522cycle = (uint32_t)hal_get_cycles();
    512523if( DEBUG_HAL_EXCEPTIONS < cycle )
    513 printk("\n[DBG] %s : thread %x in process %x exit / core[%x,%d] / epc %x / xcode %x / cycle %d\n",
    514 __FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid, excPC, excCode, cycle );
     524printk("\n[%s] thread[%x,%x] exit / core[%x,%d] / epc %x / xcode %x / cycle %d\n",
     525__FUNCTION__, this->process->pid, this->trdid,
     526local_cxy, this->core->lid, excPC, excCode, cycle );
    515527#endif
    516528
  • trunk/hal/tsar_mips32/core/hal_ppm.c

    r570 r610  
    22 * hal_ppm.c - Generic Physical Page Manager API implementation for TSAR
    33 *
    4  * Authors  Alain Greiner (2016,2017)
     4 * Authors  Alain Greiner (2016,2017,2018)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    6363
    6464        // initialize lock protecting the dirty_pages list
    65         queuelock_init( &ppm->dirty_lock , LOCK_PPM_DIRTY );
     65        remote_queuelock_init( XPTR( local_cxy , &ppm->dirty_lock ) , LOCK_PPM_DIRTY );
    6666
    6767        // initialize all free_pages[] lists as empty
  • trunk/hal/tsar_mips32/core/hal_remote.c

    r570 r610  
    381381    uint32_t scxy = (uint32_t)GET_CXY( src );
    382382
     383/*
     384if( local_cxy == 1 )
     385printk("\n@@@ %s : scxy %x / sptr %x / dcxy %x / dptr %x\n",
     386__FUNCTION__, scxy, sptr, dcxy, dptr );
     387*/
    383388    hal_disable_irq( &save_sr );
    384389
  • trunk/hal/tsar_mips32/core/hal_uspace.c

    r457 r610  
    4343    uint32_t dst = (uint32_t)k_dst;
    4444
     45#if DEBUG_HAL_USPACE
     46thread_t * this = CURRENT_THREAD;
     47printk("\n[%s] thread[%x,%x] enter in cluster %x / u_src %x / k_dst %x / size %d\n",
     48__FUNCTION__, this->process->pid, this->trdid, local_cxy, u_src, k_dst, size );
     49#endif
     50
    4551        if( (dst & 0x3) || (src & 0x3) ) wsize = 0;          // do it all in bytes
    4652    else                             wsize = size >> 2;
     
    8086
    8187    hal_restore_irq( save_sr );
     88
     89#if DEBUG_HAL_USPACE
     90printk("\n[%s] thread[%x,%x] exit\n",
     91__FUNCTION__, this->process->pid, this->trdid );
     92#endif
    8293
    8394}  // end hal_copy_from_uspace()
     
    94105    uint32_t dst = (uint32_t)u_dst;
    95106
     107#if DEBUG_HAL_USPACE
     108thread_t * this = CURRENT_THREAD;
     109printk("\n[%s] thread[%x,%x] enter in cluster %x / k_src %x / u_dst %x / size %d\n",
     110__FUNCTION__, this->process->pid, this->trdid, local_cxy, k_src, u_dst, size );
     111#endif
     112
    96113        if( (dst & 0x3) || (src & 0x3) ) wsize = 0;          // not aligned
    97114    else                             wsize = size >> 2;
     
    118135        asm volatile(
    119136        "mfc2   $15,   $1           \n"   /* save   MMU_MODE                */
    120         "lw         $13,   0(%0)        \n"   /* read data from kernel space    */
     137        "lb         $13,   0(%0)        \n"   /* read data from kernel space    */
    121138        "ori    $14,   $0,  0x7     \n" 
    122139        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
     
    130147
    131148    hal_restore_irq( save_sr );
     149
     150#if DEBUG_HAL_USPACE
     151printk("\n[%s] thread[%x,%x] exit\n",
     152__FUNCTION__, this->process->pid, this->trdid );
     153#endif
    132154
    133155}  // end hal_copy_to_uspace()
  • trunk/hal/tsar_mips32/drivers/soclib_bdv.c

    r570 r610  
    3232void soclib_bdv_init( chdev_t * chdev )
    3333{
    34     // get extended pointer on SOCLIB_BDV peripheral base address
     34    // get extended pointer on SOCLIB_BDV peripheral base
    3535        xptr_t  bdv_xp = chdev->base;
    3636
     
    6262    xptr_t     buf_xp;
    6363    xptr_t     ioc_xp;
     64    uint32_t   status;      // I/0 operation status (from BDV)
     65    reg_t      save_sr;     // for critical section
     66    uint32_t   op;          // BDV_OP_READ / BDV_OP_WRITE
    6467
    6568    // get client thread cluster and local pointer
     
    6770    thread_t * th_ptr = GET_PTR( th_xp );
    6871
     72#if (DEBUG_HAL_IOC_RX || DEBUG_HAL_IOC_TX)
     73uint32_t    cycle        = (uint32_t)hal_get_cycles();
     74thread_t  * this         = CURRENT_THREAD;
     75process_t * process      = hal_remote_lpt( XPTR( th_cxy , &th_ptr->process ) );
     76pid_t       client_pid   = hal_remote_l32( XPTR( th_cxy , &process->pid ) );
     77trdid_t     client_trdid = hal_remote_l32( XPTR( th_cxy , &th_ptr->trdid ) );
     78#endif
     79
    6980    // get command arguments and extended pointer on IOC device
    70     cmd_type =         hal_remote_l32 ( XPTR( th_cxy , &th_ptr->ioc_cmd.type   ) );
    71     lba      =         hal_remote_l32 ( XPTR( th_cxy , &th_ptr->ioc_cmd.lba    ) );
    72     count    =         hal_remote_l32 ( XPTR( th_cxy , &th_ptr->ioc_cmd.count  ) );
     81    cmd_type =         hal_remote_l32( XPTR( th_cxy , &th_ptr->ioc_cmd.type   ) );
     82    lba      =         hal_remote_l32( XPTR( th_cxy , &th_ptr->ioc_cmd.lba    ) );
     83    count    =         hal_remote_l32( XPTR( th_cxy , &th_ptr->ioc_cmd.count  ) );
    7384    buf_xp   = (xptr_t)hal_remote_l64( XPTR( th_cxy , &th_ptr->ioc_cmd.buf_xp ) );
    7485    ioc_xp   = (xptr_t)hal_remote_l64( XPTR( th_cxy , &th_ptr->ioc_cmd.dev_xp ) );
    7586
    7687#if DEBUG_HAL_IOC_RX
    77 uint32_t cycle = (uint32_t)hal_get_cycles();
    7888if( (DEBUG_HAL_IOC_RX < cycle) && (cmd_type != IOC_WRITE ) )
    79 printk("\n[DBG] %s : thread %x enter for RX / cycle %d\n",
    80 __FUNCTION__ , CURRENT_THREAD , cycle );
    81 #endif
    82 
    83 #if DEBUG_HAL_IOC_TX
    84 uint32_t cycle = (uint32_t)hal_get_cycles();
     89printk("\n[%s] thread[%x,%x] enters for client thread[%x,%x] / RX / cycle %d\n",
     90__FUNCTION__ , this->process->pid, this->trdid, client_pid, client_trdid, cycle );
     91#endif
     92
     93#if DEBUG_HAL_IOC_TX
    8594if( (DEBUG_HAL_IOC_TX < cycle) && (cmd_type == IOC_WRITE) )
    86 printk("\n[DBG] %s : thread %x enter for TX / cycle %d\n",
    87 __FUNCTION__ , CURRENT_THREAD , cycle );
     95printk("\n[%s] thread[%x,%x] enters for client thread[%x,%x] / TX / cycle %d\n",
     96__FUNCTION__ , this->process->pid, this->trdid, client_pid, client_trdid, cycle );
    8897#endif
    8998
     
    101110    uint32_t   buf_msb = (uint32_t)(buf_xp>>32);
    102111
    103     // set operation
    104     uint32_t   op;
     112    // select operation
    105113    if( cmd_type == IOC_WRITE ) op = BDV_OP_WRITE;
    106114    else                        op = BDV_OP_READ;
    107115
    108     // set SOCLIB_BDV registers to start one I/O operation
     116    // set SOCLIB_BDV registers to configure the I/O operation
    109117    hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_IRQ_ENABLE_REG ) , 1       );
    110118    hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_BUFFER_REG     ) , buf_lsb );
     
    112120    hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_LBA_REG        ) , lba     );
    113121    hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_COUNT_REG      ) , count   );
    114     hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_OP_REG         ) , op      );
    115122
    116123    // waiting policy  depends on the command type
    117124    // - for IOC_READ / IOC_WRITE commands, this function is called by the server thread
    118     // - for IOC_SYNC_READ command, this function is directly called by the client thread
     125    //   that blocks and deschedules after launching the I/O transfer.
     126    //   The I/O operation status is reported in the command by the ISR.
     127    // - for IOC_SYNC_READ command, this function is called by the client thread
     128    //   that polls the BDV status register until I/O transfer completion.
    119129
    120130    if( cmd_type == IOC_SYNC_READ )                   // status polling policy
    121131    {
    122         uint32_t status;
     132        // launch I/O operation on BDV device
     133        hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_OP_REG ) , op );
     134       
     135        // wait completion
    123136        while (1)
    124137        {
     
    143156    else                                            // descheduling + IRQ policy
    144157    {
     158        // enter critical section to atomically
     159        // lauch I/O operation and deschedule 
     160        hal_disable_irq( &save_sr );
     161
     162        // launch I/O operation on BDV device
     163        hal_remote_s32( XPTR( seg_cxy , seg_ptr + BDV_OP_REG ) , op );
     164       
     165        // server thread blocks on ISR
    145166        thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
     167
     168#if DEBUG_HAL_IOC_RX
     169if( (DEBUG_HAL_IOC_RX < cycle) && (cmd_type != IOC_WRITE ) )
     170printk("\n[%s] thread[%x,%x] blocks & deschedules after lauching RX transfer\n",
     171__FUNCTION__ , this->process->pid, this->trdid );
     172#endif
     173
     174#if DEBUG_HAL_IOC_TX
     175if( (DEBUG_HAL_IOC_TX < cycle) && (cmd_type == IOC_WRITE) )
     176printk("\n[%s] thread[%x,%x] blocks & deschedules after lauching TX transfer\n",
     177__FUNCTION__ , this->process->pid, this->trdid );
     178#endif
     179        // server thread deschedules
    146180        sched_yield("blocked on ISR");
    147181
    148         // the IO operation status is reported in the command by the ISR
     182        // exit critical section
     183        hal_restore_irq( save_sr );
    149184    }
    150185   
    151186#if DEBUG_HAL_IOC_RX
    152187cycle = (uint32_t)hal_get_cycles();
    153 if( (DEBUG_HAL_IOC_RX < cycle) && (cmd_type != TXT_WRITE) )
    154 printk("\n[DBG] %s : thread %x exit after RX / cycle %d\n",
    155 __FUNCTION__ , CURRENT_THREAD , cycle );
     188if( (DEBUG_HAL_IOC_RX < cycle) && (cmd_type != IOC_WRITE) )
     189printk("\n[%s] thread[%x,%x] exit after RX for client thread[%x,%x] / cycle %d\n",
     190__FUNCTION__, this->process->pid, this->trdid, client_pid, client_trdid, cycle );
    156191#endif
    157192
    158193#if DEBUG_HAL_IOC_TX
    159194cycle = (uint32_t)hal_get_cycles();
    160 if( (DEBUG_HAL_IOC_TX < cycle) && (cmd_type == TXT_WRITE) )
    161 printk("\n[DBG] %s : thread %x exit after TX / cycle %d\n",
    162 __FUNCTION__ , CURRENT_THREAD , cycle );
     195if( (DEBUG_HAL_IOC_TX < cycle) && (cmd_type == IOC_WRITE) )
     196printk("\n[%s] thread[%x,%x] exit after TX for client thread[%x,%x] / cycle %d\n",
     197__FUNCTION__, this->process->pid, this->trdid, client_pid, client_trdid, cycle );
    163198#endif
    164199
     
    171206    error_t  error = 0;
    172207
     208    // get extended pointer on server thread
     209    xptr_t server_xp = XPTR( local_cxy , chdev->server );
     210
    173211    // get extended pointer on client thread
    174     xptr_t root = XPTR( local_cxy , &chdev->wait_root );
     212    xptr_t root      = XPTR( local_cxy , &chdev->wait_root );
    175213    xptr_t client_xp = XLIST_FIRST( root , thread_t , wait_list );
    176 
    177     // get extended pointer on server thread
    178     xptr_t server_xp = XPTR( local_cxy , &chdev->server );
    179214
    180215    // get client thread cluster and local pointer
    181216    cxy_t      client_cxy = GET_CXY( client_xp );
    182     thread_t * client_ptr = (thread_t *)GET_PTR( client_xp );
     217    thread_t * client_ptr = GET_PTR( client_xp );
    183218
    184219    // get command type
    185220    uint32_t   cmd_type = hal_remote_l32( XPTR( client_cxy , &client_ptr->ioc_cmd.type ) );
    186221   
     222#if (DEBUG_HAL_IOC_RX || DEBUG_HAL_IOC_TX)
     223uint32_t    cycle        = (uint32_t)hal_get_cycles();
     224process_t * process      = hal_remote_lpt( XPTR( client_cxy , &client_ptr->process ) );
     225pid_t       client_pid   = hal_remote_l32( XPTR( client_cxy , &process->pid ) );
     226trdid_t     client_trdid = hal_remote_l32( XPTR( client_cxy , &client_ptr->trdid ) );
     227thread_t  * server       = GET_PTR( server_xp );
     228pid_t       server_pid   = server->process->pid;
     229trdid_t     server_trdid = server->trdid;
     230#endif
     231
    187232    // get SOCLIB_BDV device cluster and local pointer
    188233    cxy_t      bdv_cxy  = GET_CXY( chdev->base );
    189     uint32_t * bdv_ptr  = (uint32_t *)GET_PTR( chdev->base );
     234    uint32_t * bdv_ptr  = GET_PTR( chdev->base );
    190235
    191236    // get BDV status register and acknowledge IRQ
     
    197242
    198243#if DEBUG_HAL_IOC_RX
    199 uint32_t cycle = (uint32_t)hal_get_cycles();
    200244if( DEBUG_HAL_IOC_RX < cycle )
    201 printk("\n[DBG] %s : IOC_IRQ / RX transfer / client %x / server %x / cycle %d\n",
    202 __FUNCTION__, client_ptr , chdev->server , cycle );
     245printk("\n[%s] RX transfer completed for client[%x,%x] / server[%x,%x] / cycle %d\n",
     246__FUNCTION__, client_pid, client_trdid, server_pid, server_trdid, cycle );
    203247#endif
    204248
     
    209253
    210254#if DEBUG_HAL_IOC_TX
    211 uint32_t cycle = (uint32_t)hal_get_cycles();
    212255if( DEBUG_HAL_IOC_TX < cycle )
    213 printk("\n[DBG] %s : IOC_IRQ / RX transfer / client %x / server %x / cycle %d\n",
    214 __FUNCTION__, client_ptr , chdev->server , cycle );
     256printk("\n[%s] TX transfer completed for client[%x,%x] / server[%x,%x] / cycle %d\n",
     257__FUNCTION__, client_pid, client_trdid, server_pid, server_trdid, cycle );
    215258#endif
    216259
  • trunk/kernel/Makefile

    r590 r610  
    138138              build/syscalls/sys_condvar.o         \
    139139              build/syscalls/sys_barrier.o         \
    140               build/syscalls/sys_mutex.o
    141 
    142 SYS_OBJS_1  = build/syscalls/sys_exit.o            \
     140              build/syscalls/sys_mutex.o 
     141
     142SYS_OBJS_1  = build/syscalls/sys_rename.o          \
    143143              build/syscalls/sys_munmap.o          \
    144144              build/syscalls/sys_open.o            \
     
    183183              build/syscalls/sys_fg.o              \
    184184              build/syscalls/sys_is_fg.o
     185
     186SYS_OBJS_5  = build/syscalls/sys_exit.o
    185187
    186188VFS_OBJS    = build/fs/vfs.o              \
     
    292294                        $(SYS_OBJS_3)                \
    293295                        $(SYS_OBJS_4)                \
     296                        $(SYS_OBJS_5)                \
    294297                        $(HAL_ARCH)/kernel.ld
    295298        $(LD) -o $@ -T $(HAL_ARCH)/kernel.ld $(LIBGCC)         \
     
    297300          $(LIBK_OBJS) $(DRIVERS_OBJS) $(VFS_OBJS)         \
    298301          $(SYS_OBJS_0) $(SYS_OBJS_1) $(SYS_OBJS_2)        \
    299           $(SYS_OBJS_3) $(SYS_OBJS_4) -lgcc
     302          $(SYS_OBJS_3) $(SYS_OBJS_4) $(SYS_OBJS_5) -lgcc
    300303        $(DU) -D $@ > $@.txt
    301304
  • trunk/kernel/fs/devfs.c

    r602 r610  
    9393    xptr_t   unused_xp;   // required by vfs_add_child_in_parent()
    9494
    95     // creates DEVFS "dev" inode in cluster 0
     95    // create DEVFS "dev" inode in cluster 0
    9696    error = vfs_add_child_in_parent( 0,                // cxy
    9797                                     INODE_TYPE_DIR,
     
    102102                                     devfs_dev_inode_xp );
    103103
    104     assert( (error == 0) , "cannot create <dev>\n" );
     104// check success
     105assert( (error == 0) , "cannot create <dev>\n" );
    105106
    106107#if DEBUG_DEVFS_INIT
     
    149150    // create "internal" directory
    150151    snprintf( node_name , 16 , "internal_%x" , local_cxy );
     152
    151153    vfs_add_child_in_parent( local_cxy,
    152154                             INODE_TYPE_DIR,
     
    169171    {
    170172        chdev_ptr = GET_PTR( chdev_xp );
     173        chdev_cxy = GET_CXY( chdev_xp );
     174
     175assert( (chdev_cxy == local_cxy ),
     176"illegal MMC chdev_xp in cluster %x\n", local_cxy );
     177
    171178        vfs_add_child_in_parent( local_cxy,
    172179                                 INODE_TYPE_DEV,
     
    198205        {
    199206            chdev_ptr = GET_PTR( chdev_xp );
     207            chdev_cxy = GET_CXY( chdev_xp );
     208
     209assert( (chdev_cxy == local_cxy ),
     210"illegal DMA[%d] chdev_xp in cluster %x\n", channel, local_cxy );
     211
    200212            vfs_add_child_in_parent( local_cxy,
    201213                                     INODE_TYPE_DEV,
     
    226238        chdev_cxy = GET_CXY( chdev_xp );
    227239        chdev_ptr = GET_PTR( chdev_xp );
     240
    228241        if( chdev_cxy == local_cxy )
    229242        {
     
    256269        chdev_cxy = GET_CXY( chdev_xp );
    257270        chdev_ptr = GET_PTR( chdev_xp );
     271
    258272        if( chdev_cxy == local_cxy )
    259273        {
     
    288302            chdev_cxy = GET_CXY( chdev_xp );
    289303            chdev_ptr = GET_PTR( chdev_xp );
     304
    290305            if( chdev_cxy == local_cxy )
    291306            {
     
    321336            chdev_cxy = GET_CXY( chdev_xp );
    322337            chdev_ptr = GET_PTR( chdev_xp );
     338
    323339            if( chdev_cxy == local_cxy )
    324340            {
     
    354370            chdev_cxy = GET_CXY( chdev_xp );
    355371            chdev_ptr = GET_PTR( chdev_xp );
     372
    356373            if( chdev_cxy == local_cxy )
    357374            {
     
    387404            chdev_cxy = GET_CXY( chdev_xp );
    388405            chdev_ptr = GET_PTR( chdev_xp );
     406
    389407            if( chdev_cxy == local_cxy )
    390408            {
     
    419437        {
    420438            chdev_cxy = GET_CXY( chdev_xp );
    421             chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     439            chdev_ptr = GET_PTR( chdev_xp );
     440
    422441            if( chdev_cxy == local_cxy )
    423442            {
     
    447466            chdev_cxy = GET_CXY( chdev_xp );
    448467            chdev_ptr = GET_PTR( chdev_xp );
     468
    449469            if( chdev_cxy == local_cxy )
    450470            {
  • trunk/kernel/fs/fatfs.c

    r602 r610  
    12461246vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    12471247if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1248 printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     1248printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    12491249__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    12501250#endif
     
    12801280    uint32_t  page_id    = dentry_id >> 7;
    12811281    uint32_t  offset     = (dentry_id & 0x7F)<<5;
     1282
     1283#if DEBUG_FATFS_REMOVE_DENTRY & 1
     1284if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     1285printk("\n[%s] dentry_id %x / page_id %x / offset %x\n",
     1286__FUNCTION__, dentry_id, page_id, offset );
     1287#endif
    12821288
    12831289    // get extended pointer on page descriptor from parent directory mapper
     
    13451351cycle = (uint32_t)hal_get_cycles();
    13461352if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1347 printk("\n[%s]  thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
     1353printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
    13481354__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    13491355#endif
     
    13581364                          xptr_t        child_inode_xp )
    13591365{
    1360     // Two embedded loops:
     1366    // Two embedded loops to scan the directory mapper:
    13611367    // - scan the parent directory mapper pages
    13621368    // - scan the directory entries in each 4 Kbytes page
     
    15121518    // get child inode cluster and local pointer
    15131519    cxy_t          inode_cxy = GET_CXY( child_inode_xp );
    1514     vfs_inode_t  * inode_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
     1520    vfs_inode_t  * inode_ptr = GET_PTR( child_inode_xp );
     1521
     1522    // build extended pointer on parent dentried root
     1523    xptr_t parents_root_xp = XPTR( inode_cxy , &inode_ptr->parents );
     1524
     1525// check child inode has at least one parent
     1526assert( (xlist_is_empty( parents_root_xp ) == false ), "child inode must have one parent\n");
    15151527
    15161528    // get dentry pointers and cluster
    1517     xptr_t         dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 
     1529    xptr_t         dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
    15181530    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    15191531    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    15201532
    1521 // dentry descriptor must be in same cluster as parent inode
     1533// check dentry descriptor in same cluster as parent inode
    15221534assert( (dentry_cxy == local_cxy) , "illegal dentry cluster\n" );
    15231535
  • trunk/kernel/fs/fatfs.h

    r602 r610  
    311311 * This function implements the generic vfs_fs_child_init() function for the FATFS.
    312312 *****************************************************************************************
    313  * It scan the mapper of an existing parent directory, identified by the <parent>
    314  * argument, to find a directory entry identified by the <name> argument.
    315  * It updates the existing remote child inode, identified by the <child_xp> argument,
     313 * It tries to initialise a new child (new inode/dentry couple in Inode Tree), identified
     314 * by the <child_inode_xp> argument, from the parent directory mapper, identified by the
     315 * <parent_inode> argument.
     316 * - It scan the parent mapper to find the <name> argument.
    316317 * - it set the "type", "size", and "extend" fields in inode descriptor.
    317318 * - it set the " extend" field in dentry descriptor.
  • trunk/kernel/fs/vfs.c

    r602 r610  
    141141}
    142142
    143 //////////////////////////////////////////////////////
    144 error_t vfs_inode_create( xptr_t            dentry_xp,
    145                           vfs_fs_type_t     fs_type,
     143////////////////////////////////////////////////////
     144error_t vfs_inode_create( vfs_fs_type_t     fs_type,
    146145                          vfs_inode_type_t  inode_type,
    147146                          uint32_t          attr,
     
    212211        vfs_ctx_inum_release( ctx , inum );
    213212        mapper_destroy( mapper );
    214         return ENOMEM;
     213        return -1;
    215214    }
    216215
    217216    // initialize inode descriptor
    218     inode->gc         = 0;
    219217    inode->type       = inode_type;
    220218    inode->inum       = inum;
     
    223221    inode->uid        = uid;
    224222    inode->gid        = gid;
    225     inode->refcount   = 0;
    226     inode->parent_xp  = dentry_xp;
    227223    inode->ctx        = ctx;
    228224    inode->mapper     = mapper;
    229225    inode->extend     = NULL;
     226    inode->links      = 0;
    230227
    231228    // initialise inode field in mapper
     
    233230 
    234231    // initialise threads waiting queue
    235     xlist_root_init( XPTR( local_cxy , &inode->wait_root ) );
    236 
    237     // initialize dentries hash table
     232    // xlist_root_init( XPTR( local_cxy , &inode->wait_root ) );
     233
     234    // initialize chidren dentries xhtab
    238235    xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );
    239236
    240     // initialize inode lock
    241     remote_rwlock_init( XPTR( local_cxy , &inode->data_lock ), LOCK_VFS_INODE );
    242 
    243     // initialise lock protecting inode three traversal
    244     remote_busylock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN );
     237    // initialize parents dentries xlist
     238    xlist_root_init( XPTR( local_cxy , &inode->parents ) );
     239 
     240    // initialize lock protecting size
     241    remote_rwlock_init( XPTR( local_cxy , &inode->size_lock ), LOCK_VFS_SIZE );
     242
     243    // initialise lock protecting inode tree traversal
     244    remote_rwlock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN );
     245
     246    // return extended pointer on inode
     247    *inode_xp = XPTR( local_cxy , inode );
    245248
    246249#if DEBUG_VFS_INODE_CREATE
     
    251254#endif
    252255 
    253     // return extended pointer on inode
    254     *inode_xp = XPTR( local_cxy , inode );
    255256    return 0;
    256257
     
    260261void vfs_inode_destroy( vfs_inode_t * inode )
    261262{
    262 
    263 // check inode refcount
    264 assert( (inode->refcount == 0) , "inode refcount non zero\n" );
    265 
    266263    // release memory allocated for mapper
    267264    mapper_destroy( inode->mapper );
     
    275272}  // end vfs_inode_destroy()
    276273
    277 ////////////////////////////////////////////
    278 void vfs_inode_remote_up( xptr_t  inode_xp )
    279 {
    280     // get inode cluster and local pointer
    281     cxy_t         inode_cxy = GET_CXY( inode_xp );
    282     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    283 
    284     hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , 1 );   
    285 }
    286 
    287 //////////////////////////////////////////////
    288 void vfs_inode_remote_down( xptr_t  inode_xp )
    289 {
    290     // get inode cluster and local pointer
    291     cxy_t         inode_cxy = GET_CXY( inode_xp );
    292     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    293 
    294     hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->refcount ) , -1 );   
    295 }
    296 
    297274//////////////////////////////////////////////
    298275uint32_t vfs_inode_get_size( xptr_t inode_xp )
     
    303280
    304281    // get size
    305     remote_rwlock_rd_acquire( XPTR( cxy , &ptr->data_lock ) );
     282    remote_rwlock_rd_acquire( XPTR( cxy , &ptr->size_lock ) );
    306283    uint32_t size = hal_remote_l32( XPTR( cxy , &ptr->size ) );
    307     remote_rwlock_rd_release( XPTR( cxy , &ptr->data_lock ) );
     284    remote_rwlock_rd_release( XPTR( cxy , &ptr->size_lock ) );
    308285    return size;
    309286}
     
    318295
    319296    // set size
    320     remote_rwlock_wr_release( XPTR( cxy , &ptr->data_lock ) );
     297    remote_rwlock_wr_release( XPTR( cxy , &ptr->size_lock ) );
    321298    hal_remote_s32( XPTR( cxy , &ptr->size ) , size );
    322     remote_rwlock_wr_release( XPTR( cxy , &ptr->data_lock ) );
     299    remote_rwlock_wr_release( XPTR( cxy , &ptr->size_lock ) );
    323300}
    324301
     
    345322}
    346323
    347 /////////////////////////////////////////
    348 void vfs_inode_get_name( xptr_t inode_xp,
    349                          char * name )
    350 {
    351     cxy_t          inode_cxy;
    352     vfs_inode_t  * inode_ptr;
    353     xptr_t         dentry_xp;
    354     cxy_t          dentry_cxy;
    355     vfs_dentry_t * dentry_ptr;
     324///////////////////////////////////////////
     325void vfs_inode_get_name( xptr_t   inode_xp,
     326                         char   * name )
     327{
     328    cxy_t          inode_cxy;          // inode cluster identifier
     329    vfs_inode_t  * inode_ptr;          // local pointer on inode
     330    xptr_t         parents_root_xp;    // extended pointer on inode parents root
    356331   
    357332    // get inode cluster and local pointer
     
    359334    inode_ptr = GET_PTR( inode_xp );
    360335
    361     // get parent dentry
    362     dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    363 
    364     // get local copy of name
    365     if( dentry_xp == XPTR_NULL )  // it is the VFS root
     336    // build extended pointer on parents dentries root
     337    parents_root_xp  = XPTR( inode_cxy , &inode_ptr->parents );
     338
     339    // check VFS root
     340    if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root
    366341    {
    367342        strcpy( name , "/" );
    368343    }
    369     else                          // not the VFS root
    370     {
     344    else                                     // not the VFS root
     345    {
     346        xptr_t         dentry_xp;
     347        cxy_t          dentry_cxy;
     348        vfs_dentry_t * dentry_ptr;
     349
     350        // get first name in list of parents
     351        dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
    371352        dentry_cxy = GET_CXY( dentry_xp );
    372353        dentry_ptr = GET_PTR( dentry_xp );
    373354
    374355        hal_remote_strcpy( XPTR( local_cxy  , name ) ,
    375                            XPTR( dentry_cxy , &dentry_ptr->name ) );
    376     }
     356                           XPTR( dentry_cxy , dentry_ptr->name ) );
     357    }
     358
    377359}  // end vfs_inode_get_name()
    378360
     
    433415error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
    434416                           char          * name,
    435                            vfs_inode_t   * parent,
    436417                           xptr_t        * dentry_xp )
    437418{
     
    439420    vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated)
    440421        kmem_req_t       req;        // request to kernel memory allocator
    441     error_t          error;
    442422
    443423#if DEBUG_VFS_DENTRY_CREATE
     
    456436    {
    457437        ctx = NULL;
    458         return EINVAL;
     438        return -1;
    459439    }
    460440
     
    470450        dentry     = (vfs_dentry_t *)kmem_alloc( &req );
    471451
    472     if( dentry == NULL ) return ENOMEM;
     452    if( dentry == NULL )
     453    {
     454        printk("\n[ERROR] in %s : cannot allocate dentry descriptor\n",
     455        __FUNCTION__ );
     456        return -1;
     457    }
    473458
    474459    // initialize dentry descriptor
    475 
    476460    dentry->ctx     = ctx;
    477461    dentry->length  = length;
    478     dentry->parent  = parent;
    479462    dentry->extend  = NULL;
    480463    strcpy( dentry->name , name );
    481 
    482 #if( DEBUG_VFS_DENTRY_CREATE & 1 )
    483 cycle = (uint32_t)hal_get_cycles();
    484 if( DEBUG_VFS_DENTRY_CREATE < cycle )
    485 printk("\n[%s] thread[%x,%x] / dentry <%s> initialised / cycle %d\n",
    486 __FUNCTION__, this->process->pid, this->trdid, dentry->name, cycle );
    487 #endif
    488 
    489     // register dentry in hash table rooted in parent inode
    490     error = xhtab_insert( XPTR( local_cxy , &parent->children ),
    491                           name,
    492                           XPTR( local_cxy , &dentry->list ) );
    493 
    494     if( error ) return EINVAL;
    495 
    496 #if( DEBUG_VFS_DENTRY_CREATE & 1 )
    497 cycle = (uint32_t)hal_get_cycles();
    498 if( DEBUG_VFS_DENTRY_CREATE < cycle )
    499 printk("\n[%s] thread[%x,%x] / dentry <%s> registered / cycle %d\n",
    500 __FUNCTION__, this->process->pid, this->trdid, dentry->name, cycle );
    501 #endif
    502464
    503465    // return extended pointer on dentry
     
    518480void vfs_dentry_destroy( vfs_dentry_t * dentry )
    519481{
    520 
    521 // check dentry refcount
    522 assert( (dentry->refcount == 0) , "dentry refcount non zero\n" );
    523 
    524     // get pointer on parent inode
    525     vfs_inode_t * parent = dentry->parent;
    526 
    527     // remove this dentry from parent inode htab
    528     xhtab_remove( XPTR( local_cxy , &parent->children ),
    529                   dentry->name,
    530                   XPTR( local_cxy , &dentry->list ) );
    531 
    532482    // release memory allocated to dentry
    533483        kmem_req_t req;
     
    537487
    538488}  // end vfs_dentry_destroy()
    539 
    540 //////////////////////////////////////////////
    541 void vfs_dentry_remote_up( xptr_t  dentry_xp )
    542 {
    543     // get dentry cluster and local pointer
    544     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    545     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    546 
    547     hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , 1 );   
    548 }
    549 
    550 ////////////////////////////////////////////////
    551 void vfs_dentry_remote_down( xptr_t  dentry_xp )
    552 {
    553     // get dentry cluster and local pointer
    554     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    555     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    556 
    557     hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , -1 );   
    558 }
    559 
    560489
    561490
     
    616545void vfs_file_destroy( vfs_file_t *  file )
    617546{
    618     if( file->refcount )
    619     {
    620         assert( false , "refcount non zero\n" );
    621     }       
     547
     548// check refcount
     549assert( (file->refcount == 0) , "refcount non zero\n" );
    622550
    623551        kmem_req_t req;
     
    664592
    665593//////////////////////////////////////
    666 error_t vfs_open( process_t * process,
     594error_t vfs_open( xptr_t      root_xp,
    667595                          char      * path,
     596                  xptr_t      process_xp,
    668597                          uint32_t    flags,
    669598                  uint32_t    mode,
     
    671600                  uint32_t  * new_file_id )
    672601{
    673     error_t       error;
    674     xptr_t        inode_xp;     // extended pointer on target inode
    675     cxy_t         inode_cxy;    // inode cluster identifier       
    676     vfs_inode_t * inode_ptr;    // inode local pointer
    677     uint32_t      file_attr;    // file descriptor attributes
    678     uint32_t      lookup_mode;  // lookup working mode       
    679     xptr_t        file_xp;      // extended pointer on created file descriptor
    680     uint32_t      file_id;      // created file descriptor index in reference fd_array
    681 
     602    error_t        error;
     603    xptr_t         inode_xp;       // extended pointer on target inode
     604    cxy_t          inode_cxy;      // inode cluster identifier       
     605    vfs_inode_t  * inode_ptr;      // inode local pointer
     606    uint32_t       file_attr;      // file descriptor attributes
     607    uint32_t       lookup_mode;    // lookup working mode       
     608    xptr_t         file_xp;        // extended pointer on created file descriptor
     609    uint32_t       file_id;        // created file descriptor index in reference fd_array
     610    xptr_t         vfs_root_xp;    // extended pointer on VFS root inode
     611    vfs_inode_t  * vfs_root_ptr;   // local pointer on VFS root inode
     612    cxy_t          vfs_root_cxy;   // VFS root inode cluster identifier
     613    xptr_t         lock_xp;        // extended pointer on Inode Tree lock
    682614
    683615    if( mode != 0 )
     
    687619    }
    688620
     621    thread_t  * this    = CURRENT_THREAD;
     622    process_t * process = this->process;
     623
    689624#if DEBUG_VFS_OPEN
    690 thread_t * this = CURRENT_THREAD;
    691625uint32_t cycle = (uint32_t)hal_get_cycles();
    692626if( DEBUG_VFS_OPEN < cycle )
    693 printk("\n[%s]   thread[%x,%x] enter for <%s> / cycle %d\n",
    694 __FUNCTION__, this->process->pid, this->trdid, path, cycle );
     627printk("\n[%s] thread[%x,%x] enter for <%s> / root_inode (%x,%x) / cycle %d\n",
     628__FUNCTION__, process->pid, this->trdid, path, GET_CXY(root_xp), GET_PTR(root_xp), cycle );
    695629#endif
    696630
     
    709643    if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC;
    710644
     645    // build extended pointer on lock protecting Inode Tree
     646    vfs_root_xp  = process->vfs_root_xp;
     647    vfs_root_ptr = GET_PTR( vfs_root_xp );
     648    vfs_root_cxy = GET_CXY( vfs_root_xp );
     649    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     650
     651    // take lock protecting Inode Tree in read mode
     652    remote_rwlock_rd_acquire( lock_xp );
     653
    711654    // get extended pointer on target inode
    712     error = vfs_lookup( process->vfs_cwd_xp , path , lookup_mode , &inode_xp );
    713 
    714     if( error ) return error;
     655    error = vfs_lookup( root_xp,
     656                        path,
     657                        lookup_mode,
     658                        &inode_xp,
     659                        NULL );
     660
     661    // release lock protecting Inode Tree
     662    remote_rwlock_rd_release( lock_xp );
     663
     664    if( error )
     665    {
     666        printk("\n[ERROR] in %s : cannot get inode <%s>\n",
     667        __FUNCTION__ , path );
     668        return -1;
     669    }
    715670
    716671    // get target inode cluster and local pointer
     
    718673    inode_ptr = GET_PTR( inode_xp );
    719674   
     675#if (DEBUG_VFS_OPEN & 1)
     676cycle = (uint32_t)hal_get_cycles();
     677if( DEBUG_VFS_OPEN < cycle )
     678printk("\n[%s] thread[%x,%x] found inode(%x,%x) for <%s>\n",
     679__FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr, path );
     680#endif
     681
    720682    // create a new file descriptor in cluster containing inode
    721683    if( inode_cxy == local_cxy )      // target cluster is local
     
    730692    if( error )  return error;
    731693
     694#if (DEBUG_VFS_OPEN & 1)
     695cycle = (uint32_t)hal_get_cycles();
     696if( DEBUG_VFS_OPEN < cycle )
     697printk("\n[%s] thread[%x,%x] created file descriptor (%x,%x) for <%s>\n",
     698__FUNCTION__, process->pid, this->trdid, GET_CXY(file_xp), GET_PTR(file_xp), path );
     699#endif
     700
    732701    // allocate and register a new file descriptor index in reference process
    733     error = process_fd_register( process , file_xp , &file_id );
     702    error = process_fd_register( process_xp , file_xp , &file_id );
    734703
    735704    if( error ) return error;
     
    738707cycle = (uint32_t)hal_get_cycles();
    739708if( DEBUG_VFS_OPEN < cycle )
    740 printk("\n[%s]   thread[%x,%x] exit for <%s> / fdid %d / cluster %x / cycle %d\n",
    741 __FUNCTION__, this->process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle );
     709printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / cluster %x / cycle %d\n",
     710__FUNCTION__, process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle );
    742711#endif
    743712
     
    780749
    781750    // move data between mapper and buffer
    782     if( file_cxy == local_cxy )
    783     {
    784         error = mapper_move_user( mapper,
    785                                   to_buffer,
    786                                   file_offset,
    787                                   buffer,
    788                                   size );
    789     }
    790     else
    791     {
    792         rpc_mapper_move_user_client( file_cxy,
    793                                      mapper,
    794                                      to_buffer,
    795                                      file_offset,
    796                                      buffer,
    797                                      size,
    798                                      &error );
    799     }
     751    error = mapper_move_user( XPTR( file_cxy , mapper ),
     752                              to_buffer,
     753                              file_offset,
     754                              buffer,
     755                              size );
    800756
    801757    // update file offset in file descriptor
     
    834790    // get inode type from remote file descriptor
    835791    inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) );
    836    
     792
    837793    // action depends on inode type
    838794    if( inode_type == INODE_TYPE_FILE )
     
    10441000
    10451001////////////////////////////////////
    1046 error_t vfs_unlink( xptr_t   cwd_xp,
     1002error_t vfs_mkdir( xptr_t   root_xp,
     1003                   char   * path,
     1004                   uint32_t rights )
     1005{
     1006    error_t        error;
     1007    xptr_t         vfs_root_xp;        // extended pointer on VFS root inode
     1008    vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode
     1009    cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier
     1010    xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree
     1011    xptr_t         inode_xp;           // extended pointer on target inode
     1012    vfs_inode_t  * inode_ptr;          // local pointer on target inode
     1013    cxy_t          inode_cxy;          // target inode cluster identifier
     1014    xptr_t         dentry_xp;          // extended pointer on new dentry
     1015    vfs_dentry_t * dentry_ptr;         // target dentry local pointer
     1016    xptr_t         parent_xp;          // extended pointer on new parent inode
     1017    vfs_inode_t  * parent_ptr;         // local pointer on new parent inode 
     1018    cxy_t          parent_cxy;         // new parent inode cluster identifier
     1019    vfs_ctx_t    * parent_ctx_ptr;     // local pointer on target inode context
     1020    uint32_t       parent_fs_type;     // target inode file system type
     1021
     1022    xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root)
     1023    xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry
     1024    xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root)
     1025    xptr_t         children_entry_xp;  // extended pointer on children field in dentry
     1026
     1027    char           last_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1028
     1029    thread_t  * this    = CURRENT_THREAD;
     1030    process_t * process = this->process;
     1031
     1032#if DEBUG_VFS_MKDIR
     1033char root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1034vfs_inode_get_name( root_xp , root_name );
     1035uint32_t   cycle = (uint32_t)hal_get_cycles();
     1036if( DEBUG_VFS_MKDIR < cycle )
     1037printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n",
     1038__FUNCTION__, process->pid, this->trdid, root_name, path, cycle );
     1039#endif
     1040
     1041    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1042    vfs_root_xp  = process->vfs_root_xp;
     1043    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1044    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1045    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1046
     1047    // take the lock protecting Inode Tree in write mode
     1048    remote_rwlock_wr_acquire( lock_xp );
     1049
     1050    // 1. get pointers on parent inode
     1051    error = vfs_lookup( root_xp,
     1052                        path,
     1053                        VFS_LOOKUP_DIR | VFS_LOOKUP_PARENT,
     1054                        &parent_xp,
     1055                        last_name );
     1056    if( error )
     1057    {
     1058        remote_rwlock_wr_release( lock_xp );
     1059        printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n",
     1060        __FUNCTION__, path );
     1061        return -1;
     1062    }
     1063
     1064    // get parent inode cluster and local pointer
     1065    parent_cxy = GET_CXY( parent_xp );
     1066    parent_ptr = GET_PTR( parent_xp );
     1067
     1068#if( DEBUG_VFS_MKDIR & 1 )
     1069if( DEBUG_VFS_MKDIR < cycle )
     1070printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n",
     1071__FUNCTION__, process->pid, this->trdid, parent_cxy, parent_ptr, path );
     1072#endif
     1073
     1074    // get parent inode context, and FS type
     1075    parent_ctx_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
     1076    parent_fs_type = hal_remote_l32( XPTR( parent_cxy , &parent_ctx_ptr->type ) );
     1077
     1078    // 2. create one new dentry in parent cluster
     1079    if( parent_cxy == local_cxy ) 
     1080    {
     1081        error = vfs_dentry_create( parent_fs_type,
     1082                                   last_name,
     1083                                   &dentry_xp );
     1084    }
     1085    else
     1086    {
     1087        rpc_vfs_dentry_create_client( parent_cxy,
     1088                                      parent_fs_type,
     1089                                      last_name,
     1090                                      &dentry_xp,
     1091                                      &error );
     1092    }
     1093
     1094    if( error )
     1095    {
     1096        remote_rwlock_wr_release( lock_xp );
     1097        printk("\n[ERROR] in %s : cannot create new dentry in cluster %x for <%s>\n",
     1098        __FUNCTION__, parent_cxy, path );
     1099        return -1;
     1100    }
     1101
     1102    // get local pointer on dentry
     1103    dentry_ptr = GET_PTR( dentry_xp );
     1104
     1105#if( DEBUG_VFS_MKDIR & 1 )
     1106if( DEBUG_VFS_MKDIR < cycle )
     1107printk("\n[%s] thread[%x,%x] created new dentry (%x,%x) for <%s>\n",
     1108__FUNCTION__, process->pid, this->trdid, parent_cxy, dentry_ptr, path );
     1109#endif
     1110
     1111    // 3. create new directory inode in child cluster
     1112    // TODO : define attr / uid / gid
     1113    uint32_t attr = 0;
     1114    uint32_t uid  = 0;
     1115    uint32_t gid  = 0;
     1116
     1117    // select a target cluster for new inode
     1118    inode_cxy = cluster_random_select();
     1119   
     1120    if( inode_cxy == local_cxy )      // child cluster is local
     1121    {
     1122        error = vfs_inode_create( parent_fs_type,
     1123                                  INODE_TYPE_DIR,
     1124                                  attr,
     1125                                  rights,
     1126                                  uid,
     1127                                  gid,
     1128                                  &inode_xp );
     1129    }
     1130    else                              // child cluster is remote
     1131    {
     1132        rpc_vfs_inode_create_client( inode_cxy,
     1133                                     parent_fs_type,
     1134                                     INODE_TYPE_DIR,
     1135                                     attr,
     1136                                     rights,
     1137                                     uid,
     1138                                     gid,
     1139                                     &inode_xp,
     1140                                     &error );
     1141    }
     1142                                     
     1143    if( error )
     1144    {
     1145        printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n",
     1146               __FUNCTION__ , inode_cxy , path );
     1147 
     1148        if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr );
     1149        else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr );
     1150        return -1;
     1151    }
     1152
     1153    // get new inode local pointer
     1154    inode_ptr = GET_PTR( inode_xp );
     1155   
     1156#if(DEBUG_VFS_MKDIR & 1)
     1157if( DEBUG_VFS_MKDIR < cycle )
     1158printk("\n[%s] thread[%x,%x] created new inode (%x,%x) for <%s>\n",
     1159__FUNCTION__ , process->pid, this->trdid, inode_cxy, inode_ptr, path );
     1160#endif
     1161
     1162    // 4. register dentry in new inode list of parents
     1163    parents_root_xp  = XPTR( inode_cxy  , &inode_ptr->parents );
     1164    parents_entry_xp = XPTR( parent_cxy , &dentry_ptr->parents );
     1165    xlist_add_first( parents_root_xp , parents_entry_xp );
     1166    hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 );
     1167
     1168    // 5. register dentry in parent inode
     1169    children_xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
     1170    children_entry_xp = XPTR( parent_cxy , &dentry_ptr->children );
     1171    xhtab_insert( children_xhtab_xp , last_name , children_entry_xp );
     1172
     1173    // 6. update "parent" and "child_xp" fields in dentry
     1174    hal_remote_s64( XPTR( parent_cxy , &dentry_ptr->child_xp ) , inode_xp );
     1175    hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->parent ) , parent_ptr );
     1176
     1177#if(DEBUG_VFS_MKDIR & 1)
     1178if( DEBUG_VFS_MKDIR < cycle )
     1179printk("\n[%s] thread[%x,%x] updated Inode Tree for <%s>\n",
     1180__FUNCTION__, process->pid, this->trdid, path );
     1181#endif
     1182
     1183    // release the lock protecting Inode Tree
     1184    remote_rwlock_wr_release( lock_xp );
     1185
     1186    // 5. update parent directory mapper
     1187    //    and synchronize the parent directory on IOC device
     1188    if (parent_cxy == local_cxy)
     1189    {
     1190        error = vfs_fs_add_dentry( parent_ptr,
     1191                                   dentry_ptr );
     1192    }
     1193    else
     1194    {
     1195        rpc_vfs_fs_add_dentry_client( parent_cxy,
     1196                                      parent_ptr,
     1197                                      dentry_ptr,
     1198                                      &error );
     1199    }
     1200
     1201    if( error )
     1202    {
     1203        printk("\n[ERROR] in %s : cannot update parent directory for <%s>\n",
     1204        __FUNCTION__, path );
     1205        return -1;
     1206    }
     1207
     1208#if(DEBUG_VFS_MKDIR & 1)
     1209if( DEBUG_VFS_MKDIR < cycle )
     1210printk("\n[%s] thread[%x,%x] updated parent dir (mapper and IOC) for <%s>\n",
     1211__FUNCTION__, process->pid, this->trdid, path );
     1212#endif
     1213
     1214    return 0;
     1215
     1216}  // end vfs_mkdir()
     1217
     1218///////////////////////////////////////
     1219error_t vfs_link( xptr_t   old_root_xp,
     1220                  char   * old_path,
     1221                  xptr_t   new_root_xp,
     1222                  char   * new_path )
     1223{
     1224    error_t        error;
     1225    xptr_t         vfs_root_xp;        // extended pointer on VFS root inode
     1226    vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode
     1227    cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier
     1228    xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree
     1229    xptr_t         inode_xp;           // extended pointer on target inode
     1230    vfs_inode_t  * inode_ptr;          // local pointer on target inode
     1231    cxy_t          inode_cxy;          // target inode cluster identifier
     1232    uint32_t       inode_type;         // target inode type
     1233    vfs_ctx_t    * inode_ctx_ptr;      // local pointer on target inode context
     1234    uint32_t       inode_fs_type;      // target inode file system type
     1235    xptr_t         dentry_xp;          // extended pointer on new dentry
     1236    vfs_dentry_t * dentry_ptr;         // target dentry local pointer
     1237    xptr_t         new_parent_xp;      // extended pointer on new parent inode
     1238    vfs_inode_t  * new_parent_ptr;     // local pointer on new parent inode 
     1239    cxy_t          new_parent_cxy;     // new parent inode cluster identifier
     1240
     1241    xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root)
     1242    xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry
     1243    xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root)
     1244    xptr_t         children_entry_xp;  // extended pointer on children field in dentry
     1245
     1246    char           new_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1247
     1248    thread_t  * this    = CURRENT_THREAD;
     1249    process_t * process = this->process;
     1250
     1251#if DEBUG_VFS_LINK
     1252char old_root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1253char new_root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1254vfs_inode_get_name( old_root_xp , old_root_name );
     1255vfs_inode_get_name( new_root_xp , new_root_name );
     1256uint32_t   cycle = (uint32_t)hal_get_cycles();
     1257if( DEBUG_VFS_LINK < cycle )
     1258printk("\n[%s] thread[%x,%x] enter / old_root <%s> / old_path <%s> / "
     1259"new_root <%s> / new_path <%s> / cycle %d\n",
     1260__FUNCTION__, process->pid, this->trdid,
     1261old_root_name, old_path, new_root_name, new_path, cycle );
     1262#endif
     1263
     1264    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1265    vfs_root_xp  = process->vfs_root_xp;
     1266    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1267    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1268    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1269
     1270    // take the lock protecting Inode Tree in write mode
     1271    remote_rwlock_wr_acquire( lock_xp );
     1272
     1273    // get extended pointer on target inode
     1274    error = vfs_lookup( old_root_xp,
     1275                        old_path,
     1276                        0,
     1277                        &inode_xp,
     1278                        NULL );
     1279    if( error )
     1280    {
     1281        remote_rwlock_wr_release( lock_xp );
     1282        printk("\n[ERROR] in %s : cannot get target inode for <%s>\n",
     1283        __FUNCTION__, old_path );
     1284        return -1;
     1285    }
     1286
     1287#if( DEBUG_VFS_LINK & 1 )
     1288if( DEBUG_VFS_LINK < cycle )
     1289printk("\n[%s] thread[%x,%x] get child inode (%x,%x) for <%s>\n",
     1290__FUNCTION__, process->pid, this->trdid,
     1291GET_CXY(inode_xp), GET_PTR(inode_xp), old_path, cycle );
     1292#endif
     1293
     1294    // get extended pointer on parent inode in new path
     1295    error = vfs_lookup( new_root_xp,
     1296                        new_path,
     1297                        VFS_LOOKUP_PARENT,
     1298                        &new_parent_xp,
     1299                        new_name );
     1300    if( error )
     1301    {
     1302        remote_rwlock_wr_release( lock_xp );
     1303        printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n",
     1304        __FUNCTION__, new_path );
     1305        return -1;
     1306    }
     1307
     1308#if( DEBUG_VFS_LINK & 1 )
     1309if( DEBUG_VFS_LINK < cycle )
     1310printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n",
     1311__FUNCTION__, process->pid, this->trdid,
     1312GET_CXY(new_parent_xp), GET_PTR(new_parent_xp), new_path );
     1313#endif
     1314
     1315    // get target inode cluster and local pointer
     1316    inode_cxy = GET_CXY( inode_xp );
     1317    inode_ptr = GET_PTR( inode_xp );
     1318
     1319    // get target inode type, context, and FS type
     1320    inode_type        = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     1321    inode_ctx_ptr     = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) );
     1322    inode_fs_type     = hal_remote_l32( XPTR( inode_cxy , &inode_ctx_ptr->type ) );
     1323
     1324    // get new parent inode cluster an local pointer
     1325    new_parent_ptr = GET_PTR( new_parent_xp );
     1326    new_parent_cxy = GET_CXY( new_parent_xp );
     1327
     1328    ///////////////////////////////////////////////////////////////////////
     1329    if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) )
     1330    {
     1331        // 1. create one new dentry
     1332        if( new_parent_cxy == local_cxy ) 
     1333        {
     1334            error = vfs_dentry_create( inode_fs_type,
     1335                                       new_name,
     1336                                       &dentry_xp );
     1337        }
     1338        else
     1339        {
     1340            rpc_vfs_dentry_create_client( new_parent_cxy,
     1341                                          inode_fs_type,
     1342                                          new_name,
     1343                                          &dentry_xp,
     1344                                          &error );
     1345        }
     1346
     1347        if( error )
     1348        {
     1349            remote_rwlock_wr_release( lock_xp );
     1350            printk("\n[ERROR] in %s : cannot create new dentry for <%s>\n",
     1351            __FUNCTION__, new_path );
     1352            return -1;
     1353        }
     1354
     1355        // get local pointer on dentry
     1356        dentry_ptr = GET_PTR( dentry_xp );
     1357
     1358        // 2. register dentry in target inode
     1359        parents_root_xp  = XPTR( inode_cxy      , &inode_ptr->parents );
     1360        parents_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->parents );
     1361        xlist_add_first( parents_root_xp , parents_entry_xp );
     1362        hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 );
     1363
     1364        // 3. register dentry in parent inode
     1365        children_xhtab_xp = XPTR( new_parent_cxy , &new_parent_ptr->children );
     1366        children_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->children );
     1367        xhtab_insert( children_xhtab_xp , new_name , children_entry_xp );
     1368
     1369        // 4. update "parent" and "child_xp" fields in dentry
     1370        hal_remote_s64( XPTR( new_parent_cxy , &dentry_ptr->child_xp ) , inode_xp );
     1371        hal_remote_spt( XPTR( new_parent_cxy , &dentry_ptr->parent ) , new_parent_ptr );
     1372
     1373#if(DEBUG_VFS_LINK & 1)
     1374if( DEBUG_VFS_LINK < cycle )
     1375printk("\n[%s] thread[%x,%x] updated Inode Tree / old <%s> / new <%s>\n",
     1376__FUNCTION__, process->pid, this->trdid, old_path, new_path );
     1377vfs_display( new_parent_xp );
     1378#endif
     1379
     1380        // release the lock protecting Inode Tree
     1381        remote_rwlock_wr_release( lock_xp );
     1382
     1383        // 5. update new parent directory mapper in Inode Tree
     1384        //    and synchronize the parent directory on IOC device
     1385        if (new_parent_cxy == local_cxy)
     1386        {
     1387            error = vfs_fs_add_dentry( new_parent_ptr,
     1388                                       dentry_ptr );
     1389        }
     1390        else
     1391        {
     1392            rpc_vfs_fs_add_dentry_client( new_parent_cxy,
     1393                                          new_parent_ptr,
     1394                                          dentry_ptr,
     1395                                          &error );
     1396        }
     1397        if( error )
     1398        {
     1399            printk("\n[ERROR] in %s : cannot update new parent directory for <%s>\n",
     1400            __FUNCTION__, new_path );
     1401            return -1;
     1402        }
     1403
     1404#if(DEBUG_VFS_LINK & 1)
     1405if( DEBUG_VFS_LINK < cycle )
     1406printk("\n[%s] thread[%x,%x] updated new parent dir (mapper and IOC) / old <%s> / new <%s>\n",
     1407__FUNCTION__, process->pid, this->trdid, old_path, new_path );
     1408#endif
     1409        return 0;
     1410    }
     1411    else
     1412    {
     1413        // release the lock protecting Inode Tree
     1414        remote_rwlock_wr_release( lock_xp );
     1415
     1416        printk("\n[ERROR] in %s : unsupported inode type %s\n",
     1417        __FUNCTION__ , vfs_inode_type_str( inode_type ) );
     1418        return -1;
     1419    }
     1420
     1421}  // end vfs_link()
     1422
     1423/////////////////////////////////////
     1424error_t vfs_unlink( xptr_t   root_xp,
    10471425                    char   * path )
    10481426{
    10491427    error_t           error;
     1428    xptr_t            vfs_root_xp;        // extended pointer on VFS root inode
     1429    vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode
     1430    cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier
     1431    xptr_t            lock_xp;            // extended pointer on lock protecting Inode Tree
     1432    xptr_t            parent_xp;          // extended pointer on target inode
     1433    cxy_t             parent_cxy;         // target inode cluster identifier       
     1434    vfs_inode_t     * parent_ptr;         // target inode local pointer
    10501435    xptr_t            inode_xp;           // extended pointer on target inode
    10511436    cxy_t             inode_cxy;          // target inode cluster identifier       
    10521437    vfs_inode_t     * inode_ptr;          // target inode local pointer
    1053     uint32_t          inode_refcount;     // target inode refcount
    1054     vfs_inode_type_t  type;               // target inode type
    1055     mapper_t        * mapper;             // pointer on target inode mapper
    1056     xptr_t            dentry_xp;          // extended pointer on target dentry
    1057     cxy_t             dentry_cxy;         // target dentry cluster identifier
    1058     vfs_dentry_t    * dentry_ptr;         // target dentry local pointer
    1059     uint32_t          dentry_refcount;    // target dentry refcount
    1060     vfs_inode_t     * dentry_parent_ptr;  // parent inode local pointer
     1438    uint32_t          inode_links;        // target inode links count
     1439    vfs_inode_type_t  inode_type;         // target inode type
     1440    uint32_t          inode_children;     // target inode number of children
     1441    xptr_t            dentry_xp;          // extended pointer on dentry to unlink
     1442    vfs_dentry_t    * dentry_ptr;         // local pointer on dentry to unlink
     1443
     1444    char              name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of link to remove
     1445
     1446    thread_t  * this    = CURRENT_THREAD;
     1447    process_t * process = this->process;
    10611448
    10621449#if DEBUG_VFS_UNLINK
    1063 thread_t * this  = CURRENT_THREAD;
    10641450uint32_t   cycle = (uint32_t)hal_get_cycles();
     1451char root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1452vfs_inode_get_name( root_xp , root_name );
    10651453if( DEBUG_VFS_UNLINK < cycle )
    1066 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
    1067 __FUNCTION__, this->process->pid, this->trdid, path, cycle );
    1068 #endif
    1069 
    1070     // get extended pointer on target inode
    1071     error = vfs_lookup( cwd_xp , path , 0 , &inode_xp );
    1072 
    1073     if( error ) return error;
    1074 
    1075     // get inode cluster and local pointer
     1454printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n",
     1455__FUNCTION__, process->pid, this->trdid, root_name, path, cycle );
     1456#endif
     1457
     1458    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1459    vfs_root_xp  = process->vfs_root_xp;
     1460    vfs_root_ptr = GET_PTR( root_xp );
     1461    vfs_root_cxy = GET_CXY( root_xp );
     1462    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1463
     1464    // take the lock protecting Inode Tree
     1465    remote_rwlock_wr_acquire( lock_xp );
     1466
     1467    // get extended pointer on parent inode
     1468    error = vfs_lookup( root_xp,
     1469                        path,
     1470                        VFS_LOOKUP_PARENT,
     1471                        &parent_xp,
     1472                        name );
     1473    if( error )
     1474    {
     1475        remote_rwlock_wr_release( lock_xp );
     1476        printk("\n[ERROR] in %s : cannot get parent inode for <%s> in <%s>\n",
     1477        __FUNCTION__, name, path );
     1478        return -1;
     1479    }
     1480
     1481    // get parent inode cluster and local pointer
     1482    parent_cxy = GET_CXY( parent_xp );
     1483    parent_ptr = GET_PTR( parent_xp );
     1484 
     1485#if( DEBUG_VFS_UNLINK & 1 )
     1486char parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1487vfs_inode_get_name( parent_xp , parent_name );
     1488if( DEBUG_VFS_UNLINK < cycle )
     1489printk("\n[%s] thread[%x,%x] parent inode <%s> is (%x,%x)\n",
     1490__FUNCTION__, process->pid, this->trdid, parent_name, parent_cxy, parent_ptr );
     1491#endif
     1492
     1493    // build extended pointer on parent inode "children" xhtab
     1494    xptr_t children_xp = XPTR( parent_cxy , &parent_ptr->children );
     1495
     1496    // get extended pointer on dentry to unlink
     1497    dentry_xp = xhtab_lookup( children_xp , name );
     1498   
     1499    if( dentry_xp == XPTR_NULL )
     1500    {
     1501        remote_rwlock_wr_release( lock_xp );
     1502        printk("\n[ERROR] in %s : cannot get target dentry <%s> in <%s>\n",
     1503        __FUNCTION__, name, path );
     1504        return -1;
     1505    }
     1506   
     1507    // get local pointer on dentry to unlink
     1508    dentry_ptr = GET_PTR( dentry_xp );
     1509
     1510#if( DEBUG_VFS_UNLINK & 1 )
     1511if( DEBUG_VFS_UNLINK < cycle )
     1512printk("\n[%s] thread[%x,%x] dentry <%s> to unlink is (%x,%x)\n",
     1513__FUNCTION__, process->pid, this->trdid, name, parent_cxy, dentry_ptr );
     1514#endif
     1515
     1516    // get pointer on target inode
     1517    inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
    10761518    inode_cxy = GET_CXY( inode_xp );
    10771519    inode_ptr = GET_PTR( inode_xp );
    1078 
    1079     // get inode type, refcount, mapper, dentry_xp
    1080     type              = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
    1081     inode_refcount    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) );
    1082     mapper            = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
    1083     dentry_xp         = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    1084 
    1085     // get dentry cluster, local pointer, refcount, and pointers on parent inode
    1086     dentry_ptr        = GET_PTR( dentry_xp );
    1087     dentry_cxy        = GET_CXY( dentry_xp );
    1088     dentry_refcount   = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) );
    1089     dentry_parent_ptr = hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) );
    1090 
    1091 // check inode & dentry refcount
    1092 assert( (inode_refcount  == 1), "illegal inode refcount for <%s>\n", path );
    1093 assert( (dentry_refcount == 1), "illegal dentry refcount for <%s>\n", path );
    1094 
    1095     /////////////////////////////
    1096     if( type == INODE_TYPE_FILE )
    1097     {
    1098         // 1. release clusters allocated to file in the FAT mapper
    1099         //    synchronize the FAT on IOC device
    1100         error = vfs_fs_release_inode( inode_xp );
    1101         if( error )
     1520 
     1521#if( DEBUG_VFS_UNLINK & 1 )
     1522char inode_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1523vfs_inode_get_name( inode_xp , inode_name );
     1524if( DEBUG_VFS_UNLINK < cycle )
     1525printk("\n[%s] thread[%x,%x] target inode <%s> is (%x,%x) / cycle %d\n",
     1526__FUNCTION__, process->pid, this->trdid, inode_name, inode_cxy, inode_ptr, cycle );
     1527#endif
     1528
     1529    // get target inode "type" and "links"
     1530    inode_type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     1531    inode_links  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->links ) );
     1532
     1533// check target inode links counter
     1534assert( (inode_links >= 1), "illegal inode links count %d for <%s>\n", inode_links, path );
     1535
     1536    ///////////////////////////////////////////////////////////////////////
     1537    if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) )
     1538    {
     1539        // 1. Release clusters allocated to target inode
     1540        //    and synchronize the FAT on IOC device if last link.
     1541        if( inode_links == 1 )
    11021542        {
    1103             printk("\n[ERROR] in %s : cannot update FAT mapper <%s>\n", path );
    1104             return -1;
    1105         }
     1543            // build extended pointer on target inode "children" number
     1544            xptr_t inode_children_xp = XPTR( inode_cxy , &inode_ptr->children.items );
     1545
     1546            // get target inode number of children
     1547            inode_children = hal_remote_l32( inode_children_xp );
     1548
     1549            // check no children
     1550            if( inode_children != 0 )
     1551            {
     1552                remote_rwlock_wr_release( lock_xp );
     1553                printk("\n[ERROR] in %s : cannot remove <%s> inode that has children\n",
     1554                __FUNCTION__, path );
     1555                return -1;
     1556            }
     1557
     1558            // release clusters on IOC device
     1559            error = vfs_fs_release_inode( inode_xp );
     1560
     1561            if( error )
     1562            {
     1563                remote_rwlock_wr_release( lock_xp );
     1564                printk("\n[ERROR] in %s : cannot update FAT mapper to remove <%s> inode\n",
     1565                __FUNCTION__ , path );
     1566                return -1;
     1567            }
    11061568
    11071569#if(DEBUG_VFS_UNLINK & 1)
    11081570if( DEBUG_VFS_UNLINK < cycle )
    11091571printk("\n[%s] thread[%x,%x] removed <%s> inode from FAT (mapper and IOC device)\n",
    1110 __FUNCTION__, this->process->pid, this->trdid, path );
    1111 #endif
    1112 
    1113         // 2. update parent directory in Inode Tree
    1114         //    synchronize the parent directory on IOC device
    1115         if (dentry_cxy == local_cxy)                           // dentry is local
     1572__FUNCTION__, process->pid, this->trdid, path );
     1573#endif
     1574        }
     1575
     1576        // 2. update parent directory mapper
     1577        //    and synchronize the parent directory on IOC device
     1578        if (parent_cxy == local_cxy)
    11161579        {
    1117             error = vfs_fs_remove_dentry( dentry_parent_ptr,
     1580            error = vfs_fs_remove_dentry( parent_ptr,
    11181581                                          dentry_ptr );
    11191582        }
    1120         else                                                  // dentry is remote
     1583        else           
    11211584        {
    1122             rpc_vfs_fs_remove_dentry_client( dentry_cxy,
    1123                                              dentry_parent_ptr,
     1585            rpc_vfs_fs_remove_dentry_client( parent_cxy,
     1586                                             parent_ptr,
    11241587                                             dentry_ptr,
    11251588                                             &error );
    11261589        }
     1590
    11271591        if( error )
    11281592        {
    1129             printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n", path );
     1593            remote_rwlock_wr_release( lock_xp );
     1594            printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n",
     1595            __FUNCTION__ , path );
    11301596            return -1;
    11311597        }
     
    11341600if( DEBUG_VFS_UNLINK < cycle )
    11351601printk("\n[%s] thread[%x,%x] removed <%s> inode from parent dir (mapper and IOC device)\n",
    1136 __FUNCTION__, this->process->pid, this->trdid, path );
    1137 #endif
    1138         // 3. remove inode (including mapper & dentry) from Inode Tree
    1139         vfs_remove_child_from_parent( inode_xp );
     1602__FUNCTION__, process->pid, this->trdid, path );
     1603#endif
     1604        // 3. remove dentry from Inode Tree (and associated chils inode when last link)
     1605        vfs_remove_child_from_parent( dentry_xp );
     1606
     1607        // release the lock protecting Inode Tree
     1608        remote_rwlock_wr_release( lock_xp );
    11401609
    11411610#if DEBUG_VFS_UNLINK
    11421611if( DEBUG_VFS_UNLINK < cycle )
    11431612printk("\n[%s] thread[%x,%x] exit / removed <%s> inode from Inode Tree / cycle %d\n",
    1144 __FUNCTION__, this->process->pid, this->trdid, path, cycle );
     1613__FUNCTION__, process->pid, this->trdid, path, cycle );
    11451614#endif
    11461615        return 0;
    11471616    }
    1148     /////////////////////////////////
    1149     else if( type == INODE_TYPE_DIR )
    1150     {
    1151         printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) );
     1617    else
     1618    {
     1619        remote_rwlock_wr_release( lock_xp );
     1620        printk("\n[ERROR] in %s : unsupported inode type %s\n",
     1621        __FUNCTION__ , vfs_inode_type_str( inode_type ) );
    11521622        return -1;
    11531623    }
    1154     ////
    1155     else
    1156     {
    1157         printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) );
     1624
     1625}  // end vfs_unlink()
     1626
     1627///////////////////////////////////////////
     1628error_t vfs_stat( xptr_t     root_inode_xp,
     1629                  char     * path,
     1630                  stat_t   * st )
     1631{
     1632    error_t       error;
     1633    xptr_t        inode_xp;           // extended pointer on target inode
     1634    vfs_inode_t * inode_ptr;          // local pointer on target inode
     1635    cxy_t         inode_cxy;          // target inode cluster identifier
     1636    xptr_t        vfs_root_xp;        // extended pointer on VFS root inode
     1637    vfs_inode_t * vfs_root_ptr;       // local_pointer on VFS root inode
     1638    cxy_t         vfs_root_cxy;       // VFS root inode cluster identifier
     1639    xptr_t        lock_xp;            // extended pointer on lock protecting Inode Tree
     1640
     1641    thread_t  * this    = CURRENT_THREAD;
     1642    process_t * process = this->process;
     1643
     1644    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1645    vfs_root_xp  = process->vfs_root_xp;
     1646    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1647    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1648    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1649
     1650    // get the lock protecting Inode Tree in read mode
     1651    remote_rwlock_rd_acquire( lock_xp );
     1652
     1653    // get extended pointer on target inode
     1654    error = vfs_lookup( root_inode_xp,
     1655                        path,
     1656                        0,
     1657                        &inode_xp,
     1658                        NULL );
     1659
     1660    // release the lock protecting Inode Tree
     1661    remote_rwlock_rd_release( lock_xp );
     1662
     1663    if( error )
     1664    {
     1665        printk("\n[ERROR] in %s : cannot found inode <%s>\n",
     1666        __FUNCTION__ , path );
    11581667        return -1;
    11591668    }
    11601669
    1161 }  // end vfs_unlink()
    1162 
    1163 //////////////////////////////////////
    1164 error_t vfs_stat( xptr_t     inode_xp,
    1165                   stat_t   * st )
    1166 {
    11671670    // get cluster and local pointer on inode descriptor
    1168     vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    1169     cxy_t         inode_cxy = GET_CXY( inode_xp );
     1671    inode_ptr = GET_PTR( inode_xp );
     1672    inode_cxy = GET_CXY( inode_xp );
    11701673
    11711674    // get relevant infos from inode descriptor
     
    11861689#if DEBUG_VFS_STAT
    11871690uint32_t cycle  = (uint32_t)hal_get_cycles();
    1188 thread_t * this = CURRENT_THREAD;
    11891691if( DEBUG_VFS_STAT < cycle )
    11901692printk("\n[%s] thread[%x,%x] set stat %x for inode %x in cluster %x / cycle %d\n"
    11911693       " %s / inum %d / size %d\n",
    1192 __FUNCTION__, this->process->pid, this->trdid, st, inode_ptr, inode_cxy, cycle,
     1694__FUNCTION__, process->pid, this->trdid, st, inode_ptr, inode_cxy, cycle,
    11931695vfs_inode_type_str( type ), inum, size );
    11941696#endif
     
    12071709}
    12081710
    1209 //////////////////////////////////////
    1210 error_t vfs_mkdir( xptr_t     file_xp,
    1211                    char     * path,
    1212                    uint32_t   mode )
    1213 {
    1214     assert( false , "not implemented file_xp: %x, path <%s>, mode: %x\n",
    1215       file_xp, path, mode );
    1216     return 0;
    1217 }
    1218 
    12191711////////////////////////////////////
    12201712error_t vfs_rmdir( xptr_t   file_xp,
     
    12261718}
    12271719
    1228 ///////////////////////////////////
    1229 error_t vfs_chdir( xptr_t   cwd_xp,
     1720////////////////////////////////////
     1721error_t vfs_chdir( xptr_t   root_xp,
    12301722                   char   * path )
    12311723{
    12321724    error_t           error;
    1233     xptr_t            inode_xp;     // extended pointer on target inode
    1234     cxy_t             inode_cxy;    // target inode cluster identifier       
    1235     vfs_inode_t     * inode_ptr;    // target inode local pointer
    1236     uint32_t          mode;         // lookup working mode       
    1237     vfs_inode_type_t  inode_type;   // target inode type
    1238 
    1239     // set lookup working mode
    1240     mode = 0;
     1725    xptr_t            inode_xp;           // extended pointer on target inode
     1726    cxy_t             inode_cxy;          // target inode cluster identifier       
     1727    vfs_inode_t     * inode_ptr;          // target inode local pointer
     1728    vfs_inode_type_t  inode_type;         // target inode type
     1729    xptr_t            vfs_root_xp;        // extended pointer on VFS root inode
     1730    vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode
     1731    cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier
     1732    xptr_t            main_lock_xp;       // extended pointer on lock protecting Inode Tree
     1733    xptr_t            ref_xp;             // extended pointer on reference process
     1734    process_t       * ref_ptr;            // local pointer on reference process
     1735    cxy_t             ref_cxy;            // reference process cluster
     1736    xptr_t            cwd_lock_xp;        // extended pointer on lock protecting CWD change
     1737    xptr_t            cwd_xp_xp;          // extended pointer on cwd_xp in reference process
     1738
     1739    thread_t  * this    = CURRENT_THREAD;
     1740    process_t * process = this->process;
     1741
     1742#if DEBUG_VFS_CHDIR
     1743uint32_t cycle = (uint32_t)hal_get_cycles();
     1744if( DEBUG_VFS_CHDIR < cycle )
     1745printk("\n[%s] thread[%x,%x] enter for path <%s> / cycle %d\n",
     1746__FUNCTION__, process->pid, this->trdid, path, cycle );
     1747#endif
     1748
     1749    // build extended pointer on lock protecting Inode Tree (in VFS root inode)
     1750    vfs_root_xp  = process->vfs_root_xp;
     1751    vfs_root_ptr = GET_PTR( vfs_root_xp );
     1752    vfs_root_cxy = GET_CXY( vfs_root_xp );
     1753    main_lock_xp = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     1754
     1755    // take lock protecting Inode Tree in read mode
     1756    remote_rwlock_rd_acquire( main_lock_xp );
    12411757
    12421758    // get extended pointer on target inode
    1243     error = vfs_lookup( cwd_xp , path , mode , &inode_xp );
    1244 
    1245     if( error ) return error;
    1246 
    1247     // get inode cluster and local pointer
     1759    error = vfs_lookup( root_xp,
     1760                        path,
     1761                        VFS_LOOKUP_DIR,
     1762                        &inode_xp,
     1763                        NULL );
     1764
     1765    // release lock protecting Inode Tree in read mode
     1766    remote_rwlock_rd_release( main_lock_xp );
     1767
     1768    if( error )
     1769    {
     1770        printk("\n[ERROR] in %s : <%s> not found\n",
     1771        __FUNCTION__, path );
     1772        return -1;
     1773    }
     1774
     1775    // get inode type from remote file
    12481776    inode_cxy = GET_CXY( inode_xp );
    12491777    inode_ptr = GET_PTR( inode_xp );
    1250 
    1251     // get inode type from remote file
    12521778    inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
    12531779
    12541780    if( inode_type != INODE_TYPE_DIR )
    12551781    {
    1256         CURRENT_THREAD->errno = ENOTDIR;
     1782        printk("\n[ERROR] in %s : <%s> is not a directory\n",
     1783        __FUNCTION__, path );
    12571784        return -1;
    12581785    }
    12591786
    1260     // TODO implement this function using process CWD lock
    1261 
    1262 assert( false , "not implemented\n" );
     1787    // build extended pointer on cwd_lock and cwd_xp
     1788    ref_xp       = process->ref_xp;
     1789    ref_ptr      = GET_PTR( ref_xp );
     1790    ref_cxy      = GET_CXY( ref_xp );
     1791    cwd_lock_xp  = XPTR( ref_cxy , &ref_ptr->cwd_lock );
     1792    cwd_xp_xp    = XPTR( ref_cxy , &ref_ptr->cwd_xp );
     1793
     1794    // take lock protecting CWD changes
     1795    remote_busylock_acquire( cwd_lock_xp );
     1796
     1797    // update cwd_xp field in reference process descriptor
     1798    hal_remote_s64( cwd_xp_xp , inode_xp );
     1799
     1800    // release lock protecting CWD changes
     1801    remote_busylock_release( cwd_lock_xp );
     1802
     1803#if DEBUG_VFS_CHDIR
     1804cycle = (uint32_t)hal_get_cycles();
     1805if( DEBUG_VFS_CHDIR < cycle )
     1806printk("\n[%s] thread[%x,%x] exit : inode (%x,%x) / &cwd_xp (%x,%x) / cycle %d\n",
     1807__FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr,
     1808GET_CXY(cwd_xp_xp), GET_PTR(cwd_xp_xp), cycle );
     1809#endif
    12631810
    12641811    return 0;
    1265 }
     1812
     1813}  // end vfs_chdir()
    12661814
    12671815///////////////////////////////////
     
    12811829 
    12821830    // get extended pointer on target inode
    1283     error = vfs_lookup( cwd_xp , path , 0 , &inode_xp );
     1831    error = vfs_lookup( cwd_xp,
     1832                        path,
     1833                        0,
     1834                        &inode_xp,
     1835                        NULL );
    12841836
    12851837    if( error ) return error;
     
    12921844    inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
    12931845
    1294    
    1295     assert( false , "not implemented\n" );
     1846    // TODO implement this function
     1847
     1848assert( false , "not implemented\n" );
     1849
    12961850    return 0;
    12971851}
     
    13601914assert( (indent < 16)           , "depth cannot be larger than 15\n" );
    13611915   
    1362     // get inode cluster and local pointer
     1916    // get current inode cluster and local pointer
    13631917    inode_cxy = GET_CXY( inode_xp );
    13641918    inode_ptr = GET_PTR( inode_xp );
     
    14281982    cxy_t          dentry_cxy;
    14291983    vfs_dentry_t * dentry_ptr;
     1984    xptr_t         parents_root_xp;   // root of parent dentries xlist
    14301985
    14311986    // get target inode cluster and local pointer
     
    14331988    vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    14341989
    1435     // get extended pointer on associated dentry
    1436     dentry_xp   = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    1437 
    1438     // check if target inode is the File System root
    1439     if( dentry_xp == XPTR_NULL )
     1990    // build extended pointer on parents dentries root
     1991    parents_root_xp = XPTR( inode_cxy , &inode_ptr->parents );
     1992
     1993    // check VFS root     
     1994    if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root
    14401995    {
    14411996        // build extended pointer on root name
     
    14441999    else
    14452000    {
    1446         // get dentry cluster and local pointer
     2001        // get first parent dentry cluster and pointers
     2002        dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
    14472003        dentry_cxy = GET_CXY( dentry_xp );
    14482004        dentry_ptr = GET_PTR( dentry_xp );
     
    15202076                             xptr_t * child_xp )
    15212077{
    1522     xptr_t  xhtab_xp;    // extended pointer on hash table containing children dentries
    1523     xptr_t  dentry_xp;   // extended pointer on children dentry
     2078    xptr_t         xhtab_xp;    // extended pointer on hash table for children dentries
     2079    xptr_t         dentry_xp;   // extended pointer on children dentry
     2080    cxy_t          dentry_cxy;
     2081    vfs_dentry_t * dentry_ptr;
    15242082
    15252083    // get parent inode cluster and local pointer
     
    15302088    xhtab_xp = XPTR( parent_cxy , &parent_ptr->children );
    15312089
    1532     // search extended pointer on matching dentry
    1533     dentry_xp = xhtab_lookup( xhtab_xp , name );
    1534 
    1535     if( dentry_xp == XPTR_NULL ) return false;
    1536 
    1537     // get dentry cluster and local pointer
    1538     cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    1539     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    1540 
    1541     // return child inode
    1542     *child_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
    1543     return true;
     2090    // get pointers on matching dentry
     2091    dentry_xp  = xhtab_lookup( xhtab_xp , name );
     2092    dentry_cxy = GET_CXY( dentry_xp );
     2093    dentry_ptr = GET_PTR( dentry_xp );
     2094
     2095    if( dentry_xp == XPTR_NULL )
     2096    {
     2097        return false;
     2098    }
     2099    else
     2100    {
     2101        *child_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
     2102        return true;
     2103    }
    15442104
    15452105}  // end vfs_get_child()
     
    15532113// last name in the path. The names are supposed to be separated by one or several '/'
    15542114// characters, that are not written in  the <name> buffer.
     2115//
     2116// WARNING: the leading characters '/' in the path are skiped before analysis.
     2117//          The path "/" identifies the VFS root, and is therefore anaysed as an empty
     2118//          string. This empty string is dignaled by the (-1) return value. 
    15552119//////////////////////////////////////////////////////////////////////////////////////////
    15562120// @ current   : pointer on first character to analyse in buffer containing the path.
     
    15582122// @ next      : [out] pointer on next character to analyse in buffer containing the path.
    15592123// @ last      : [out] true if the returned name is the last (NUL character found).
    1560 // @ return 0 if success / return EINVAL if string empty (first chracter is NUL).
     2124// @ return 0 if success / return -1 if string empty (first chracter is NUL).
    15612125//////////////////////////////////////////////////////////////////////////////////////////
    15622126static error_t vfs_get_name_from_path( char     * current,
     
    15702134    while( *ptr == '/' ) ptr++;
    15712135
    1572     // return EINVAL if string empty
    1573     if( *ptr == 0 ) return EINVAL;
     2136    // signal empty string
     2137    if( *ptr == 0 )
     2138    {
     2139        *last = true;
     2140        return -1;
     2141    }
    15742142
    15752143    // copy all characters in name until NUL or '/'
     
    15942162}  // end vfs_get name_from_path()
    15952163   
    1596 //////////////////////////////////////////////
    1597 error_t vfs_lookup( xptr_t             cwd_xp,
     2164///////////////////////////////////////////////
     2165error_t vfs_lookup( xptr_t             root_xp,
    15982166                    char             * pathname,
    1599                     uint32_t           mode,
    1600                                         xptr_t           * inode_xp )
     2167                    uint32_t           lookup_mode,
     2168                                        xptr_t           * inode_xp,
     2169                                        char             * last_name )
    16012170{
    16022171    char               name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path
     
    16192188    bool_t             create;       // searched inode must be created if not found
    16202189    bool_t             excl;         // searched inode must not exist
     2190    bool_t             par;          // searched inode is the parent
    16212191    thread_t         * this;         // pointer on calling thread descriptor
    16222192    process_t        * process;      // pointer on calling process descriptor
     
    16262196    process = this->process;
    16272197
     2198// check pathname / root_xp consistency
     2199assert( ((pathname[0] != '/') || (root_xp == process->vfs_root_xp)),
     2200"root inode must be VFS root for path <%s>\n", pathname );
     2201
    16282202#if DEBUG_VFS_LOOKUP
    16292203uint32_t cycle = (uint32_t)hal_get_cycles();
     2204char     root_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2205vfs_inode_get_name( root_xp , root_name );
    16302206if( DEBUG_VFS_LOOKUP < cycle )
    1631 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
    1632 __FUNCTION__, process->pid, this->trdid, pathname, cycle );
     2207printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / mode %x / cycle %d\n",
     2208__FUNCTION__, process->pid, this->trdid, root_name, pathname, lookup_mode, cycle );
    16332209#endif
    16342210
    16352211    // compute lookup flags
    1636     dir    = mode & VFS_LOOKUP_DIR;
    1637     create = mode & VFS_LOOKUP_CREATE;
    1638     excl   = mode & VFS_LOOKUP_EXCL;
    1639    
    1640     // get extended pointer on first inode to search
    1641     if( pathname[0] == '/' ) parent_xp = process->vfs_root_xp;
    1642     else                     parent_xp = cwd_xp;
    1643 
    1644     // initialise other loop variables
    1645     current  = pathname;
    1646     next     = NULL;
    1647     last     = false;
    1648     child_xp = XPTR_NULL;
    1649 
    1650     // take lock on parent inode
    1651     vfs_inode_lock( parent_xp );
    1652 
    1653     // sequencially loop on nodes in pathname
    1654     // load from device if one node in path not found in inode tree
     2212    dir    = (lookup_mode & VFS_LOOKUP_DIR)    == VFS_LOOKUP_DIR;
     2213    create = (lookup_mode & VFS_LOOKUP_CREATE) == VFS_LOOKUP_CREATE;
     2214    excl   = (lookup_mode & VFS_LOOKUP_EXCL)   == VFS_LOOKUP_EXCL;
     2215    par    = (lookup_mode & VFS_LOOKUP_PARENT) == VFS_LOOKUP_PARENT;
     2216
     2217    // initialise loop variables
     2218    parent_xp = root_xp;
     2219    current   = pathname;
     2220    next      = NULL;
     2221    last      = false;
     2222    child_xp  = XPTR_NULL;
     2223
     2224    // loop on nodes in pathname
     2225    // load from device if one node in path not found in Inode Tree
    16552226    // exit loop when last name found (i.e. last == true)
    1656     do
    1657     {
    1658         // get one name from path, and "last" flag
    1659         vfs_get_name_from_path( current , name , &next , &last );
     2227    while( 1 )
     2228    {
     2229        // get parent inode cluster and local pointer
     2230        parent_cxy = GET_CXY( parent_xp );
     2231        parent_ptr = GET_PTR( parent_xp );
     2232
     2233        // get one "name" from path, and "last" flag
     2234        error = vfs_get_name_from_path( current , name , &next , &last );
     2235
     2236        // VFS root case
     2237        if ( error )
     2238        {
     2239
     2240#if DEBUG_VFS_LOOKUP
     2241cycle = (uint32_t)hal_get_cycles();
     2242if( DEBUG_VFS_LOOKUP < cycle )
     2243printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n",
     2244__FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle );
     2245#endif
     2246            *inode_xp = process->vfs_root_xp;
     2247            break;
     2248        }
    16602249
    16612250#if (DEBUG_VFS_LOOKUP & 1)
     
    16652254#endif
    16662255
    1667         // search a child dentry matching name in parent inode
     2256        // search the child dentry matching name in parent inode
    16682257        found = vfs_get_child( parent_xp,
    16692258                               name,
    16702259                               &child_xp );
    16712260
    1672         if (found == false )  // child not found in inode tree
     2261        // analyse found & last, depending on lookup_mode
     2262        if( found == false )                              // not found in Inode Tree
    16732263        {
     2264            // when a inode is not found in the Inode Tree:
     2265            // - if (last and par) the Inode Tree is not modified
     2266            // - else we speculatively introduce a new (dentry/inode) in inode tree,
     2267            //        and scan the parent directory mapper to initialise it.
     2268            //     . if it is not found in the parent mapper:
     2269            //         - if(last and create), a brand new file or directory is created
     2270            //         - else, an error is reported
     2271            //     . if it is found in parent mapper:
     2272            //         - if( last and excl ), an error is reported
     2273            //         - else the new child (inode & dentry) is initialised in Inode Tree
     2274            //         - if the child is a directory, the child mapper is loaded from device
     2275
     2276            if( last && par )   //  does nothing
     2277            {
    16742278
    16752279#if (DEBUG_VFS_LOOKUP & 1)
    16762280if( DEBUG_VFS_LOOKUP < cycle )
    1677 printk("\n[%s] thread[%x,%x] miss <%s> node => try to create it\n",
     2281printk("\n[%s] thread[%x,%x] child not found but only parent requested in <%s>\n",
     2282__FUNCTION__, process->pid, this->trdid, pathname );
     2283#endif
     2284            }
     2285            else                                    // try to get it from parent mapper
     2286            {
     2287
     2288#if (DEBUG_VFS_LOOKUP & 1)
     2289if( DEBUG_VFS_LOOKUP < cycle )
     2290printk("\n[%s] thread[%x,%x] miss <%s> inode in Inode Tree => build from parent mapper\n",
    16782291__FUNCTION__, process->pid, this->trdid, name );
    16792292#endif
    1680             // if a child node is not found in the inode tree,
    1681             // we introduce a new (dentry/inode) in inode tree,
    1682             // and try to find it by scanning the parent directory mapper.
    1683             // . if it is found in parent mapper:
    1684             //   - if the child is a directory, the child mapper is loaded from device
    1685             //   - if the child is not a directory, the search is completed
    1686             // . if it is not found in the parent mapper:
    1687             //   - if ( not last or not create ) an error is reported
    1688             //   - if (last and create) a new file or directory is created
    1689 
    1690             // release lock on parent inode
    1691             vfs_inode_unlock( parent_xp );
     2293                // get parent inode FS type
     2294                ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
     2295                fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
     2296
     2297                // select a cluster for new inode
     2298                child_cxy = cluster_random_select();
     2299
     2300                // define child inode type
     2301                if( dir ) child_type = INODE_TYPE_DIR;
     2302                else      child_type = INODE_TYPE_FILE;
    16922303 
    1693             // get parent inode cluster and local pointer
    1694             parent_cxy = GET_CXY( parent_xp );
    1695             parent_ptr = GET_PTR( parent_xp );
    1696 
    1697             // get parent inode FS type
    1698             ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) );
    1699             fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) );
    1700 
    1701             // select a cluster for missing inode
    1702             child_cxy = cluster_random_select();
    1703 
    1704             // define child inode type
    1705             if( dir ) child_type = INODE_TYPE_DIR;
    1706             else      child_type = INODE_TYPE_FILE;
    1707  
    1708             // insert a new child dentry/inode in inode tree
    1709             error = vfs_add_child_in_parent( child_cxy,
    1710                                              child_type,
    1711                                              fs_type,
    1712                                              parent_xp,
    1713                                              name,
    1714                                              &dentry_xp,
    1715                                              &child_xp );
    1716             if( error )
    1717             {
    1718                 printk("\n[ERROR] in %s : cannot create node <%s> in path <%s>\n",
    1719                 __FUNCTION__ , name, pathname );
    1720                 return -1;
    1721             }
    1722 
    1723             // get child inode local pointer
    1724             child_ptr = GET_PTR( child_xp );
     2304                // insert (speculatively) a new child dentry/inode in inode tree
     2305                error = vfs_add_child_in_parent( child_cxy,
     2306                                                 child_type,
     2307                                                 fs_type,
     2308                                                 parent_xp,
     2309                                                 name,
     2310                                                 &dentry_xp,
     2311                                                 &child_xp );
     2312                if( error )
     2313                {
     2314                    printk("\n[ERROR] in %s : cannot create inode <%s> in path <%s>\n",
     2315                    __FUNCTION__ , name, pathname );
     2316                    return -1;
     2317                }
     2318
     2319                // get child inode local pointer
     2320                child_ptr = GET_PTR( child_xp );
    17252321
    17262322#if (DEBUG_VFS_LOOKUP & 1)
     
    17292325__FUNCTION__, process->pid, this->trdid, name, child_cxy );
    17302326#endif
    1731             // scan parent mapper to find the missing dentry, and complete
    1732             // the initialisation of dentry and child inode desciptors
    1733             if( parent_cxy == local_cxy )
    1734 
    1735             {
    1736                 error = vfs_fs_child_init( parent_ptr,
    1737                                            name,
    1738                                            child_xp );
    1739             }
    1740             else
    1741             {
    1742                 rpc_vfs_fs_child_init_client( parent_cxy,
    1743                                               parent_ptr,
    1744                                               name,
    1745                                               child_xp,
    1746                                               &error );
    1747             }
    1748 
    1749             if ( error )   // child not found in parent mapper
    1750             {
    1751                 if ( last && create )  // add a new dentry in parent
     2327                // scan parent mapper to find the missing dentry, and complete
     2328                // the initialisation of dentry and child inode desciptors
     2329                if( parent_cxy == local_cxy )
     2330
    17522331                {
    1753                     error = vfs_new_child_init( parent_xp,               
    1754                                                 dentry_xp,
    1755                                                 child_xp );
    1756                     if ( error )
     2332                    error = vfs_fs_child_init( parent_ptr,
     2333                                               name,
     2334                                               child_xp );
     2335                }
     2336                else
     2337                {
     2338                    rpc_vfs_fs_child_init_client( parent_cxy,
     2339                                                  parent_ptr,
     2340                                                  name,
     2341                                                  child_xp,
     2342                                                  &error );
     2343                }
     2344
     2345                if ( error )   // child not found in parent mapper
     2346                {
     2347                    if ( last && create )  // add a brand new dentry in parent
    17572348                    {
    1758                         printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
    1759                         __FUNCTION__, name, pathname );
    1760                         vfs_remove_child_from_parent( child_xp );
     2349                        error = vfs_new_child_init( parent_xp,               
     2350                                                    dentry_xp,
     2351                                                    child_xp );
     2352                        if ( error )
     2353                        {
     2354                            printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n",
     2355                            __FUNCTION__, name, pathname );
     2356                            vfs_remove_child_from_parent( dentry_xp );
     2357                            return -1;
     2358                        }
     2359
     2360#if (DEBUG_VFS_LOOKUP & 1)
     2361if( DEBUG_VFS_LOOKUP < cycle )
     2362printk("\n[%s] thread[%x,%x] child <%s> not found in parent mapper => create it\n",
     2363__FUNCTION__, process->pid, this->trdid, name );
     2364#endif
     2365                    }
     2366                    else                   // not last or not create => error
     2367                    {                       
     2368                        printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
     2369                        __FUNCTION__ , name , pathname );
     2370                        vfs_remove_child_from_parent( dentry_xp );
    17612371                        return -1;
    17622372                    }
     2373                }
     2374                else          // child has been found in parent mapper
     2375                {
     2376                    // check the excl
     2377                    if( last && create && excl )
     2378                    {
     2379                        printk("\n[ERROR] in %s : node already exist <%s>\n",
     2380                        __FUNCTION__, name );
     2381                       return -1;
     2382                    }
    17632383
    17642384#if (DEBUG_VFS_LOOKUP & 1)
    17652385if( DEBUG_VFS_LOOKUP < cycle )
    1766 printk("\n[%s] thread[%x,%x] created inode <%s> in path\n",
     2386printk("\n[%s] thread[%x,%x] initialised inode <%s> from parent mapper\n",
    17672387__FUNCTION__, process->pid, this->trdid, name );
    17682388#endif
    1769                 }
    1770                 else                   // not last or not create => error
    1771                 {                       
    1772                      printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n",
    1773                      __FUNCTION__ , name , pathname );
    1774                      vfs_remove_child_from_parent( child_xp );
    1775                      return ENOENT;
     2389                    // load child mapper from device if child is a directory (prefetch)
     2390                    uint32_t type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
     2391                    if( type == INODE_TYPE_DIR )
     2392                    {
     2393                        if( child_cxy == local_cxy )
     2394                        {
     2395                            error = vfs_inode_load_all_pages( child_ptr );
     2396                        }
     2397                        else
     2398                        {
     2399                            rpc_vfs_inode_load_all_pages_client( child_cxy,
     2400                                                                 child_ptr,
     2401                                                                 &error );
     2402                        }
     2403                        if ( error )
     2404                        {
     2405                            printk("\n[ERROR] in %s : cannot load <%s> from device\n",
     2406                            __FUNCTION__ , name );
     2407                            vfs_remove_child_from_parent( dentry_xp );
     2408                            return -1;
     2409                        }
     2410
     2411#if (DEBUG_VFS_LOOKUP & 1)
     2412if( DEBUG_VFS_LOOKUP < cycle )
     2413printk("\n[%s] thread[%x,%x] loaded directory mapper for <%s> from IOC\n",
     2414__FUNCTION__ , process->pid, this->trdid, name );
     2415#endif
     2416                    }
    17762417                }
    17772418            }
    1778             else          // child found in parent mapper
    1779             {
    1780                 // load child mapper from device if child is a directory (prefetch)
    1781                 if( hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ) == INODE_TYPE_DIR )
    1782                 {
    1783                     if( child_cxy == local_cxy )
    1784                     {
    1785                         error = vfs_inode_load_all_pages( child_ptr );
    1786                     }
    1787                     else
    1788                     {
    1789                         rpc_vfs_inode_load_all_pages_client( child_cxy,
    1790                                                              child_ptr,
    1791                                                              &error );
    1792                     }
    1793                     if ( error )
    1794                     {
    1795                         printk("\n[ERROR] in %s : cannot load <%s> from device\n",
    1796                         __FUNCTION__ , name );
    1797                         vfs_remove_child_from_parent( child_xp );
    1798                         return EIO;
    1799                     }
    1800 
    1801 #if (DEBUG_VFS_LOOKUP & 1)
    1802 if( DEBUG_VFS_LOOKUP < cycle )
    1803 printk("\n[%s] thread[%x,%x] loaded from IOC device mapper for <%s> in <%s>\n",
    1804 __FUNCTION__ , process->pid, this->trdid, name, pathname );
    1805 #endif
    1806                 }
    1807             }
    1808 
    1809             // take lock on parent inode
    1810             vfs_inode_lock( parent_xp );
    18112419        }
    1812         else   // child found in inode tree
     2420        else                                    // child directly found in inode tree
    18132421        {
    18142422       
    18152423#if (DEBUG_VFS_LOOKUP & 1)
    18162424if( DEBUG_VFS_LOOKUP < cycle )
    1817 printk("\n[%s] thread[%x,%x] found <%s> / inode %x in cluster %x\n",
    1818 __FUNCTION__, process->pid, this->trdid, name, GET_PTR(child_xp), GET_CXY(child_xp) );
    1819 #endif
     2425printk("\n[%s] thread[%x,%x] found <%s> in Inode Tree / inode (%x,%x)\n",
     2426__FUNCTION__, process->pid, this->trdid, name, GET_CXY(child_xp), GET_PTR(child_xp) );
     2427#endif
     2428            // get child inode local pointer and cluster
    18202429            child_ptr  = GET_PTR( child_xp );
    18212430            child_cxy  = GET_CXY( child_xp );
    1822             parent_cxy = GET_CXY( parent_xp );
    1823             parent_ptr = GET_PTR( parent_xp );
    1824 
    1825             if( last && (mode & VFS_LOOKUP_CREATE) && (mode & VFS_LOOKUP_EXCL) )
     2431
     2432            // check the excl flag
     2433            if( last && create && excl )
    18262434            {
    1827                 printk("\n[ERROR] in %s : node already exist <%s>\n", __FUNCTION__, name );
    1828                 return EINVAL;
     2435                printk("\n[ERROR] in %s : node <%s> already exist\n",
     2436                __FUNCTION__, name );
     2437                return -1;
    18292438            }
    18302439        }
     
    18422451
    18432452        // take lock on child inode and release lock on parent
    1844         vfs_inode_lock( child_xp );
    1845         vfs_inode_unlock( parent_xp );
    1846 
    1847         // update loop variables
    1848         parent_xp = child_xp;
    1849         current   = next;
    1850     }
    1851     while( last == false );
    1852 
    1853     // release lock
    1854     vfs_inode_unlock( parent_xp );
     2453        // vfs_inode_lock( child_xp );
     2454        // vfs_inode_unlock( parent_xp );
     2455
     2456        // exit when last
     2457        if ( last )           // last inode in path  => return relevant info
     2458        {
     2459            if ( par )  // return parent inode and child name
     2460            {
    18552461
    18562462#if DEBUG_VFS_LOOKUP
    18572463cycle = (uint32_t)hal_get_cycles();
    18582464if( DEBUG_VFS_LOOKUP < cycle )
    1859 printk("\n[%s] thread[%x,%x] exit for <%s> cycle %d\n",
    1860 __FUNCTION__ , process->pid, this->trdid, pathname, cycle );
    1861 #endif
    1862 
    1863     // return searched pointer
    1864     if( mode & VFS_LOOKUP_PARENT ) *inode_xp = parent_xp;
    1865     else                           *inode_xp = child_xp;
     2465printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n",
     2466__FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle );
     2467#endif
     2468                *inode_xp = parent_xp;
     2469                strcpy( last_name , name );
     2470                break;
     2471            }
     2472            else        // return child inode name     
     2473            {
     2474
     2475#if DEBUG_VFS_LOOKUP
     2476cycle = (uint32_t)hal_get_cycles();
     2477if( DEBUG_VFS_LOOKUP < cycle )
     2478printk("\n[%s] thread[%x,%x] exit / child inode (%x,%x) / <%s> / cycle %d\n",
     2479__FUNCTION__ , process->pid, this->trdid, child_cxy, child_ptr, pathname, cycle );
     2480#endif
     2481                *inode_xp = child_xp;
     2482                break;
     2483            }
     2484        }
     2485        else                     // not the last inode in path => update loop variables
     2486        {
     2487            parent_xp = child_xp;
     2488            current   = next;
     2489        }
     2490    }
    18662491
    18672492    return 0;
    18682493
    18692494}  // end vfs_lookup()
    1870 
    1871 
    18722495
    18732496///////////////////////////////////////////////
     
    19542577cycle = (uint32_t)hal_get_cycles();
    19552578if( DEBUG_VFS_NEW_CHILD_INIT < cycle )
    1956 printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%> / cycle %d\n",
     2579printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n",
    19572580__FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle );
    19582581#endif
     
    19622585}  // end vfs_new_child_init()
    19632586
    1964 ////////////////////////////////////////////
    1965 error_t vfs_get_path( xptr_t    searched_xp,
    1966                       char    * buffer,
    1967                       uint32_t  max_size )
    1968 {
    1969         xptr_t       dentry_xp;   // extended pointer on current dentry
    1970     char       * name;        // local pointer on current dentry name
    1971         uint32_t     length;      // length of current dentry name
    1972         uint32_t     count;       // number of characters written in buffer
    1973         uint32_t     index;       // slot index in buffer
    1974     xptr_t       inode_xp;    // extended pointer on   
    1975 
    1976     // implementation note:
    1977     // we use two variables "index" and "count" because the buffer
    1978     // is written in decreasing index order (from leaf to root)
    1979     // TODO  : handle conflict with a concurrent rename [AG]
    1980     // FIXME : handle synchro in the loop  [AG]
    1981 
    1982         // set the NUL character in buffer / initialise buffer index and count
     2587//////////////////////////////////////////
     2588error_t vfs_get_path( xptr_t     inode_xp,
     2589                      char     * buffer,
     2590                      char    ** first,
     2591                      uint32_t   max_size )
     2592{
     2593        xptr_t         dentry_xp;        // extended pointer on current dentry
     2594    vfs_dentry_t * dentry_ptr;       // local pointer on current dentry
     2595    cxy_t          dentry_cxy;       // current dentry cluster identifier
     2596    xptr_t         name_xp;          // extended pointer on current dentry name
     2597        uint32_t       length;           // length of current dentry name
     2598        int32_t        index;            // slot index in buffer
     2599    xptr_t         current_xp;       // extended pointer on current inode
     2600    vfs_inode_t  * current_ptr;      // local pointer on current inode
     2601    cxy_t          current_cxy;      // current inode cluster identifier
     2602    xptr_t         vfs_root_xp;      // extended pointer on VFS root inode
     2603    vfs_inode_t  * vfs_root_ptr;     // local pointer on VFS root inode
     2604    cxy_t          vfs_root_cxy;     // VFS root inode cluster identifier
     2605    xptr_t         lock_xp;          // extended pointer on Inode Tree lock
     2606    xptr_t         parents_root_xp;  // extended pointer on current inode parents root
     2607    bool_t         found;            // condition to exit the while loop
     2608
     2609    thread_t  * this    = CURRENT_THREAD;
     2610    process_t * process = this->process;
     2611
     2612#if DEBUG_VFS_GET_PATH
     2613uint32_t cycle = (uint32_t)hal_get_cycles();
     2614if( DEBUG_VFS_GET_PATH < cycle )
     2615printk("\n[%s] thread[%x,%x] enter : inode (%x,%x) / cycle %d\n",
     2616__FUNCTION__ , process->pid, this->trdid,
     2617GET_CXY( inode_xp ), GET_PTR( inode_xp ), cycle );
     2618#endif
     2619
     2620        // set the NUL character in buffer / initialise buffer index
    19832621        buffer[max_size - 1] = 0;
    1984         count    = 1;
    1985     index    = max_size - 2;
     2622    index    = (int32_t)(max_size - 1);
    19862623
    19872624    // initialize current inode
    1988     inode_xp  = searched_xp;
    1989 
    1990     // exit when root inode found (i.e. dentry_xp == XPTR_NULL)
     2625    current_xp  = inode_xp;
     2626
     2627    // build extended pointer on lock protecting Inode Tree
     2628    vfs_root_xp  = process->vfs_root_xp;
     2629    vfs_root_ptr = GET_PTR( vfs_root_xp );
     2630    vfs_root_cxy = GET_CXY( vfs_root_xp );
     2631    lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock );
     2632
     2633    // take lock protecting Inode Tree in read mode
     2634    remote_rwlock_rd_acquire( lock_xp );
     2635
     2636    // traverse Inode Tree from target inode to VFS root
     2637    // selecting always the first parent dentry
     2638    // the buffer is written in "reverse order" (from target inode to root)
     2639    // exit the while loop when the VFS root has been found
    19912640        do
    19922641    {
    1993         // get inode cluster and local pointer
    1994         cxy_t         inode_cxy = GET_CXY( inode_xp );
    1995         vfs_inode_t * inode_ptr = GET_PTR( inode_xp );
    1996 
    1997         // get extended pointer on parent dentry               
    1998         dentry_xp = (xptr_t)hal_remote_l64( XPTR( inode_cxy , inode_ptr->parent_xp ) );
    1999 
    2000         // get dentry cluster and local pointer
    2001         cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    2002         vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    2003 
    2004         // get dentry name length and pointer
    2005         length =  hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->length ) );
    2006         name   = (char *)hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->name ) );
    2007 
    2008         // update index and count
    2009         index -= (length + 1);
    2010         count += (length + 1);
    2011 
    2012         // check buffer overflow
    2013         if( count >= max_size )
     2642        // get current inode cluster and local pointer
     2643        current_cxy = GET_CXY( current_xp );
     2644        current_ptr = GET_PTR( current_xp );
     2645
     2646        // build extended pointer on parents dentries root
     2647        parents_root_xp = XPTR( current_cxy , &current_ptr->parents );
     2648
     2649        // compute exit condition <=> current inode is VFS root   
     2650        found = xlist_is_empty( parents_root_xp );
     2651
     2652        if( found )                              // parent is the VFS root
    20142653        {
    2015             printk("\n[ERROR] in %s : kernel buffer too small\n", __FUNCTION__ );
    2016             return EINVAL;
     2654            if( index == (int32_t)(max_size - 1) )
     2655            {
     2656                // update index
     2657                index--;
     2658                 
     2659                // set separator 
     2660                        buffer[index] = '/';
     2661
     2662// check buffer overflow
     2663assert( (index >= 0) , "kernel buffer too small\n" );
     2664
     2665            }
    20172666        }
    2018 
    2019         // update pathname
    2020         hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
    2021                            XPTR( dentry_cxy , name ) , length );
    2022                 buffer[index] = '/';
    2023 
    2024                 // get extended pointer on next inode
    2025         inode_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , dentry_ptr->parent ) );
    2026     }
    2027     while( (dentry_xp != XPTR_NULL) );
    2028 
     2667        else                                     // not the VFS root
     2668        {
     2669            // get first parent dentry cluster and pointers
     2670            dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents );
     2671            dentry_cxy = GET_CXY( dentry_xp );
     2672            dentry_ptr = GET_PTR( dentry_xp );
     2673
     2674            // get extended pointer on dentry name and name length
     2675            name_xp = XPTR( dentry_cxy , dentry_ptr->name );
     2676            length  = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->length ) );
     2677
     2678#if (DEBUG_VFS_GET_PATH & 1)
     2679char debug_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2680hal_remote_strcpy( XPTR( local_cxy , debug_name ) , name_xp );
     2681if( DEBUG_VFS_GET_PATH < cycle )
     2682printk("\n[%s] thread(%x,%s) get current dentry <%s> in cluster %x\n",
     2683__FUNCTION__ , process->pid, this->trdid, debug_name, current_cxy );
     2684#endif
     2685            // update index
     2686            index -= (length + 1);
     2687
     2688// check buffer overflow
     2689assert( (index >= 0) , "kernel buffer too small\n" );
     2690
     2691            // update pathname
     2692            hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) ,
     2693                               name_xp , length );
     2694
     2695            // set separator 
     2696                    buffer[index] = '/';
     2697
     2698            // get extended pointer on parent inode
     2699            current_xp = XPTR( dentry_cxy ,
     2700                               hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) ) );
     2701        }
     2702    }
     2703    while( found == false );
     2704
     2705    // release lock protecting Inode Tree in read mode
     2706    remote_rwlock_rd_release( lock_xp );
     2707
     2708#if DEBUG_VFS_GET_PATH
     2709cycle = (uint32_t)hal_get_cycles();
     2710if( DEBUG_VFS_GET_PATH < cycle )
     2711printk("\n[%s] thread[%x,%x] exit : path <%s> / cycle %d\n",
     2712__FUNCTION__ , process->pid, this->trdid, &buffer[index], cycle );
     2713#endif
     2714
     2715    // return pointer on first character in buffer
     2716    *first = &buffer[index];
    20292717        return 0;
    20302718
     
    20332721     
    20342722////////////////////////////////////////////////////////////////////
    2035 error_t vfs_add_child_in_parent( cxy_t              child_inode_cxy,
    2036                                  vfs_inode_type_t   child_inode_type,
     2723error_t vfs_add_child_in_parent( cxy_t              child_cxy,
     2724                                 vfs_inode_type_t   child_type,
    20372725                                 vfs_fs_type_t      fs_type,
    20382726                                 xptr_t             parent_inode_xp,
    20392727                                 char             * name,
    2040                                  xptr_t           * dentry_xp,
     2728                                 xptr_t           * child_dentry_xp,
    20412729                                 xptr_t           * child_inode_xp )
    20422730{
    2043     error_t         error;
    2044     xptr_t          new_dentry_xp;       // extended pointer on created dentry
    2045     vfs_dentry_t  * new_dentry_ptr;      // created dentry local pointer
    2046     xptr_t          new_inode_xp;        // extended pointer on created child inode
    2047     cxy_t           parent_inode_cxy;    // parent inode cluster identifier
    2048     vfs_inode_t   * parent_inode_ptr;    // parent inode local pointer
    2049 
    2050     // get parent inode cluster and local pointer
    2051     parent_inode_cxy = GET_CXY( parent_inode_xp );
     2731    error_t        error;
     2732    cxy_t          parent_cxy;          // parent inode cluster identifier
     2733    vfs_inode_t  * parent_inode_ptr;    // parent inode local pointer
     2734    xptr_t         new_dentry_xp;       // extended pointer on created dentry
     2735    vfs_dentry_t * new_dentry_ptr;      // created dentry local pointer
     2736    xptr_t         new_inode_xp;        // extended pointer on created child inode
     2737    vfs_inode_t  * new_inode_ptr;       // local pointer on created child inode
     2738
     2739    xptr_t         parents_root_xp;     // extended pointer on child inode  "parents" field
     2740    xptr_t         parents_entry_xp;    // extended pointer on child dentry "parents" field
     2741    xptr_t         children_xhtab_xp;   // extended pointer on parent inode "children" field
     2742    xptr_t         children_entry_xp;   // extended pointer on child dentry "children" field
     2743   
     2744    // get parent inode cluster and pointer
     2745    parent_cxy       = GET_CXY( parent_inode_xp );
    20522746    parent_inode_ptr = GET_PTR( parent_inode_xp );
    20532747
     
    20582752thread_t * this = CURRENT_THREAD;
    20592753if( DEBUG_VFS_ADD_CHILD < cycle )
    2060 printk("\n[%s] thread[%x,%x] enter / child <%s> cxy %x / parent <%s> cxy %x / cycle %d\n",
    2061 __FUNCTION__, this->process->pid, this->trdid, name, child_inode_cxy,
    2062 parent_name, parent_inode_cxy, (uint32_t)hal_get_cycles() );
    2063 #endif
    2064 
    2065     // 1. create dentry
    2066     if( parent_inode_cxy == local_cxy )      // parent cluster is the local cluster
     2754printk("\n[%s] thread[%x,%x] enter / child <%s> / parent <%s> / cycle %d\n",
     2755__FUNCTION__, this->process->pid, this->trdid, name,
     2756parent_name, (uint32_t)hal_get_cycles() );
     2757#endif
     2758
     2759    // 1. create dentry in parent cluster
     2760    if( parent_cxy == local_cxy )           // parent cluster is local
    20672761    {
    20682762        error = vfs_dentry_create( fs_type,
    20692763                                   name,
    2070                                    parent_inode_ptr,
    20712764                                   &new_dentry_xp );
    20722765    }
    2073     else                               // parent cluster is remote
    2074     {
    2075         rpc_vfs_dentry_create_client( parent_inode_cxy,
     2766    else                                    // parent cluster is remote
     2767    {
     2768        rpc_vfs_dentry_create_client( parent_cxy,
    20762769                                      fs_type,
    20772770                                      name,
    2078                                       parent_inode_ptr,
    20792771                                      &new_dentry_xp,
    20802772                                      &error );
     
    20842776    {
    20852777        printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n",
    2086         __FUNCTION__ , name , parent_inode_cxy );
     2778        __FUNCTION__ , name , parent_cxy );
    20872779        return -1;
    20882780    }
     
    20932785#if(DEBUG_VFS_ADD_CHILD & 1)
    20942786if( DEBUG_VFS_ADD_CHILD < cycle )
    2095 printk("\n[%s] thread[%x,%x] / dentry <%s> created in cluster %x\n",
    2096 __FUNCTION__, this->process->pid, this->trdid, name, parent_inode_cxy );
    2097 #endif
    2098 
    2099     // 2. create child inode TODO : define attr / mode / uid / gid
     2787printk("\n[%s] thread[%x,%x] / dentry <%s> created (%x,%x)\n",
     2788__FUNCTION__, this->process->pid, this->trdid, name, parent_cxy, new_dentry_ptr );
     2789#endif
     2790
     2791    // 2. create child inode in child cluster
     2792    // TODO : define attr / mode / uid / gid
    21002793    uint32_t attr = 0;
    21012794    uint32_t mode = 0;
     
    21032796    uint32_t gid  = 0;
    21042797   
    2105     if( child_inode_cxy == local_cxy )      // child cluster is the local cluster
    2106     {
    2107         error = vfs_inode_create( new_dentry_xp,
    2108                                   fs_type,
    2109                                   child_inode_type,
     2798    if( child_cxy == local_cxy )      // child cluster is local
     2799    {
     2800        error = vfs_inode_create( fs_type,
     2801                                  child_type,
    21102802                                  attr,
    21112803                                  mode,
     
    21162808    else                              // child cluster is remote
    21172809    {
    2118         rpc_vfs_inode_create_client( child_inode_cxy,
    2119                                      new_dentry_xp,
     2810        rpc_vfs_inode_create_client( child_cxy,
    21202811                                     fs_type,
    2121                                      child_inode_type,
     2812                                     child_type,
    21222813                                     attr,
    21232814                                     mode,
     
    21312822    {
    21322823        printk("\n[ERROR] in %s : cannot create inode in cluster %x\n",
    2133                __FUNCTION__ , child_inode_cxy );
     2824               __FUNCTION__ , child_cxy );
    21342825 
    2135         if( parent_inode_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
    2136         else rpc_vfs_dentry_destroy_client( parent_inode_cxy , new_dentry_ptr );
     2826        if( parent_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr );
     2827        else rpc_vfs_dentry_destroy_client( parent_cxy , new_dentry_ptr );
    21372828        return -1;
    21382829    }
    21392830
     2831    // get new inode local pointer
     2832    new_inode_ptr = GET_PTR( new_inode_xp );
     2833   
    21402834#if(DEBUG_VFS_ADD_CHILD & 1)
    21412835if( DEBUG_VFS_ADD_CHILD < cycle )
    2142 printk("\n[%s] thread[%x,%x] / inode <%s> created in cluster %x\n",
    2143 __FUNCTION__ , this->process->pid, this->trdid, name , child_inode_cxy );
    2144 #endif
    2145 
    2146     // 3. update "child_xp" field in dentry and increment refcounts
    2147     hal_remote_s64( XPTR( parent_inode_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp );
    2148     vfs_inode_remote_up( new_inode_xp );
    2149     vfs_dentry_remote_up( new_dentry_xp );
     2836printk("\n[%s] thread[%x,%x] / inode <%s> created (%x,%x)\n",
     2837__FUNCTION__ , this->process->pid, this->trdid, name , child_cxy, new_inode_ptr );
     2838#endif
     2839
     2840    // 3. register new_dentry in new_inode xlist of parents
     2841    parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents );
     2842    parents_entry_xp = XPTR( parent_cxy, &new_dentry_ptr->parents );
     2843    xlist_add_first( parents_root_xp , parents_entry_xp );
     2844    hal_remote_atomic_add( XPTR( child_cxy , &new_inode_ptr->links ) , 1 );
     2845
     2846#if(DEBUG_VFS_ADD_CHILD & 1)
     2847if( local_cxy == 1 )
     2848// if( DEBUG_VFS_ADD_CHILD < cycle )
     2849printk("\n[%s] thread[%x,%x] / dentry (%x,%x) registered in child inode (%x,%x)\n",
     2850__FUNCTION__, this->process->pid, this->trdid,
     2851parent_cxy, new_dentry_ptr, child_cxy, new_inode_ptr );
     2852#endif
     2853
     2854    // 4. register new_dentry in parent_inode xhtab of children
     2855    children_xhtab_xp = XPTR( parent_cxy , &parent_inode_ptr->children );
     2856    children_entry_xp = XPTR( parent_cxy , &new_dentry_ptr->children );
     2857    xhtab_insert( children_xhtab_xp , name , children_entry_xp );
     2858
     2859#if(DEBUG_VFS_ADD_CHILD & 1)
     2860if( DEBUG_VFS_ADD_CHILD < cycle )
     2861printk("\n[%s] thread[%x,%x] / dentry (%x,%x) registered in parent inode (%x,%x)\n",
     2862__FUNCTION__, this->process->pid, this->trdid,
     2863parent_cxy, new_dentry_ptr, parent_cxy, parent_inode_ptr );
     2864#endif
     2865
     2866    // 5. update "parent" and "child_xp" fields in new_dentry
     2867    hal_remote_s64( XPTR( parent_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp );
     2868    hal_remote_spt( XPTR( parent_cxy , &new_dentry_ptr->parent ) , parent_inode_ptr );
    21502869
    21512870#if DEBUG_VFS_ADD_CHILD
     
    21572876
    21582877    // return extended pointer on dentry & child inode
    2159     *dentry_xp      = new_dentry_xp;
    2160     *child_inode_xp = new_inode_xp;
     2878    *child_dentry_xp = new_dentry_xp;
     2879    *child_inode_xp  = new_inode_xp;
    21612880    return 0;
    21622881
    21632882}  // end vfs_add_child_in_parent()
    21642883
    2165 ////////////////////////////////////////////////////
    2166 void vfs_remove_child_from_parent( xptr_t inode_xp )
    2167 {
    2168     cxy_t          inode_cxy;
    2169     vfs_inode_t  * inode_ptr;
    2170     xptr_t         dentry_xp;
    2171     cxy_t          dentry_cxy;
    2172     vfs_dentry_t * dentry_ptr;
     2884/////////////////////////////////////////////////////
     2885void vfs_remove_child_from_parent( xptr_t dentry_xp )
     2886{
     2887    cxy_t          parent_cxy;         // parent inode cluster identifier
     2888    cxy_t          child_cxy;          // child inode cluster identifier
     2889    vfs_dentry_t * dentry_ptr;         // local pointer on dentry
     2890    xptr_t         child_inode_xp;     // extended pointer on child inode
     2891    vfs_inode_t  * child_inode_ptr;    // local pointer on child inode
     2892    vfs_inode_t  * parent_inode_ptr;   // local pointer on parent inode
     2893    uint32_t       links;              // number of child inode parents
     2894
     2895    char dentry_name[CONFIG_VFS_MAX_NAME_LENGTH];
    21732896   
    2174     // get inode cluster and local pointer
    2175     inode_cxy = GET_CXY( inode_xp );
    2176     inode_ptr = GET_PTR( inode_xp );
    2177 
    2178     // get associated dentry cluster and pointers
    2179     dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
    2180     dentry_cxy = GET_CXY( dentry_xp );
     2897    // get parent cluster and dentry local pointer
     2898    parent_cxy = GET_CXY( dentry_xp );
    21812899    dentry_ptr = GET_PTR( dentry_xp );
    21822900
    2183 // check dentry refcount
    2184 assert( ( hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) ) == 1 ),
    2185 "dentry refcount must be 1\n" );
    2186 
    2187 // check inode refcount
    2188 assert( ( hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) ) == 1 ),
    2189 "inode refcount must be 1\n" );
    2190 
    2191     // decrement refcount for inode and dentry
    2192     vfs_inode_remote_down( inode_xp );
    2193     vfs_dentry_remote_down( dentry_xp );
    2194 
    2195     // delete dentry
    2196     if( dentry_cxy == local_cxy )
     2901    // get a local copy of dentry name
     2902    hal_remote_strcpy( XPTR( local_cxy  , dentry_name ),
     2903                       XPTR( parent_cxy , &dentry_ptr->name ) );
     2904
     2905    // get parent_inode local pointer
     2906    parent_inode_ptr = hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->parent ) );
     2907 
     2908    // get child cluster and child_inode pointers
     2909    child_inode_xp   = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2910    child_cxy        = GET_CXY( child_inode_xp );
     2911    child_inode_ptr  = GET_PTR( child_inode_xp );
     2912
     2913    // remove dentry from parent_inode
     2914    xhtab_remove( XPTR( parent_cxy , &parent_inode_ptr->children ),
     2915                  dentry_name,
     2916                  XPTR( parent_cxy , &dentry_ptr->children ) );
     2917
     2918    // remove dentry from child_inode
     2919    xlist_unlink( XPTR( parent_cxy , &dentry_ptr->parents ) );
     2920    links = hal_remote_atomic_add( XPTR( child_cxy , &child_inode_ptr->links ) , -1 );
     2921
     2922    // delete dentry descriptor
     2923    if( parent_cxy == local_cxy )
    21972924    {
    21982925         vfs_dentry_destroy( dentry_ptr );
     
    22002927    else
    22012928    {
    2202          rpc_vfs_dentry_destroy_client( dentry_cxy,
     2929         rpc_vfs_dentry_destroy_client( parent_cxy,
    22032930                                        dentry_ptr );
    22042931    }
    22052932
    2206     // delete inode
    2207     if( inode_cxy == local_cxy )
    2208     {
    2209          vfs_inode_destroy( inode_ptr );
    2210     }
    2211     else
    2212     {
    2213          rpc_vfs_inode_destroy_client( inode_cxy,
    2214                                        inode_ptr );
     2933    // delete child_inode descriptor if last link
     2934    if( links == 1 )
     2935    {
     2936        if( child_cxy == local_cxy )
     2937        {
     2938            vfs_inode_destroy( child_inode_ptr );
     2939        }
     2940        else
     2941        {
     2942            rpc_vfs_inode_destroy_client( child_cxy , child_inode_ptr );
     2943        }
    22152944    }
    22162945
     
    23743103} // end vfs_fs_child_init()
    23753104
     3105////////////////////////////////////////////////
     3106error_t vfs_fs_sync_inode( vfs_inode_t * inode )
     3107{
     3108    error_t error = 0;
     3109
     3110// check arguments
     3111assert( (inode != NULL) , "inode pointer is NULL\n");
     3112
     3113    // get inode FS type
     3114    vfs_fs_type_t fs_type = inode->ctx->type;
     3115
     3116    // call relevant FS function
     3117    if( fs_type == FS_TYPE_FATFS )
     3118    {
     3119        error = fatfs_sync_inode( inode );
     3120    }
     3121    else if( fs_type == FS_TYPE_RAMFS )
     3122    {
     3123        assert( false , "should not be called for RAMFS\n" );
     3124    }
     3125    else if( fs_type == FS_TYPE_DEVFS )
     3126    {
     3127        assert( false , "should not be called for DEVFS\n" );
     3128    }
     3129    else
     3130    {
     3131        assert( false , "undefined file system type\n" );
     3132    }
     3133
     3134    return error;
     3135
     3136}  // end vfs_fs_sync_inode()
     3137
     3138////////////////////////////////////////////////
     3139error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type )
     3140{
     3141    error_t error = 0;
     3142
     3143    // call relevant FS function
     3144    if( fs_type == FS_TYPE_FATFS )
     3145    {
     3146        error = fatfs_sync_fat();
     3147    }
     3148    else if( fs_type == FS_TYPE_RAMFS )
     3149    {
     3150        assert( false , "should not be called for RAMFS\n" );
     3151    }
     3152    else if( fs_type == FS_TYPE_DEVFS )
     3153    {
     3154        assert( false , "should not be called for DEVFS\n" );
     3155    }
     3156    else
     3157    {
     3158        assert( false , "undefined file system type\n" );
     3159    }
     3160
     3161    return error;
     3162
     3163}  // end vfs_fs_sync_fat()
     3164
     3165//////////////////////////////////////////////////////
     3166error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type )
     3167{
     3168    error_t error = 0;
     3169
     3170    // call relevant FS function
     3171    if( fs_type == FS_TYPE_FATFS )
     3172    {
     3173        error = fatfs_sync_free_info();
     3174    }
     3175    else if( fs_type == FS_TYPE_RAMFS )
     3176    {
     3177        assert( false , "should not be called for RAMFS\n" );
     3178    }
     3179    else if( fs_type == FS_TYPE_DEVFS )
     3180    {
     3181        assert( false , "should not be called for DEVFS\n" );
     3182    }
     3183    else
     3184    {
     3185        assert( false , "undefined file system type\n" );
     3186    }
     3187
     3188    return error;
     3189
     3190}  // end vfs_fs_sync_fat()
     3191
    23763192/////////////////////////////////////////////////
    23773193error_t vfs_fs_cluster_alloc( uint32_t   fs_type,
  • trunk/kernel/fs/vfs.h

    r602 r610  
    6969 *****************************************************************************************/
    7070
    71 #define VFS_LOOKUP_DIR      0x01     /* the searched inode is a directory                */
     71#define VFS_LOOKUP_DIR      0x01     /* the searched inode must be a directory           */
    7272#define VFS_LOOKUP_OPEN         0x02     /* the search is for an open/opendir                */
    7373#define VFS_LOOKUP_PARENT       0x04     /* return the parent inode (not the inode itself)   */
    7474#define VFS_LOOKUP_CREATE   0x10     /* file must be created if missing                  */
    75 #define VFS_LOOKUP_EXCL     0x20     /* file cannot previously exist                     */   
     75#define VFS_LOOKUP_EXCL     0x20     /* file cannot previously exist                     */
    7676
    7777/******************************************************************************************
     
    117117/******************************************************************************************
    118118 * This structure define a VFS inode.
    119  * It contains an extended pointer on the parent dentry, and (for directory only)
    120  * an hash table (xhtab) registering all children dentries.
    121  * The <parent> inode is unique for a directory (no hard links for directories).
    122  * For a file, the parent field points to the first dentry who created this inode.
     119 * An inode has several children dentries (if it is a directory), an can have several
     120 * parents dentries (if it hass several aliases links):
     121 * - The "parents" field is the root of the xlist of parents dentries, and the "links"
     122 *   fiels define the number of aliases parent dentries. only a FILE inode can have
     123 *   several parents (no hard links for directories).
     124 * - The "children" field is an embedded xhtab containing pointers on all local children
     125 *   dentries. This set of children is empty for a FILE inode.
    123126 * Synchronisation:
    124  * - the main_lock (remote_busylock) is used during the inode tree traversal,
    125  *   or for inode modification (add/remove children).
    126  * - the data_lock (remote_rwlock) is used during read/write accesses to the data
    127  *   stored in the mapper.
    128  * - the mapper lock (remote rwlock) is only used during the radix tree traversal
    129  *   to return the relevant page for read/write.
     127 * - the main_lock (remote_rwlock) is used during the inode tree traversal,
     128 *   or for inode modification (add/remove children in xhtab).
     129 * - the size_lock (remote_rwlock) is used during read/write accesses to the size
     130 *   field in the mapper.
     131 * - access to the data stored in the associated mapper use the mapper remote_rwlock
     132 *   protecting radix tree traversal and modifications.
    130133 *****************************************************************************************/
    131134
     
    158161{
    159162        struct vfs_ctx_s * ctx;              /*! local pointer on FS context                 */
    160     uint32_t           gc;               /*! generation counter                          */
    161163        uint32_t           inum;             /*! inode identifier (unique in file system)    */
    162164        uint32_t           attr;             /*! inode attributes (see above)                */
    163165        vfs_inode_type_t   type;             /*! inode type (see above)                      */
    164166        uint32_t           size;             /*! number of bytes                             */
    165         uint32_t           links;            /*! number of alias dentry                      */
    166167        uint32_t           uid;              /*! user owner identifier                       */
    167168        uint32_t           gid;              /*! group owner identifier                      */
    168169    uint32_t           rights;           /*! access rights                               */
    169         uint32_t               refcount;         /*! reference counter (all pointers)            */
    170         xptr_t             parent_xp;        /*! extended pointer on parent dentry           */
     170        xlist_entry_t      parents;          /*! root of list of parents dentries            */
     171        uint32_t           links;            /*! number of parent dentries (hard links)      */
    171172        xhtab_t            children;         /*! embedded xhtab of children dentries         */
    172         remote_rwlock_t    data_lock;        /*! protect read/write to data and to size      */
    173         remote_busylock_t  main_lock;        /*! protect inode tree traversal and modifs     */
    174         list_entry_t       list;             /*! member of set of inodes in same cluster     */
    175         xlist_entry_t      wait_root;        /*! root of threads waiting on this inode       */
     173        remote_rwlock_t    size_lock;        /*! protect read/write to size                  */
     174        remote_rwlock_t    main_lock;        /*! protect inode tree traversal and modifs     */
     175//  list_entry_t       list;             /*! member of set of inodes in same cluster     */
     176//  list_entry_t       wait_root;        /*! root of threads waiting on this inode       */
    176177        struct mapper_s  * mapper;           /*! associated file cache                       */
    177178        void             * extend;           /*! fs_type_specific inode extension            */
     
    183184#define VFS_ISUID          0x0004000
    184185#define VFS_ISGID          0x0002000
    185 #define VFS_ISVTX          0x0001000
     186define VFS_ISVTX           0x0001000
    186187
    187188#define VFS_IRWXU      0x0000700
     
    203204 * This structure defines a directory entry.
    204205 * A dentry contains the name of a remote file/dir, an extended pointer on the
    205  * inode representing this file/dir, and a local pointer on the inode representing
     206 * inode representing this file/dir, a local pointer on the inode representing
    206207 * the parent directory.
     208 * A dentry can be member of the set of children of a given directory inode (xhtab).
     209 * A dentry can be member of the set of parents  of a given inode (xlist).
    207210 *****************************************************************************************/
    208211
     
    212215        char                 name[CONFIG_VFS_MAX_NAME_LENGTH];
    213216        uint32_t             length;         /*! name length (bytes)                         */
    214         uint32_t             refcount;       /*! reference counter (all pointers)            */
    215217    struct vfs_inode_s * parent;         /*! local pointer on parent inode               */
    216218    xptr_t               child_xp;       /*! extended pointer on child inode             */
    217     xlist_entry_t        list;           /*! member of list of dentries with same key    */
     219    xlist_entry_t        children;       /*! member of set of children dentries          */
     220    xlist_entry_t        parents;        /*! member of set of parent dentries            */
    218221        void               * extend;         /*! FS specific extension                       */
    219222}
     
    301304
    302305
    303 
    304306/******************************************************************************************
    305307 *        These low-level functions access / modify a VFS inode descriptor
     
    314316 * This function allocates memory from local cluster for an inode descriptor and the
    315317 * associated mapper. It initialise these descriptors from arguments values.
    316  * The parent dentry must have been previously created.
    317318 * If the client thread is not running in the cluster containing this inode,
    318319 * it must use the rpc_vfs_inode_create_client() function.
    319320 ******************************************************************************************
    320  * @ dentry_xp  : extended pointer on associated dentry (in parent inode cluster).
    321321 * @ fs_type    : file system type.
    322322 * @ inode_type : inode type.
     
    328328 * @ return 0 if success / return ENOMEM or EINVAL if error.
    329329 *****************************************************************************************/
    330 error_t vfs_inode_create( xptr_t            dentry_xp,
    331                           vfs_fs_type_t     fs_type,
     330error_t vfs_inode_create( vfs_fs_type_t     fs_type,
    332331                          vfs_inode_type_t  inode_type,
    333332                          uint32_t          attr,
     
    340339 * This function releases memory allocated to an inode descriptor, including
    341340 * all memory allocated to the mapper (both mapper descriptor and radix tree).
    342  * The mapper should not contain any dirty page (shold be synchronized before deletion),
    343  * and the inode refcount must be zero.
     341 * The mapper should not contain any dirty page (should be synchronized before deletion).
    344342 * It must be executed by a thread running in the cluster containing the inode.
    345343 * Use the rpc_vfs_inode_destroy_client() function if required.
     
    348346 *****************************************************************************************/
    349347void vfs_inode_destroy( vfs_inode_t *  inode ); 
    350 
    351 /******************************************************************************************
    352  * This function atomically increment/decrement the inode refcount.
    353  * It can be called by any thread running in any cluster.
    354  *****************************************************************************************/
    355 void vfs_inode_remote_up( xptr_t  inode_xp );
    356 void vfs_inode_remote_down( xptr_t  inode_xp );
    357348
    358349/******************************************************************************************
     
    423414 * This function allocates memory from local cluster for a dentry descriptor,
    424415 * initialises it from  arguments values, and returns the extended pointer on dentry.
    425  * The inode field is not initialized, because the inode does not exist yet.
    426416 * If the client thread is not running in the target cluster for this inode,
    427417 * it must use the rpc_dentry_create_client() function.
     
    429419 * @ fs_type    : file system type.
    430420 * @ name       : directory entry file/dir name.
    431  * @ parent     : local pointer on parent inode.
    432421 * @ dentry_xp  : [out] buffer for extended pointer on created dentry.
    433422 * @ return 0 if success / return ENOMEM or EINVAL if error.
     
    435424error_t vfs_dentry_create( vfs_fs_type_t   fs_type,
    436425                           char          * name,
    437                            vfs_inode_t   * parent,
    438426                           xptr_t        * dentry_xp );
    439427 
    440428/******************************************************************************************
    441  * This function releases memory allocated to a dentry descriptor.
    442  * The dentry refcount must be zero.
     429 * This function removes the dentry from the parent inode xhtab, and releases the memory
     430 * allocated to the dentry descriptor.
    443431 * It must be executed by a thread running in the cluster containing the dentry.
    444432 * Use the rpc_vfs_dentry_destroy_client() function if required.
     
    447435 *****************************************************************************************/
    448436void vfs_dentry_destroy( vfs_dentry_t *  dentry ); 
    449 
    450 /******************************************************************************************
    451  * These functions atomically increment/decrement the dentry refcount.
    452  * It can be called by any thread running in any cluster.
    453  *****************************************************************************************/
    454 void vfs_dentry_remote_up( xptr_t dentry_xp );
    455 void vfs_dentry_remote_down( xptr_t dentry_xp );
    456437
    457438
     
    496477
    497478/******************************************************************************************
    498  *        These functions access / modify the distributed VFS Inode Treee
    499  *****************************************************************************************/
    500 
    501 /******************************************************************************************
    502  * This function returns in a kernel buffer allocated by the caller function,
    503  * the pathname of a file/dir identified by an extended pointer on the inode.
     479 *        These functions access / modify the distributed VFS Inode Tree
     480 *****************************************************************************************/
     481
     482/******************************************************************************************
     483 * This function returns in a kernel <buffer> allocated by the caller function,
     484 * the pathname of a file/dir identified by the <inode_xp> argument.
    504485 * It traverse the Inode Tree from the target node to the root.
    505486 * It can be called by any thread running in any cluster.
    506  ******************************************************************************************
    507  * @ inode_xp    : pointer on inode descriptor.
    508  * @ buffer      : kernel buffer for pathname (must be allocated by caller).
    509  * @ size        : max number of characters in buffer.
     487 * As this buffer if filled in "reverse order" (i.e. from the target inode to the root),
     488 * the pathname is stored in the higher part of the buffer.
     489 * A pointer on the first character of the pathname is returned in <first> buffer.
     490 *
     491 * WARNING : This function takes & releases the remote_rwlock protecting the Inode Tree.
     492 ******************************************************************************************
     493 * @ inode_xp    : [in]  extended pointer on target inode descriptor.
     494 * @ buffer      : [in]  kernel buffer for pathname (allocated by caller).
     495 * @ first       : [out] pointer on first character in buffer.
     496 * @ max_size    : [in]  max number of characters in buffer.
    510497 * @ return 0 if success / return EINVAL if buffer too small.
    511498 *****************************************************************************************/
    512499error_t vfs_get_path( xptr_t    inode_xp,
    513500                      char    * buffer,
     501                      char   ** first,
    514502                      uint32_t  max_size );
    515503
    516504/******************************************************************************************
    517  * This function takes a pathname (absolute or relative to cwd) and returns an extended
    518  * pointer on the associated inode.
     505 * This function traverses the the Inode Tree, from inode identified by the <root_xp>
     506 * argument, and returns in <inode_xp> the inode identified by the < pathname> argument.
     507 * It can be called by a thread running in any cluster.
     508 * It supports the following flags that define the lookup modes :
     509 * - VFS_LOOKUP_DIR    : the searched inode must be a directory
     510 * - VFS_LOOKUP_OPEN   : the search is for an open/opendir
     511 * - VFS_LOOKUP_PARENT : return the parent inode (not the inode itself)
     512 * - VFS_LOOKUP_CREATE : file/directory must be created if missing on IOC
     513 * - VFS_LOOKUP_EXCL   : file cannot previously exist
     514 * As the inode Tree is a cache, the search policy is the following :
    519515 * - If a given directory name in the path is not found in the inode tree, it try to load
    520516 *   the missing dentry/inode couple, from informations found in the parent directory.
    521  * - If this directory entry does not exist on device, it returns an error.
    522  * - If the the file identified by the pathname does not exist on device but the
    523  *   flag CREATE is set, the inode is created.
    524  * - If the the file identified by the pathname exist on device but both flags EXCL
     517 * - If this directory entry does not exist on IOC, it returns an error.
     518 * - If the the file identified by the pathname does not exist on IOC but the
     519 *   flag CREATE is set, the inode is created. It returns an error otherwise.
     520 * - If the the file identified by the pathname exist on device, but both flags EXCL
    525521 *   and CREATE are set, an error is returned.
    526  ******************************************************************************************
    527  * @ cwd_xp      : extended pointer on current directory (for relative path).
    528  * @ pathname    : path in kernel space (can be relative or absolute).
    529  * @ lookup_mode : flags defining the working mode (defined above in this file).
     522 * - If the PARENT flag is set, it returns in <inode_xp> an extended pointer on the parent
     523 *   inode, and copies in <last_name> buffer a string containing the last name in path.
     524 *
     525 * WARNING : The remote_rwlock protecting the Inode Tree must be taken by the caller.
     526 *
     527 * TODO the access rights are not checked yet.
     528 ******************************************************************************************
     529 * @ root_xp     : [in]  extended pointer on root inode (can be root of a subtree).
     530 * @ pathname    : [in]  path (can be relative or absolute).
     531 * @ lookup_mode : [in]  flags defining the searching mode.
    530532 * @ inode_xp    : [out] buffer for extended pointer on searched inode.
     533 * @ last_name   : [out] pointer on buffer for last name in path.
    531534 * @ return 0 if success / ENOENT if inode not found , EACCES if permisson denied,
    532  *                         EAGAIN if a new complete lookup must be made
    533  *****************************************************************************************/
    534 error_t vfs_lookup( xptr_t             cwd_xp,
     535 *****************************************************************************************/
     536error_t vfs_lookup( xptr_t             root_xp,
    535537                    char             * pathname,
    536538                    uint32_t           lookup_mode,
    537                                         xptr_t           * inode_xp );
     539                                        xptr_t           * inode_xp,
     540                    char             * last_name );
    538541
    539542/******************************************************************************************
    540543 * This function creates a new couple dentry/inode, and insert it in the Inode-Tree.
     544 * Only the distributed Inode Tree is modified: it does NOT modify the parent mapper,
     545 * and does NOT update the FS on IOC device.
    541546 * It can be executed by any thread running in any cluster (can be different from both
    542  * the child cluster and the parent cluster), as it uses RPCs if required.
    543  * Only the distributed Inode Tree is modified: Even for a new file, this function
    544  * does NOT modify the parent mapper, and does NOT update the FS on IOC device.
     547 * the child cluster and the parent cluster).
    545548 *
    546549 * [Implementation]
     
    563566 * @ return 0 if success / -1 if dentry or inode cannot be created.
    564567 *****************************************************************************************/
    565 error_t vfs_add_child_in_parent( cxy_t              child_inodecxy,
    566                                  vfs_inode_type_t   chilg_inode_type,
     568error_t vfs_add_child_in_parent( cxy_t              child_inode_cxy,
     569                                 vfs_inode_type_t   child_inode_type,
    567570                                 vfs_fs_type_t      fs_type,
    568571                                 xptr_t             parent_inode_xp,
     
    572575
    573576/******************************************************************************************
    574  * This function removes a couple dentry/inode from the Inode-Tree.
    575  * Both the inode and dentry references counters must be 1.
     577 * This function removes a remote dentry from the Inode-Tree.
     578 * - It removes the dentry from the parent inode xhtab ("children" field), and from the
     579 *   child inode xlist ("parents" field).
     580 * - It releases the memory allocated to the dentry descriptor.
     581 * - If the number of parents of the child inode is one, it also releases the memory
     582 *   allocated to the child inode.
     583 * Only the Inode Tree is modified: it does NOT modify the parent mapper,
     584 * and does NOT update the FS on IOC device.
    576585 * It can be executed by any thread running in any cluster (can be different from both
    577  * the inode cluster and the dentry cluster), as it uses RPCs if required.
    578  ******************************************************************************************
    579  * @ child_xp   : extended pointer on removed inode.
    580  *****************************************************************************************/
    581 void vfs_remove_child_from_parent( xptr_t inode_xp );
     586 * the inode cluster and the dentry cluster).
     587 ******************************************************************************************
     588 * @ dentry_xp   : extended pointer on removed dentry.
     589 *****************************************************************************************/
     590void vfs_remove_child_from_parent( xptr_t dentry_xp );
    582591
    583592/******************************************************************************************
     
    599608 *****************************************************************************************/
    600609error_t vfs_new_child_init( xptr_t   parent_xp,
    601                          xptr_t   dentry_xp,
    602                          xptr_t   child_xp );
     610                            xptr_t   dentry_xp,
     611                            xptr_t   child_xp );
    603612
    604613/******************************************************************************************
     
    661670/******************************************************************************************
    662671 * This function allocates a vfs_file_t structure in the cluster containing the inode
    663  * associated to the file identified by the <cwd_xp> & <path> arguments.
     672 * identified by the <root_xp> & <path> arguments.
    664673 * It initializes it, register it in the reference process fd_array identified by the
    665  * <process> argument, and returns both the extended pointer on the file descriptor,
    666  * and the allocated index in the fd_array.
     674 * <process_xp> argument, and returns both the extended pointer on the file descriptor,
     675 * and the allocated index in the <file_xp> and <file_id> buffers.
    667676 * The pathname can be relative to current directory or absolute.
    668  * If the inode does not exist in the inode cache, it try to find the file on the mounted
     677 * If the inode does not exist in the inode cache, it try to find the file on the IOC
    669678 * device, and creates an inode on a pseudo randomly selected cluster if found.
    670679 * It the requested file does not exist on device, it creates a new inode if the
    671680 * O_CREAT flag is set, and return an error otherwise.
     681 *
     682 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
    672683 ******************************************************************************************
    673  * @ process     : local pointer on local process descriptor copy.
     684 * @ root_xp     : extended pointer on path root inode.
    674685 * @ path        : file pathname (absolute or relative to current directory).
     686 * @ process_xp  : extended pointer on client reference process.
    675687 * @ flags       : defined in vfs_file_t structure.
    676688 * @ mode        : access rights (as defined by chmod).
     
    679691 * @ return 0 if success / return non-zero if error.
    680692 *****************************************************************************************/
    681 error_t vfs_open( struct process_s * process,
     693error_t vfs_open( xptr_t             root_xp,
    682694                          char             * path,
     695                  xptr_t             process_xp,
    683696                          uint32_t           flags,
    684697                  uint32_t           mode,
     
    721734/******************************************************************************************
    722735 * This function is called by the kernel to create in the file system a new directory
    723  * entry identified by the <cwd_xp> & <path_1>, linked to the node identified by the
    724  * <cwd_xp> & <path_2> arguments.  It can be any type of node.
    725  * If the link is successful, the link count of the target node is incremented.
    726  * <path_1> and <path_2> share equal access rights to the underlying object.
     736 * identified by the <root_xp> & <path> arguments, with the access permission defined
     737 * by the <rights> argument. All nodes in the path - but the last -  must exist.
     738 *
     739 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     740 ******************************************************************************************
     741 * @ root_xp : extended pointer on path root inode (any inode in Inode Tree).
     742 * @ path    : pathname (absolute or relative to current directory).
     743 * @ rights  : access rights.
     744 * @ returns 0 if success / -1 if error.
     745 *****************************************************************************************/
     746error_t vfs_mkdir( xptr_t   root_xp,
     747                   char   * path,
     748                   uint32_t rights );
     749
     750/******************************************************************************************
     751 * This function is called by the kernel to create in the file system a new directory
     752 * entry identified by the <new_root_xp> & <new_path> arguments, to be linked to an
     753 * existing inode, identified by the  <old_root_xp> & <old_path> arguments.
     754 * If the link is successful, the link count of the target inode is incremented.
     755 * The <new_path> and <old_path> share equal access rights to the underlying inode.
    727756 * Both the IOC device and the Inode Tree are modified.
    728  ******************************************************************************************
    729  * @ cwd_xp   : extended pointer on current working directory file descriptor.
    730  * @ path_1   : new pathname (absolute or relative to current directory).
    731  * @ path_1   : existing pathname (absolute or relative to current directory).
     757 $
     758 * TODO This function should handle any type of node, but the current implementation
     759 * handles only the FILE and DIR types.
     760 *
     761 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     762 ******************************************************************************************
     763 * @ old_root_xp : extended pointer on old path root inode (any inode in Inode Tree).
     764 * @ old_path    : old pathname (absolute or relative to current directory).
     765 * @ nld_root_xp : extended pointer on new path root inode (any inode in Inode Tree).
     766 * @ new_path    : new pathname (absolute or relative to current directory).
    732767 * @ returns 0 if success / -1 if error.
    733768 *****************************************************************************************/
    734 error_t vfs_link( xptr_t   cwd_xp,
    735                   char   * path_1,
    736                   char   * path_2 );
     769error_t vfs_link( xptr_t   old_root_xp,
     770                  char   * old_path,
     771                  xptr_t   new_root_xp,
     772                  char   * new_path );
    737773
    738774/******************************************************************************************
    739775 * This function is called by the kernel to remove from the file system a directory entry
    740  * identified by the  <cwd_xp> & <path> arguments. The target node can be any type of node.
    741  * The link count of the target node is decremented. If the removed link is the last,
    742  * the target node is deleted.
     776 * identified by the  <root_xp> & <path> arguments.
     777 * The link count of the target node is decremented.
     778 * If the removed link is the last, the target inode is deleted.
    743779 * Both the IOC device and the Inode Tree are modified.
    744  ******************************************************************************************
    745  * @ cwd_xp   : extended pointer on the current working directory file descriptor.
     780 *
     781 * TODO This function should handle any type of node, but the current implementation
     782 * handles only only the FILE and DIR types.
     783 *
     784 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     785 ******************************************************************************************
     786 * @ root_xp  : extended pointer on root inode (can be any inode in Inode Tree).
    746787 * @ path     : pathname (absolute or relative to current directory).
    747788 * @ returns 0 if success / -1 if error.
    748789 *****************************************************************************************/
    749 error_t vfs_unlink( xptr_t   cwd_xp,
     790error_t vfs_unlink( xptr_t   root_xp,
    750791                    char   * path );
    751792
    752793/******************************************************************************************
    753  * This function returns, in the structure pointed by the <st> pointer,
    754  * various informations on the inode identified by the <inode_xp> argument.
    755  * TODO : only partially implemented yet...
    756  ******************************************************************************************
    757  * @ inode_xp   : extended pointer on the remote inode.
     794 * This function returns, in the structure pointed by the <st> pointer, various
     795 * informations on the inode identified by the <root_inode_xp> and <patname> arguments.
     796 *
     797 * TODO : only partially implemented yet (only size and inum fields).
     798 *
     799 * WARNING : this function takes & releases the remote_rwlock protecting the Inode Tree.
     800 ******************************************************************************************
     801 * @ root_xp    : extended pointer on path root inode (any inode in Inode Tree)
     802 * @ pathname   : pathname to target inode.
    758803 * @ st         : local pointer on the stat structure in kernel space.
    759804 * @ returns 0 if success / -1 if error.
    760805 *****************************************************************************************/
    761 error_t vfs_stat( xptr_t        inode_xp,
     806error_t vfs_stat( xptr_t        root_xp,
     807                  char        * pathname,
    762808                  struct stat * st );
    763809
     
    775821
    776822/******************************************************************************************
    777  * This function  creates a new inode and associated dentry  for the directory defined
    778  * by the <cwd_xp> & <path> arguments.
     823 * This function  creates a new directory as defined by the <root_xp> & <path> arguments.
    779824 * TODO not implemented yet...
    780825 ******************************************************************************************
    781  * @ cwd_xp   : extended pointer on the current working directory file descriptor.
    782  * @ path     : pathname (absolute or relative to current directory).                     
     826 * @ root_xp  : extended pointer on the path root directory.
     827 * @ path     : pathname (absolute or relative to CWD).                     
    783828 * @ mode     : access rights (as defined by chmod)
    784829 * @ returns 0 if success / -1 if error.
    785830 *****************************************************************************************/
    786 error_t vfs_mkdir( xptr_t     cwd_xp,
     831error_t vfs_mkdir( xptr_t     root_xp,
    787832                   char     * path,
    788833                   uint32_t   mode );
    789834
    790835/******************************************************************************************
    791  * This function makes the directory identified by <cwd_xp / path> arguments to become
    792  * the working directory for the calling process.
     836 * This function makes the directory identified by the <root_xp and <path> arguments
     837 * to become the working directory for the calling process.
    793838 ******************************************************************************************
    794  * @ cwd_xp      : extended pointer on current directory file descriptor (relative path).
    795  * @ path        : file pathname (absolute or relative to current directory).
     839 * @ root_xp  : extended pointer on the path root directory.
     840 * @ path     : pathname (absolute or relative to CWD).
    796841 * return 0 if success / -1 if error.
    797842 *****************************************************************************************/
    798 error_t vfs_chdir( xptr_t   cwd_xp,
     843error_t vfs_chdir( xptr_t   root_xp,
    799844                   char   * path );
    800845
    801846/******************************************************************************************
    802  * This function change the access rigths for the file identified by the <cwd_xp / path>
    803  * arguments. The new access rights are defined by the <mode> argument value.
     847 * This function change the access rigths for the file/directory identified by the
     848 * <root_xp> and <path> arguments as defined by the <mode> argument value.
    804849 ******************************************************************************************
    805  * @ cwd_xp      : extended pointer on current directory file descriptor (relative path).
    806  * @ path        : file pathname (absolute or relative to current directory).
    807  * @ mode        : access rights new value.
     850 * @ root_xp  : extended pointer on the path root directory.
     851 * @ path     : pathname (absolute or relative to CWD).
     852 * @ mode     : access rights
    808853 * return 0 if success / -1 if error.
    809854 *****************************************************************************************/
    810 error_t vfs_chmod( xptr_t        cwd_xp,
     855error_t vfs_chmod( xptr_t        root_xp,
    811856                   char        * path,
    812857                   uint32_t      mode );
     
    816861 * TODO not implemented yet                                                         
    817862 ******************************************************************************************
    818  * @ path        : FIFO pathname (absolute or relative to current directory).
    819  * @ cwd_xp      : extended pointer on the current working directory file descriptor.
    820  * @ mode        : access rights new value.
    821  *****************************************************************************************/
    822 error_t vfs_mkfifo( xptr_t       cwd_xp,
     863 * @ root_xp  : extended pointer on the path root directory.
     864 * @ path     : pathname (absolute or relative to CWD).
     865 * @ mode     : access rights new value.
     866 *****************************************************************************************/
     867error_t vfs_mkfifo( xptr_t       root_xp,
    823868                    char       * path,
    824869                    uint32_t     mode );
     
    905950
    906951/*****************************************************************************************
    907  * This function updates the FS on the IOC device for the FAT itself.
    908  * It scan all clusters registered in the FAT mapper, and copies to device
    909  * each page marked as dirty.
     952 * This function updates the FS defined by the <fs_type> argument on the IOC device
     953 * for the FAT itself. It scan all clusters registered in the FAT mapper, and copies
     954 * to device each page marked as dirty.
    910955 *
    911956 * Depending on the file system type, it calls the relevant, FS specific function.
    912957 * It can be called by a thread running in any cluster.
    913958 *****************************************************************************************
     959 * @ fs_type   : specific file system type.
    914960 * @ return 0 if success / return EIO if failure during device access.
    915961 ****************************************************************************************/
    916 error_t vfs_fs_sync_fat( void );
     962error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type );
    917963
    918964/*****************************************************************************************
    919  * This function updates the free clusters info on the IOC device.
     965 * This function updates the free clusters info on the IOC device for the FS defined
     966 * by the <fs_type> argument.
    920967 *
    921968 * Depending on the file system type, it calls the relevant, FS specific function.
    922969 * It can be called by a thread running in any cluster.
    923970 *****************************************************************************************
     971 * @ fs_type   : specific file system type.
    924972 * @ return 0 if success / return EIO if failure during device access.
    925973 ****************************************************************************************/
    926 error_t vfs_fs_sync_free_info( void );
     974error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type );
    927975
    928976/******************************************************************************************
  • trunk/kernel/kern/do_syscall.c

    r583 r610  
    22 * do_syscall.c - architecture independant entry-point for system calls.
    33 *
    4  * Author    Alain Greiner (2016)
     4 * Author    Alain Greiner (2016,2017,2018)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    6161    sys_mutex,              // 9
    6262
    63     sys_exit,               // 10
     63    sys_rename,             // 10
    6464    sys_munmap,             // 11
    6565    sys_open,               // 12
     
    104104    sys_fg,                 // 48
    105105    sys_is_fg,              // 49
     106
     107    sys_exit,               // 50
    106108};
    107109
     
    122124    case SYS_MUTEX :                       return "MUTEX";            // 9
    123125
    124     case SYS_EXIT:                         return "EXIT";             // 10
     126    case SYS_RENAME:                       return "RENAME";           // 10
    125127    case SYS_MUNMAP:                       return "MUNMAP";           // 11
    126128    case SYS_OPEN:                         return "OPEN";             // 12
     
    165167    case SYS_FG:                           return "FG";               // 48
    166168    case SYS_IS_FG:                        return "IS_FG";            // 49
     169
     170    case SYS_EXIT:                         return "EXIT";             // 50
     171
    167172    default:                               return "undefined";
    168173    }
  • trunk/kernel/kern/kernel_init.c

    r601 r610  
    146146
    147147    "THREAD_JOIN",           // 10
    148     "VFS_MAIN",              // 11
     148    "XHTAB_STATE",           // 11
    149149    "CHDEV_QUEUE",           // 12
    150150    "CHDEV_TXT0",            // 13
     
    154154    "CONDVAR_STATE",         // 17
    155155    "SEM_STATE",             // 18
    156     "XHTAB_STATE",           // 19
     156    "RPOCESS_CWD",           // 19
    157157
    158158    "unused_20",             // 20
     
    171171
    172172    "MAPPER_STATE",          // 30
    173     "PROCESS_CWD",           // 31
    174     "VFS_INODE",             // 32
    175     "VFS_FILE",              // 33
    176     "VMM_VSL",               // 34
    177     "VMM_GPT",               // 35
     173    "VFS_SIZE",              // 31
     174    "VFS_FILE",              // 32
     175    "VMM_VSL",               // 33
     176    "VMM_GPT",               // 34
     177    "VFS_MAIN",              // 35
    178178};       
    179179
     
    970970#if DEBUG_KERNEL_INIT
    971971if( (core_lid ==  0) & (local_cxy == 0) )
    972 printk("\n[%s] : exit barrier 0 : TXT0 initialized / sr %x / cycle %d\n",
    973 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     972printk("\n[%s] : exit barrier 0 : TXT0 initialized / cycle %d\n",
     973__FUNCTION__, (uint32_t)hal_get_cycles() );
    974974#endif
    975975
     
    10121012#if DEBUG_KERNEL_INIT
    10131013if( (core_lid ==  0) & (local_cxy == 0) )
    1014 printk("\n[%s] : exit barrier 1 : clusters initialised / sr %x / cycle %d\n",
    1015 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1014printk("\n[%s] : exit barrier 1 : clusters initialised / cycle %d\n",
     1015__FUNCTION__, (uint32_t)hal_get_cycles() );
    10161016#endif
    10171017
     
    10391039#if DEBUG_KERNEL_INIT
    10401040if( (core_lid ==  0) & (local_cxy == 0) )
    1041 printk("\n[%s] : exit barrier 2 : PIC initialised / sr %x / cycle %d\n",
    1042 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1041printk("\n[%s] : exit barrier 2 : PIC initialised / cycle %d\n",
     1042__FUNCTION__, (uint32_t)hal_get_cycles() );
    10431043#endif
    10441044
     
    10721072#if DEBUG_KERNEL_INIT
    10731073if( (core_lid ==  0) & (local_cxy == 0) )
    1074 printk("\n[%s] : exit barrier 3 : all chdevs initialised / sr %x / cycle %d\n",
    1075 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1074printk("\n[%s] : exit barrier 3 : all chdevs initialised / cycle %d\n",
     1075__FUNCTION__, (uint32_t)hal_get_cycles() );
    10761076#endif
    10771077
     
    11361136 
    11371137            // 4. create VFS root inode in cluster 0
    1138             error = vfs_inode_create( XPTR_NULL,                           // dentry_xp
    1139                                       FS_TYPE_FATFS,                       // fs_type
     1138            error = vfs_inode_create( FS_TYPE_FATFS,                       // fs_type
    11401139                                      INODE_TYPE_DIR,                      // inode_type
    11411140                                      0,                                   // attr
     
    11741173        // register VFS root inode in process_zero descriptor of cluster 0
    11751174        process_zero.vfs_root_xp = vfs_root_inode_xp;
    1176         process_zero.vfs_cwd_xp  = vfs_root_inode_xp;
     1175        process_zero.cwd_xp      = vfs_root_inode_xp;
    11771176    }
    11781177
     
    11851184#if DEBUG_KERNEL_INIT
    11861185if( (core_lid ==  0) & (local_cxy == 0) )
    1187 printk("\n[%s] : exit barrier 4 : VFS root initialized in cluster 0 / sr %x / cycle %d\n",
    1188 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1186printk("\n[%s] : exit barrier 4 : VFS root (%x,%x) in cluster 0 / cycle %d\n",
     1187__FUNCTION__, GET_CXY(process_zero.vfs_root_xp),
     1188GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() );
    11891189#endif
    11901190
     
    12431243        // update local process_zero descriptor
    12441244        process_zero.vfs_root_xp = vfs_root_inode_xp;
    1245         process_zero.vfs_cwd_xp  = vfs_root_inode_xp;
     1245        process_zero.cwd_xp      = vfs_root_inode_xp;
    12461246    }
    12471247
     
    12541254#if DEBUG_KERNEL_INIT
    12551255if( (core_lid ==  0) & (local_cxy == 1) )
    1256 printk("\n[%s] : exit barrier 5 : VFS root initialized in cluster 1 / sr %x / cycle %d\n",
    1257 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1256printk("\n[%s] : exit barrier 4 : VFS root (%x,%x) in cluster 1 / cycle %d\n",
     1257__FUNCTION__, GET_CXY(process_zero.vfs_root_xp),
     1258GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() );
    12581259#endif
    12591260
     
    13031304#if DEBUG_KERNEL_INIT
    13041305if( (core_lid ==  0) & (local_cxy == 0) )
    1305 printk("\n[%s] : exit barrier 6 : DEVFS root initialized in cluster 0 / sr %x / cycle %d\n",
    1306 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1306printk("\n[%s] : exit barrier 6 : DEVFS root initialized in cluster 0 / cycle %d\n",
     1307__FUNCTION__, (uint32_t)hal_get_cycles() );
    13071308#endif
    13081309
     
    13401341#if DEBUG_KERNEL_INIT
    13411342if( (core_lid ==  0) & (local_cxy == 0) )
    1342 printk("\n[%s] : exit barrier 7 : DEV initialized in cluster 0 / sr %x / cycle %d\n",
    1343 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1343printk("\n[%s] : exit barrier 7 : DEV initialized in cluster 0 / cycle %d\n",
     1344__FUNCTION__, (uint32_t)hal_get_cycles() );
    13441345#endif
    13451346
     
    13661367#if DEBUG_KERNEL_INIT
    13671368if( (core_lid ==  0) & (local_cxy == 0) )
    1368 printk("\n[%s] : exit barrier 8 : process init created / sr %x / cycle %d\n",
    1369 __FUNCTION__, (uint32_t)hal_get_sr(), (uint32_t)hal_get_cycles() );
     1369printk("\n[%s] : exit barrier 8 : process init created / cycle %d\n",
     1370__FUNCTION__, (uint32_t)hal_get_cycles() );
    13701371#endif
    13711372
     
    14361437    dev_pic_enable_timer( CONFIG_SCHED_TICK_MS_PERIOD );
    14371438
     1439    /////////////////////////////////////////////////////////////////////////////////
     1440    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),
     1441                                        (info->x_size * info->y_size) );
     1442    barrier_wait( &local_barrier , info->cores_nr );
     1443    /////////////////////////////////////////////////////////////////////////////////
     1444
    14381445#if DEBUG_KERNEL_INIT
    1439 printk("\n[%s] : thread %x on core[%x,%d] jumps to thread_idle_func() / cycle %d\n",
    1440 __FUNCTION__ , CURRENT_THREAD , local_cxy , core_lid , (uint32_t)hal_get_cycles() );
     1446thread_t * this = CURRENT_THREAD;
     1447printk("\n[%s] : thread[%x,%x] on core[%x,%d] jumps to thread_idle_func() / cycle %d\n",
     1448__FUNCTION__ , this->process->pid, this->trdid,
     1449local_cxy, core_lid, (uint32_t)hal_get_cycles() );
    14411450#endif
    14421451
    14431452    // each core jump to thread_idle_func
    14441453    thread_idle_func();
    1445 }
    1446 
     1454
     1455}  // end kernel_init()
     1456
  • trunk/kernel/kern/process.c

    r593 r610  
    9595                             xptr_t      parent_xp )
    9696{
     97    xptr_t      process_xp;
    9798    cxy_t       parent_cxy;
    9899    process_t * parent_ptr;
     
    113114    pid_t       parent_pid;
    114115
     116    // build extended pointer on this reference process
     117    process_xp = XPTR( local_cxy , process );
     118
    115119    // get parent process cluster and local pointer
    116120    parent_cxy = GET_CXY( parent_xp );
     
    121125
    122126#if DEBUG_PROCESS_REFERENCE_INIT
     127thread_t * this = CURRENT_THREAD;
    123128uint32_t cycle = (uint32_t)hal_get_cycles();
    124 if( DEBUG_PROCESS_REFERENCE_INIT )
    125 printk("\n[%s] thread %x in process %x enter to initalialize process %x / cycle %d\n",
    126 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid , pid , cycle );
    127 #endif
    128 
    129     // initialize PID, REF_XP, PARENT_XP, and STATE
     129if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     130printk("\n[%s] thread[%x,%x] enter to initalialize process %x / cycle %d\n",
     131__FUNCTION__, parent_pid, this->trdid, pid, cycle );
     132#endif
     133
     134    // initialize pid, ref_xp, parent_xp, owner_xp, term_state fields
    130135        process->pid        = pid;
    131136    process->ref_xp     = XPTR( local_cxy , process );
     
    134139    process->term_state = 0;
    135140
     141    // initialize VFS root inode and CWD inode
     142    process->vfs_root_xp = hal_remote_l64( XPTR( parent_cxy, &parent_ptr->vfs_root_xp ) );
     143    process->cwd_xp      = hal_remote_l64( XPTR( parent_cxy, &parent_ptr->cwd_xp ) );
     144
    136145    // initialize vmm as empty
    137146    error = vmm_init( process );
     
    141150#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    142151cycle = (uint32_t)hal_get_cycles();
    143 if( DEBUG_PROCESS_REFERENCE_INIT )
    144 printk("\n[%s] thread %x in process %x / vmm empty for process %x / cycle %d\n",
    145 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid , pid, cycle );
     152if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     153printk("\n[%s] thread[%x,%x] / vmm empty for process %x / cycle %d\n",
     154__FUNCTION__, parent_pid, this->trdid, pid, cycle );
    146155#endif
    147156
     
    161170#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    162171cycle = (uint32_t)hal_get_cycles();
    163 if( DEBUG_PROCESS_REFERENCE_INIT )
    164 printk("\n[%s] thread %x in process %x / process %x attached to TXT%d / cycle %d\n",
    165 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, txt_id, cycle );
     172if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     173printk("\n[%s] thread[%x,%x] / process %x attached to TXT%d / cycle %d\n",
     174__FUNCTION__, parent_pid, this->trdid, pid, txt_id, cycle );
    166175#endif
    167176        // build path to TXT_RX[i] and TXT_TX[i] chdevs
     
    170179
    171180        // create stdin pseudo file         
    172         error = vfs_open( process,
     181        error = vfs_open(  process->vfs_root_xp,
    173182                           rx_path,
     183                           process_xp,
    174184                           O_RDONLY,
    175185                           0,                // FIXME chmod
     
    182192#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    183193cycle = (uint32_t)hal_get_cycles();
    184 if( DEBUG_PROCESS_REFERENCE_INIT )
    185 printk("\n[%s] thread %x in process %x / stdin open for process %x / cycle %d\n",
    186 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
     194if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     195printk("\n[%s] thread[%x,%x] / stdin open for process %x / cycle %d\n",
     196__FUNCTION__, parent_pid, this->trdid, pid, cycle );
    187197#endif
    188198
    189199        // create stdout pseudo file         
    190         error = vfs_open( process,
     200        error = vfs_open(  process->vfs_root_xp,
    191201                           tx_path,
     202                           process_xp,
    192203                           O_WRONLY,
    193204                           0,                // FIXME chmod
     
    200211#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    201212cycle = (uint32_t)hal_get_cycles();
    202 if( DEBUG_PROCESS_REFERENCE_INIT )
    203 printk("\n[%s] thread %x in process %x / stdout open for process %x / cycle %d\n",
    204 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
     213if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     214printk("\n[%s] thread[%x,%x] / stdout open for process %x / cycle %d\n",
     215__FUNCTION__, parent_pid, this->trdid, pid, cycle );
    205216#endif
    206217
    207218        // create stderr pseudo file         
    208         error = vfs_open( process,
     219        error = vfs_open(  process->vfs_root_xp,
    209220                           tx_path,
     221                           process_xp,
    210222                           O_WRONLY,
    211223                           0,                // FIXME chmod
     
    218230#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    219231cycle = (uint32_t)hal_get_cycles();
    220 if( DEBUG_PROCESS_REFERENCE_INIT )
    221 printk("\n[%s] thread %x in process %x / stderr open for process %x / cycle %d\n",
    222 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
     232if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     233printk("\n[%s] thread[%x,%x] / stderr open for process %x / cycle %d\n",
     234__FUNCTION__, parent_pid, this->trdid, pid, cycle );
    223235#endif
    224236
     
    247259    }
    248260
    249     // initialize specific inodes root and cwd
    250     process->vfs_root_xp = (xptr_t)hal_remote_l64( XPTR( parent_cxy,
    251                                                          &parent_ptr->vfs_root_xp ) );
    252     process->vfs_cwd_xp  = (xptr_t)hal_remote_l64( XPTR( parent_cxy,
    253                                                          &parent_ptr->vfs_cwd_xp ) );
    254     vfs_inode_remote_up( process->vfs_root_xp );
    255     vfs_inode_remote_up( process->vfs_cwd_xp );
    256 
    257     remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ), LOCK_PROCESS_CWD );
     261    // initialize lock protecting CWD changes
     262    remote_busylock_init( XPTR( local_cxy , &process->cwd_lock ), LOCK_PROCESS_CWD );
    258263
    259264#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    260265cycle = (uint32_t)hal_get_cycles();
    261 if( DEBUG_PROCESS_REFERENCE_INIT )
    262 printk("\n[%s] thread %x in process %x / set fd_array for process %x / cycle %d\n",
    263 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid , cycle );
     266if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     267printk("\n[%s] thread[%x,%x] / set fd_array for process %x / cycle %d\n",
     268__FUNCTION__, parent_pid, this->trdid, pid , cycle );
    264269#endif
    265270
     
    300305#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    301306cycle = (uint32_t)hal_get_cycles();
    302 if( DEBUG_PROCESS_REFERENCE_INIT )
    303 printk("\n[%s] thread %x in process %x exit for process %x / cycle %d\n",
    304 __FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
     307if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     308printk("\n[%s] thread[%x,%x] exit for process %x / cycle %d\n",
     309__FUNCTION__, parent_pid, this->trdid, pid, cycle );
    305310#endif
    306311
     
    325330
    326331#if DEBUG_PROCESS_COPY_INIT
    327 thread_t * this = CURRET_THREAD; 
     332thread_t * this = CURRENT_THREAD; 
    328333uint32_t cycle = (uint32_t)hal_get_cycles();
    329 if( DEBUG_PROCESS_COPY_INIT )
    330 printk("\n[%s] thread %x in process %x enter for process %x / cycle %d\n",
    331 __FUNCTION__, this->trdid, this->process->pid, local_process->pid, cycle );
     334if( DEBUG_PROCESS_COPY_INIT < cycle )
     335printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n",
     336__FUNCTION__, this->process->pid, this->trdid, local_process->pid, cycle );
    332337#endif
    333338
     
    342347        process_fd_init( local_process );
    343348
    344     // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
     349    // reset vfs_root_xp / vfs_bin_xp / cwd_xp fields
    345350    local_process->vfs_root_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
    346351    local_process->vfs_bin_xp  = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
    347     local_process->vfs_cwd_xp  = XPTR_NULL;
     352    local_process->cwd_xp      = XPTR_NULL;
    348353
    349354    // reset children list root (not used in a process descriptor copy)
     
    382387#if DEBUG_PROCESS_COPY_INIT
    383388cycle = (uint32_t)hal_get_cycles();
    384 if( DEBUG_PROCESS_COPY_INIT )
    385 printk("\n[%s] thread %x in process %x exit for process %x / cycle %d\n",
    386 __FUNCTION__, this->trdid, this->process->pid, local_process->pid, cycle );
     389if( DEBUG_PROCESS_COPY_INIT < cycle )
     390printk("\n[%s] thread[%x,%x] exit for process %x / cycle %d\n",
     391__FUNCTION__, this->process->pid, this->trdid, local_process->pid, cycle );
    387392#endif
    388393
     
    406411
    407412#if DEBUG_PROCESS_DESTROY
     413thread_t * this = CURRENT_THREAD;
    408414uint32_t cycle = (uint32_t)hal_get_cycles();
    409 if( DEBUG_PROCESS_DESTROY )
    410 printk("\n[%s] thread %x in process %x enter for process %x in cluster %x / cycle %d\n",
    411 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, pid, local_cxy, cycle );
     415if( DEBUG_PROCESS_DESTROY < cycle )
     416printk("\n[%s] thread[%x,%x] enter for process %x in cluster %x / cycle %d\n",
     417__FUNCTION__, this->process->pid, this->trdid, pid, local_cxy, cycle );
    412418#endif
    413419
     
    446452        if( process->vfs_bin_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
    447453        if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
    448         if( process->vfs_cwd_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
     454        if( process->cwd_xp      != XPTR_NULL ) vfs_file_count_down( process->cwd_xp );
    449455
    450456    // Destroy VMM
     
    456462#if DEBUG_PROCESS_DESTROY
    457463cycle = (uint32_t)hal_get_cycles();
    458 if( DEBUG_PROCESS_DESTROY )
    459 printk("\n[%s] thread %x in process %x exit / process %x in cluster %x / cycle %d\n",
    460 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, pid, local_cxy, cycle );
     464if( DEBUG_PROCESS_DESTROY < cycle )
     465printk("\n[%s] thread[%x,%x] exit / process %x in cluster %x / cycle %d\n",
     466__FUNCTION__, this->process->pid, this->trdid, pid, local_cxy, cycle );
    461467#endif
    462468
     
    561567        process_ptr = GET_PTR( process_xp );
    562568
    563 // printk("\n@@@ in %s : process_cxy %x / process_ptr %x / pid %x\n",
    564 // __FUNCTION__, process_cxy, process_ptr, hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) ) );
    565 
    566569        if( process_cxy == local_cxy )    // process copy is local
    567570        {
     
    652655assert( (LPID_FROM_PID( process->pid ) != 0 ), "target process must be an user process" );
    653656
    654     // get target process cluster
     657    // get target process owner cluster
    655658    owner_cxy = CXY_FROM_PID( process->pid );
    656659
     
    697700    while( 1 )
    698701    {
    699         // exit when all scheduler acknoledges received
     702        // exit when all scheduler acknowledges received
    700703        if ( ack_count == 0 ) break;
    701704   
     
    927930    uint32_t fd;
    928931
     932    // initialize lock
    929933    remote_queuelock_init( XPTR( local_cxy , &process->fd_array.lock ), LOCK_PROCESS_FDARRAY );
    930934
     935    // initialize number of open files
    931936    process->fd_array.current = 0;
    932937
     
    937942    }
    938943}
    939 /////////////////////////////////////////////////
    940 error_t process_fd_register( process_t * process,
     944////////////////////////////////////////////////////
     945error_t process_fd_register( xptr_t      process_xp,
    941946                             xptr_t      file_xp,
    942947                             uint32_t  * fdid )
     
    944949    bool_t    found;
    945950    uint32_t  id;
    946     uint32_t  count;
    947951    xptr_t    xp;
    948952
    949953    // get reference process cluster and local pointer
    950     xptr_t ref_xp = process->ref_xp;
    951     process_t * ref_ptr = GET_PTR( ref_xp );
    952     cxy_t       ref_cxy = GET_CXY( ref_xp );
     954    process_t * process_ptr = GET_PTR( process_xp );
     955    cxy_t       process_cxy = GET_CXY( process_xp );
     956
     957// check client process is reference process
     958assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->ref_xp ) ) ),
     959"client process must be reference process\n" );
     960
     961#if DEBUG_PROCESS_FD_REGISTER
     962thread_t * this  = CURRENT_THREAD;
     963uint32_t   cycle = (uint32_t)hal_get_cycles();
     964pid_t      pid   = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) );
     965if( DEBUG_PROCESS_FD_REGISTER < cycle )
     966printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n",
     967__FUNCTION__, this->process->pid, this->trdid, pid, cycle );
     968#endif
     969
     970    // build extended pointer on lock protecting reference fd_array
     971    xptr_t lock_xp = XPTR( process_cxy , &process_ptr->fd_array.lock );
    953972
    954973    // take lock protecting reference fd_array
    955         remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
     974        remote_queuelock_acquire( lock_xp );
    956975
    957976    found   = false;
     
    959978    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
    960979    {
    961         xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
     980        xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[id] ) );
    962981        if ( xp == XPTR_NULL )
    963982        {
    964983            // update reference fd_array
    965             hal_remote_s64( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
    966                 count = hal_remote_l32( XPTR( ref_cxy , &ref_ptr->fd_array.current ) ) + 1;
    967             hal_remote_s32( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , count );
    968 
    969             // update local fd_array copy if required
    970             if( ref_cxy != local_cxy )
    971             {
    972                 process->fd_array.array[id] = file_xp;
    973                 process->fd_array.current   = count;
    974             }
     984            hal_remote_s64( XPTR( process_cxy , &process_ptr->fd_array.array[id] ) , file_xp );
     985                hal_remote_atomic_add( XPTR( process_cxy , &process_ptr->fd_array.current ) , 1 );
    975986
    976987            // exit
     
    981992    }
    982993
    983     // release lock protecting reference fd_array
    984         remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
     994    // release lock protecting fd_array
     995        remote_queuelock_release( lock_xp );
     996
     997#if DEBUG_PROCESS_FD_REGISTER
     998cycle = (uint32_t)hal_get_cycles();
     999if( DEBUG_PROCESS_FD_REGISTER < cycle )
     1000printk("\n[%s] thread[%x,%x] exit for process %x / fdid %d / cycle %d\n",
     1001__FUNCTION__, this->process->pid, this->trdid, pid, id, cycle );
     1002#endif
    9851003
    9861004    if ( !found ) return -1;
    9871005    else          return 0;
    988 }
     1006
     1007}  // end process_fd_register()
    9891008
    9901009////////////////////////////////////////////////
     
    11191138        // returns trdid
    11201139        *trdid = TRDID( local_cxy , ltid );
    1121 
    1122 // if( LPID_FROM_PID( process->pid ) == 0 )
    1123 // printk("\n@@@ %s : allocate ltid %d for a thread %s in cluster %x\n",
    1124 // __FUNCTION__, ltid, thread_type_str( thread->type), local_cxy );
    1125 
    11261140    }
    11271141
     
    11581172    process->th_tbl[ltid] = NULL;
    11591173    process->th_nr = count-1;
    1160 
    1161 // if( LPID_FROM_PID( process->pid ) == 0 )
    1162 // printk("\n@@@ %s : release ltid %d for a thread %s in cluster %x\n",
    1163 // __FUNCTION__, ltid, thread_type_str( thread->type), local_cxy );
    11641174
    11651175    // release lock protecting th_tbl
     
    13631373    process_t      * process;                 // local pointer on this process
    13641374    pid_t            pid;                     // this process identifier
     1375    xptr_t           ref_xp;                  // reference process for this process
    13651376        error_t          error;                   // value returned by called functions
    13661377    char           * path;                    // path to .elf file
     
    13701381    char          ** args_pointers;           // array of pointers on main thread arguments
    13711382
    1372     // get thread, process & PID
     1383    // get thread, process, pid and ref_xp
    13731384    thread  = CURRENT_THREAD;
    13741385    process = thread->process;
    13751386    pid     = process->pid;
     1387    ref_xp  = process->ref_xp;
    13761388
    13771389        // get relevant infos from exec_info
     
    13901402    file_xp = XPTR_NULL;
    13911403    file_id = 0xFFFFFFFF;
    1392         error   = vfs_open( process,
     1404        error   = vfs_open( process->vfs_root_xp,
    13931405                            path,
     1406                        ref_xp,
    13941407                            O_RDONLY,
    13951408                            0,
     
    15431556#endif
    15441557
    1545 }  // end process_zero_init()
     1558}  // end process_zero_create()
    15461559
    15471560////////////////////////////////
     
    15581571
    15591572#if DEBUG_PROCESS_INIT_CREATE
     1573thread_t * this = CURRENT_THREAD;
    15601574uint32_t cycle = (uint32_t)hal_get_cycles();
    15611575if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1562 printk("\n[%s] thread %x in process %x enter / cycle %d\n",
    1563 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
     1576printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1577__FUNCTION__, this->process->pid, this->trdid, cycle );
    15641578#endif
    15651579
     
    15711585"no memory for process descriptor in cluster %x\n", local_cxy  );
    15721586
     1587    // set the CWD and VFS_ROOT fields in process descriptor
     1588    process->cwd_xp      = process_zero.vfs_root_xp;
     1589    process->vfs_root_xp = process_zero.vfs_root_xp;
     1590
    15731591    // get PID from local cluster
    15741592    error = cluster_pid_alloc( process , &pid );
     
    15891607#if(DEBUG_PROCESS_INIT_CREATE & 1)
    15901608if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1591 printk("\n[%s] thread %x in process %x initialized process descriptor\n",
    1592 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid );
     1609printk("\n[%s] thread[%x,%x] initialized process descriptor\n",
     1610__FUNCTION__, this->process->pid, this->trdid );
    15931611#endif
    15941612
     
    15961614    file_xp = XPTR_NULL;
    15971615    file_id = -1;
    1598         error   = vfs_open( process,
     1616        error   = vfs_open( process->vfs_root_xp,
    15991617                            CONFIG_PROCESS_INIT_PATH,
     1618                        XPTR( local_cxy , process ),
    16001619                            O_RDONLY,
    16011620                            0,
     
    16081627#if(DEBUG_PROCESS_INIT_CREATE & 1)
    16091628if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1610 printk("\n[%s] thread %x in process %x open .elf file decriptor\n",
    1611 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid );
     1629printk("\n[%s] thread[%x,%x] open .elf file decriptor\n",
     1630__FUNCTION__, this->process->pid, this->trdid );
    16121631#endif
    16131632
     
    16211640#if(DEBUG_PROCESS_INIT_CREATE & 1)
    16221641if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1623 printk("\n[%s] thread %x in process %x registered code/data vsegs in VMM\n",
    1624 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid );
     1642printk("\n[%s] thread[%x,%x] registered code/data vsegs in VMM\n",
     1643__FUNCTION__, this->process->pid, this->trdid );
    16251644#endif
    16261645
     
    16411660#if(DEBUG_PROCESS_INIT_CREATE & 1)
    16421661if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1643 printk("\n[%s] thread %x in process %x registered init process in parent\n",
    1644 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid );
     1662printk("\n[%s] thread[%x,%x] registered init process in parent\n",
     1663__FUNCTION__, this->process->pid, this->trdid );
    16451664#endif
    16461665
     
    16681687#if(DEBUG_PROCESS_INIT_CREATE & 1)
    16691688if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1670 printk("\n[%s] thread %x in process %x created main thread\n",
    1671 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid );
     1689printk("\n[%s] thread[%x,%x] created main thread\n",
     1690__FUNCTION__, this->process->pid, this->trdid );
    16721691#endif
    16731692
     
    16801699cycle = (uint32_t)hal_get_cycles();
    16811700if( DEBUG_PROCESS_INIT_CREATE < cycle )
    1682 printk("\n[%s] thread %x in process %x exit / cycle %d\n",
    1683 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
     1701printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1702__FUNCTION__, this->process->pid, this->trdid, cycle );
    16841703#endif
    16851704
     
    18651884
    18661885#if DEBUG_PROCESS_TXT
     1886thread_t * this = CURRENT_THREAD;
    18671887uint32_t cycle = (uint32_t)hal_get_cycles();
    18681888if( DEBUG_PROCESS_TXT < cycle )
    1869 printk("\n[%s] thread %x in process %x attached process %x to TXT %d / cycle %d\n",
    1870 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
    1871 process->pid, txt_id , cycle );
     1889printk("\n[%s] thread[%x,%x] attached process %x to TXT %d / cycle %d\n",
     1890__FUNCTION__, this->process->pid, this->trdid, process->pid, txt_id , cycle );
    18721891#endif
    18731892
     
    19191938
    19201939#if DEBUG_PROCESS_TXT
     1940thread_t * this = CURRENT_THREAD;
    19211941uint32_t cycle  = (uint32_t)hal_get_cycles();
    19221942uint32_t txt_id = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
    19231943if( DEBUG_PROCESS_TXT < cycle )
    1924 printk("\n[%s] thread %x in process %x detached process %x from TXT %d / cycle %d\n",
    1925 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
    1926 process_pid, txt_id, cycle );
     1944printk("\n[%s] thread[%x,%x] detached process %x from TXT %d / cycle %d\n",
     1945__FUNCTION__, this->process->pid, this->trdid, process_pid, txt_id, cycle );
    19271946#endif
    19281947
     
    19611980
    19621981#if DEBUG_PROCESS_TXT
     1982thread_t * this = CURRENT_THREAD;
    19631983uint32_t cycle  = (uint32_t)hal_get_cycles();
    19641984uint32_t txt_id = hal_remote_l32( XPTR( txt_cxy , &txt_ptr->channel ) );
    19651985if( DEBUG_PROCESS_TXT < cycle )
    1966 printk("\n[%s] thread %x in process %x give TXT %d to process %x / cycle %d\n",
    1967 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, process_pid, cycle );
     1986printk("\n[%s] thread[%x,%x] give TXT %d to process %x / cycle %d\n",
     1987__FUNCTION__, this->process->pid, this->trdid, txt_id, process_pid, cycle );
    19681988#endif
    19691989
     
    19902010
    19912011#if DEBUG_PROCESS_TXT
    1992 uint32_t cycle;
     2012thread_t * this  = CURRENT_THREAD;
     2013uint32_t   cycle;
    19932014#endif
    19942015
     
    20422063
    20432064#if DEBUG_PROCESS_TXT
    2044 cycle   = (uint32_t)hal_get_cycles();
     2065cycle = (uint32_t)hal_get_cycles();
    20452066uint32_t ksh_pid = hal_remote_l32( XPTR( current_cxy , &current_ptr->pid ) );
    20462067if( DEBUG_PROCESS_TXT < cycle )
    2047 printk("\n[%s] thread %x in process %x release TXT %d to KSH %x / cycle %d\n",
    2048 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, ksh_pid, cycle );
     2068printk("\n[%s] thread[%x,%x] release TXT %d to KSH %x / cycle %d\n",
     2069__FUNCTION__, this->process->pid, this->trdid, txt_id, ksh_pid, cycle );
    20492070process_txt_display( txt_id );
    20502071#endif
     
    20792100
    20802101#if DEBUG_PROCESS_TXT
    2081 cycle   = (uint32_t)hal_get_cycles();
     2102cycle  = (uint32_t)hal_get_cycles();
    20822103uint32_t new_pid = hal_remote_l32( XPTR( current_cxy , &current_ptr->pid ) );
    20832104if( DEBUG_PROCESS_TXT < cycle )
    2084 printk("\n[%s] thread %x in process %x release TXT %d to process %x / cycle %d\n",
    2085 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, new_pid, cycle );
     2105printk("\n[%s] thread[%x,%x] release TXT %d to process %x / cycle %d\n",
     2106__FUNCTION__,this->process->pid, this->trdid, txt_id, new_pid, cycle );
    20862107process_txt_display( txt_id );
    20872108#endif
     
    20992120cycle = (uint32_t)hal_get_cycles();
    21002121if( DEBUG_PROCESS_TXT < cycle )
    2101 printk("\n[%s] thread %x in process %x release TXT %d to nobody / cycle %d\n",
    2102 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, cycle );
     2122printk("\n[%s] thread[%x,%x] release TXT %d to nobody / cycle %d\n",
     2123__FUNCTION__, this->process->pid, this->trdid, txt_id, cycle );
    21032124process_txt_display( txt_id );
    21042125#endif
     
    21132134if( DEBUG_PROCESS_TXT < cycle )
    21142135printk("\n[%s] thread %x in process %d does nothing (not TXT owner) / cycle %d\n",
    2115 __FUNCTION__, CURRENT_THREAD->trdid, process_pid, cycle );
     2136__FUNCTION__, this->trdid, process_pid, cycle );
    21162137process_txt_display( txt_id );
    21172138#endif
  • trunk/kernel/kern/process.h

    r601 r610  
    125125        fd_array_t         fd_array;         /*! embedded open file descriptors array            */
    126126
    127         xptr_t             vfs_root_xp;      /*! extended pointer on current VFS root inode      */
     127        xptr_t             vfs_root_xp;      /*! extended pointer on VFS root inode              */
    128128        xptr_t             vfs_bin_xp;       /*! extended pointer on .elf file descriptor        */
    129129        pid_t              pid;              /*! process identifier                              */
     
    132132    xptr_t             parent_xp;        /*! extended pointer on parent process              */
    133133
    134         xptr_t             vfs_cwd_xp;       /*! extended pointer on current working dir inode   */
    135         remote_rwlock_t    cwd_lock;         /*! lock protecting working directory changes       */
     134        xptr_t             cwd_xp;           /*! extended pointer on current working dir inode   */
     135        remote_busylock_t  cwd_lock;         /*! lock protecting working directory changes       */
    136136
    137137        xlist_entry_t      children_root;    /*! root of the children process xlist              */
     
    338338 * It scan the list of local thread, and sets the THREAD_BLOCKED_GLOBAL bit for all threads.
    339339 * It request the relevant schedulers to acknowledge the blocking, using IPI if required,
    340  * and returns only when all threads in cluster, but the calling thread, are actually blocked.
     340 * when the target thread is running on another core than the calling thread.
     341 * It returns only when all threads in cluster, including the caller are actually blocked.
    341342 * The threads are not detached from the scheduler, and not detached from the local process.
    342343 *********************************************************************************************
     
    425426
    426427/*********************************************************************************************
    427  * This function allocates a free slot in the fd_array of the reference process,
    428  * register the <file_xp> argument in the allocated slot, and return the slot index.
     428 * This function allocates a free slot in the fd_array of the reference process
     429 * identified by the <process_xp> argument, register the <file_xp> argument in the
     430 * allocated slot, and return the slot index in the <fdid> buffer.
    429431 * It can be called by any thread in any cluster, because it uses portable remote access
    430432 * primitives to access the reference process descriptor.
    431433 * It takes the lock protecting the reference fd_array against concurrent accesses.
    432434 *********************************************************************************************
    433  * @ file_xp  : extended pointer on the file descriptor to be registered.
    434  * @ fdid     : [out] buffer for fd_array slot index.
     435 * @ process_xp : [in]  extended pointer on client reference process.
     436 * @ file_xp    : [in]  extended pointer on the file descriptor to be registered.
     437 * @ fdid       : [out] buffer for fd_array slot index.
    435438 * @ return 0 if success / return EMFILE if array full.
    436439 ********************************************************************************************/
    437 error_t process_fd_register( process_t * process,
     440error_t process_fd_register( xptr_t      process_xp,
    438441                             xptr_t      file_xp,
    439442                             uint32_t  * fdid );
     
    447450 * TODO this function is not implemented yet.
    448451 *********************************************************************************************
    449  * @ process  : pointer on the local process descriptor.
    450  * @ fdid     : file descriptor index in the fd_array.
     452 * @ process  : [in] pointer on the local process descriptor.
     453 * @ fdid     : [in] file descriptor index in the fd_array.
    451454 ********************************************************************************************/
    452455void process_fd_remove( process_t * process,
  • trunk/kernel/kern/rpc.c

    r601 r610  
    7575    &rpc_kcm_alloc_server,                 // 22
    7676    &rpc_kcm_free_server,                  // 23
    77     &rpc_mapper_move_user_server,          // 24
     77    &rpc_undefined,                        // 24   unused slot
    7878    &rpc_mapper_handle_miss_server,        // 25
    7979    &rpc_undefined,                        // 26   unused slot
     
    111111    "KCM_ALLOC",                 // 22
    112112    "KCM_FREE",                  // 23
    113     "MAPPER_MOVE_USER",          // 24
     113    "undefined",                 // 24
    114114    "MAPPER_HANDLE_MISS",        // 25
    115115    "undefined",                 // 26
     
    302302uint32_t cycle = (uint32_t)hal_get_cycles();
    303303if( DEBUG_RPC_SERVER_GENERIC < cycle )
    304 printk("\n[DBG] %s : RPC thread %x on core[%d] takes RPC_FIFO ownership / cycle %d\n",
     304printk("\n[%s] RPC thread %x on core[%d] takes RPC_FIFO ownership / cycle %d\n",
    305305__FUNCTION__, server_ptr->trdid, server_core_lid, cycle );
    306306#endif
     
    318318                desc_ptr = GET_PTR( desc_xp );
    319319
    320                     index    = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->index ) );
    321                 blocking = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->blocking ) );
     320                    index      = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->index ) );
     321                blocking   = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->blocking ) );
     322                client_ptr = hal_remote_lpt( XPTR( desc_cxy , &desc_ptr->thread ) );
    322323
    323324#if DEBUG_RPC_SERVER_GENERIC
     
    325326uint32_t items = remote_fifo_items( XPTR( local_cxy , rpc_fifo ) );
    326327if( DEBUG_RPC_SERVER_GENERIC < cycle )
    327 printk("\n[DBG] %s : RPC thread %x got rpc %s / client_cxy %x / items %d / cycle %d\n",
     328printk("\n[%s] RPC thread %x got rpc %s / client_cxy %x / items %d / cycle %d\n",
    328329__FUNCTION__, server_ptr->trdid, rpc_str[index], desc_cxy, items, cycle );
    329330#endif
     331                // register client thread in RPC thread descriptor
     332                server_ptr->rpc_client_xp = XPTR( desc_cxy , client_ptr );
     333 
    330334                // call the relevant server function
    331335                rpc_server[index]( desc_xp );
     
    334338cycle = (uint32_t)hal_get_cycles();
    335339if( DEBUG_RPC_SERVER_GENERIC < cycle )
    336 printk("\n[DBG] %s : RPC thread %x completes rpc %s / client_cxy %x / cycle %d\n",
     340printk("\n[%s] RPC thread %x completes rpc %s / client_cxy %x / cycle %d\n",
    337341__FUNCTION__, server_ptr->trdid, rpc_str[index], desc_cxy, cycle );
    338342#endif
     
    355359cycle = (uint32_t)hal_get_cycles();
    356360if( DEBUG_RPC_SERVER_GENERIC < cycle )
    357 printk("\n[DBG] %s : RPC thread %x unblocked client thread %x / cycle %d\n",
     361printk("\n[%s] RPC thread %x unblocked client thread %x / cycle %d\n",
    358362__FUNCTION__, server_ptr->trdid, client_ptr->trdid, cycle );
    359363#endif
     
    372376uint32_t cycle = (uint32_t)hal_get_cycles();
    373377if( DEBUG_RPC_SERVER_GENERIC < cycle )
    374 printk("\n[DBG] %s : RPC thread %x suicides / cycle %d\n",
     378printk("\n[%s] RPC thread %x suicides / cycle %d\n",
    375379__FUNCTION__, server_ptr->trdid, cycle );
    376380#endif
     
    391395uint32_t cycle = (uint32_t)hal_get_cycles();
    392396if( DEBUG_RPC_SERVER_GENERIC < cycle )
    393 printk("\n[DBG] %s : RPC thread %x block IDLE & deschedules / cycle %d\n",
     397printk("\n[%s] RPC thread %x block IDLE & deschedules / cycle %d\n",
    394398__FUNCTION__, server_ptr->trdid, cycle );
    395399#endif
     
    870874uint32_t  action = rpc->args[0];
    871875pid_t     pid    = rpc->args[1];
     876thread_t * this = CURRENT_THREAD;
    872877if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
    873 printk("\n[DBG] %s : enter to request %s of process %x in cluster %x / cycle %d\n",
    874 __FUNCTION__ , process_action_str( action ) , pid , cxy , cycle );
     878printk("\n[%s] thread[%x,%x] enter to request %s of process %x in cluster %x / cycle %d\n",
     879__FUNCTION__, this->process->pid, this->trdid, process_action_str(action), pid, cxy, cycle );
    875880#endif
    876881
     
    885890cycle = (uint32_t)hal_get_cycles();
    886891if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
    887 printk("\n[DBG] %s : exit after requesting to %s process %x in cluster %x / cycle %d\n",
    888 __FUNCTION__ , process_action_str( action ) , pid , cxy , cycle );
     892printk("\n[%s] thread[%x,%x] requested %s of process %x in cluster %x / cycle %d\n",
     893__FUNCTION__, this->process->pid, this->trdid, process_action_str(action), pid, cxy, cycle );
    889894#endif
    890895
     
    915920#if DEBUG_RPC_PROCESS_SIGACTION
    916921uint32_t cycle = (uint32_t)hal_get_cycles();
     922thread_t * this = CURRENT_THREAD;
    917923if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
    918 printk("\n[DBG] %s : enter to %s process %x in cluster %x / cycle %d\n",
    919 __FUNCTION__ , process_action_str( action ) , pid , local_cxy , cycle );
     924printk("\n[%s] thread[%x,%x] enter to %s process %x in cluster %x / cycle %d\n",
     925__FUNCTION__, this->process->pid, this->trdid,
     926process_action_str( action ), pid, local_cxy, cycle );
    920927#endif
    921928
     
    954961cycle = (uint32_t)hal_get_cycles();
    955962if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
    956 printk("\n[DBG] %s : exit after %s process %x in cluster %x / cycle %d\n",
    957 __FUNCTION__ , process_action_str( action ) , pid , local_cxy , cycle );
     963printk("\n[%s] thread[%x,%x] exit after %s process %x in cluster %x / cycle %d\n",
     964__FUNCTION__, this->process->pid, this->trdid,
     965process_action_str( action ), pid, local_cxy, cycle );
    958966#endif
    959967
     
    966974/////////////////////////////////////////////////////
    967975void rpc_vfs_inode_create_client( cxy_t          cxy,     
    968                                   xptr_t         dentry_xp,  // in
    969976                                  uint32_t       fs_type,    // in
    970977                                  uint32_t       inode_type, // in
     
    9931000
    9941001    // set input arguments in RPC descriptor
    995     rpc.args[0] = (uint64_t)dentry_xp;
    996     rpc.args[1] = (uint64_t)fs_type;
    997     rpc.args[2] = (uint64_t)inode_type;
    998     rpc.args[3] = (uint64_t)attr;
    999     rpc.args[4] = (uint64_t)rights;
    1000     rpc.args[5] = (uint64_t)uid;
    1001     rpc.args[6] = (uint64_t)gid;
     1002    rpc.args[0] = (uint64_t)fs_type;
     1003    rpc.args[1] = (uint64_t)inode_type;
     1004    rpc.args[2] = (uint64_t)attr;
     1005    rpc.args[3] = (uint64_t)rights;
     1006    rpc.args[4] = (uint64_t)uid;
     1007    rpc.args[5] = (uint64_t)gid;
    10021008
    10031009    // register RPC request in remote RPC fifo
     
    10051011
    10061012    // get output values from RPC descriptor
    1007     *inode_xp = (xptr_t)rpc.args[7];
    1008     *error    = (error_t)rpc.args[8];
     1013    *inode_xp = (xptr_t)rpc.args[6];
     1014    *error    = (error_t)rpc.args[7];
    10091015
    10101016#if DEBUG_RPC_VFS_INODE_CREATE
     
    10271033#endif
    10281034
    1029     xptr_t           dentry_xp;
    10301035    uint32_t         fs_type;
    10311036    uint32_t         inode_type;
     
    10421047
    10431048    // get input arguments from client rpc descriptor
    1044     dentry_xp  = (xptr_t)    hal_remote_l64( XPTR( client_cxy , &desc->args[0] ) );
    1045     fs_type    = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[1] ) );
    1046     inode_type = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[2] ) );
    1047     attr       = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[3] ) );
    1048     rights     = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[4] ) );
    1049     uid        = (uid_t)     hal_remote_l64( XPTR( client_cxy , &desc->args[5] ) );
    1050     gid        = (gid_t)     hal_remote_l64( XPTR( client_cxy , &desc->args[6] ) );
     1049    fs_type    = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[0] ) );
     1050    inode_type = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[1] ) );
     1051    attr       = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[2] ) );
     1052    rights     = (uint32_t)  hal_remote_l64( XPTR( client_cxy , &desc->args[3] ) );
     1053    uid        = (uid_t)     hal_remote_l64( XPTR( client_cxy , &desc->args[4] ) );
     1054    gid        = (gid_t)     hal_remote_l64( XPTR( client_cxy , &desc->args[5] ) );
    10511055
    10521056    // call local kernel function
    1053     error = vfs_inode_create( dentry_xp,
    1054                               fs_type,
     1057    error = vfs_inode_create( fs_type,
    10551058                              inode_type,
    10561059                              attr,
     
    10611064
    10621065    // set output arguments
    1063     hal_remote_s64( XPTR( client_cxy , &desc->args[7] ) , (uint64_t)inode_xp );
    1064     hal_remote_s64( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)error );
     1066    hal_remote_s64( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)inode_xp );
     1067    hal_remote_s64( XPTR( client_cxy , &desc->args[7] ) , (uint64_t)error );
    10651068
    10661069#if DEBUG_RPC_VFS_INODE_CREATE
     
    11491152                                   uint32_t               type,         // in
    11501153                                   char                 * name,         // in
    1151                                    struct vfs_inode_s   * parent,       // in
    11521154                                   xptr_t               * dentry_xp,    // out
    11531155                                   error_t              * error )       // out
     
    11721174    rpc.args[0] = (uint64_t)type;
    11731175    rpc.args[1] = (uint64_t)(intptr_t)name;
    1174     rpc.args[2] = (uint64_t)(intptr_t)parent;
    11751176
    11761177    // register RPC request in remote RPC fifo
     
    11781179
    11791180    // get output values from RPC descriptor
    1180     *dentry_xp = (xptr_t)rpc.args[3];
    1181     *error     = (error_t)rpc.args[4];
     1181    *dentry_xp = (xptr_t)rpc.args[2];
     1182    *error     = (error_t)rpc.args[3];
    11821183
    11831184#if DEBUG_RPC_VFS_DENTRY_CREATE
     
    12021203    uint32_t      type;
    12031204    char        * name;
    1204     vfs_inode_t * parent;
    12051205    xptr_t        dentry_xp;
    12061206    error_t       error;
     
    12121212
    12131213    // get arguments "name", "type", and "parent" from client RPC descriptor
    1214     type   = (uint32_t)               hal_remote_l64( XPTR( client_cxy , &desc->args[0] ) );
    1215     name   = (char *)(intptr_t)       hal_remote_l64( XPTR( client_cxy , &desc->args[1] ) );
    1216     parent = (vfs_inode_t *)(intptr_t)hal_remote_l64( XPTR( client_cxy , &desc->args[2] ) );
     1214    type   = (uint32_t)         hal_remote_l64( XPTR( client_cxy , &desc->args[0] ) );
     1215    name   = (char *)(intptr_t) hal_remote_l64( XPTR( client_cxy , &desc->args[1] ) );
    12171216
    12181217    // makes a local copy of  name
     
    12231222    error = vfs_dentry_create( type,
    12241223                               name_copy,
    1225                                parent,
    12261224                               &dentry_xp );
    12271225    // set output arguments
    1228     hal_remote_s64( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)dentry_xp );
    1229     hal_remote_s64( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
     1226    hal_remote_s64( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)dentry_xp );
     1227    hal_remote_s64( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
    12301228
    12311229#if DEBUG_RPC_VFS_DENTRY_CREATE
     
    21122110
    21132111/////////////////////////////////////////////////////////////////////////////////////////
    2114 // [24]          Marshaling functions attached to RPC_MAPPER_MOVE_USER 
    2115 /////////////////////////////////////////////////////////////////////////////////////////
    2116 
    2117 /////////////////////////////////////////////////
    2118 void rpc_mapper_move_user_client( cxy_t      cxy,
    2119                                   mapper_t * mapper,        // in
    2120                                   bool_t     to_buffer,     // in
    2121                                   uint32_t   file_offset,   // in
    2122                                   void     * buffer,        // in
    2123                                   uint32_t   size,          // in
    2124                                   error_t  * error )        // out
    2125 {
    2126 #if DEBUG_RPC_MAPPER_MOVE_USER
    2127 uint32_t cycle = (uint32_t)hal_get_cycles();
    2128 if( cycle > DEBUG_RPC_MAPPER_MOVE_USER )
    2129 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n",
    2130 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
    2131 #endif
    2132 
    2133     assert( (cxy != local_cxy) , "target cluster is not remote\n");
    2134 
    2135     // initialise RPC descriptor header