Changeset 238 for trunk/kernel/vfs


Ignore:
Timestamp:
Jul 19, 2017, 3:31:39 PM (7 years ago)
Author:
alain
Message:

Fixing bugs in vfs_lookup()

Location:
trunk/kernel/vfs
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/vfs/devfs.h

    r204 r238  
    2828//////////////////////////////////////////////////////////////////////////////////////////
    2929// The DEVFS File System contains inodes and dentries associated to all chdev descriptors
    30 // availables in the architecture. It is structured as a three levels tree structure :
     30// availables in the architecture.
     31//
     32// It is structured as a three levels tree structure :
    3133// - The "dev" directory inode is stored in cluster_IO. It is the root of the DEVFS
    3234//   file system. The parent inode is the "/" VFS root.
     
    3840//   The parent dentry is stored in cluster_IO.
    3941//
    40 // The DEVFS file system uses the DEVFS context extension to register an extended pointer
    41 // on the DEVFS "dev" inode, and and another extended pointer on the "external" inode.
    42 //
    43 // The DEVFS file system uses the VFS inode extension to store the pointer
    44 // on the associated chdev descriptor.
     42// The DEVFS extensions to the generic VFS are the following:
     43// 1) The vfs_ctx_t "extend" field is a void* pointing on the devfs_ctx_t structure.
     44//    This structure contains two extended pointers on the DEVFS "dev" directory inode,
     45//    and on the "external" directory inode.
     46// 2) The vfs_inode_t "extend" field is a void*, pointing on the associated
     47//    chdev descriptor.
    4548//////////////////////////////////////////////////////////////////////////////////////////
    4649
  • trunk/kernel/vfs/fatfs.c

    r188 r238  
    22 * fatfs.c - FATFS file system API implementation.
    33 *
    4  * Author    Mohamed Lamine Karaoui (2014,2015)
    5  *           Alain Greiner (2016,2017)
     4 * Author    Alain Greiner (2016,2017)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    3029#include <ppm.h>
    3130#include <vfs.h>
     31#include <string.h>
    3232#include <rpc.h>
    3333#include <mapper.h>
     
    4646 
    4747//////////////////////////////////////////////////////////////////////////////////////////
    48 //              FATFS private functions
    49 //////////////////////////////////////////////////////////////////////////////////////////
     48//              FATFS private and static functions
     49//////////////////////////////////////////////////////////////////////////////////////////
     50
     51//////////////////////////////////////////////////////////////////////////////////////////
     52// These functions return the "offset" and "length" values of an
     53// [offset,length] constant defined in the fatfs.h file.
     54//////////////////////////////////////////////////////////////////////////////////////////
     55
     56static inline int get_length( int offset , int length ) { return length; }
     57
     58static inline int get_offset( int offset , int length ) { return offset; }
     59
    5060
    5161//////////////////////////////////////////////////////////////////////////////////////////
     
    6373}
    6474
    65 /////////////////////////////////////////////
    66 error_t fatfs_get_cluster( mapper_t * mapper,
    67                            uint32_t   first_cluster,
    68                            uint32_t   searched_page,
    69                            uint32_t * cluster )
    70 {
    71     page_t   * current_page_desc;      // pointer on current page descriptor
    72     uint32_t * current_page_buffer;    // pointer on current page (array of uint32_t)
    73     uint32_t   current_page_index;     // index of current page in mapper
    74     uint32_t   current_page_offset;    // offset of slot in current page
    75     uint32_t   page_count_in_file;     // index of page in file (index in linked list)
    76     uint32_t   current_cluster;        // content of current FAT slot
    77 
    78     // compute number of FAT slots per PPM page
    79     uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2;
    80 
    81     // initialize loop variable
    82     current_page_index  = first_cluster / slots_per_page;
    83     current_page_offset = first_cluster % slots_per_page;
    84     page_count_in_file  = 0;
    85 
    86     // scan FAT (i.e. traverse FAT linked list)
    87     while( page_count_in_file <= searched_page )
    88     {
    89         // get pointer on current page descriptor
    90         current_page_desc = mapper_get_page( mapper , current_page_index );
    91 
    92         if( current_page_desc == NULL ) return EIO;
    93 
    94         // get pointer on buffer for current page
    95         current_page_buffer = (uint32_t *)ppm_page2vaddr( current_page_desc );
    96 
    97         // get FAT slot content
    98         current_cluster = current_page_buffer[current_page_offset];
    99 
    100         // update loop variables
    101         current_page_index  = current_cluster / slots_per_page;
    102         current_page_offset = current_cluster % slots_per_page;
    103         page_count_in_file++;
    104     }
    105    
    106     // return success
    107     *cluster = current_cluster;
    108     return 0;
    109 
    110 }  // end fatfs_get_cluster()
    111 
    112 ///////////////////////////////////////////////////////////////////////////////////////
    113 // This static function return an integer record value (one, two, or four bytes)
     75
     76//////////////////////////////////////////////////////////////////////////////////////////
     77// This function return an integer record value (one, two, or four bytes)
    11478// from a memory buffer, taking into account endianness.
    115 ///////////////////////////////////////////////////////////////////////////////////////
     79//////////////////////////////////////////////////////////////////////////////////////////
    11680// @ offset        : first byte of record in buffer.
    11781// @ size          : record length in bytes (1/2/4).
     
    11983// @ little endian : the most significant byte has the highest address when true.
    12084// @ return the integer value in a 32 bits word.
    121 ///////////////////////////////////////////////////////////////////////////////////////
    122 static uint32_t get_record_from_buffer( uint32_t    offset,
    123                                         uint32_t    size,
    124                                         uint8_t   * buffer,
    125                                         uint32_t    little_endian )
     85//////////////////////////////////////////////////////////////////////////////////////////
     86static uint32_t fatfs_get_record( uint32_t    offset,
     87                                  uint32_t    size,
     88                                  uint8_t   * buffer,
     89                                  uint32_t    little_endian )
    12690{
    12791    uint32_t n;
     
    138102    return res;
    139103
    140 }  // end get_record_from_buffer()
    141 
    142 
    143 
    144 ////////////////////////////////////////////////////////////////////////////////////////
     104}  // end fatfs_get_record()
     105
     106//////////////////////////////////////////////////////////////////////////////////////////
     107// This static function retun in the <name> buffer a short name stored in
     108// a SFN FATFS directory entry.
     109/////////////////////////i////////////////////////////////////////////////////////////////
     110// @ buffer   : pointer on buffer containing the directory entry.
     111// @ name     : [out] buffer allocated by the caller.
     112//////////////////////////////////////////////////////////////////////////////////////////
     113static void fatfs_get_name_from_short( uint8_t * buffer,
     114                                       char    * name )
     115{
     116    uint32_t i;
     117    uint32_t j = 0;
     118
     119    // get name
     120    for ( i = 0; i < 8 && buffer[i] != ' '; i++ )
     121    {
     122        name[j] = to_lower( buffer[i] );
     123        j++;
     124    }
     125
     126    // get extension
     127    for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )
     128    {
     129        // we entered the loop so there is an extension. add the dot
     130        if ( i == 8 )
     131        {
     132            name[j] = '.';
     133            j++;
     134        }
     135
     136        name[j] = to_lower( buffer[i] );
     137        j++;
     138    }
     139
     140    name[j] = '\0';
     141}
     142
     143//////////////////////////////////////////////////////////////////////////////////////////
     144// This static function retun in the <name> buffer a partial name stored in
     145// a LFN FATFS directory entry.
     146/////////////////////////i////////////////////////////////////////////////////////////////
     147// @ buffer   : pointer on buffer containing the directory entry.
     148// @ name     : [out] buffer allocated by the caller.
     149//////////////////////////////////////////////////////////////////////////////////////////
     150static void fatfs_get_name_from_long( uint8_t * buffer,
     151                                      char    * name )
     152{
     153    uint32_t   name_offset   = 0;
     154    uint32_t   buffer_offset = get_length(LDIR_ORD);
     155    uint32_t   l_name_1      = get_length(LDIR_NAME_1);
     156    uint32_t   l_name_2      = get_length(LDIR_NAME_2);
     157    uint32_t   l_name_3      = get_length(LDIR_NAME_3);
     158    uint32_t   l_attr        = get_length(LDIR_ATTR);
     159    uint32_t   l_type        = get_length(LDIR_TYPE);
     160    uint32_t   l_chksum      = get_length(LDIR_CHKSUM);
     161    uint32_t   l_rsvd        = get_length(LDIR_RSVD);
     162
     163    uint32_t   j             = 0;
     164    uint32_t   eof           = 0;
     165
     166    while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
     167    {
     168        while (j != l_name_1 && !eof )
     169        {
     170            if ( (buffer[buffer_offset] == 0x00) ||
     171                 (buffer[buffer_offset] == 0xFF) )
     172            {
     173                eof = 1;
     174                continue;
     175            }
     176            name[name_offset] = buffer[buffer_offset];
     177            buffer_offset += 2;
     178            j += 2;
     179            name_offset++;
     180        }
     181
     182        buffer_offset += (l_attr + l_type + l_chksum);
     183        j = 0;
     184
     185        while (j != l_name_2 && !eof )
     186        {
     187            if ( (buffer[buffer_offset] == 0x00) ||
     188                 (buffer[buffer_offset] == 0xFF) )
     189            {
     190                eof = 1;
     191                continue;
     192            }
     193            name[name_offset] = buffer[buffer_offset];
     194            buffer_offset += 2;
     195            j += 2;
     196            name_offset++;
     197        }
     198
     199        buffer_offset += l_rsvd;
     200        j = 0;
     201
     202        while (j != l_name_3 && !eof )
     203        {
     204            if ( (buffer[buffer_offset] == 0x00) ||
     205                 (buffer[buffer_offset] == 0xFF) )
     206            {
     207                eof = 1;
     208                continue;
     209            }
     210            name[name_offset] = buffer[buffer_offset];
     211            buffer_offset += 2;
     212            j += 2;
     213            name_offset++;
     214        }
     215    }
     216    name[name_offset] = 0;
     217
     218} // end get_name_from_long()
     219
     220//////////////////////////////////////////////////////////////////////////////////////////
    145221// This function returns the FATFS cluster index of a page identified by its page
    146222// index in the file, using the FAT mapper. It scans the FAT mapper, starting from the
     
    152228// in the cluster containing the FAT mapper, and the RPC latency is not critical
    153229// compared to the device access latency.
    154 ////////////////////////////////////////////////////////////////////////////////////////
     230//////////////////////////////////////////////////////////////////////////////////////////
    155231// @ ctx               : pointer on local FATFS context.
    156232// @ first_cluster : first cluster allocated to a file in FATFS.
     
    158234// @ cluster_index : [out] pointer on buffer for FATFS cluster index.
    159235// @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.
    160 ////////////////////////////////////////////////////////////////////////////////////////
     236//////////////////////////////////////////////////////////////////////////////////////////
    161237static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,
    162238                                         uint32_t      first_cluster,
     
    203279}  // end fatfs_cluster_from_index()
    204280
     281//////////////////////////////////////////////////////////////////////////////////////////
     282//              FATFS specific but public functions (used by RPC_FATFS_GET_CLUSTER)
     283//////////////////////////////////////////////////////////////////////////////////////////
     284
     285/////////////////////////////////////////////
     286error_t fatfs_get_cluster( mapper_t * mapper,
     287                           uint32_t   first_cluster,
     288                           uint32_t   searched_page,
     289                           uint32_t * cluster )
     290{
     291    page_t   * current_page_desc;      // pointer on current page descriptor
     292    uint32_t * current_page_buffer;    // pointer on current page (array of uint32_t)
     293    uint32_t   current_page_index;     // index of current page in mapper
     294    uint32_t   current_page_offset;    // offset of slot in current page
     295    uint32_t   page_count_in_file;     // index of page in file (index in linked list)
     296    uint32_t   current_cluster;        // content of current FAT slot
     297
     298    // compute number of FAT slots per PPM page
     299    uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2;
     300
     301    // initialize loop variable
     302    current_page_index  = first_cluster / slots_per_page;
     303    current_page_offset = first_cluster % slots_per_page;
     304    page_count_in_file  = 0;
     305
     306    // scan FAT (i.e. traverse FAT linked list)
     307    while( page_count_in_file <= searched_page )
     308    {
     309        // get pointer on current page descriptor
     310        current_page_desc = mapper_get_page( mapper , current_page_index );
     311
     312        if( current_page_desc == NULL ) return EIO;
     313
     314        // get pointer on buffer for current page
     315        current_page_buffer = (uint32_t *)ppm_page2vaddr( current_page_desc );
     316
     317        // get FAT slot content
     318        current_cluster = current_page_buffer[current_page_offset];
     319
     320        // update loop variables
     321        current_page_index  = current_cluster / slots_per_page;
     322        current_page_offset = current_cluster % slots_per_page;
     323        page_count_in_file++;
     324    }
     325   
     326    // return success
     327    *cluster = current_cluster;
     328    return 0;
     329
     330}  // end fatfs_get_cluster()
    205331
    206332
    207333
    208334///////////////////////////////////////////////////////////////////////////////////////
    209 // Generic API : the following functions are called by the kernel
     335// Generic API : the following functions are called by the kernel (VFS)
    210336//               and must be defined by all supported file systems.
    211337///////////////////////////////////////////////////////////////////////////////////////
     
    275401
    276402    // check sector size from boot record
    277     uint32_t sector_size = get_record_from_buffer( BPB_BYTSPERSEC , buffer , 1 );
     403    uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 );
    278404
    279405    nolock_assert( (sector_size == 512) , __FUNCTION__ ,
     
    281407
    282408    // check cluster size from boot record
    283     uint32_t nb_sectors = get_record_from_buffer( BPB_SECPERCLUS , buffer , 1 );
     409    uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 );
    284410
    285411    nolock_assert( (nb_sectors == 8) , __FUNCTION__ ,
     
    287413
    288414    // check number of FAT copies from boot record
    289     uint32_t nb_fats = get_record_from_buffer( BPB_NUMFATS , buffer , 1 );
     415    uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 );
    290416
    291417    nolock_assert( (nb_fats == 1) , __FUNCTION__ ,
     
    293419
    294420    // get & check number of sectors in FAT from boot record
    295     uint32_t fat_sectors = get_record_from_buffer( BPB_FAT32_FATSZ32 , buffer , 1 );
     421    uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 );
    296422
    297423    nolock_assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ ,
     
    299425
    300426    // get and check root cluster from boot record
    301     uint32_t root_cluster = get_record_from_buffer( BPB_FAT32_ROOTCLUS , buffer , 1 );
     427    uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 );
    302428
    303429    nolock_assert( (root_cluster == 2) , __FUNCTION__ ,
     
    305431
    306432    // get FAT lba from boot record
    307     uint32_t fat_lba = get_record_from_buffer( BPB_RSVDSECCNT , buffer , 1 );
     433    uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 );
    308434
    309435    // release the 512 bytes buffer
     
    353479}
    354480
    355 ////////////////////////////////////////////////
    356 static error_t fatfs_access_page( page_t * page,
    357                                   bool_t   is_read )
     481///////////////////////////////////////
     482error_t fatfs_move_page( page_t * page,
     483                         bool_t   to_mapper )
    358484{
    359485    // get memory buffer base address
     
    388514
    389515    // access device
    390     if( is_read ) error = dev_ioc_read ( buffer , lba , count );
    391     else          error = dev_ioc_write( buffer , lba , count );     
     516    if( to_mapper ) error = dev_ioc_read ( buffer , lba , count );
     517    else            error = dev_ioc_write( buffer , lba , count );     
    392518
    393519    if( error )
     
    401527}
    402528
    403 ////////////////////////////////////////////////
    404 error_t fatfs_write_page( struct page_s * page )
    405 {
    406     bool_t is_read = false;
    407     return fatfs_access_page( page , is_read );
    408 }
    409 
    410 ///////////////////////////////////////////////
    411 error_t fatfs_read_page( struct page_s * page )
    412 {
    413     bool_t is_read = true;
    414     return fatfs_access_page( page , is_read );
    415 }
    416 
     529/////////////////////////////////////////////////////////////////
     530error_t fatfs_inode_load( vfs_inode_t * parent_inode,
     531                          char        * name,
     532                          xptr_t        child_inode_xp )
     533{
     534    // Two embedded loops:
     535    // - scan the parent mapper pages
     536    // - scan the directory entries in each 4 Kbytes page
     537
     538    fatfs_dmsg("\n[INFO] %s : enter for child <%s> in parent inode %l\n",
     539               __FUNCTION__ , name , child_inode_xp );
     540
     541    mapper_t * mapper = parent_inode->mapper;
     542
     543    assert( (mapper != NULL) , __FUNCTION__ , "parent mapper undefined\n");
     544   
     545    char       cname[CONFIG_VFS_MAX_NAME_LENGTH];  // name extracter from each directory entry
     546
     547    char       lfn1[16];         // buffer for one partial cname
     548    char       lfn2[16];         // buffer for one partial cname
     549    char       lfn3[16];         // buffer for one partial cname
     550    page_t   * page;             // pointer on current page descriptor
     551    uint8_t  * base;             // pointer on current page base
     552    uint32_t   offset  = 0;      // byte offset in page
     553    uint32_t   index   = 0;      // page index in mapper
     554    uint32_t   attr;             // directory entry ATTR field
     555    uint32_t   ord;              // directory entry ORD field
     556    uint32_t   seq;              // sequence index
     557    uint32_t   lfn     = 0;      // LFN entries number
     558    uint32_t   size    = 0;      // searched file/dir size (bytes)
     559    uint32_t   cluster = 0;      // searched file/dir cluster index
     560    uint32_t   is_dir  = 0;      // searched file/dir type
     561    uint32_t   dentry;           // directory entry index
     562    int32_t    found   = 0;      // not found (0) / name found (1) / end of dir (-1)
     563
     564    // scan the parent directory mapper
     565    while ( found == 0 )
     566    {
     567        // get one page
     568        page = mapper_get_page( mapper , index );
     569
     570        assert( (page != NULL) , __FUNCTION__ , "bad parent mapper\n");
     571
     572        // get page base
     573        base = ppm_page2vaddr( page );
     574
     575        // scan this page until end of directory, end of page, or name found
     576        while( (offset < 4096) && (found == 0) )
     577        {
     578            attr = fatfs_get_record( DIR_ATTR , base + offset , 0 );   
     579            ord  = fatfs_get_record( LDIR_ORD , base + offset , 0 );   
     580
     581            if (ord == NO_MORE_ENTRY)                 // no more entry => break
     582            {
     583                found = -1;
     584            }
     585            else if ( ord == FREE_ENTRY )             // free entry => skip
     586            {
     587                offset = offset + 32;
     588            }
     589            else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => get partial cname
     590            {
     591                seq = ord & 0x3;
     592                lfn = (seq > lfn) ? seq : lfn;   
     593                if      ( seq == 1 ) fatfs_get_name_from_long( base + offset, lfn1 );
     594                else if ( seq == 2 ) fatfs_get_name_from_long( base + offset, lfn2 );
     595                else if ( seq == 3 ) fatfs_get_name_from_long( base + offset, lfn3 );
     596                offset = offset + 32;
     597            }
     598            else                                 // NORMAL entry
     599            {
     600                // build the extracted name
     601                if      ( lfn == 0 )
     602                {
     603                    fatfs_get_name_from_short( base + offset , cname );
     604                }
     605                else if ( lfn == 1 )
     606                {
     607                    strcpy( cname      , lfn1 );
     608                }   
     609                else if ( lfn == 2 )
     610                {
     611                    strcpy( cname      , lfn1 );
     612                    strcpy( cname + 13 , lfn2 );
     613                }
     614                else if ( lfn == 3 )
     615                {
     616                    strcpy( cname      , lfn1 );
     617                    strcpy( cname + 13 , lfn2 );
     618                    strcpy( cname + 26 , lfn3 );
     619                }
     620
     621                // get dentry arguments if extracted cname == searched name
     622                if ( strcmp( name , cname ) == 0 )
     623                {
     624                    cluster = (fatfs_get_record( DIR_FST_CLUS_HI , base + offset , 1 ) << 16) |
     625                              (fatfs_get_record( DIR_FST_CLUS_LO , base + offset , 1 )      ) ;
     626                    dentry  = ((index<<12) + offset)>>5;
     627                    is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     628                    size    = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );
     629                    found   = 1;
     630                }
     631                offset = offset + 32;
     632                lfn    = 0;
     633            }
     634        }  // end loop on directory entries
     635        index++;
     636        offset = 0;
     637    }  // end loop on pages
     638
     639    // analyse the result of scan
     640
     641    if ( found == -1 )  // found end of directory => failure
     642    {
     643        fatfs_dmsg("\n[INFO] %s : child <%s> not found in parent inode %l\n",
     644                   __FUNCTION__ , name , parent_inode_xp );
     645
     646        return ENOENT;
     647    }
     648    else               // found searched child name
     649    {
     650        fatfs_dmsg("\n[INFO] %s : child <%s> found in parent inode %l\n",
     651                   __FUNCTION__ , name , parent_inode_xp );
     652
     653        // get child inode cluster and local pointer
     654        cxy_t         child_cxy = GET_CXY( child_inode_xp );
     655        vfs_inode_t * child_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
     656
     657        // update the child inode "type", "size", and "extend" fields
     658        vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
     659
     660        hal_remote_sw( XPTR( child_cxy , &child_ptr->type   ) , type );
     661        hal_remote_sw( XPTR( child_cxy , &child_ptr->size   ) , size );
     662        hal_remote_sw( XPTR( child_cxy , &child_ptr->extend ) , cluster );
     663
     664        return 0;
     665    }
     666}  // end fatfs_inode_load()
  • trunk/kernel/vfs/fatfs.h

    r188 r238  
    3333///////////////////////////////////////////////////////////////////////////////////////////
    3434// The FATFS File System implements a FAT32 read/write file system.
     35//
     36// The FATFS extensions to the generic VFS are the following:
     37// 1) The vfs_ctx_t "extend" field is a void* pointing on the fatfs_ctx_t structure.
     38//    This structure contains various general informations such as the total
     39//    number of sectors in FAT region, the number of bytes per sector, the number
     40//    of sectors per cluster, the lba of FAT region, the lba of data region, or the
     41//    cluster index for the root directory. It contains also an extended pointer
     42//    on the FAT mapper.
     43// 2) The vfs_inode_t "extend" field is a void*, but contains for each inode,
     44//    the first FAT cluster index (after cast to intptr).
    3545///////////////////////////////////////////////////////////////////////////////////////////
    3646
     
    173183
    174184//////////////////////////////////////////////////////////////////////////////////////////
     185//              FATFS specific but public functions (used by RPC)
     186//////////////////////////////////////////////////////////////////////////////////////////
     187
     188/******************************************************************************************
     189 * This static function scan the FAT (File Allocation Table), stored in the FAT mapper,
     190 * and returns the FATFS cluster index for a given page of a given file.
     191 * It must be called by a thread running in the cluster containing the FAT mapper.
     192 * The FAT is actually an array of uint32_t slots. Each slot in this array contains the
     193 * index of another slot in this array, to form one linked list for each file stored on
     194 * device in the FATFS file system. This index in the FAT array is also the index of the
     195 * FATFS cluster on the device. One FATFS cluster is supposed to contain one PPM page.
     196 * For a given file, the entry point in the FAT is simply the index of the FATFS cluster
     197 * containing the first page of the file. The mapper being a cache, this function
     198 * automatically updates the FAT mapper from informations stored on device in case of miss.
     199 ******************************************************************************************
     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.
     205 *****************************************************************************************/
     206error_t fatfs_get_cluster( struct mapper_s * mapper,
     207                           uint32_t          first_cluster,
     208                           uint32_t          searched_page,
     209                           uint32_t        * cluster );
     210
     211
     212
     213
     214//////////////////////////////////////////////////////////////////////////////////////////
    175215// Generic API: These functions are called by the kernel,
    176216//              and must be implemented by all File Systems.
     
    185225
    186226/*****************************************************************************************
    187  * This function access the external boot device, and initialises it
     227 * This function access the boot device, and initialises the FATFS context
    188228 * from informations contained in the boot record.
    189229 *****************************************************************************************
     
    200240
    201241/*****************************************************************************************
    202  * This function moves a page from the mapper to the FATFS file system on device.
     242 * This function moves a page from/to the mapper to/from the FATFS file system on device.
    203243 * It must be called by a thread running in cluster containing the mapper.
    204244 * The pointer on the mapper and the page index in file are registered
    205245 * in the page descriptor.
    206246 *****************************************************************************************
    207  * @ page    : local pointer on page descriptor.
     247 * @ page      : local pointer on page descriptor.
     248 * @ to_mapper : transfer direction
    208249 * @ return 0 if success / return EIO if error.
    209250 ****************************************************************************************/
    210 error_t fatfs_write_page( struct page_s * page );
    211 
    212 /*****************************************************************************************
    213  * This function moves a page from the FATFS file system on device to the mapper.
    214  * It must be called by a thread running in cluster containing the mapper.
    215  * The pointer on the mapper and the page index in file are registered
    216  * in the page descriptor.
    217  *****************************************************************************************
    218  * @ page    : local pointer on page descriptor.
    219  * @ return 0 if success / return EIO if error.
    220  ****************************************************************************************/
    221 error_t fatfs_read_page( struct page_s * page );
    222 
    223 /*****************************************************************************************
    224  * This function scan the FAT (File Allocation Table), stored in the FAT mapper,
    225  * and return the FATFS cluster index for a given page of a given file.
    226  * It must be called by a thread running in the cluster containing the FAT mapper
    227  * (can be a local thread or a RPC thread).
    228  * The FAT is actually an array of uint32_t slots. Each slot in this array contains the
    229  * index of another slot in this array, to form one linked list for each file stored on
    230  * device in the RAMFS file system. This index in the FAT array is also the index of the
    231  * FATFS cluster on the device. One FATFS cluster is supposed to contain one PPM page.
    232  * For a given file, the entry point in the FAT is simply the index of the FATFS cluster
    233  * containing the first page of the file. The mapper being a cache, this function
    234  * automatically updates the FAT mapper from informations stored on device in case of miss.
    235  *****************************************************************************************
    236  * @ mapper              : local pointer on the FAT mapper.
    237  * @ first_cluster       : index of the first FATFS cluster allocated to the file.
    238  * @ searched_page   : index of searched page in the file.
    239  * @ cluster         : [out] pointer on buffer for the found FATFS cluster index.
    240  * @ return 0 if success / return EIO if FAT mapper miss cannot be solved.
    241  ****************************************************************************************/
    242 error_t fatfs_get_cluster( struct mapper_s * mapper,
    243                            uint32_t          first_cluster,
    244                            uint32_t          searched_page,
    245                            uint32_t *        cluster );
     251error_t fatfs_move_page( struct page_s * page,
     252                         bool_t          to_mapper );
     253
     254
     255/*****************************************************************************************
     256 * This function scan an existing parent directory, identified by the <parent> argument,
     257 * to find a directory entry identified by the <name> argument and update the remote
     258 * child inode, identified by the <child_xp> argument.
     259 * It set the "type", "size", and "extend" (FAT cluster index) fields in child inode.
     260 * It must be called by a thread running in the cluster containing the parent inode.
     261 *****************************************************************************************
     262 * @ parent_inode    : local pointer on parent inode (directory).
     263 * @ name            : child name.
     264 * @ child_inode_xp  : extended pointer on remote child inode (file or directory).
     265 * @ return 0 if success / return ENOENT if child not found.
     266 ****************************************************************************************/
     267error_t fatfs_inode_load( struct vfs_inode_s * parent_inode,
     268                          char               * name,
     269                          xptr_t               child_inode_xp );
    246270
    247271#endif  /* _FATFS_H_ */
  • trunk/kernel/vfs/vfs.c

    r222 r238  
    248248}  // end vfs_inode_destroy()
    249249
     250/////////////////////////////////////////////
     251error_t vfs_inode_load( vfs_inode_t * parent,
     252                        char        * name,
     253                        xptr_t        child_xp )
     254{
     255    error_t error = 0;
     256
     257    assert( (parent != NULL) , __FUNCTION__ , "parent pointer is NULL\n");
     258
     259    assert( (child_xp != XPTR_NULL) , __FUNCTION__ , "child pointer is NULL\n");
     260
     261    // get parent inode FS type
     262    vfs_fs_type_t fs_type = parent->ctx->type;
     263
     264    // call relevant FS function
     265    if( fs_type == FS_TYPE_FATFS )
     266    {
     267        error = fatfs_inode_load( parent , name , child_xp );
     268    }
     269    else if( fs_type == FS_TYPE_RAMFS )
     270    {
     271        assert( false , __FUNCTION__ , "should not be called for RAMFS\n" );
     272    }
     273    else if( fs_type == FS_TYPE_DEVFS )
     274    {
     275        assert( false , __FUNCTION__ , "should not be called for DEVFS\n" );
     276    }
     277    else
     278    {
     279        assert( false , __FUNCTION__ , "undefined file system type\n" );
     280    }
     281
     282    return error;
     283
     284} // end vfs_load_inode()
     285
    250286////////////////////////////////////////////
    251287void vfs_inode_remote_up( xptr_t  inode_xp )
     
    594630
    595631    if( error ) return error;
     632
     633    vfs_dmsg("\n[INFO] %s exit for %s / file_id = %d / file_xp = %l / at cycle %d\n",
     634             __FUNCTION__ , path , file_id , file_xp , hal_get_cycles() );
    596635
    597636    // success
     
    11611200    cxy_t              child_cxy;    // cluster for child inode
    11621201    vfs_inode_t      * child_ptr;    // local pointer on child inode 
    1163     vfs_inode_type_t   inode_type;   // child inode type
     1202    vfs_inode_type_t   child_type;   // child inode type
    11641203    vfs_fs_type_t      fs_type;      // File system type
    11651204    vfs_ctx_t        * ctx_ptr;      // local pointer on FS context
     
    12061245                               &child_xp );
    12071246
    1208         if( found == false ) // child inode not found in inode tree => try to load it
     1247        // if a child inode is not found in the inode tree:
     1248        // - we create the missing inode/dentry couple in the inode tree,
     1249        // - we scan the parent mapper to complete the child inode (type and extension),
     1250        // - we return an error if child not found on device.
     1251        // - if the missing child is a directory, we load the child mapper from device
     1252
     1253        // for the last name, the behaviour depends on the "mode" argument:
     1254
     1255        if (found == false ) // directory node not found in inode tree
    12091256        {
    12101257            vfs_dmsg("\n[INFO] %s : <%s> not found, try to load it\n",
     
    12141261            vfs_inode_unlock( parent_xp );
    12151262
    1216             // get cluster and local pointer on parent inode
     1263            // get parent inode FS type
    12171264            parent_cxy = GET_CXY( parent_xp );
    12181265            parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
    12191266
    1220             // get local pointer on parent inode context
    1221             ctx_ptr = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) );
    1222 
    1223             // get parent inode FS type
    1224             fs_type = hal_remote_lw( XPTR( parent_cxy , &ctx_ptr->type ) );
    1225 
    1226             // get child inode type
    1227             if( (last == false) || (mode & VFS_LOOKUP_DIR) ) inode_type = INODE_TYPE_DIR;
    1228             else                                             inode_type = INODE_TYPE_FILE;
    1229 
    1230             // select a cluster for child inode
    1231             cxy_t child_cxy = vfs_cluster_random_select();
     1267            ctx_ptr    = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy ,
     1268                                                            &parent_ptr->ctx ) );
     1269            fs_type    = hal_remote_lw( XPTR( parent_cxy , &ctx_ptr->type ) );
     1270
     1271            // select a cluster for missing inode
     1272            child_cxy = vfs_cluster_random_select();
    12321273                     
    1233 printk("\n@@@ name not found : <%s>\n", name );
    1234 
    12351274            // insert a new child dentry/inode in parent inode
    12361275            error = vfs_add_child_in_parent( child_cxy,
    1237                                              inode_type,
     1276                                             INODE_TYPE_DIR,
    12381277                                             fs_type,
    12391278                                             parent_xp,
    12401279                                             name,
    1241                                              NULL,           // fs_type_specific inode extend
     1280                                             NULL,     // fs_type_specific inode extend
    12421281                                             &child_xp );
    12431282            if( error )
     1283            {
     1284                printk("\n[ERROR] in %s : no memory for inode %s in path %s\n",
     1285                       __FUNCTION__ , name , pathname );
     1286                return ENOMEM;
     1287            }
     1288
     1289            // scan parent mapper to complete the missing inode
     1290            if( parent_cxy == local_cxy )
     1291            {
     1292                error = vfs_inode_load( parent_ptr,
     1293                                        name,
     1294                                        child_xp );
     1295            }
     1296            else
     1297            {
     1298                rpc_vfs_inode_load_client( parent_cxy,
     1299                                           parent_ptr,
     1300                                           name,
     1301                                           child_xp,
     1302                                           &error );
     1303            }
     1304
     1305            if ( error )
    12441306            {
    12451307                printk("\n[ERROR] in %s : node %s not found in path %s\n",
     
    12481310            }
    12491311
     1312            // get child inode type
     1313            child_ptr  = (vfs_inode_t *)GET_PTR( child_xp );
     1314            child_type = hal_remote_lw( XPTR( child_cxy , &child_ptr->type ) );
     1315
     1316            // load child mapper from device if it is a directory
     1317            if( child_type == INODE_TYPE_DIR )
     1318            {
     1319                if( child_cxy == local_cxy )
     1320                {
     1321                    error = vfs_mapper_load_all( child_ptr );
     1322                }
     1323                else
     1324                {
     1325                    rpc_vfs_mapper_load_all_client( child_cxy,
     1326                                                    child_ptr,
     1327                                                    &error );
     1328                }
     1329
     1330                if ( error )
     1331                {
     1332                    printk("\n[ERROR] in %s : cannot access device for node %s in path %s\n",
     1333                           __FUNCTION__ , name , pathname );
     1334                    return EIO;
     1335                }
     1336            }
     1337
     1338            // TODO handle lookup mode here [AG]
     1339
    12501340            // take lock on parent inode
    12511341            vfs_inode_lock( parent_xp );
    12521342        }
    12531343
    1254 vfs_inode_display( child_xp );
    1255 
    1256 vfs_display( parent_xp );
    1257 
    12581344        vfs_dmsg("\n[INFO] %s : found <%s> / parent = %l / child = %l / last = %d\n",
    1259                  __FUNCTION__ , name , parent_xp , child_xp , last );
     1345                     __FUNCTION__ , name , parent_xp , child_xp , last );
    12601346
    12611347        // TODO check access rights
     
    12691355        // }
    12701356
    1271         // TODO TODO TODO access device and load inode mapper if required...
    1272 
    1273         // take lock on child inode if not last
    1274         if( last == false ) vfs_inode_lock( child_xp );
    1275 
    1276         // release lock on parent inode
     1357        // take lock on child inode and release lock on parent
     1358        vfs_inode_lock( child_xp );
    12771359        vfs_inode_unlock( parent_xp );
    12781360
     
    12801362        parent_xp = child_xp;
    12811363        current   = next;
    1282 
    1283         vfs_dmsg("\n[INFO] %s : complete node <%s> / last = %d\n",
    1284                  __FUNCTION__ , name , last );
    1285 
    12861364    }
    12871365    while( last == false );
    12881366
    1289     vfs_dmsg("\n[INFO] in %s : searched inode found for %s\n",
    1290                  __FUNCTION__ , pathname );
    1291 
    1292     // get cluster and local pointer on child inode
    1293     child_cxy = GET_CXY( child_xp );
    1294     child_ptr = (vfs_inode_t *)GET_PTR( child_xp );
    1295 
    1296     // return searched pointers
     1367    // release lock
     1368    vfs_inode_unlock( parent_xp );
     1369
     1370    vfs_dmsg("\n[INFO] in %s : exit / %s found / inode = %l\n",
     1371                 __FUNCTION__ , pathname , child_xp );
     1372
     1373    // return searched pointer
    12971374    *inode_xp = child_xp;
    12981375
     
    13851462    cxy_t           parent_cxy;  // parent inode cluster identifier
    13861463    vfs_inode_t   * parent_ptr;  // parent inode local pointer
    1387     vfs_ctx_t     * parent_ctx;  // parent inode context local pointer
    13881464
    13891465    // get parent inode cluster and local pointer
     
    14711547}  // end vfs_add_child_in_parent()
    14721548
    1473 
    1474 
    1475 
    14761549//////////////////////////////////////////////////////////////////////////////////////////
    14771550//            Mapper related functions
    14781551//////////////////////////////////////////////////////////////////////////////////////////
    14791552
    1480 ////////////////////////////////////////////////
    1481 error_t vfs_move_page_to_mapper( page_t * page )
     1553////////////////////////////////////////////
     1554error_t vfs_mapper_move_page( page_t * page,
     1555                              bool_t   to_mapper )
    14821556{
    14831557    error_t error = 0;
     
    14921566    vfs_fs_type_t fs_type = mapper->inode->ctx->type;
    14931567
    1494     // update mapper if permitted by file system type
     1568    // call relevant FS function
    14951569    if( fs_type == FS_TYPE_FATFS )
    14961570    {
    1497         // get mapper lock in WRITE_MODE
    14981571        rwlock_wr_lock( &mapper->lock );
    1499 
    1500         error = fatfs_read_page( page );
    1501 
    1502         // release mapper lock
     1572        error = fatfs_move_page( page , to_mapper );
    15031573        rwlock_wr_unlock( &mapper->lock );
    15041574    }
     
    15181588    return error;
    15191589
    1520 }  // end vfs_move_page_to_mapper()
     1590}  // end vfs_move_page()
    15211591
    15221592//////////////////////////////////////////////////
    1523 error_t vfs_move_page_from_mapper( page_t * page )
    1524 {
    1525     error_t         error = 0;
    1526 
    1527     assert( (page != NULL) , __FUNCTION__ , "page pointer is NULL\n" );
    1528 
    1529     mapper_t * mapper = page->mapper;
     1593error_t vfs_mapper_load_all( vfs_inode_t * inode )
     1594{
     1595    assert( (inode != NULL) , __FUNCTION__ , "page pointer is NULL\n" );
     1596
     1597    uint32_t   index;
     1598    page_t   * page;
     1599
     1600    mapper_t * mapper = inode->mapper;
     1601    uint32_t   size   = inode->size;
    15301602
    15311603    assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" );
    15321604
    1533     // get FS type
    1534     vfs_fs_type_t  fs_type = mapper->inode->ctx->type;
    1535 
    1536     // update file system if permitted by file system type
    1537     if( fs_type == FS_TYPE_FATFS )
    1538     {
    1539             if( page_is_flag( page , PG_DIRTY ) )
    1540             {
    1541             // get mapper lock in READ_MODE
    1542             rwlock_rd_lock( &mapper->lock );
    1543 
    1544             error = fatfs_write_page( page );
    1545 
    1546             // release mapper lock from READ_MODE
    1547             rwlock_rd_unlock( &mapper->lock );
    1548 
    1549             // clear dirty bit if success
    1550                     if( error == 0 ) page_undo_dirty( page );
    1551          }
    1552     }
    1553     else if( fs_type == FS_TYPE_RAMFS )
    1554     {
    1555         assert( false , __FUNCTION__ , "should not be called for RAMFS\n" );
    1556     }
    1557     else if( fs_type == FS_TYPE_DEVFS )
    1558     {
    1559         assert( false , __FUNCTION__ , "should not be called for DEVFS\n" );
    1560     }
    1561     else
    1562     {
    1563         assert( false , __FUNCTION__ , "undefined file system type\n" );
    1564     }
    1565        
    1566     return error;
    1567 
    1568 }  // end vfs_move_page_from_mapper()
    1569 
    1570 
     1605    assert( (size != 0) , __FUNCTION__ , "size cannot be 0\n");
     1606
     1607    uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT;
     1608    if( size & CONFIG_PPM_PAGE_MASK ) npages++;
     1609
     1610    // loop on all pages
     1611    for( index = 0 ; index < npages ; index ++ )
     1612    {
     1613        // this function allocates the missing page in mapper,
     1614        // and call the vfs_mapper_move_page() to load the page from device
     1615        page = mapper_get_page( mapper , index );
     1616
     1617        if( page == NULL ) return EIO;
     1618    }
     1619
     1620    return 0;
     1621
     1622}  // end vfs_mapper_load_all()
     1623
  • trunk/kernel/vfs/vfs.h

    r204 r238  
    399399void vfs_inode_destroy( vfs_inode_t *  inode ); 
    400400
     401/******************************************************************************************
     402 * This function scan an existing parent inode directory, identified by the <parent>
     403 * argument to find a directory entry identified by the <name> argument, and update
     404 * the remote child inode, identified by the <child_xp> argument.
     405 * Depending on the file system type, it calls the relevant, FS specific function,
     406 * to scan the directory, and set the "type", "size", and "extend" fields.
     407 * It must be called by a thread running in the cluster containing the parent inode.
     408 ******************************************************************************************
     409 * @ parent    : local pointer on parent inode (directory).
     410 * @ name      : child name.
     411 * @ child_xp  : extended pointer on remote child inode (file or directory)
     412 * @ return 0 if success / return ENOENT if not found.
     413 *****************************************************************************************/
     414error_t vfs_inode_load( vfs_inode_t * parent,
     415                        char        * name,
     416                        xptr_t        child_xp );
     417
    401418/******************************************************************************************
    402419 * This function atomically increment/decrement the inode refcount.
     
    617634 * @ pathname    : path in kernel space (can be relative or absolute).
    618635 * @ lookup_mode : flags defining the working mode (defined above in this file).
    619  * @ inode_xp    : [out] buffer for extended pointer on inode.
     636 * @ inode_xp    : [out] buffer for extended pointer on searched inode.
    620637 * @ return 0 if success / ENOENT if inode not found , EACCES if permissopn denied,
    621638 *                        EAGAIN if a new complete lookup must be made
     
    635652 * 2) The inode and its associated mapper are created in cluster identified by <child_cxy>.
    636653 *    The new inode and the parent inode can have different FS types.
    637  * 3) The "child_xp" field in created dentry (pointing on thecreated inode) is updated.
     654 * 3) The "child_xp" field in created dentry (pointing on the created inode) is updated.
    638655 ******************************************************************************************
    639656 * @ child_cxy  : target cluster for child inode.
     
    666683 * This recursive function diplays a complete inode/dentry sub-tree.
    667684 * Any inode can be selected as the sub-tree root.
    668  * TODO this function is not ptotected against a concurrent node removal...
     685 * TODO this function is not protected against a concurrent inode/dentry removal...
    669686 ******************************************************************************************
    670687 * @ inode_xp   : extended pointer on sub-tree root inode.
     
    857874
    858875/******************************************************************************************
    859  * This function makes an I/O operation to move one page from VFS to a given mapper,
    860  * in case of MISS on the mapper cache.
     876 * This function makes an I/O operation to move one page to/from device from/to the mapper.
     877 * It is used in case of MISS on the mapper, or when a dirty page in the mapper must
     878 * be updated in the File System.
    861879 * Depending on the file system type, it calls the proper, FS specific function.
    862880 * It must be executed by a thread running in the cluster containing the mapper.
     
    864882 * It takes the mapper lock before launching the IO operation.
    865883 ******************************************************************************************
    866  * @ page   : local pointer on the page descriptor.
     884 * @ page      : local pointer on the page descriptor.
     885 * @ to_mapper : transfer direction.
    867886 * @ returns 0 if success / return EINVAL if it cannot access the external device.
    868887 *****************************************************************************************/
    869 error_t vfs_move_page_to_mapper( struct page_s * page );
    870 
    871 /******************************************************************************************
    872  * This function makes an I/0 operation to move one page from a given mapper to VFS,
    873  * when a dirty page in the mapper cache must be updated in the File System.
     888error_t vfs_mapper_move_page( struct page_s * page,
     889                              bool_t          to_mapper );
     890
     891/******************************************************************************************
     892 * This function makes an I/O operation to move, from device to mapper, all pages covering
     893 * a given inode, identified by the <inode> argument. It can be a directory or a file,
     894 * but is mainly used to load (prefetch) a complete directory in the inode mapper.
    874895 * Depending on the file system type, it calls the proper, FS specific function.
    875896 * It must be executed by a thread running in the cluster containing the mapper.
    876  * The mapper pointer is obtained from the page descriptor.
     897 * The mapper pointer is obtained from the inode descriptor.
    877898 * It takes the mapper lock before launching the IO operation.
    878  * It does nothing if the page is not dirty. If the page is dirty, it clear the page
    879  * dirty bit, and remove the page from the PPM dirty list.
    880  ******************************************************************************************
    881  * @ page   : local pointer on the page descriptor.
    882  * @ returns 0 if success / return EINVAL if it cannot access the external device.
    883  *****************************************************************************************/
    884 error_t vfs_move_page_from_mapper( struct page_s * page );       
    885 
    886 
    887 
    888 
    889 
    890 
    891 ///////////////////////////////////////////////////////////////////////////////////////////
    892 // These typedef define the FS specific operations that must be implemented by any
    893 // specific file system to be supported by the ALMOS_MKH VFS.
    894 // These typedef are not actually used, and are only defined for documentation
    895 ///////////////////////////////////////////////////////////////////////////////////////////
    896 
    897 typedef error_t (fs_init_t)          ( xptr_t vfs_root_xp );
    898 
    899 typedef error_t (fs_inode_extend_t)  ( struct vfs_inode_s * inode,
    900                                        void               * extend );
    901  
    902 typedef void    (fs_inode_release_t) ( struct vfs_inode_s * inode );
    903 
    904 typedef error_t (fs_write_page_t)    ( struct page_s * page );
    905 
    906 typedef error_t (fs_read_page_t)     ( struct page_s * page );
    907 
    908 
    909 
    910 
    911 
     899 ******************************************************************************************
     900 * @ inode  : local pointer on inode.
     901 * @ return 0 if success / return EIO if device access failure.
     902 *****************************************************************************************/
     903error_t vfs_mapper_load_all( vfs_inode_t * inode );
    912904
    913905
Note: See TracChangeset for help on using the changeset viewer.