Changeset 761 for soft/giet_vm/giet_fat32/fat32.c
- Timestamp:
- Jan 19, 2016, 11:34:45 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_fat32/fat32.c
r750 r761 53 53 // Fat-Descriptor 54 54 __attribute__((section(".kdata"))) 55 fat_desc_t _fat __attribute__((aligned(64)));55 fat_desc_t _fat __attribute__((aligned(64))); 56 56 57 57 // buffer used by boot code as a simple cache when scanning FAT … … 180 180 181 181 ////////////////////////////////////////////////////////////////////////////////// 182 // The following function introduces the inode identified by the "child"argument,183 // as a new child of the "parent"inode in the Inode-Tree.182 // The following function introduces the inode identified by the <child> argument, 183 // as a new child of the <parent> inode in the Inode-Tree. 184 184 // All checking are supposed to be done by the caller. 185 185 // Nor the File-Cache, neither the block device are modified. … … 190 190 191 191 ////////////////////////////////////////////////////////////////////////////////// 192 // The following function removes one inode identified by the "inode"argument192 // The following function removes one inode identified by the <inode> argument 193 193 // from the Inode-Tree. All checking are supposed to be done by the caller. 194 194 // Nor the File-Cache, neither the block device are modified. … … 200 200 // This recursive function scan one File-Cache (or Fat-Cache) from root to leaves, 201 201 // to writes all dirty clusters to block device, and reset the dirty bits. 202 // The cache is identified by the "root" an "levels"arguments.203 // The "string"argument is only used for debug : inode name or Fat.202 // The cache is identified by the <root> an <levels> arguments. 203 // The <string> argument is only used for debug : inode name or Fat. 204 204 // It returns 0 on success. 205 205 // It returns 1 on error. … … 223 223 // The following function read a data field (from one to four bytes) 224 224 // from an unsigned char[] buffer, taking endianness into account. 225 // The analysed field is defined by the "offset" and "size"arguments.225 // The analysed field is defined by the <offset> and <size> arguments. 226 226 ////////////////////////////////////////////////////////////////////////////// 227 227 … … 249 249 250 250 ////////////////////////////////////////////////////////////////////////////////// 251 // The following function search in the directory identified by the "parent"252 // inode pointer a child (file or directory) identified by its "name".253 // It returns in the "inode"argument the searched child inode pointer.251 // The following function search in the directory identified by the <parent> 252 // inode pointer a child (file or directory) identified by its <name>. 253 // It returns in the <inode> argument the searched child inode pointer. 254 254 // If the searched name is not found in the Inode-Tree, the function accesses 255 // the "file_cache"associated to the parent directory.255 // the File-cache associated to the parent directory. 256 256 // If the child exists on block device, the Inode-Tree is updated, and 257 257 // a success code is returned. … … 356 356 ////////////////////////////////////////////////////////////////////////////////// 357 357 // The following function releases all clusters allocated to a file or directory, 358 // from the cluster index defined by the "cluster"argument, until the end358 // from the cluster index defined by the <cluster> argument, until the end 359 359 // of the FAT linked list. 360 360 // It calls _get_fat_entry() and _set_fat_entry() functions to scan the FAT, … … 368 368 369 369 ////////////////////////////////////////////////////////////////////////////////// 370 // This function allocate "nb_clusters_more" new clusters to a file (or directory) 371 // identified by the "inode" pointer. It allocates also the associated buffers 372 // and buffer descriptors in the Cache-File. 370 // This function allocate one cluster in FAT to a file (or directory) identified 371 // by the <inode> pointer. The allocated cluster index is returned in the 372 // <cluster> argument. 373 // It allocates also the associated buffers and buffer descriptors in Cache-File. 373 374 // It calls _get_fat_entry() and _set_fat_entry() functions to update the 374 375 // clusters chaining in the Cache-Fat. The FAT region on block device is updated. … … 377 378 ////////////////////////////////////////////////////////////////////////////////// 378 379 379 static unsigned int _clusters_allocate( fat_inode_t* inode, 380 unsigned int nb_clusters_current, 381 unsigned int nb_clusters_more ); 380 static unsigned int _cluster_allocate( fat_inode_t* inode, 381 unsigned int* cluster ); 382 382 383 383 ////////////////////////////////////////////////////////////////////////////////// … … 393 393 394 394 ////////////////////////////////////////////////////////////////////////////////// 395 // The following function allocates and initializes a new Fat-Cache node.395 // The following function allocates and initializes a new cache node. 396 396 // Its first child can be specified (used when adding a cache level). 397 // The Fat-Cache is initialized as empty: all childrenset to NULL.397 // The 63 other children are set to NULL. 398 398 // It returns a pointer to a new Fat-Cache node. 399 399 ////////////////////////////////////////////////////////////////////////////////// … … 404 404 // The following function allocates and initializes a new inode, 405 405 // using the values defined by the arguments. 406 // If the "cache_allocate" argument is true ansempty cache is allocated.406 // If the "cache_allocate" argument is true, an empty cache is allocated. 407 407 // It returns a pointer on the new inode. 408 408 ////////////////////////////////////////////////////////////////////////////////// … … 417 417 418 418 ////////////////////////////////////////////////////////////////////////////////// 419 // The following function allocates one 4 Kbytes buffer andassociated cluster420 // descriptor for the file (or directory) identified by the "inode"argument,421 // and updates the Cache_File slot identified by the "cluster_id"argument.419 // The following function allocates a 4 Kbytes buffer and the associated cluster 420 // descriptor for the file (or directory) identified by the <inode> argument, 421 // and updates the Cache_File slot identified by the <cluster_id> argument. 422 422 // The File-Cache slot must be empty. 423 // It updates the cluster descriptor, using the "cluster"argument, that is423 // It updates the buffer descriptor, using the <cluster> argument, that is 424 424 // the cluster index in FAT. The cluster descriptor dirty field is set. 425 425 // It traverse the 64-tree Cache-file from top to bottom to find the last level. … … 431 431 432 432 ////////////////////////////////////////////////////////////////////////////////// 433 // The following function allocates one free cluster from the FAT "heap" of free434 // clusters, and returns the cluster index in the "cluster"argument.433 // The following function allocates one free cluster from the FAT 434 // and returns the cluster index in the <cluster> argument. 435 435 // It updates the FAT slot, and the two FAT global variables: first_free_cluster, 436 436 // and free_clusters_number. … … 443 443 ///////////////////////////////////////////////////////////////////////////// 444 444 // This function remove from the file system a file or a directory 445 // identified by the "inode"argument.445 // identified by the <inode> argument. 446 446 // The remove condition must be checked by the caller. 447 447 // The relevant lock(s) must have been taken by te caller. … … 483 483 484 484 ////////////////////////////////////////////////////////////////////////////////// 485 // The following functions return the length or the sizeof a FAT field,485 // The following functions return the the size (bytes) of a FAT field, 486 486 // identified by an (offset,length) mnemonic defined in the fat32.h file. 487 487 ////////////////////////////////////////////////////////////////////////////////// … … 491 491 static inline int get_offset( int offset , int length ) { return offset; } 492 492 493 ////////////////////////////////////////////////////////////////////////////////// 494 // The following function returns in the <desc> argument a pointer on a buffer 495 // descriptor contained in the Fat_Cache. 496 // The <cluster_id> argument is the buffer index in the FAT_Cache. 497 // In case of miss, a 4 Kbytesbuffer and a buffer descriptor are allocated 498 // from the local heap, and the missing cluster is loaded in the Fat_Cache. 499 // It returns 0 on success. 500 // It returns 1 on error. 501 ////////////////////////////////////////////////////////////////////////////////// 502 503 static unsigned int _get_fat_cache_buffer( unsigned int cluster_id, 504 fat_cache_desc_t** desc ); 493 505 494 506 … … 855 867 856 868 857 //////////////////////////////////////////////////////////// 869 ////////////////////////////////////////////////////////////////////////////////// 858 870 static fat_cache_node_t* _allocate_one_cache_node( fat_cache_node_t* first_child ) 859 871 { … … 1006 1018 unsigned int entry_id = cluster & 0x3FF; 1007 1019 1008 // get pointer on the relevant cluster descriptor in FAT cache1020 // get pointer on the relevant buffer descriptor in FAT cache 1009 1021 fat_cache_desc_t* pdesc; 1010 1022 unsigned int* buffer; 1011 if ( _fat_buffer_from_cache( NULL, // Fat-Cache 1012 cluster_id, 1013 &pdesc ) ) return 1; 1023 if ( _get_fat_cache_buffer( cluster_id, 1024 &pdesc ) ) return 1; 1014 1025 1015 1026 // get value from FAT slot … … 1031 1042 unsigned int entry_id = cluster & 0x3FF; 1032 1043 1033 // get pointer on the relevant cluster descriptor in FAT cache1044 // get pointer on the relevant buffer descriptor in FAT cache 1034 1045 fat_cache_desc_t* pdesc; 1035 1046 unsigned int* buffer; 1036 if ( _fat_buffer_from_cache( NULL, // Fat-Cache 1037 cluster_id, 1038 &pdesc ) ) return 1; 1047 if ( _get_fat_cache_buffer( cluster_id, 1048 &pdesc ) ) return 1; 1039 1049 1040 1050 // set value into FAT slot … … 1053 1063 unsigned int cluster ) 1054 1064 { 1065 1066 #if (GIET_DEBUG_FAT & 1) 1067 if ( _get_proctime() > GIET_DEBUG_FAT ) 1068 _printf("\n[DEBUG FAT] _allocate_one_buffer(): in cache <%s> for cluster_id %d\n", 1069 inode->name, cluster_id ); 1070 #endif 1071 1055 1072 // add cache levels if needed 1056 1073 while ( _get_levels_from_size( (cluster_id + 1) * 4096 ) > inode->levels ) 1057 1074 { 1075 1058 1076 #if (GIET_DEBUG_FAT & 1) 1059 1077 if ( _get_proctime() > GIET_DEBUG_FAT ) … … 1077 1095 { 1078 1096 fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index]; 1097 1079 1098 if ( pdesc != NULL ) // slot not empty!!! 1080 1099 { 1081 _printf("\n[FAT ERROR] allocate_one buffer(): slot not empty " 1082 "in File-Cache <%s> / cluster_id = %d\n", inode->name , cluster_id ); 1100 _printf("\n[FAT ERROR] in _allocate_one buffer() : slot not empty " 1101 "in File-Cache <%s>\n cluster_id = %d / cache = %x / pdesc[0] = %x\n", 1102 inode->name , cluster_id , 1103 (unsigned int)node , (unsigned int)pdesc ); 1083 1104 _exit(); 1084 1105 } … … 1155 1176 #if (GIET_DEBUG_FAT & 1) 1156 1177 if ( _get_proctime() > GIET_DEBUG_FAT ) 1157 _printf("\n[DEBUG FAT] _allocate_one_cluster(): cluster = %x / first_free = %x\n",1178 _printf("\n[DEBUG FAT] _allocate_one_cluster(): allocated cluster = %x / first_free = %x\n", 1158 1179 free , current ); 1159 1180 #endif … … 1176 1197 unsigned int ret = 0; 1177 1198 1178 if ( levels == 1 ) // last level => children are cluster descriptors1199 if ( levels == 1 ) // last level => children are buffer descriptors 1179 1200 { 1180 1201 for( index = 0 ; index < 64 ; index++ ) … … 1273 1294 1274 1295 1275 ///////////////////////////////////////////////////////////// 1276 static unsigned int _clusters_allocate( fat_inode_t* inode, 1277 unsigned int nb_current_clusters, 1278 unsigned int nb_required_clusters ) 1279 { 1280 // Check if FAT contains enough free clusters 1281 if ( nb_required_clusters > _fat.free_clusters_number ) 1282 { 1283 _printf("\n[FAT ERROR] _clusters_allocate(): required_clusters = %d" 1284 " / free_clusters = %d\n", nb_required_clusters , _fat.free_clusters_number ); 1296 //////////////////////////////////////////////////////////// 1297 static unsigned int _cluster_allocate( fat_inode_t* inode, 1298 unsigned int* cluster ) 1299 { 1300 // Check free cluster available 1301 if ( _fat.free_clusters_number == 0 ) 1302 { 1303 _printf("\n[FAT ERROR] in _cluster_allocate(): no more free clusters\n"); 1285 1304 return 1; 1286 1305 } 1287 1306 1288 #if (GIET_DEBUG_FAT & 1) 1289 if ( _get_proctime() > GIET_DEBUG_FAT ) 1290 _printf("\n[DEBUG FAT] _clusters_allocate(): enters for <%s> / nb_current_clusters = %d " 1291 "/ nb_required_clusters = %d\n", 1292 inode->name , nb_current_clusters , nb_required_clusters ); 1293 #endif 1294 1295 // compute last allocated cluster index when (nb_current_clusters > 0) 1307 // compute number of already allocated clusters 1308 // and last allocated cluster index 1309 unsigned int nb_current_clusters = 0; 1296 1310 unsigned int current = inode->cluster; 1297 unsigned int next; 1298 unsigned int last; 1299 if ( nb_current_clusters ) // clusters allocated => search last 1300 { 1301 while ( current < END_OF_CHAIN_CLUSTER_MIN ) 1302 { 1303 // get next cluster 1304 if ( _get_fat_entry( current , &next ) ) return 1; 1305 last = current; 1306 current = next; 1307 } 1311 unsigned int last = current; 1312 unsigned int next = 0; 1313 unsigned int new = 0; 1314 1315 while ( current < END_OF_CHAIN_CLUSTER_MIN ) 1316 { 1317 // get next cluster 1318 if ( _get_fat_entry( current , &next ) ) return 1; 1319 1320 // increment number of allocated clusters 1321 nb_current_clusters++; 1322 1323 // update loop variables 1324 last = current; 1325 current = next; 1308 1326 } 1309 1327 1310 // Loop on the new clusters to be allocated 1311 // if (nb_current_clusters == 0) the first new cluster index must 1312 // be written in inode->cluster field 1313 // if (nb_current_clusters > 0) the first new cluster index must 1314 // be written in FAT[last] 1315 unsigned int cluster_id; 1316 unsigned int new; 1317 for ( cluster_id = nb_current_clusters ; 1318 cluster_id < (nb_current_clusters + nb_required_clusters) ; 1319 cluster_id ++ ) 1320 { 1321 // allocate one cluster on block device 1322 if ( _allocate_one_cluster( &new ) ) return 1; 1323 1324 // allocate one 4K buffer to File-Cache 1325 _allocate_one_buffer( inode, 1326 cluster_id, 1327 new ); 1328 1329 if ( cluster_id == 0 ) // update inode 1330 { 1331 inode->cluster = new; 1332 } 1333 else // update FAT 1334 { 1335 if ( _set_fat_entry( last , new ) ) return 1; 1336 } 1337 1338 #if (GIET_DEBUG_FAT & 1) 1339 if ( _get_proctime() > GIET_DEBUG_FAT ) 1340 _printf("\n[DEBUG FAT] _clusters_allocate(): done for cluster_id = %d / cluster = %x\n", 1341 cluster_id , new ); 1342 #endif 1343 1344 // update loop variables 1345 last = new; 1346 1347 } // end for loop 1348 1349 // update FAT : last slot should contain END_OF_CHAIN_CLUSTER_MAX 1350 if ( _set_fat_entry( last , END_OF_CHAIN_CLUSTER_MAX ) ) return 1; 1328 // allocate one free cluster from FAT 1329 if ( _allocate_one_cluster( &new ) ) return 1; 1330 1331 // allocate one 4K buffer to File-Cache 1332 _allocate_one_buffer( inode, 1333 nb_current_clusters, 1334 new ); 1335 1336 if ( nb_current_clusters == 0 ) // first cluster : inode and directory entry 1337 { 1338 // update inode 1339 inode->cluster = new; 1340 1341 // update directory entry 1342 _update_dir_entry( inode ); 1343 } 1344 else // update previous last cluster in FAT 1345 { 1346 if ( _set_fat_entry( last , new ) ) return 1; 1347 } 1351 1348 1352 1349 // update the FAT on block device … … 1354 1351 _fat.fat_cache_root, 1355 1352 "FAT" ) ) return 1; 1353 #if (GIET_DEBUG_FAT & 1) 1354 if ( _get_proctime() > GIET_DEBUG_FAT ) 1355 _printf("\n[DEBUG FAT] _cluster_allocate(): for <%s> / current_clusters = %d" 1356 " / last_cluster = %x / new_cluster = %x\n", 1357 inode->name , nb_current_clusters , last , new ); 1358 #endif 1359 1360 // returns allocated cluster index 1361 *cluster = new; 1362 1356 1363 return 0; 1357 } // end _cluster s_allocate()1364 } // end _cluster_allocate() 1358 1365 1359 1366 … … 1518 1525 { 1519 1526 // get one 4 Kytes buffer from File_Cache 1520 if ( _ fat_buffer_from_cache( inode,1527 if ( _get_file_cache_buffer( inode, 1521 1528 cluster_id, 1529 0, 1522 1530 &pdesc ) ) return 1; 1523 1531 buffer = pdesc->buffer; … … 1600 1608 { 1601 1609 // get one 4 Kytes buffer from File_Cache 1602 if ( _ fat_buffer_from_cache( parent,1610 if ( _get_file_cache_buffer( parent, 1603 1611 cluster_id, 1612 0, 1604 1613 &pdesc ) ) return 1; 1605 1614 … … 1658 1667 if ( offset >= 4096 ) // new buffer required 1659 1668 { 1660 if ( _ fat_buffer_from_cache( parent,1669 if ( _get_file_cache_buffer( parent, 1661 1670 cluster_id + 1, 1671 0, 1662 1672 &pdesc ) ) return 1; 1663 1673 buffer = pdesc->buffer; … … 1832 1842 fat_cache_desc_t* pdesc; 1833 1843 1834 if ( _ fat_buffer_from_cache( inode->parent,1844 if ( _get_file_cache_buffer( inode->parent, 1835 1845 cluster_id, 1846 0, 1836 1847 &pdesc ) ) return 1; 1837 1848 buffer = pdesc->buffer; … … 1849 1860 break; 1850 1861 1851 if ( _ fat_buffer_from_cache( inode->parent,1862 if ( _get_file_cache_buffer( inode->parent, 1852 1863 cluster_id - 1, 1864 0, 1853 1865 &pdesc ) ) return 1; 1854 1866 buffer = pdesc->buffer; … … 1885 1897 unsigned int offset = (inode->dentry & 0x7F)<<5; 1886 1898 1887 if ( _ fat_buffer_from_cache( inode->parent,1899 if ( _get_file_cache_buffer( inode->parent, 1888 1900 cluster_id, 1901 0, 1889 1902 &pdesc ) ) return 1; 1890 1903 buffer = pdesc->buffer; … … 1938 1951 } 1939 1952 1940 // not found in Inode-Tree => access the parent directory 1941 // file_cache.Two embedded loops:1953 // not found in Inode-Tree => access the parent directory file_cache. 1954 // Two embedded loops: 1942 1955 // - scan the clusters allocated to this directory 1943 1956 // - scan the directory entries in each 4 Kbytes buffer … … 1970 1983 // get one 4 Kytes buffer from parent File_Cache 1971 1984 fat_cache_desc_t* pdesc; 1972 if ( _ fat_buffer_from_cache( parent,1985 if ( _get_file_cache_buffer( parent, 1973 1986 cluster_id, 1987 0, 1974 1988 &pdesc ) ) return 2; 1975 1989 buffer = pdesc->buffer; … … 1978 1992 while( (offset < 4096) && (found == 0) ) 1979 1993 { 1980 1981 #if (GIET_DEBUG_FAT & 1)1982 if ( _get_proctime() > GIET_DEBUG_FAT )1983 _printf("\n[DEBUG FAT] _get_child_from_parent(): scan buffer %d for <%s>\n",1984 cluster_id , name );1985 #endif1986 1994 attr = _read_entry( DIR_ATTR , buffer + offset , 0 ); 1987 1995 ord = _read_entry( LDIR_ORD , buffer + offset , 0 ); … … 2027 2035 } 2028 2036 2029 // testif extracted name == searched name2037 // get dir-entry arguments if extracted name == searched name 2030 2038 if ( _strcmp( name , cname ) == 0 ) 2031 2039 { … … 2036 2044 size = _read_entry( DIR_FILE_SIZE , buffer + offset , 1 ); 2037 2045 found = 1; 2046 2047 // adjust size for a directory : 2048 // size must be non-zero and rounded to a multiple of 4 Kbytes 2049 if ( is_dir ) 2050 { 2051 if ( size == 0 ) size = 4096; 2052 else if ( size & 0xFFF ) size = ((size>>12) + 1)<<12; 2053 } 2038 2054 } 2039 2055 offset = offset + 32; … … 2449 2465 2450 2466 2467 ////////////////////////////////////////////////////////////////////////// 2468 static unsigned int _get_fat_cache_buffer( unsigned int cluster_id, 2469 fat_cache_desc_t** desc ) 2470 { 2471 // get cache pointer and number of levels 2472 fat_cache_node_t* node = _fat.fat_cache_root; 2473 unsigned int level = _fat.fat_cache_levels; 2474 2475 if ( _get_levels_from_size( (cluster_id + 1) * 4096 ) > level ) 2476 { 2477 _printf("\n[FAT ERROR] in _get_fat_cache_buffer() : " 2478 "cluster_id %d too large", cluster_id ); 2479 return 1; 2480 } 2481 2482 // search the 64-tree cache from top to bottom 2483 while ( level ) 2484 { 2485 // compute child index at each level 2486 unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F; 2487 2488 if ( level == 1 ) // last level => children are buffer descriptors 2489 { 2490 fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index]; 2491 2492 if ( pdesc == NULL ) // miss 2493 { 2494 2495 #if (GIET_DEBUG_FAT & 1) 2496 if ( _get_proctime() > GIET_DEBUG_FAT ) 2497 _printf("\n[DEBUG FAT] _get_fat_cache_buffer(): miss for cluster_id %d\n", cluster_id ); 2498 #endif 2499 // compute missing cluster lba 2500 unsigned int lba = _fat.fat_lba + (cluster_id << 3); 2501 2502 // allocate a 4 Kbytes buffer and a buffer descriptor 2503 void* buf = _malloc( 4096 ); 2504 pdesc = _malloc( sizeof(fat_cache_desc_t) ); 2505 pdesc->lba = lba; 2506 pdesc->buffer = buf; 2507 pdesc->dirty = 0; 2508 node->children[index] = pdesc; 2509 2510 // load cluster from device 2511 if ( _fat_ioc_access( 1, // descheduling 2512 1, // to memory 2513 lba, 2514 (unsigned int)buf, 2515 8 ) ) 2516 { 2517 _free( buf ); 2518 _free( pdesc ); 2519 _printf("\n[FAT ERROR] in _get_fat_cache_buffer() : " 2520 ": cannot access block device for lba = %x\n", lba ); 2521 return 1; 2522 } 2523 2524 } 2525 2526 #if (GIET_DEBUG_FAT & 1) 2527 if ( _get_proctime() > GIET_DEBUG_FAT ) 2528 _printf("\n[DEBUG FAT] _get_fat_cache_buffer() : found buffer = %x\n", 2529 (unsigned int)pdesc->buffer ); 2530 #endif 2531 // return pdesc pointer 2532 *desc = pdesc; 2533 2534 // prepare next iteration 2535 level--; 2536 } 2537 else // not last level => children are 64-tree nodes 2538 { 2539 fat_cache_node_t* child = (fat_cache_node_t*)node->children[index]; 2540 if ( child == NULL ) // miss 2541 { 2542 // allocate a cache node if miss 2543 child = _allocate_one_cache_node( NULL ); 2544 node->children[index] = child; 2545 } 2546 2547 // prepare next iteration 2548 node = child; 2549 level--; 2550 } 2551 } // end while 2552 2553 return 0; 2554 } // end _get_fat_cache_buffer() 2555 2556 2451 2557 2452 2558 ///////////////////////////////////////////////////////////////////////////// … … 2459 2565 ///////////////////////////////////////////////////////////////////////////// 2460 2566 // This function initializes the FAT structures. 2461 // - The Fat-Descriptor is always initialized.2567 // - The Fat-Descriptor is initialized in both boot and kernel modes. 2462 2568 // - The dynamically allocated structures (the Inode-Tre, the Fat_Cache, 2463 2569 // and the File-Cache for the root directory) are only allocated … … 2582 2688 2583 2689 // create Inode-Tree root 2584 _fat.inode_tree_root = _allocate_one_inode("/", // dir name2585 1, //directory2586 2, // cluster id2587 0, // no size2588 0, // no children2589 0, // no dentry2590 1); // allocate cache2690 _fat.inode_tree_root = _allocate_one_inode("/", // dir name 2691 1, // is directory 2692 2, // cluster index 2693 4096, // at least one buffer 2694 0, // no children 2695 0, // no dentry 2696 1); // allocate cache 2591 2697 2592 2698 // initialize lock … … 2614 2720 /////////////////////////////////////////////////////////////////////////////// 2615 2721 // This function implements the giet_fat_open() system call. 2616 // The semantic is similar to the UNIX open() function, but only the O_CREATE 2617 // and O_RDONLY flags are supported. The UNIX access rights are not supported. 2618 // If the file does not exist in the specified directory, it is created. 2722 // The semantic is similar to the UNIX open() function, with some limitations: 2723 // - only the O_CREATE, O_RDONLY, and O_TRUNC flags are supported. 2724 // - the UNIX access rights are not supported. 2725 // If the file does not exist in the specified directory, it is created when 2726 // the O_CREATE flag is set. 2619 2727 // If the specified directory does not exist, an error is returned. 2620 2728 // It allocates a file descriptor to the calling task, for the file identified 2621 // by "pathname". If several tasks try to open the same file, each task2622 // obtains a private file descriptor.2729 // by the <pathname> argument. If several tasks try to open the same file, 2730 // each task obtains a private file descriptor. 2623 2731 // A node name (file or directory) cannot be larger than 31 characters. 2624 2732 /////////////////////////////////////////////////////////////////////////////// … … 2672 2780 code = _get_inode_from_path( pathname , &inode ); 2673 2781 2674 if ( code == 2 ) 2782 if ( code == 2 ) // parent inode not found 2675 2783 { 2676 2784 _spin_lock_release( &_fat.fat_lock ); … … 2681 2789 return GIET_FAT32_FILE_NOT_FOUND; 2682 2790 } 2683 else if ( code == 3 ) 2791 else if ( code == 3 ) // illegal path name 2684 2792 { 2685 2793 _spin_lock_release( &_fat.fat_lock ); … … 2690 2798 return GIET_FAT32_NAME_TOO_LONG; 2691 2799 } 2692 else if ( (code == 1) && (create == 0) ) 2800 else if ( (code == 1) && (create == 0) ) // inode not found 2693 2801 { 2694 2802 _spin_lock_release( &_fat.fat_lock ); … … 2699 2807 return GIET_FAT32_FILE_NOT_FOUND; 2700 2808 } 2701 else if ( (code == 1) && (create != 0) ) // file name not found => create2809 else if ( (code == 1) && (create != 0) ) // inode not found => create 2702 2810 { 2703 2811 // set parent inode pointer … … 2720 2828 0, // size : new file is empty 2721 2829 0, // count incremented later 2722 0, // dentryset by add_dir_entry2830 0, // set by add_dir_entry 2723 2831 1 ); // cache_allocate 2724 2832 … … 2776 2884 // no need to truncate a new file 2777 2885 truncate = 0; 2778 } 2779 else // code == 0 2886 2887 #if GIET_DEBUG_FAT 2888 if ( _get_proctime() > GIET_DEBUG_FAT ) 2889 { 2890 _printf("\n[DEBUG FAT] _fat_open() : new inode created for <%s>\n" 2891 " size = %x / cluster = %x / cache = %x", 2892 child->name , child->size , child->cluster , child->cache ); 2893 if ( child->cache != NULL ) 2894 { 2895 _printf(" / pdesc[0] = %x\n", (unsigned int)(child->cache->children[0]) ); 2896 } 2897 else 2898 { 2899 _printf("\n"); 2900 } 2901 } 2902 #endif 2903 2904 } 2905 else // inode found 2780 2906 { 2781 2907 // set searched file inode pointer … … 2846 2972 } 2847 2973 2974 #if GIET_DEBUG_FAT 2975 if ( _get_proctime() > GIET_DEBUG_FAT ) 2976 _printf("\n[DEBUG FAT] _fat_open(): P[%d,%d,%d] got fd = %d for <%s> / " 2977 "size = %x / read_only = %d\n", 2978 x , y , p , fd_id , pathname , read_only ); 2979 #endif 2980 2848 2981 // releases the lock 2849 2982 _spin_lock_release( &_fat.fat_lock ); 2850 2983 _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 2851 2984 2852 2853 #if GIET_DEBUG_FAT2854 if ( _get_proctime() > GIET_DEBUG_FAT )2855 _printf("\n[DEBUG FAT] _fat_open(): P[%d,%d,%d] got fd = %d for <%s> / "2856 "read_only = %d\n",2857 x , y , p , fd_id , pathname , read_only );2858 #endif2859 2985 return fd_id; 2860 2986 } // end _fat_open() … … 2910 3036 fat_inode_t* inode = _fat.fd[fd_id].inode; 2911 3037 3038 #if GIET_DEBUG_FAT 3039 if ( _get_proctime() > GIET_DEBUG_FAT ) 3040 _printf("\n[FAT DEBUG] _fat_close() for file <%s> : refcount = %d" 3041 " / size = %x / cluster = %x\n", 3042 inode->name , inode->count , inode->size , inode->cluster ); 3043 #endif 3044 2912 3045 // decrement reference count 2913 3046 inode->count = inode->count - 1; 2914 3047 2915 #if GIET_DEBUG_FAT2916 if ( _get_proctime() > GIET_DEBUG_FAT )2917 _printf("\n[FAT DEBUG] _fat_close() for file <%s> : refcount = %d\n",2918 inode->name , inode->count );2919 #endif2920 2921 3048 // update block device and release File-Cache if no more references 2922 3049 if ( inode->count == 0 ) … … 2937 3064 #if GIET_DEBUG_FAT 2938 3065 if ( _get_proctime() > GIET_DEBUG_FAT ) 2939 _printf("\n[FAT DEBUG] _fat_close() update device for file <%s>\n", inode->name );2940 #endif 2941 2942 // update dir ectory dirty clusters for parent directory3066 _printf("\n[FAT DEBUG] _fat_close() updated device for file <%s>\n", inode->name ); 3067 #endif 3068 3069 // update dirty clusters for parent directory 2943 3070 if ( inode->parent && 2944 3071 _update_device_from_cache( inode->parent->levels, … … 2956 3083 #if GIET_DEBUG_FAT 2957 3084 if ( _get_proctime() > GIET_DEBUG_FAT ) 2958 _printf("\n[FAT DEBUG] _fat_close() update device for parent directory <%s>\n",3085 _printf("\n[FAT DEBUG] _fat_close() updated device for parent directory <%s>\n", 2959 3086 inode->parent->name ); 2960 3087 #endif … … 3138 3265 unsigned char* cbuf; 3139 3266 fat_cache_desc_t* pdesc; 3140 if ( _ fat_buffer_from_cache( inode,3267 if ( _get_file_cache_buffer( inode, 3141 3268 cluster_id, 3269 0, 3142 3270 &pdesc ) ) 3143 3271 { … … 3314 3442 if ( new_size > old_size ) 3315 3443 { 3444 // compute current and required numbers of clusters 3445 unsigned old_clusters = old_size >> 12; 3446 if ( old_size & 0xFFF ) old_clusters++; 3447 3448 unsigned new_clusters = new_size >> 12; 3449 if ( new_size & 0xFFF ) new_clusters++; 3450 3451 // allocate new clusters from FAT if required 3452 if ( new_clusters > old_clusters ) 3453 { 3454 3455 #if GIET_DEBUG_FAT 3456 if ( _get_proctime() > GIET_DEBUG_FAT ) 3457 _printf("\n[DEBUG FAT] _fat_write(): P[%d,%d,%d] allocates new clusters for file <%s>" 3458 " / current = %d / required = %d\n", 3459 x , y , p , inode->name , old_clusters , new_clusters ); 3460 #endif 3461 // allocate missing clusters 3462 unsigned int cid; 3463 unsigned int index; // unused 3464 for ( cid = 0 ; cid < (new_clusters - old_clusters) ; cid++ ) 3465 { 3466 if ( _cluster_allocate( inode , &index ) ) 3467 { 3468 _spin_lock_release( &_fat.fat_lock ); 3469 _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , 3470 ~LOCKS_MASK_FAT ); 3471 3472 _printf("\n[FAT ERROR] in _fat_write(): no free cluster" 3473 " for file <%s>\n", _fat.fd[fd_id].inode->name ); 3474 return GIET_FAT32_NO_FREE_SPACE; 3475 } 3476 } 3477 } 3478 3316 3479 // update size in inode 3317 3480 inode->size = new_size; 3318 3481 3319 // compute current and required numbers of clusters3320 unsigned old_clusters = old_size >> 12;3321 if ( old_size & 0xFFF ) old_clusters++;3322 3323 unsigned new_clusters = new_size >> 12;3324 if ( new_size & 0xFFF ) new_clusters++;3325 3326 // allocate new clusters from FAT if required3327 if ( new_clusters > old_clusters )3328 {3329 3330 #if GIET_DEBUG_FAT3331 if ( _get_proctime() > GIET_DEBUG_FAT )3332 _printf("\n[DEBUG FAT] _fat_write(): P[%d,%d,%d] allocates new clusters for file <%s>"3333 " / current = %d / required = %d\n",3334 x , y , p , inode->name , old_clusters , new_clusters );3335 #endif3336 // allocate missing clusters3337 if ( _clusters_allocate( inode,3338 old_clusters,3339 new_clusters - old_clusters ) )3340 {3341 _spin_lock_release( &_fat.fat_lock );3342 _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT );3343 3344 _printf("\n[FAT ERROR] _fat_write(): no free clusters"3345 " for file <%s>\n", _fat.fd[fd_id].inode->name );3346 return GIET_FAT32_NO_FREE_SPACE;3347 }3348 }3349 3350 3482 // update parent directory entry (size and cluster index) 3351 3483 if ( _update_dir_entry( inode ) ) … … 3393 3525 unsigned char* cbuf; 3394 3526 fat_cache_desc_t* pdesc; 3395 if ( _ fat_buffer_from_cache( inode,3527 if ( _get_file_cache_buffer( inode, 3396 3528 cluster_id, 3529 0, 3397 3530 &pdesc ) ) 3398 3531 { … … 3915 4048 0 ); // no cache_allocate 3916 4049 3917 // give the "old" File-Cache to the "newinode4050 // attach the "old" File-Cache to the "new" inode 3918 4051 new->levels = old->levels; 3919 4052 new->cache = old->cache; … … 4107 4240 1, // it's a directory 4108 4241 cluster, 4109 0, // size not defined4242 4096, // one buffer for a directory 4110 4243 0, // count 4111 4244 0, // dentry set by _add_dir_entry() … … 4479 4612 4480 4613 4481 ////////////////////////////////////////////////////////////////////////////////// 4482 // The following function returns in the "desc" argument a pointer on a buffer 4483 // descriptor contained in a File_Cache, or in the Fat_Cache. 4484 // The searched buffer is idenfified by the "inode" and "cluster_id" arguments. 4485 // If the "inode" pointer is not NULL, the searched cache is a File-Cache. 4486 // If the "inode" pointer is NULL, the searched cache is the Fat-Cache, 4487 // The "cluster_id" argument is the buffer index in the file (or in the FAT). 4488 // In case of miss, it allocate a 4 Kbytes buffer and a cluster descriptor 4489 // from the local kernel heap, and calls the _fat_ioc_access() function to load 4490 // the missing cluster from the block device. 4614 4615 ////////////////////////////////////////////////////////////////////////////////// 4616 // The following function returns in the <desc> argument a pointer on a buffer 4617 // descriptor contained in a File_Cache. 4618 // The searched buffer is idenfified by the <inode> and <cluster_id> arguments. 4619 // The <cluster_id> argument is the buffer index in the file. 4620 // The <writable> argument define the behaviour in case of miss in File-Cache: 4621 // - if [all clusters (from 0 to cluster_id) are already allocated in FAT] 4622 // we scan the FAT to find the cluster index on device, and we load the 4623 // missing cluster in the File-Cache, marked as dirty if writable is set. 4624 // - else if [writable is not set] we return an error. 4625 // - else [writable set, but all clusters (from 0 to cluster_id) not allocated] 4626 // we allocate in FAT all required clusters, we update the size in the inode 4627 // and dentry, and we allocate a buffer descriptor for the missing cluster, 4628 // marked as dirty. 4629 // This function can be called by the FAT functions, and by _sys_fat_mmap(). 4630 // It does not take the FAT lock, that must be taken by the caller. 4491 4631 ////////////////////////////////////////////////////////////////////////////////// 4492 4632 // It returns 0 on success. 4493 4633 // It returns 1 on error. 4494 4634 ////////////////////////////////////////////////////////////////////////////////// 4495 int _fat_buffer_from_cache( fat_inode_t* inode, 4496 unsigned int cluster, 4635 int _get_file_cache_buffer( fat_inode_t* inode, 4636 unsigned int cluster_id, 4637 unsigned int writable, 4497 4638 fat_cache_desc_t** desc ) 4498 4639 { 4499 // get cache pointer and levels4500 fat_cache_node_t* node; // pointer on a 64-tree node4501 unsigned int level; // cache level4502 4503 if ( inode == NULL ) // searched cache is the Fat-Cache4504 {4505 node = _fat.fat_cache_root;4506 level = _fat.fat_cache_levels;4507 4640 4508 4641 #if (GIET_DEBUG_FAT & 1) 4509 4642 if ( _get_proctime() > GIET_DEBUG_FAT ) 4510 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): enters in FAT-Cache" 4511 " for cluster = %d\n", cluster ); 4512 #endif 4513 } 4514 else // searched cache is a File-Cache 4515 { 4516 // add cache levels if needed 4517 while ( _get_levels_from_size( (cluster + 1) * 4096 ) > inode->levels ) 4518 { 4643 _printf("\n[DEBUG FAT] _get_file_cache_buffer(): enters in File-Cache <%s>" 4644 " for cluster_id = %d\n size = %x / cache = %x / desc[%d] = %x\n", 4645 inode->name , cluster_id , 4646 inode->size , (unsigned int)inode->cache , cluster_id , 4647 (unsigned int)inode->cache->children[cluster_id] ); 4648 #endif 4649 4650 // checking FAT initialized 4651 if( _fat.initialized != FAT_INITIALIZED ) 4652 { 4653 _printf("\n[FAT ERROR] in _get_file_cache_buffer() : FAT not initialized\n"); 4654 return GIET_FAT32_NOT_INITIALIZED; 4655 } 4656 4657 // checking arguments 4658 if ( inode == NULL ) // illegal inode argument 4659 { 4660 _printf("\n[FAT ERROR] in _get_file_cache_buffer() : illegal inode argument\n"); 4661 return GIET_FAT32_INVALID_ARG; 4662 } 4663 4664 // add cache levels if needed 4665 while ( _get_levels_from_size( (cluster_id + 1) * 4096 ) > inode->levels ) 4666 { 4667 4519 4668 #if (GIET_DEBUG_FAT & 1) 4520 4669 if ( _get_proctime() > GIET_DEBUG_FAT ) 4521 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): adding a File-Cache level\n" ); 4522 #endif 4523 4524 inode->cache = _allocate_one_cache_node( inode->cache ); 4525 inode->levels++; 4526 } 4527 4528 node = inode->cache; 4529 level = inode->levels; 4530 4531 #if (GIET_DEBUG_FAT & 1) 4532 if ( _get_proctime() > GIET_DEBUG_FAT ) 4533 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): enters in File-Cache <%s>" 4534 " for cluster = %d\n", inode->name , cluster ); 4535 #endif 4536 } 4670 _printf("\n[DEBUG FAT] _get_file_cache_buffer() : add a File-Cache level\n" ); 4671 #endif 4672 4673 inode->cache = _allocate_one_cache_node( inode->cache ); 4674 inode->levels++; 4675 } 4676 4677 // get File-Cache 4678 fat_cache_node_t* node = inode->cache; 4679 unsigned int level = inode->levels; 4680 4537 4681 4538 4682 // search the 64-tree cache from top to bottom … … 4540 4684 { 4541 4685 // compute child index at each level 4542 unsigned int index = (cluster >> (6*(level-1))) & 0x3F; 4543 4544 if ( level == 1 ) // last level => children are cluster descriptors 4545 { 4546 fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index]; 4547 4548 if ( pdesc == NULL ) // miss 4686 unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F; 4687 4688 if ( level == 1 ) // last level => children are buffer descriptors 4689 { 4690 fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index]; 4691 unsigned int current = inode->cluster; 4692 unsigned int next = 0; 4693 unsigned int prev = 0; 4694 unsigned int cid; 4695 unsigned int lba; 4696 4697 if ( pdesc == NULL ) // miss in File-Cache 4549 4698 { 4550 // get missing cluster index lba 4551 unsigned int lba; 4552 unsigned int next; 4553 unsigned int current = inode->cluster; 4554 unsigned int count = cluster; 4555 4556 if ( inode == NULL ) // searched cache is the Fat-Cache 4699 4700 #if (GIET_DEBUG_FAT & 1) 4701 if ( _get_proctime() > GIET_DEBUG_FAT ) 4702 _printf("\n[DEBUG FAT] _get_file_cache_buffer() : miss in cache <%s> for cluster_id = %d\n" 4703 " cluster = %x / size = %x / cache = %x / desc[%d] = %x\n", 4704 inode->name , cluster_id , inode-> cluster , inode->size , 4705 (unsigned int)inode->cache , cluster_id , 4706 (unsigned int)inode->cache->children[cluster_id] ); 4707 #endif 4708 if ( inode->size > (cluster_id<<12) ) // all clusters allocated in FAT 4557 4709 { 4558 4559 #if (GIET_DEBUG_FAT & 1) 4560 if ( _get_proctime() > GIET_DEBUG_FAT ) 4561 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): miss in FAT-Cache for cluster %d\n", 4562 cluster ); 4563 #endif 4564 lba = _fat.fat_lba + (cluster << 3); 4565 } 4566 else // searched cache is a File-Cache 4567 { 4568 4569 #if (GIET_DEBUG_FAT & 1) 4570 if ( _get_proctime() > GIET_DEBUG_FAT ) 4571 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): miss in File-Cache <%s> " 4572 "for cluster %d\n", inode->name, cluster ); 4573 #endif 4574 while ( count ) 4575 { 4710 // scan the FAT to find the cluster index for cluster_id 4711 for ( cid = 0 ; cid < cluster_id ; cid++ ) 4712 { 4713 // get next cluster index from FAT 4576 4714 if ( _get_fat_entry( current , &next ) ) return 1; 4577 4715 current = next; 4578 count--;4579 4716 } 4717 4718 // compute lba 4580 4719 lba = _cluster_to_lba( current ); 4720 4721 // allocate a 4 Kbytes buffer and a buffer descriptor 4722 // the selected heap depends on the calling thread 4723 void* buf = _malloc( 4096 ); 4724 pdesc = _malloc( sizeof(fat_cache_desc_t) ); 4725 4726 // set buffer descriptor 4727 pdesc->lba = lba; 4728 pdesc->buffer = buf; 4729 pdesc->dirty = writable; 4730 node->children[index] = pdesc; 4731 4732 // load cluster from device 4733 if ( _fat_ioc_access( 1, // descheduling 4734 1, // to memory 4735 lba, 4736 (unsigned int)buf, 4737 8 ) ) 4738 { 4739 4740 _free( buf ); 4741 _free( pdesc ); 4742 _printf("\n[FAT ERROR] in _get_file_cache_buffer() : " 4743 "cannot access block device for lba = %x\n", lba ); 4744 return GIET_FAT32_IO_ERROR; 4745 } 4581 4746 } 4582 4583 // allocate a 4 Kbytes buffer in cluster running the calling thread 4584 void* buf = _malloc( 4096 ); 4585 4586 // load one cluster (8 blocks) from block device 4587 if ( _fat_ioc_access( 1, // descheduling 4588 1, // to memory 4589 lba, 4590 (unsigned int)buf, 4591 8 ) ) 4747 else if ( writable == 0 ) 4592 4748 { 4593 _free( buf ); 4594 _printf("\n[FAT ERROR] _fat_buffer_from_cache()" 4595 ": cannot access block device for lba = %x\n", lba ); 4596 return 1; 4749 _printf("\n[FAT ERROR] in _get_file_cache_buffer() : " 4750 " file size too small for <%s>\n" 4751 " size = %x / cluster_id = %d / procid = %x\n", 4752 inode->name , inode->size , cluster_id , _get_procid() ); 4753 return GIET_FAT32_IO_ERROR; 4597 4754 } 4598 4599 // allocate buffer descriptor 4600 pdesc = _malloc( sizeof(fat_cache_desc_t) ); 4601 pdesc->lba = lba; 4602 pdesc->buffer = buf; 4603 pdesc->dirty = 0; 4604 node->children[index] = pdesc; 4605 4606 #if (GIET_DEBUG_FAT & 1) 4607 if ( _get_proctime() > GIET_DEBUG_FAT ) 4608 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): buffer loaded from device" 4609 " at vaddr = %x\n", (unsigned int)buf ); 4610 #endif 4755 else // writable and all clusters NOT allocated in FAT 4756 { 4757 // scan the FAT to allocate all required clusters 4758 for ( cid = 0 ; cid <= cluster_id ; cid++ ) 4759 { 4760 if ( current >= END_OF_CHAIN_CLUSTER_MIN ) // non allocated 4761 { 4762 // allocate one cluster on device 4763 if ( _cluster_allocate( inode , ¤t ) ) 4764 { 4765 _printf("\n[FAT ERROR] in _get_file_cache_buffer() : " 4766 "cannot allocate new cluster for file <%s>\n", 4767 inode->name ); 4768 return GIET_FAT32_IO_ERROR; 4769 } 4770 } 4771 4772 // get next cluster index from FAT 4773 if ( _get_fat_entry( current , &next ) ) 4774 { 4775 _printf("\n[FAT ERROR] in _get_file_cache_buffer() : " 4776 "cannot get next cluster for file <%s>\n", 4777 inode->name ); 4778 return GIET_FAT32_IO_ERROR; 4779 } 4780 prev = current; 4781 current = next; 4782 } 4783 4784 // update size in inode and directory entry 4785 inode->size = (cluster_id + 1)<<12; 4786 _update_dir_entry( inode ); 4787 4788 // compute lba 4789 lba = _cluster_to_lba( current ); 4790 4791 // allocate a 4 Kbytes buffer and a buffer descriptor 4792 // the selected heap depends on the calling thread 4793 void* buf = _malloc( 4096 ); 4794 pdesc = _malloc( sizeof(fat_cache_desc_t) ); 4795 4796 // set buffer descriptor 4797 pdesc->lba = lba; 4798 pdesc->buffer = buf; 4799 pdesc->dirty = writable; 4800 node->children[index] = pdesc; 4801 } 4611 4802 } 4612 4803 … … 4614 4805 *desc = pdesc; 4615 4806 4807 #if (GIET_DEBUG_FAT & 1) 4808 if ( _get_proctime() > GIET_DEBUG_FAT ) 4809 _printf("\n[DEBUG FAT] _fat_buffer_from_cache(): found buffer = %x " 4810 " in file <%s> for cluster_id %d\n", 4811 (unsigned int)pdesc->buffer , inode->name , cluster_id ); 4812 #endif 4616 4813 // prepare next iteration 4617 4814 level--; … … 4633 4830 } // end while 4634 4831 4635 return 0; 4636 } // end _fat_buffer_from_cache() 4637 4638 4639 4832 return GIET_FAT32_OK; 4833 4834 } // end _get_file_cache_buffer() 4640 4835 4641 4836 // Local Variables:
Note: See TracChangeset
for help on using the changeset viewer.