Changeset 265 for trunk/kernel


Ignore:
Timestamp:
Jul 21, 2017, 7:36:08 AM (7 years ago)
Author:
alain
Message:

Fix several bugs in VFS.

Location:
trunk/kernel
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/kern/kernel_init.c

    r249 r265  
    860860            fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc();
    861861
    862 printk("\n@@@ %s extend = %x\n", __FUNCTION__ , fatfs_ctx );
    863 
    864862            nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ ,
    865863                           "cannot create FATFS context in cluster 0\n" );
     
    901899            hal_core_sleep();
    902900        }
    903 
    904 ///////////////////////////////@@@
    905 fatfs_ctx_display();
    906 ///////////////////////////////@@@
    907901
    908902        // register VFS root inode in process_zero
  • trunk/kernel/kern/rpc.c

    r248 r265  
    7474    &rpc_kcm_alloc_server,              // 22
    7575    &rpc_kcm_free_server,               // 23
    76     &rpc_mapper_move_server,            // 24
     76    &rpc_mapper_move_buffer_server,     // 24
    7777    &rpc_undefined,                     // 25
    7878    &rpc_undefined,                     // 26
     
    11841184
    11851185/////////////////////////////////////////////////////////////////////////////////////////
    1186 // [24]          Marshaling functions attached to RPC_MAPPER_MOVE
    1187 /////////////////////////////////////////////////////////////////////////////////////////
    1188 
    1189 ///////////////////////////////////////////
    1190 void rpc_mapper_move_client( cxy_t      cxy,
    1191                              mapper_t * mapper,        // in
    1192                              uint32_t   to_buffer,     // in
    1193                              uint32_t   file_offset,   // in
    1194                              void     * buffer,        // in
    1195                              uint32_t   size,          // in
    1196                              error_t  * error )        // out
    1197 {
    1198     assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
    1199 
    1200     // initialise RPC descriptor header
    1201     rpc_desc_t  rpc;
    1202     rpc.index    = RPC_MAPPER_MOVE;
     1186// [24]          Marshaling functions attached to RPC_MAPPER_MOVE_BUFFER
     1187/////////////////////////////////////////////////////////////////////////////////////////
     1188
     1189///////////////////////////////////////////////////
     1190void rpc_mapper_move_buffer_client( cxy_t      cxy,
     1191                                    mapper_t * mapper,        // in
     1192                                    bool_t     to_buffer,     // in
     1193                                    bool_t     is_user,       // in
     1194                                    uint32_t   file_offset,   // in
     1195                                    void     * buffer,        // in
     1196                                    uint32_t   size,          // in
     1197                                    error_t  * error )        // out
     1198{
     1199    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
     1200
     1201    // initialise RPC descriptor header
     1202    rpc_desc_t  rpc;
     1203    rpc.index    = RPC_MAPPER_MOVE_BUFFER;
    12031204    rpc.response = 1;
    12041205
     
    12061207    rpc.args[0] = (uint64_t)(intptr_t)mapper;
    12071208    rpc.args[1] = (uint64_t)to_buffer;
    1208     rpc.args[2] = (uint64_t)file_offset;
    1209     rpc.args[3] = (uint64_t)(intptr_t)buffer;
    1210     rpc.args[4] = (uint64_t)size;
     1209    rpc.args[2] = (uint64_t)is_user;
     1210    rpc.args[3] = (uint64_t)file_offset;
     1211    rpc.args[4] = (uint64_t)(intptr_t)buffer;
     1212    rpc.args[5] = (uint64_t)size;
    12111213
    12121214    // register RPC request in remote RPC fifo (blocking function)
     
    12141216
    12151217    // get output values from RPC descriptor
    1216     *error     = (error_t)rpc.args[5];
    1217 }
    1218 
    1219 ////////////////////////////////////////
    1220 void rpc_mapper_move_server( xptr_t xp )
     1218    *error     = (error_t)rpc.args[6];
     1219}
     1220
     1221///////////////////////////////////////////////
     1222void rpc_mapper_move_buffer_server( xptr_t xp )
    12211223{
    12221224    mapper_t * mapper;
    1223     uint32_t   to_buffer;
     1225    bool_t     to_buffer;
     1226    bool_t     is_user;
    12241227    uint32_t   file_offset;
    12251228    void     * buffer;
     
    12341237    mapper      = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
    12351238    to_buffer   =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
    1236     file_offset =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
    1237     buffer      = (void     *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
    1238     size        =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
     1239    is_user     =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
     1240    file_offset =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
     1241    buffer      = (void     *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
     1242    size        =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
    12391243
    12401244    // call local kernel function
    1241     error = mapper_move( mapper,
    1242                          to_buffer,
    1243                          file_offset,
    1244                          buffer,
    1245                          size );
     1245    error = mapper_move_buffer( mapper,
     1246                                to_buffer,
     1247                                is_user,
     1248                                file_offset,
     1249                                buffer,
     1250                                size );
    12461251
    12471252    // set output argument to client RPC descriptor
    1248     hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error );
     1253    hal_remote_swd( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)error );
    12491254}
    12501255
  • trunk/kernel/kern/rpc.h

    r238 r265  
    7979    RPC_KCM_ALLOC              = 22,
    8080    RPC_KCM_FREE               = 23,
    81     RPC_MAPPER_MOVE            = 24,
     81    RPC_MAPPER_MOVE_BUFFER     = 24,
    8282
    8383    RPC_MAX_INDEX              = 30,
     
    551551
    552552/***********************************************************************************
    553  * [24] The RPC_MAPPER_MOVE is called by the vfs_move() function.
     553 * [24] The RPC_MAPPER_MOVE_USER is called by the vfs_move() function.
    554554 * It allows a client thread to requires a remote mapper to move data to/from
    555555 * an user buffer, as specified by the arguments.
     
    558558 * @ mapper      : [in]  local pointer on mapper
    559559 * @ to_buffer   : [in]  move data from buffer to mapper if non zero.
     560 * @ is_user     : [in]  buffer in user space if non zero.
    560561 * @ file_offset : [in]  first byte to move in mapper
    561562 * @ buffer      : [in]  pointer on buffer in user space
     
    563564 * @ error       : [out] error status (0 if success).
    564565 **********************************************************************************/
    565 void rpc_mapper_move_client( cxy_t             cxy,
    566                              struct mapper_s * mapper,
    567                              uint32_t          to_buffer,
    568                              uint32_t          file_offset,
    569                              void            * buffer,
    570                              uint32_t          size,
    571                              error_t         * error );
    572 
    573 void rpc_mapper_move_server( xptr_t xp );
     566void rpc_mapper_move_buffer_client( cxy_t             cxy,
     567                                    struct mapper_s * mapper,
     568                                    bool_t            to_buffer,
     569                                    bool_t            is_user,
     570                                    uint32_t          file_offset,
     571                                    void            * buffer,
     572                                    uint32_t          size,
     573                                    error_t         * error );
     574
     575void rpc_mapper_move_buffer_server( xptr_t xp );
    574576
    575577
  • trunk/kernel/libk/elf.c

    r227 r265  
    8787
    8888        // load .elf header
    89         count = vfs_move( true ,
     89        count = vfs_move( true,     // to_buffer
     90                      false,    // is_user
    9091                          file_xp,
    9192                          buffer,
     
    9495        if( count != size )
    9596        {
    96                 printk("\n[ERROR] in %s : failed to read ELF header\n", __FUNCTION__ );
     97                printk("\n[ERROR] in %s : cannot read ELF header size : %d / done = %d\n",
     98               __FUNCTION__ , size , count );
    9799                return -1;
    98100        }
     
    231233        error_t      error;
    232234
    233     elf_dmsg("\n[INFO] %s : enter for %s\n", __FUNCTION__ , pathname );
     235    elf_dmsg("\n[INFO] %s : enters for <%s>\n", __FUNCTION__ , pathname );
    234236
    235237    // avoid GCC warning
     
    250252        }
    251253
    252     elf_dmsg("\n[INFO] %s : file %s open\n", __FUNCTION__ , pathname );
     254    elf_dmsg("\n[INFO] %s : file <%s> open\n", __FUNCTION__ , pathname );
    253255
    254256        // load header in local buffer
     
    301303
    302304        // load seg descriptors array to local buffer
    303         count = vfs_move( true,
     305        count = vfs_move( true,       // to_buffer
     306                      false,      // is_user
    304307                          file_xp,
    305308                          segs_base,
  • trunk/kernel/mm/mapper.c

    r246 r265  
    169169        if ( page == NULL )   // missing page => create it and load it from file system
    170170        {
    171             mapper_dmsg("\n[INFO] %s : missing page => load from FS\n", __FUNCTION__ );
     171            mapper_dmsg("\n[INFO] %s : missing page => load from device\n", __FUNCTION__ );
    172172
    173173            // allocate one page from PPM
     
    298298}  // end mapper_release_page()
    299299
    300 /////////////////////////////////////////
    301 error_t mapper_move( mapper_t  *  mapper,
    302                      bool_t       to_buffer,
    303                      uint32_t     file_offset,
    304                      void      *  buffer,
    305                      uint32_t     size )
     300////////////////////////////////////////////////
     301error_t mapper_move_buffer( mapper_t  *  mapper,
     302                            bool_t       to_buffer,
     303                            bool_t       is_user,
     304                            uint32_t     file_offset,
     305                            void      *  buffer,
     306                            uint32_t     size )
    306307{
    307308    uint32_t   page_offset;    // first byte to move to/from a mapper page
     
    313314    uint8_t  * buf_ptr;        // current buffer  address
    314315 
    315     mapper_dmsg("\n[INFO] %s : enter / to_buf = %d / buffer = %x\n",
     316    mapper_dmsg("\n[INFO] %s : enters / to_buf = %d / buffer = %x\n",
    316317                __FUNCTION__ , to_buffer , buffer );
    317318
     
    339340        else                       page_count = CONFIG_PPM_PAGE_SIZE;
    340341
     342        mapper_dmsg("\n[INFO] %s : index = %d / offset = %d / count = %d\n",
     343                    __FUNCTION__ , index , page_offset , page_count );
     344
    341345        // get page descriptor
    342346        page = mapper_get_page( mapper , index );
     
    350354        buf_ptr = (uint8_t *)buffer + done;
    351355
     356        mapper_dmsg("\n[INFO] %s : index = %d / buf_ptr = %x / map_ptr = %x\n",
     357                    __FUNCTION__ , index , buf_ptr , map_ptr );
     358
    352359        // move fragment
    353360        if( to_buffer )
    354361        {
    355             hal_copy_to_uspace( buf_ptr , map_ptr , page_count );
    356         }
    357         else
     362            if( is_user ) hal_copy_to_uspace( buf_ptr , map_ptr , page_count );
     363            else          memcpy( buf_ptr , map_ptr , page_count );
     364        }
     365        else                 
    358366        {
    359367            page_do_dirty( page );
    360             hal_copy_from_uspace( map_ptr , buf_ptr , page_count );
     368            if( is_user ) hal_copy_from_uspace( map_ptr , buf_ptr , page_count );
     369            else          memcpy( map_ptr , buf_ptr , page_count );
    361370        }
    362371
     
    369378    return 0;
    370379
    371 }  // end mapper_move()
    372 
     380}  // end mapper_move_buffer()
     381
  • trunk/kernel/mm/mapper.h

    r246 r265  
    5151 * - The mapper_get_page() function that return a page descriptor pointer from a page
    5252 *   index in file is in charge of handling the miss on the mapper cache.
    53  * - The vfs_mapper_move_page() function is used to handle miss on one specific page,
     53 * - The vfs_mapper_move_page() function access the file system to handle a mapper miss,
    5454 *   or update a dirty page on device.
    55  * - The vfs_mapper_load_all() functions is used to load all pages of a given directory
    56  *   into the mapper.
    57  * - the mapper_move() function is used to move data to or from an user buffer.
     55 * - The vfs_mapper_load_all() functions is used to load all pages of a given file
     56 *   or directory into the mapper.
     57 * - the mapper_move_user() function is used to move data to or from an user buffer.
    5858 *   This user space buffer can be physically distributed in several clusters.
    5959 * - In the present implementation the cache size for a given file increases on demand,
     
    117117
    118118/*******************************************************************************************
    119  * This function move data between a kernel mapper and an user buffer.
     119 * This function move data between a mapper and an user or kernel buffer.
    120120 * It must be called by a thread running in the cluster containing the mapper.
    121  * It split the data in fragments : one fragment is a set of contiguous bytes
    122  * stored in the same mapper page. 
    123  * It uses "hal_uspace" accesses to move fragments to/from the user buffer.
     121 * - A kernel buffer must be entirely contained in the same cluster as the mapper.
     122 * - An user buffer can be physically distributed in several clusters.
     123 * In both cases, the data transfer is split in "fragments": one fragment contains
     124 * contiguous bytes in the same mapper page.
     125 * - It uses "hal_uspace" accesses to move a fragment to/from the user buffer.
     126 * - It uses a simple memcpy" access to move a fragment to/from a kernel buffer.
    124127 * In case of write, the dirty bit is set for all pages written in the mapper.
    125128 * The offset in the file descriptor is not modified by this function.
    126129 *******************************************************************************************
    127  * @ mapper       : local pointer on local mapper.
    128  * @ to_buffer    : move data from mapper to buffer if true.
     130 * @ mapper       : local pointer on mapper.
     131 * @ to_buffer    : mapper -> buffer if true / buffer -> mapper if false.
     132 * @ is_user      : user space buffer if true / kernel local buffer if false.
    129133 * @ file_offset  : first byte to move in file.
    130  * @ buffer       : buffer address in user space.
     134 * @ buffer       : pointer on buffer (local kernel buffer or user spaceaddress in user space.
    131135 * @ size         : number of bytes to move.
    132136 * returns O if success / returns EINVAL if error.
    133137 ******************************************************************************************/
    134 error_t mapper_move( mapper_t * mapper,
    135                      bool_t     to_buffer,
    136                      uint32_t   file_offset,
    137                      void     * buffer,
    138                      uint32_t   size );
     138error_t mapper_move_buffer( mapper_t * mapper,
     139                            bool_t     to_buffer,
     140                            bool_t     is_user,
     141                            uint32_t   file_offset,
     142                            void     * buffer,
     143                            uint32_t   size );
    139144
    140145/*******************************************************************************************
  • trunk/kernel/syscalls/sys_read.c

    r124 r265  
    110110
    111111        // transfer nbytes to kernel buffer
    112         error = vfs_move( true,               // read => (to_buffer = true)
     112        error = vfs_move( true,               // to_buffer
     113                          true,               // is_user
    113114                          file_xp ,
    114115                          kbuf ,
  • trunk/kernel/syscalls/sys_write.c

    r124 r265  
    110110
    111111        // transfer nbytes from kernel buffer
    112         error = vfs_move( false,               // write => (to_buffer = false)
     112        error = vfs_move( false,               // from buffer
     113                          true,                // is_user
    113114                          file_xp,
    114115                          kbuf ,
  • trunk/kernel/vfs/fatfs.c

    r246 r265  
    4646 
    4747//////////////////////////////////////////////////////////////////////////////////////////
    48 //              FATFS private and static functions
     48//              FATFS specific and static functions
    4949//////////////////////////////////////////////////////////////////////////////////////////
    5050
     
    7474
    7575//////////////////////////////////////////////////////////////////////////////////////////
    76 // This function display the content of the FATFS context.
     76// This function return an integer record value (one, two, or four bytes)
     77// from a memory buffer, taking into account endianness.
     78//////////////////////////////////////////////////////////////////////////////////////////
     79// @ offset        : first byte of record in buffer.
     80// @ size          : record length in bytes (1/2/4).
     81// @ buffer        : pointer on buffer base.
     82// @ little endian : the most significant byte has the highest address when true.
     83// @ return the integer value in a 32 bits word.
     84//////////////////////////////////////////////////////////////////////////////////////////
     85static uint32_t fatfs_get_record( uint32_t    offset,
     86                                  uint32_t    size,
     87                                  uint8_t   * buffer,
     88                                  uint32_t    little_endian )
     89{
     90    uint32_t n;
     91    uint32_t res  = 0;
     92
     93    if ( little_endian)
     94    {
     95        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
     96    }
     97    else
     98    {
     99        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
     100    }
     101    return res;
     102
     103}  // end fatfs_get_record()
     104
     105//////////////////////////////////////////////////////////////////////////////////////////
     106// This static function retun in the <name> buffer a short name stored in
     107// a SFN FATFS directory entry.
     108/////////////////////////i////////////////////////////////////////////////////////////////
     109// @ buffer   : pointer on buffer containing the directory entry.
     110// @ name     : [out] buffer allocated by the caller.
     111//////////////////////////////////////////////////////////////////////////////////////////
     112static void fatfs_get_name_from_short( uint8_t * buffer,
     113                                       char    * name )
     114{
     115    uint32_t i;
     116    uint32_t j = 0;
     117
     118    // get name
     119    for ( i = 0; i < 8 && buffer[i] != ' '; i++ )
     120    {
     121        name[j] = to_lower( buffer[i] );
     122        j++;
     123    }
     124
     125    // get extension
     126    for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )
     127    {
     128        // we entered the loop so there is an extension. add the dot
     129        if ( i == 8 )
     130        {
     131            name[j] = '.';
     132            j++;
     133        }
     134
     135        name[j] = to_lower( buffer[i] );
     136        j++;
     137    }
     138
     139    name[j] = '\0';
     140}
     141
     142//////////////////////////////////////////////////////////////////////////////////////////
     143// This static function retun in the <name> buffer a partial name stored in
     144// a LFN FATFS directory entry.
     145/////////////////////////i////////////////////////////////////////////////////////////////
     146// @ buffer   : pointer on buffer containing the directory entry.
     147// @ name     : [out] buffer allocated by the caller.
     148//////////////////////////////////////////////////////////////////////////////////////////
     149static void fatfs_get_name_from_long( uint8_t * buffer,
     150                                      char    * name )
     151{
     152    uint32_t   name_offset   = 0;
     153    uint32_t   buffer_offset = get_length(LDIR_ORD);
     154    uint32_t   l_name_1      = get_length(LDIR_NAME_1);
     155    uint32_t   l_name_2      = get_length(LDIR_NAME_2);
     156    uint32_t   l_name_3      = get_length(LDIR_NAME_3);
     157    uint32_t   l_attr        = get_length(LDIR_ATTR);
     158    uint32_t   l_type        = get_length(LDIR_TYPE);
     159    uint32_t   l_chksum      = get_length(LDIR_CHKSUM);
     160    uint32_t   l_rsvd        = get_length(LDIR_RSVD);
     161
     162    uint32_t   j             = 0;
     163    uint32_t   eof           = 0;
     164
     165    while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
     166    {
     167        while (j != l_name_1 && !eof )
     168        {
     169            if ( (buffer[buffer_offset] == 0x00) ||
     170                 (buffer[buffer_offset] == 0xFF) )
     171            {
     172                eof = 1;
     173                continue;
     174            }
     175            name[name_offset] = buffer[buffer_offset];
     176            buffer_offset += 2;
     177            j += 2;
     178            name_offset++;
     179        }
     180
     181        buffer_offset += (l_attr + l_type + l_chksum);
     182        j = 0;
     183
     184        while (j != l_name_2 && !eof )
     185        {
     186            if ( (buffer[buffer_offset] == 0x00) ||
     187                 (buffer[buffer_offset] == 0xFF) )
     188            {
     189                eof = 1;
     190                continue;
     191            }
     192            name[name_offset] = buffer[buffer_offset];
     193            buffer_offset += 2;
     194            j += 2;
     195            name_offset++;
     196        }
     197
     198        buffer_offset += l_rsvd;
     199        j = 0;
     200
     201        while (j != l_name_3 && !eof )
     202        {
     203            if ( (buffer[buffer_offset] == 0x00) ||
     204                 (buffer[buffer_offset] == 0xFF) )
     205            {
     206                eof = 1;
     207                continue;
     208            }
     209            name[name_offset] = buffer[buffer_offset];
     210            buffer_offset += 2;
     211            j += 2;
     212            name_offset++;
     213        }
     214    }
     215    name[name_offset] = 0;
     216
     217} // end get_name_from_long()
     218
     219//////////////////////////////////////////////////////////////////////////////////////////
     220// This function returns the FATFS cluster index of a page identified by its page
     221// index in the file, using the FAT mapper. It scans the FAT mapper, starting from the
     222// FATFS cluster index allocated to the first page of the file, until it reaches the
     223// searched page. The FAT mapper is automatically updated in case of miss.
     224// This function can be called by any thread running in any cluster, as it uses the
     225// RPC_FATFS_GET_CLUSTER to access the remote FAT mapper if required.
     226// We use a RPC to scan the FAT because the RPC_FIFO will avoid contention
     227// in the cluster containing the FAT mapper, and the RPC latency is not critical
     228// compared to the device access latency.
     229//////////////////////////////////////////////////////////////////////////////////////////
     230// @ ctx               : pointer on local FATFS context.
     231// @ first_cluster : first cluster allocated to a file in FATFS.
     232// @ page_index    : index of searched page in file (one page occupies one cluster).
     233// @ cluster_index : [out] pointer on buffer for FATFS cluster index.
     234// @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.
     235//////////////////////////////////////////////////////////////////////////////////////////
     236static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,
     237                                         uint32_t      first_cluster,
     238                                         uint32_t      page_index,
     239                                         uint32_t    * cluster_index )
     240{
     241    uint32_t searched_cluster;   // searched FATFS cluster index
     242    error_t  error;
     243
     244    // get extended pointer on FAT mapper
     245    xptr_t fat_mapper_xp = ctx->fat_mapper_xp;
     246
     247    // get cluster cxy and local pointer on FAT mapper
     248    cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
     249    mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
     250
     251    if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
     252    {
     253        error = fatfs_get_cluster( fat_mapper_ptr,
     254                                   first_cluster,
     255                                   page_index,
     256                                   &searched_cluster );
     257    }
     258    else                                 // FAT mapper is remote
     259    {
     260        rpc_fatfs_get_cluster_client( fat_mapper_cxy,
     261                                      fat_mapper_ptr,
     262                                      first_cluster,
     263                                      page_index,
     264                                      &searched_cluster,
     265                                      &error );
     266    }
     267   
     268    if( error )
     269    {
     270        printk("\n[ERROR] in %s : cannot access FAT\n", __FUNCTION__ );
     271        return error;
     272    }
     273
     274    // return success
     275    *cluster_index = searched_cluster;
     276    return 0;
     277
     278}  // end fatfs_cluster_from_index()
     279
     280//////////////////////////////////////////////////////////////////////////////////////////
     281//              FATFS specific but extern functions
     282//////////////////////////////////////////////////////////////////////////////////////////
     283
    77284//////////////////////////////////////////////////////////////////////////////////////////
    78285void fatfs_ctx_display()
    79286{
    80     uint32_t      type      = FS_TYPE_FATFS;
    81287    vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
    82288    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
     
    99305}
    100306
    101 //////////////////////////////////////////////////////////////////////////////////////////
    102 // This function return an integer record value (one, two, or four bytes)
    103 // from a memory buffer, taking into account endianness.
    104 //////////////////////////////////////////////////////////////////////////////////////////
    105 // @ offset        : first byte of record in buffer.
    106 // @ size          : record length in bytes (1/2/4).
    107 // @ buffer        : pointer on buffer base.
    108 // @ little endian : the most significant byte has the highest address when true.
    109 // @ return the integer value in a 32 bits word.
    110 //////////////////////////////////////////////////////////////////////////////////////////
    111 static uint32_t fatfs_get_record( uint32_t    offset,
    112                                   uint32_t    size,
    113                                   uint8_t   * buffer,
    114                                   uint32_t    little_endian )
    115 {
    116     uint32_t n;
    117     uint32_t res  = 0;
    118 
    119     if ( little_endian)
    120     {
    121         for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
    122     }
    123     else
    124     {
    125         for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
    126     }
    127     return res;
    128 
    129 }  // end fatfs_get_record()
    130 
    131 //////////////////////////////////////////////////////////////////////////////////////////
    132 // This static function retun in the <name> buffer a short name stored in
    133 // a SFN FATFS directory entry.
    134 /////////////////////////i////////////////////////////////////////////////////////////////
    135 // @ buffer   : pointer on buffer containing the directory entry.
    136 // @ name     : [out] buffer allocated by the caller.
    137 //////////////////////////////////////////////////////////////////////////////////////////
    138 static void fatfs_get_name_from_short( uint8_t * buffer,
    139                                        char    * name )
    140 {
    141     uint32_t i;
    142     uint32_t j = 0;
    143 
    144     // get name
    145     for ( i = 0; i < 8 && buffer[i] != ' '; i++ )
    146     {
    147         name[j] = to_lower( buffer[i] );
    148         j++;
    149     }
    150 
    151     // get extension
    152     for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )
    153     {
    154         // we entered the loop so there is an extension. add the dot
    155         if ( i == 8 )
    156         {
    157             name[j] = '.';
    158             j++;
    159         }
    160 
    161         name[j] = to_lower( buffer[i] );
    162         j++;
    163     }
    164 
    165     name[j] = '\0';
    166 }
    167 
    168 //////////////////////////////////////////////////////////////////////////////////////////
    169 // This static function retun in the <name> buffer a partial name stored in
    170 // a LFN FATFS directory entry.
    171 /////////////////////////i////////////////////////////////////////////////////////////////
    172 // @ buffer   : pointer on buffer containing the directory entry.
    173 // @ name     : [out] buffer allocated by the caller.
    174 //////////////////////////////////////////////////////////////////////////////////////////
    175 static void fatfs_get_name_from_long( uint8_t * buffer,
    176                                       char    * name )
    177 {
    178     uint32_t   name_offset   = 0;
    179     uint32_t   buffer_offset = get_length(LDIR_ORD);
    180     uint32_t   l_name_1      = get_length(LDIR_NAME_1);
    181     uint32_t   l_name_2      = get_length(LDIR_NAME_2);
    182     uint32_t   l_name_3      = get_length(LDIR_NAME_3);
    183     uint32_t   l_attr        = get_length(LDIR_ATTR);
    184     uint32_t   l_type        = get_length(LDIR_TYPE);
    185     uint32_t   l_chksum      = get_length(LDIR_CHKSUM);
    186     uint32_t   l_rsvd        = get_length(LDIR_RSVD);
    187 
    188     uint32_t   j             = 0;
    189     uint32_t   eof           = 0;
    190 
    191     while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
    192     {
    193         while (j != l_name_1 && !eof )
    194         {
    195             if ( (buffer[buffer_offset] == 0x00) ||
    196                  (buffer[buffer_offset] == 0xFF) )
    197             {
    198                 eof = 1;
    199                 continue;
    200             }
    201             name[name_offset] = buffer[buffer_offset];
    202             buffer_offset += 2;
    203             j += 2;
    204             name_offset++;
    205         }
    206 
    207         buffer_offset += (l_attr + l_type + l_chksum);
    208         j = 0;
    209 
    210         while (j != l_name_2 && !eof )
    211         {
    212             if ( (buffer[buffer_offset] == 0x00) ||
    213                  (buffer[buffer_offset] == 0xFF) )
    214             {
    215                 eof = 1;
    216                 continue;
    217             }
    218             name[name_offset] = buffer[buffer_offset];
    219             buffer_offset += 2;
    220             j += 2;
    221             name_offset++;
    222         }
    223 
    224         buffer_offset += l_rsvd;
    225         j = 0;
    226 
    227         while (j != l_name_3 && !eof )
    228         {
    229             if ( (buffer[buffer_offset] == 0x00) ||
    230                  (buffer[buffer_offset] == 0xFF) )
    231             {
    232                 eof = 1;
    233                 continue;
    234             }
    235             name[name_offset] = buffer[buffer_offset];
    236             buffer_offset += 2;
    237             j += 2;
    238             name_offset++;
    239         }
    240     }
    241     name[name_offset] = 0;
    242 
    243 } // end get_name_from_long()
    244 
    245 //////////////////////////////////////////////////////////////////////////////////////////
    246 // This function returns the FATFS cluster index of a page identified by its page
    247 // index in the file, using the FAT mapper. It scans the FAT mapper, starting from the
    248 // FATFS cluster index allocated to the first page of the file, until it reaches the
    249 // searched page. The FAT mapper is automatically updated in case of miss.
    250 // This function can be called by any thread running in any cluster, as it uses the
    251 // RPC_FATFS_GET_CLUSTER to access the remote FAT mapper if required.
    252 // We use a RPC to scan the FAT because the RPC_FIFO will avoid contention
    253 // in the cluster containing the FAT mapper, and the RPC latency is not critical
    254 // compared to the device access latency.
    255 //////////////////////////////////////////////////////////////////////////////////////////
    256 // @ ctx               : pointer on local FATFS context.
    257 // @ first_cluster : first cluster allocated to a file in FATFS.
    258 // @ page_index    : index of searched page in file (one page occupies one cluster).
    259 // @ cluster_index : [out] pointer on buffer for FATFS cluster index.
    260 // @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.
    261 //////////////////////////////////////////////////////////////////////////////////////////
    262 static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,
    263                                          uint32_t      first_cluster,
    264                                          uint32_t      page_index,
    265                                          uint32_t    * cluster_index )
    266 {
    267     uint32_t searched_cluster;   // searched FATFS cluster index
    268     error_t  error;
    269 
    270     // get extended pointer on FAT mapper
    271     xptr_t fat_mapper_xp = ctx->fat_mapper_xp;
    272 
    273     // get cluster cxy and local pointer on FAT mapper
    274     cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
    275     mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
    276 
    277     if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
    278     {
    279         error = fatfs_get_cluster( fat_mapper_ptr,
    280                                    first_cluster,
    281                                    page_index,
    282                                    &searched_cluster );
    283     }
    284     else                                 // FAT mapper is remote
    285     {
    286         rpc_fatfs_get_cluster_client( fat_mapper_cxy,
    287                                       fat_mapper_ptr,
    288                                       first_cluster,
    289                                       page_index,
    290                                       &searched_cluster,
    291                                       &error );
    292     }
    293    
    294     if( error )
    295     {
    296         printk("\n[ERROR] in %s : cannot access FAT\n", __FUNCTION__ );
    297         return error;
    298     }
    299 
    300     // return success
    301     *cluster_index = searched_cluster;
    302     return 0;
    303 
    304 }  // end fatfs_cluster_from_index()
    305 
    306 //////////////////////////////////////////////////////////////////////////////////////////
    307 //              FATFS specific but extern function (used by RPC_FATFS_GET_CLUSTER)
    308 //////////////////////////////////////////////////////////////////////////////////////////
    309 
    310307/////////////////////////////////////////////
    311308error_t fatfs_get_cluster( mapper_t * mapper,
    312                            uint32_t   first_cluster,
    313                            uint32_t   searched_page,
    314                            uint32_t * cluster )
     309                           uint32_t   first_cluster_id,
     310                           uint32_t   page_index,
     311                           uint32_t * searched_cluster_id )
    315312{
    316313    page_t   * current_page_desc;      // pointer on current page descriptor
     
    319316    uint32_t   current_page_offset;    // offset of slot in current page
    320317    uint32_t   page_count_in_file;     // index of page in file (index in linked list)
    321     uint32_t   current_cluster;        // content of current FAT slot
    322 
    323     fatfs_dmsg("\n[INFO] %s : enters / first_cluster_id = %d / searched_page = %d\n",
    324                __FUNCTION__ , first_cluster , searched_page );
    325 
    326 #if CONFIG_FATFS_DEBUG
     318    uint32_t   current_cluster_id;     // content of current FAT slot
     319
     320    assert( (page_index > 0) , __FUNCTION__ , "no FAT access required for first page\n");
     321
     322    fatfs_dmsg("\n[INFO] %s : enters / mapper = %x / first_cluster_id = %d / page_index = %d\n",
     323               __FUNCTION__ , first_cluster_id , page_index );
     324
     325#if (CONFIG_FATFS_DEBUG > 1)
    327326    uint32_t * buf = (uint32_t *)ppm_page2vaddr( mapper_get_page ( mapper , 0 ) );
    328327    uint32_t line , word;
    329     printk("\n***  FAT content for first 128 entries ***\n");
    330     for( line = 0 ; line < 8 ; line++ )
    331     {
    332         printk("%d : ");
     328    printk("\n***  FAT mapper content for first 256 entries ***\n");
     329    for( line = 0 ; line < 16 ; line++ )
     330    {
     331        printk("%X : ", line );
    333332        for( word = 0 ; word < 16 ; word++ ) printk("%X ", buf[(line<<4) + word] );
    334333        printk("\n");
     
    340339
    341340    // initialize loop variable
    342     current_page_index  = first_cluster / slots_per_page;
    343     current_page_offset = first_cluster % slots_per_page;
     341    current_page_index  = first_cluster_id / slots_per_page;
     342    current_page_offset = first_cluster_id % slots_per_page;
    344343    page_count_in_file  = 0;
    345344
    346345    // scan FAT (i.e. traverse FAT linked list)
    347     while( page_count_in_file <= searched_page )
     346    while( page_count_in_file <= page_index )
    348347    {
    349348
     
    360359
    361360        // get FAT slot content
    362         current_cluster = current_page_buffer[current_page_offset];
     361        current_cluster_id = current_page_buffer[current_page_offset];
    363362
    364363        // update loop variables
    365         current_page_index  = current_cluster / slots_per_page;
    366         current_page_offset = current_cluster % slots_per_page;
     364        current_page_index  = current_cluster_id / slots_per_page;
     365        current_page_offset = current_cluster_id % slots_per_page;
    367366        page_count_in_file++;
    368367    }
    369368   
    370369    fatfs_dmsg("\n[INFO] %s : exit / cluster_id = %d\n",
    371                __FUNCTION__ , current_cluster );
    372 
    373     *cluster = current_cluster;
     370               __FUNCTION__ , current_cluster_id );
     371
     372    *searched_cluster_id = current_cluster_id;
    374373    return 0;
    375374
     
    550549    else                 // it is a normal inode mapper
    551550    {
    552         // get first cluster index from inode extension
    553         uint32_t  first_cluster = (uint32_t)(intptr_t)inode->extend;
    554 
    555         fatfs_dmsg("\n[INFO] %s : for inode %x / first cluster_id = %d\n",
    556                    __FUNCTION__ , inode , first_cluster );
    557    
    558         // compute FATFS_cluster index for the accessed page
    559         uint32_t cluster = 0;
    560         error_t  error = fatfs_cluster_from_index( fatfs_ctx,
    561                                                    first_cluster,
    562                                                    index,
    563                                                    &cluster );
    564         if( error ) return EIO;
    565 
    566         // get lba from cluster
    567         uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , cluster );
     551        uint32_t  searched_cluster_id;
     552
     553        // get first_cluster_id from inode extension
     554        uint32_t  first_cluster_id = (uint32_t)(intptr_t)inode->extend;
     555
     556        fatfs_dmsg("\n[INFO] %s : for inode %x / first_cluster_id = %d\n",
     557                   __FUNCTION__ , inode , first_cluster_id );
     558
     559        // compute cluster_id
     560        if( index == 0 )            // no need to access FAT mapper
     561        {
     562            searched_cluster_id = first_cluster_id;
     563        }
     564        else                        // FAT mapper access required
     565        {
     566            // get cluster and local pointer on FAT mapper
     567            xptr_t     fat_mapper_xp  = fatfs_ctx->fat_mapper_xp;
     568            cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
     569            mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
     570
     571            // access FAT mapper
     572            if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
     573            {
     574                error = fatfs_get_cluster( fat_mapper_ptr,
     575                                           first_cluster_id,
     576                                           index,
     577                                           &searched_cluster_id );
     578            }
     579            else                                 // FAT mapper is remote
     580            {
     581                rpc_fatfs_get_cluster_client( fat_mapper_cxy,
     582                                              fat_mapper_ptr,
     583                                              first_cluster_id,
     584                                              index,
     585                                              &searched_cluster_id,
     586                                              &error );
     587            }
     588
     589            if( error )  return EIO;
     590        }
     591
     592        // get lba from cluster_id
     593        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id );
    568594
    569595        fatfs_dmsg("\n[INFO] %s : for inode %x / page = %d / cluster_id = %d / lba = %x\n",
    570                    __FUNCTION__ , inode , index , cluster , lba );
     596                   __FUNCTION__ , inode , index , searched_cluster_id , lba );
    571597
    572598        // access device
     
    584610}  // end fatfs_mapper_move_page()
    585611
    586 /////////////////////////////////////////////////////////////////
     612/////////////////////////////////////////////////////
    587613error_t fatfs_inode_load( vfs_inode_t * parent_inode,
    588614                          char        * name,
     
    629655        // get page base
    630656        base = ppm_page2vaddr( page );
     657
     658#if (CONFIG_FATFS_DEBUG > 1)
     659    uint32_t * buf = (uint32_t *)base;
     660    uint32_t line , word;
     661    printk("\n*** DIRECTORY content for first 16 entries ***\n");
     662    for( line = 0 ; line < 16 ; line++ )
     663    {
     664        printk("%X : ", line );
     665        for( word = 0 ; word < 8 ; word++ ) printk("%X ", buf[(line<<4) + word] );
     666        printk("\n");
     667    }
     668#endif
     669
    631670
    632671        // scan this page until end of directory, end of page, or name found
  • trunk/kernel/vfs/fatfs.h

    r246 r265  
    183183
    184184//////////////////////////////////////////////////////////////////////////////////////////
    185 //              FATFS specific but public functions (used by RPC)
     185//              FATFS specific extern functions
    186186//////////////////////////////////////////////////////////////////////////////////////////
    187187
    188188/******************************************************************************************
    189  * This static function scan the FAT (File Allocation Table), stored in the FAT mapper,
     189 * This function scan the FAT (File Allocation Table), stored in the FAT mapper,
    190190 * and returns the FATFS cluster index for a given page of a given file.
    191191 * It must be called by a thread running in the cluster containing the FAT mapper.
     192 * We can use a RPC to scan the remote FAT mapper, because the RPC_FIFO will avoid
     193 * contention in the cluster containing the FAT mapper, and the RPC latency is not
     194 * critical compared to the device access latency.
    192195 * The FAT is actually an array of uint32_t slots. Each slot in this array contains the
    193196 * index of another slot in this array, to form one linked list for each file stored on
     
    198201 * automatically updates the FAT mapper from informations stored on device in case of miss.
    199202 ******************************************************************************************
    200  * @ mapper              : local pointer on the FAT mapper.
    201  * @ first_cluster       : index of the first FATFS cluster allocated to the file.
    202  * @ searched_page   : index of searched page in the file.
    203  * @ cluster         : [out] pointer on buffer for the found FATFS cluster index.
    204  * @ return 0 if success / return EIO if FAT mapper miss cannot be solved.
     203 * @ mapper                  : local pointer on the FAT mapper.
     204 * @ first_cluster_id    : index of the first FATFS cluster allocated to the file.
     205 * @ searched_page       : index of searched page in the file.
     206 * @ searched_cluster_id : [out] found FATFS cluster index.
     207 * @ return 0 if success / return EIO if a FAT mapper miss cannot be solved.
    205208 *****************************************************************************************/
    206209error_t fatfs_get_cluster( struct mapper_s * mapper,
    207210                           uint32_t          first_cluster,
    208                            uint32_t          searched_page,
    209                            uint32_t        * cluster );
    210 
    211 
     211                           uint32_t          page_index,
     212                           uint32_t        * searched_cluster_id );
     213
     214/******************************************************************************************
     215 * This function display the content of the FATFS context.
     216 *****************************************************************************************/
     217void fatfs_ctx_display();
    212218
    213219
  • trunk/kernel/vfs/vfs.c

    r246 r265  
    640640    if( error ) return error;
    641641
    642     vfs_dmsg("\n[INFO] %s exit for %s / file_id = %d / file_xp = %l / at cycle %d\n",
     642    vfs_dmsg("\n[INFO] %s : exit for <%s> / file_id = %d / file_xp = %l / at cycle %d\n",
    643643             __FUNCTION__ , path , file_id , file_xp , hal_get_cycles() );
    644644
     
    652652/////////////////////////////////////
    653653error_t vfs_move( bool_t   to_buffer,
     654                  bool_t   is_user,
    654655                  xptr_t   file_xp,
    655656                  void   * buffer,
     
    682683        if( file_cxy == local_cxy )
    683684        {
    684             error = mapper_move( mapper,
    685                                  to_buffer,
    686                                  file_offset,
    687                                  buffer,
    688                                  size );
     685            error = mapper_move_buffer( mapper,
     686                                        to_buffer,
     687                                        is_user,
     688                                        file_offset,
     689                                        buffer,
     690                                        size );
    689691        }
    690692        else
    691693        {
    692             rpc_mapper_move_client( file_cxy,
    693                                     mapper,
    694                                     to_buffer,
    695                                     file_offset,
    696                                     buffer,
    697                                     size,
    698                                     &error );
     694            rpc_mapper_move_buffer_client( file_cxy,
     695                                           mapper,
     696                                           to_buffer,
     697                                           is_user,
     698                                           file_offset,
     699                                           buffer,
     700                                           size,
     701                                           &error );
    699702        }
    700703
    701         return error;
    702     }
    703     else if (inode_type == INODE_TYPE_DIR )
    704     {
    705         printk("\n[ERROR] in %s : inode is a directory", __FUNCTION__ );
    706         return EINVAL;
    707     }
    708     else if (inode_type == INODE_TYPE_DEV )
    709     {
    710         // TODO  [AG]
    711         return 0;
    712     }
    713     else
    714     {
    715         printk("\n[PANIC] in %s : illegal inode type\n", __FUNCTION__ );
    716         hal_core_sleep();
     704        if( error ) return -1;
     705        else        return size;
     706    }
     707    else
     708    {
     709        printk("\n[ERROR] in %s : inode is not a file", __FUNCTION__ );
    717710        return -1;
    718711    }
     
    13771370    vfs_inode_unlock( parent_xp );
    13781371
    1379     vfs_dmsg("\n[INFO] in %s : exit / %s found / inode = %l\n",
     1372    vfs_dmsg("\n[INFO] in %s : exit <%s> found / inode = %l\n",
    13801373                 __FUNCTION__ , pathname , child_xp );
    13811374
     
    16091602error_t vfs_mapper_load_all( vfs_inode_t * inode )
    16101603{
    1611     assert( (inode != NULL) , __FUNCTION__ , "page pointer is NULL\n" );
     1604    assert( (inode != NULL) , __FUNCTION__ , "inode pointer is NULL\n" );
    16121605
    16131606    uint32_t   index;
     
    16171610    uint32_t   size   = inode->size;
    16181611
    1619     assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" );
    1620 
    1621     assert( (size != 0) , __FUNCTION__ , "size cannot be 0\n");
     1612    assert( (mapper != NULL) , __FUNCTION__ , "mapper pointer is NULL\n" );
    16221613
    16231614    uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
    1624     if( size & CONFIG_PPM_PAGE_MASK ) npages++;
    1625 
    1626     // loop on all pages
     1615    if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++;
     1616
     1617    // loop on pages
    16271618    for( index = 0 ; index < npages ; index ++ )
    16281619    {
  • trunk/kernel/vfs/vfs.h

    r239 r265  
    725725/******************************************************************************************
    726726 * This function moves <size> bytes between the file identified by the open file descriptor
    727  * <file_xp> and a local kernel <buffer> , taken into account the offset in <file_xp>.
     727 * <file_xp> and a local kernel or user <buffer>, as defined by the <is_user> argument,
     728 * and taken into account the offset in <file_xp>.
    728729 * The transfer direction is defined by the <to_buffer> argument.
    729730 ******************************************************************************************
    730  * @ to_buffer : mapper -> buffer if true / buffer->mapper if false.
     731 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.
     732 * @ is_user   : user space buffer if true / local kernel buffer if false.
    731733 * @ file_xp   : extended pointer on the remote file descriptor.
    732  * @ buffer    : local pointer on local kernel buffer.
     734 * @ buffer    : local pointer on buffer.
    733735 * @ size      : requested number of bytes from offset.
    734736 * @ returns number of bytes actually transfered / -1 if error.
    735737 *****************************************************************************************/
    736738error_t vfs_move( bool_t   to_buffer,
     739                  bool_t   is_user,
    737740                  xptr_t   file_xp,
    738741                  void   * buffer,
Note: See TracChangeset for help on using the changeset viewer.