Changeset 238 for trunk/kernel/vfs
- Timestamp:
- Jul 19, 2017, 3:31:39 PM (7 years ago)
- Location:
- trunk/kernel/vfs
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/vfs/devfs.h
r204 r238 28 28 ////////////////////////////////////////////////////////////////////////////////////////// 29 29 // 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 : 31 33 // - The "dev" directory inode is stored in cluster_IO. It is the root of the DEVFS 32 34 // file system. The parent inode is the "/" VFS root. … … 38 40 // The parent dentry is stored in cluster_IO. 39 41 // 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. 45 48 ////////////////////////////////////////////////////////////////////////////////////////// 46 49 -
trunk/kernel/vfs/fatfs.c
r188 r238 2 2 * fatfs.c - FATFS file system API implementation. 3 3 * 4 * Author Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017) 4 * Author Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 30 29 #include <ppm.h> 31 30 #include <vfs.h> 31 #include <string.h> 32 32 #include <rpc.h> 33 33 #include <mapper.h> … … 46 46 47 47 ////////////////////////////////////////////////////////////////////////////////////////// 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 56 static inline int get_length( int offset , int length ) { return length; } 57 58 static inline int get_offset( int offset , int length ) { return offset; } 59 50 60 51 61 ////////////////////////////////////////////////////////////////////////////////////////// … … 63 73 } 64 74 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) 114 78 // from a memory buffer, taking into account endianness. 115 /////////////////////////////////////////////////////////////////////////////////////// 79 ////////////////////////////////////////////////////////////////////////////////////////// 116 80 // @ offset : first byte of record in buffer. 117 81 // @ size : record length in bytes (1/2/4). … … 119 83 // @ little endian : the most significant byte has the highest address when true. 120 84 // @ return the integer value in a 32 bits word. 121 /////////////////////////////////////////////////////////////////////////////////////// 122 static uint32_t get_record_from_buffer( uint32_t offset,123 124 125 85 ////////////////////////////////////////////////////////////////////////////////////////// 86 static uint32_t fatfs_get_record( uint32_t offset, 87 uint32_t size, 88 uint8_t * buffer, 89 uint32_t little_endian ) 126 90 { 127 91 uint32_t n; … … 138 102 return res; 139 103 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 ////////////////////////////////////////////////////////////////////////////////////////// 113 static 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 ////////////////////////////////////////////////////////////////////////////////////////// 150 static 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 ////////////////////////////////////////////////////////////////////////////////////////// 145 221 // This function returns the FATFS cluster index of a page identified by its page 146 222 // index in the file, using the FAT mapper. It scans the FAT mapper, starting from the … … 152 228 // in the cluster containing the FAT mapper, and the RPC latency is not critical 153 229 // compared to the device access latency. 154 //////////////////////////////////////////////////////////////////////////////////////// 230 ////////////////////////////////////////////////////////////////////////////////////////// 155 231 // @ ctx : pointer on local FATFS context. 156 232 // @ first_cluster : first cluster allocated to a file in FATFS. … … 158 234 // @ cluster_index : [out] pointer on buffer for FATFS cluster index. 159 235 // @ return 0 if success / return EIO if a FAT cluster miss cannot be solved. 160 //////////////////////////////////////////////////////////////////////////////////////// 236 ////////////////////////////////////////////////////////////////////////////////////////// 161 237 static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx, 162 238 uint32_t first_cluster, … … 203 279 } // end fatfs_cluster_from_index() 204 280 281 ////////////////////////////////////////////////////////////////////////////////////////// 282 // FATFS specific but public functions (used by RPC_FATFS_GET_CLUSTER) 283 ////////////////////////////////////////////////////////////////////////////////////////// 284 285 ///////////////////////////////////////////// 286 error_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() 205 331 206 332 207 333 208 334 /////////////////////////////////////////////////////////////////////////////////////// 209 // Generic API : the following functions are called by the kernel 335 // Generic API : the following functions are called by the kernel (VFS) 210 336 // and must be defined by all supported file systems. 211 337 /////////////////////////////////////////////////////////////////////////////////////// … … 275 401 276 402 // 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 ); 278 404 279 405 nolock_assert( (sector_size == 512) , __FUNCTION__ , … … 281 407 282 408 // 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 ); 284 410 285 411 nolock_assert( (nb_sectors == 8) , __FUNCTION__ , … … 287 413 288 414 // 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 ); 290 416 291 417 nolock_assert( (nb_fats == 1) , __FUNCTION__ , … … 293 419 294 420 // 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 ); 296 422 297 423 nolock_assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ , … … 299 425 300 426 // 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 ); 302 428 303 429 nolock_assert( (root_cluster == 2) , __FUNCTION__ , … … 305 431 306 432 // 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 ); 308 434 309 435 // release the 512 bytes buffer … … 353 479 } 354 480 355 /////////////////////////////////////// /////////356 static error_t fatfs_access_page( page_t * page,357 bool_t is_read)481 /////////////////////////////////////// 482 error_t fatfs_move_page( page_t * page, 483 bool_t to_mapper ) 358 484 { 359 485 // get memory buffer base address … … 388 514 389 515 // 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 ); 392 518 393 519 if( error ) … … 401 527 } 402 528 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 ///////////////////////////////////////////////////////////////// 530 error_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 33 33 /////////////////////////////////////////////////////////////////////////////////////////// 34 34 // 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). 35 45 /////////////////////////////////////////////////////////////////////////////////////////// 36 46 … … 173 183 174 184 ////////////////////////////////////////////////////////////////////////////////////////// 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 *****************************************************************************************/ 206 error_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 ////////////////////////////////////////////////////////////////////////////////////////// 175 215 // Generic API: These functions are called by the kernel, 176 216 // and must be implemented by all File Systems. … … 185 225 186 226 /***************************************************************************************** 187 * This function access the external boot device, and initialises it227 * This function access the boot device, and initialises the FATFS context 188 228 * from informations contained in the boot record. 189 229 ***************************************************************************************** … … 200 240 201 241 /***************************************************************************************** 202 * This function moves a page from the mapper tothe FATFS file system on device.242 * This function moves a page from/to the mapper to/from the FATFS file system on device. 203 243 * It must be called by a thread running in cluster containing the mapper. 204 244 * The pointer on the mapper and the page index in file are registered 205 245 * in the page descriptor. 206 246 ***************************************************************************************** 207 * @ page : local pointer on page descriptor. 247 * @ page : local pointer on page descriptor. 248 * @ to_mapper : transfer direction 208 249 * @ return 0 if success / return EIO if error. 209 250 ****************************************************************************************/ 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 ); 251 error_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 ****************************************************************************************/ 267 error_t fatfs_inode_load( struct vfs_inode_s * parent_inode, 268 char * name, 269 xptr_t child_inode_xp ); 246 270 247 271 #endif /* _FATFS_H_ */ -
trunk/kernel/vfs/vfs.c
r222 r238 248 248 } // end vfs_inode_destroy() 249 249 250 ///////////////////////////////////////////// 251 error_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 250 286 //////////////////////////////////////////// 251 287 void vfs_inode_remote_up( xptr_t inode_xp ) … … 594 630 595 631 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() ); 596 635 597 636 // success … … 1161 1200 cxy_t child_cxy; // cluster for child inode 1162 1201 vfs_inode_t * child_ptr; // local pointer on child inode 1163 vfs_inode_type_t inode_type; // child inode type1202 vfs_inode_type_t child_type; // child inode type 1164 1203 vfs_fs_type_t fs_type; // File system type 1165 1204 vfs_ctx_t * ctx_ptr; // local pointer on FS context … … 1206 1245 &child_xp ); 1207 1246 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 1209 1256 { 1210 1257 vfs_dmsg("\n[INFO] %s : <%s> not found, try to load it\n", … … 1214 1261 vfs_inode_unlock( parent_xp ); 1215 1262 1216 // get cluster and local pointer on parent inode1263 // get parent inode FS type 1217 1264 parent_cxy = GET_CXY( parent_xp ); 1218 1265 parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); 1219 1266 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(); 1232 1273 1233 printk("\n@@@ name not found : <%s>\n", name );1234 1235 1274 // insert a new child dentry/inode in parent inode 1236 1275 error = vfs_add_child_in_parent( child_cxy, 1237 inode_type,1276 INODE_TYPE_DIR, 1238 1277 fs_type, 1239 1278 parent_xp, 1240 1279 name, 1241 NULL, 1280 NULL, // fs_type_specific inode extend 1242 1281 &child_xp ); 1243 1282 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 ) 1244 1306 { 1245 1307 printk("\n[ERROR] in %s : node %s not found in path %s\n", … … 1248 1310 } 1249 1311 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 1250 1340 // take lock on parent inode 1251 1341 vfs_inode_lock( parent_xp ); 1252 1342 } 1253 1343 1254 vfs_inode_display( child_xp );1255 1256 vfs_display( parent_xp );1257 1258 1344 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 ); 1260 1346 1261 1347 // TODO check access rights … … 1269 1355 // } 1270 1356 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 ); 1277 1359 vfs_inode_unlock( parent_xp ); 1278 1360 … … 1280 1362 parent_xp = child_xp; 1281 1363 current = next; 1282 1283 vfs_dmsg("\n[INFO] %s : complete node <%s> / last = %d\n",1284 __FUNCTION__ , name , last );1285 1286 1364 } 1287 1365 while( last == false ); 1288 1366 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 1297 1374 *inode_xp = child_xp; 1298 1375 … … 1385 1462 cxy_t parent_cxy; // parent inode cluster identifier 1386 1463 vfs_inode_t * parent_ptr; // parent inode local pointer 1387 vfs_ctx_t * parent_ctx; // parent inode context local pointer1388 1464 1389 1465 // get parent inode cluster and local pointer … … 1471 1547 } // end vfs_add_child_in_parent() 1472 1548 1473 1474 1475 1476 1549 ////////////////////////////////////////////////////////////////////////////////////////// 1477 1550 // Mapper related functions 1478 1551 ////////////////////////////////////////////////////////////////////////////////////////// 1479 1552 1480 //////////////////////////////////////////////// 1481 error_t vfs_move_page_to_mapper( page_t * page ) 1553 //////////////////////////////////////////// 1554 error_t vfs_mapper_move_page( page_t * page, 1555 bool_t to_mapper ) 1482 1556 { 1483 1557 error_t error = 0; … … 1492 1566 vfs_fs_type_t fs_type = mapper->inode->ctx->type; 1493 1567 1494 // update mapper if permitted by file system type1568 // call relevant FS function 1495 1569 if( fs_type == FS_TYPE_FATFS ) 1496 1570 { 1497 // get mapper lock in WRITE_MODE1498 1571 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 ); 1503 1573 rwlock_wr_unlock( &mapper->lock ); 1504 1574 } … … 1518 1588 return error; 1519 1589 1520 } // end vfs_move_page _to_mapper()1590 } // end vfs_move_page() 1521 1591 1522 1592 ////////////////////////////////////////////////// 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; 1593 error_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; 1530 1602 1531 1603 assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" ); 1532 1604 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 399 399 void vfs_inode_destroy( vfs_inode_t * inode ); 400 400 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 *****************************************************************************************/ 414 error_t vfs_inode_load( vfs_inode_t * parent, 415 char * name, 416 xptr_t child_xp ); 417 401 418 /****************************************************************************************** 402 419 * This function atomically increment/decrement the inode refcount. … … 617 634 * @ pathname : path in kernel space (can be relative or absolute). 618 635 * @ 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. 620 637 * @ return 0 if success / ENOENT if inode not found , EACCES if permissopn denied, 621 638 * EAGAIN if a new complete lookup must be made … … 635 652 * 2) The inode and its associated mapper are created in cluster identified by <child_cxy>. 636 653 * The new inode and the parent inode can have different FS types. 637 * 3) The "child_xp" field in created dentry (pointing on the created inode) is updated.654 * 3) The "child_xp" field in created dentry (pointing on the created inode) is updated. 638 655 ****************************************************************************************** 639 656 * @ child_cxy : target cluster for child inode. … … 666 683 * This recursive function diplays a complete inode/dentry sub-tree. 667 684 * Any inode can be selected as the sub-tree root. 668 * TODO this function is not p totected against a concurrent noderemoval...685 * TODO this function is not protected against a concurrent inode/dentry removal... 669 686 ****************************************************************************************** 670 687 * @ inode_xp : extended pointer on sub-tree root inode. … … 857 874 858 875 /****************************************************************************************** 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. 861 879 * Depending on the file system type, it calls the proper, FS specific function. 862 880 * It must be executed by a thread running in the cluster containing the mapper. … … 864 882 * It takes the mapper lock before launching the IO operation. 865 883 ****************************************************************************************** 866 * @ page : local pointer on the page descriptor. 884 * @ page : local pointer on the page descriptor. 885 * @ to_mapper : transfer direction. 867 886 * @ returns 0 if success / return EINVAL if it cannot access the external device. 868 887 *****************************************************************************************/ 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. 888 error_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. 874 895 * Depending on the file system type, it calls the proper, FS specific function. 875 896 * 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. 877 898 * 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 *****************************************************************************************/ 903 error_t vfs_mapper_load_all( vfs_inode_t * inode ); 912 904 913 905
Note: See TracChangeset
for help on using the changeset viewer.