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

Fix several bugs in VFS.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.