- Timestamp:
- Dec 3, 2018, 12:15:53 PM (6 years ago)
- Location:
- trunk/kernel/fs
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/fs/devfs.c
r598 r602 86 86 87 87 ///////////////////////////////////////////////// 88 void devfs_global_init( xptr_t parent_inode_xp,88 void devfs_global_init( xptr_t root_inode_xp, 89 89 xptr_t * devfs_dev_inode_xp, 90 90 xptr_t * devfs_external_inode_xp ) 91 91 { 92 92 error_t error; 93 xptr_t unused_xp; // required by vfs_add_child_in_parent() 93 94 94 95 // creates DEVFS "dev" inode in cluster 0 … … 96 97 INODE_TYPE_DIR, 97 98 FS_TYPE_DEVFS, 98 parent_inode_xp,99 root_inode_xp, 99 100 "dev", 100 NULL,101 devfs_dev_inode_xp ); 101 &unused_xp, 102 devfs_dev_inode_xp ); 102 103 103 104 assert( (error == 0) , "cannot create <dev>\n" ); … … 117 118 *devfs_dev_inode_xp, 118 119 "external", 119 NULL,120 devfs_external_inode_xp ); 120 &unused_xp, 121 devfs_external_inode_xp ); 121 122 122 123 assert( (error == 0) , "cannot create <external>\n" ); … … 129 130 #endif 130 131 131 } 132 } // end devfs_global_init() 132 133 133 134 /////////////////////////////////////////////////// … … 141 142 chdev_t * chdev_ptr; 142 143 xptr_t inode_xp; 144 cxy_t inode_cxy; 145 vfs_inode_t * inode_ptr; 143 146 uint32_t channel; 147 xptr_t unused_xp; // required by add_child_in_parent() 144 148 145 149 // create "internal" directory … … 150 154 devfs_dev_inode_xp, 151 155 node_name, 152 NULL,156 &unused_xp, 153 157 devfs_internal_inode_xp ); 154 158 #if DEBUG_DEVFS_INIT … … 164 168 if( chdev_xp != XPTR_NULL) 165 169 { 166 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );170 chdev_ptr = GET_PTR( chdev_xp ); 167 171 vfs_add_child_in_parent( local_cxy, 168 172 INODE_TYPE_DEV, … … 170 174 *devfs_internal_inode_xp, 171 175 chdev_ptr->name, 172 GET_PTR( chdev_xp ),176 &unused_xp, 173 177 &inode_xp ); 178 179 // update child inode "extend" field 180 inode_cxy = GET_CXY( inode_xp ); 181 inode_ptr = GET_PTR( inode_xp ); 182 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 183 174 184 #if DEBUG_DEVFS_INIT 175 185 cycle = (uint32_t)hal_get_cycles(); … … 184 194 for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ ) 185 195 { 186 chdev_xp = chdev_dir.dma[channel];196 chdev_xp = chdev_dir.dma[channel]; 187 197 if( chdev_xp != XPTR_NULL) 188 198 { 189 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );199 chdev_ptr = GET_PTR( chdev_xp ); 190 200 vfs_add_child_in_parent( local_cxy, 191 201 INODE_TYPE_DEV, … … 193 203 *devfs_internal_inode_xp, 194 204 chdev_ptr->name, 195 GET_PTR( chdev_xp ),205 &unused_xp, 196 206 &inode_xp ); 207 208 // update child inode "extend" field 209 inode_cxy = GET_CXY( inode_xp ); 210 inode_ptr = GET_PTR( inode_xp ); 211 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 212 197 213 #if DEBUG_DEVFS_INIT 198 214 cycle = (uint32_t)hal_get_cycles(); … … 209 225 { 210 226 chdev_cxy = GET_CXY( chdev_xp ); 211 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );227 chdev_ptr = GET_PTR( chdev_xp ); 212 228 if( chdev_cxy == local_cxy ) 213 229 { … … 217 233 devfs_external_inode_xp, 218 234 chdev_ptr->name, 219 GET_PTR( chdev_xp ),235 &unused_xp, 220 236 &inode_xp ); 237 238 // update child inode "extend" field 239 inode_cxy = GET_CXY( inode_xp ); 240 inode_ptr = GET_PTR( inode_xp ); 241 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 242 221 243 #if DEBUG_DEVFS_INIT 222 244 cycle = (uint32_t)hal_get_cycles(); … … 233 255 { 234 256 chdev_cxy = GET_CXY( chdev_xp ); 235 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );257 chdev_ptr = GET_PTR( chdev_xp ); 236 258 if( chdev_cxy == local_cxy ) 237 259 { … … 241 263 devfs_external_inode_xp, 242 264 chdev_ptr->name, 243 GET_PTR( chdev_xp ),265 &unused_xp, 244 266 &inode_xp ); 267 268 // update child inode "extend" field 269 inode_cxy = GET_CXY( inode_xp ); 270 inode_ptr = GET_PTR( inode_xp ); 271 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 272 245 273 #if DEBUG_DEVFS_INIT 246 274 cycle = (uint32_t)hal_get_cycles(); … … 256 284 { 257 285 chdev_xp = chdev_dir.txt_rx[channel]; 286 if( chdev_xp != XPTR_NULL ) 287 { 288 chdev_cxy = GET_CXY( chdev_xp ); 289 chdev_ptr = GET_PTR( chdev_xp ); 290 if( chdev_cxy == local_cxy ) 291 { 292 vfs_add_child_in_parent( local_cxy, 293 INODE_TYPE_DEV, 294 FS_TYPE_DEVFS, 295 devfs_external_inode_xp, 296 chdev_ptr->name, 297 &unused_xp, 298 &inode_xp ); 299 300 // update child inode "extend" field 301 inode_cxy = GET_CXY( inode_xp ); 302 inode_ptr = GET_PTR( inode_xp ); 303 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 304 305 #if DEBUG_DEVFS_INIT 306 cycle = (uint32_t)hal_get_cycles(); 307 if( DEBUG_DEVFS_INIT < cycle ) 308 printk("\n[%s] thread[%x,%x] created <txt_rx[%d]> inode in cluster %x\n", 309 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 310 #endif 311 } 312 } 313 } 314 315 // create a TXT_TX inode in each cluster containing a TXT_TX chdev 316 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ ) 317 { 318 chdev_xp = chdev_dir.txt_tx[channel]; 319 if( chdev_xp != XPTR_NULL ) 320 { 321 chdev_cxy = GET_CXY( chdev_xp ); 322 chdev_ptr = GET_PTR( chdev_xp ); 323 if( chdev_cxy == local_cxy ) 324 { 325 vfs_add_child_in_parent( local_cxy, 326 INODE_TYPE_DEV, 327 FS_TYPE_DEVFS, 328 devfs_external_inode_xp, 329 chdev_ptr->name, 330 &unused_xp, 331 &inode_xp ); 332 333 // update child inode "extend" field 334 inode_cxy = GET_CXY( inode_xp ); 335 inode_ptr = GET_PTR( inode_xp ); 336 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 337 338 #if DEBUG_DEVFS_INIT 339 cycle = (uint32_t)hal_get_cycles(); 340 if( DEBUG_DEVFS_INIT < cycle ) 341 printk("\n[%s] thread[%x,%x] created <txt_tx[%d]> inode in cluster %x\n", 342 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 343 #endif 344 } 345 } 346 } 347 348 // create an IOC inode in each cluster containing an IOC chdev 349 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) 350 { 351 chdev_xp = chdev_dir.ioc[channel]; 352 if( chdev_xp != XPTR_NULL ) 353 { 354 chdev_cxy = GET_CXY( chdev_xp ); 355 chdev_ptr = GET_PTR( chdev_xp ); 356 if( chdev_cxy == local_cxy ) 357 { 358 vfs_add_child_in_parent( local_cxy, 359 INODE_TYPE_DEV, 360 FS_TYPE_DEVFS, 361 devfs_external_inode_xp, 362 chdev_ptr->name, 363 &unused_xp, 364 &inode_xp ); 365 366 // update child inode "extend" field 367 inode_cxy = GET_CXY( inode_xp ); 368 inode_ptr = GET_PTR( inode_xp ); 369 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 370 371 #if DEBUG_DEVFS_INIT 372 cycle = (uint32_t)hal_get_cycles(); 373 if( DEBUG_DEVFS_INIT < cycle ) 374 printk("\n[%s] thread[%x,%x] created <ioc[%d]> inode in cluster %x\n", 375 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 376 #endif 377 } 378 } 379 } 380 381 // create a FBF inode in each cluster containing a FBF chdev 382 for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ ) 383 { 384 chdev_xp = chdev_dir.fbf[channel]; 385 if( chdev_xp != XPTR_NULL ) 386 { 387 chdev_cxy = GET_CXY( chdev_xp ); 388 chdev_ptr = GET_PTR( chdev_xp ); 389 if( chdev_cxy == local_cxy ) 390 { 391 vfs_add_child_in_parent( local_cxy, 392 INODE_TYPE_DEV, 393 FS_TYPE_DEVFS, 394 devfs_external_inode_xp, 395 chdev_ptr->name, 396 &unused_xp, 397 &inode_xp ); 398 399 // update child inode "extend" field 400 inode_cxy = GET_CXY( inode_xp ); 401 inode_ptr = GET_PTR( inode_xp ); 402 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 403 404 #if DEBUG_DEVFS_INIT 405 cycle = (uint32_t)hal_get_cycles(); 406 if( DEBUG_DEVFS_INIT < cycle ) 407 printk("\n[%s] thread[%x,%x] created <fbf[%d]> inode in cluster %x\n", 408 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 409 #endif 410 } 411 } 412 } 413 414 // create a NIC_RX inode in each cluster containing a NIC_RX chdev 415 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 416 { 417 chdev_xp = chdev_dir.nic_rx[channel]; 258 418 if( chdev_xp != XPTR_NULL ) 259 419 { … … 267 427 devfs_external_inode_xp, 268 428 chdev_ptr->name, 269 GET_PTR( chdev_xp ),429 &unused_xp, 270 430 &inode_xp ); 271 431 #if DEBUG_DEVFS_INIT 272 432 cycle = (uint32_t)hal_get_cycles(); 273 433 if( DEBUG_DEVFS_INIT < cycle ) 274 printk("\n[%s] thread[%x,%x] created < txt_rx[%d]> inode in cluster %x\n",434 printk("\n[%s] thread[%x,%x] created <nic_rx[%d]> inode in cluster %x\n", 275 435 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 276 436 #endif … … 279 439 } 280 440 281 // create a TXT_TX inode in each cluster containing a TXT_TX chdev282 for( channel = 0 ; channel < CONFIG_MAX_ TXT_CHANNELS ; channel++ )283 { 284 chdev_xp = chdev_dir. txt_tx[channel];441 // create a NIC_TX inode in each cluster containing a NIC_TX chdev 442 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 443 { 444 chdev_xp = chdev_dir.nic_tx[channel]; 285 445 if( chdev_xp != XPTR_NULL ) 286 446 { 287 447 chdev_cxy = GET_CXY( chdev_xp ); 288 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );448 chdev_ptr = GET_PTR( chdev_xp ); 289 449 if( chdev_cxy == local_cxy ) 290 450 { … … 294 454 devfs_external_inode_xp, 295 455 chdev_ptr->name, 296 GET_PTR( chdev_xp ),456 &unused_xp, 297 457 &inode_xp ); 298 #if DEBUG_DEVFS_INIT 299 cycle = (uint32_t)hal_get_cycles(); 300 if( DEBUG_DEVFS_INIT < cycle ) 301 printk("\n[%s] thread[%x,%x] created <txt_tx[%d]> inode in cluster %x\n", 302 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 303 #endif 304 } 305 } 306 } 307 308 // create an IOC inode in each cluster containing an IOC chdev 309 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) 310 { 311 chdev_xp = chdev_dir.ioc[channel]; 312 if( chdev_xp != XPTR_NULL ) 313 { 314 chdev_cxy = GET_CXY( chdev_xp ); 315 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp ); 316 if( chdev_cxy == local_cxy ) 317 { 318 vfs_add_child_in_parent( local_cxy, 319 INODE_TYPE_DEV, 320 FS_TYPE_DEVFS, 321 devfs_external_inode_xp, 322 chdev_ptr->name, 323 GET_PTR( chdev_xp ), 324 &inode_xp ); 325 #if DEBUG_DEVFS_INIT 326 cycle = (uint32_t)hal_get_cycles(); 327 if( DEBUG_DEVFS_INIT < cycle ) 328 printk("\n[%s] thread[%x,%x] created <ioc[%d]> inode in cluster %x\n", 329 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 330 #endif 331 } 332 } 333 } 334 335 // create a FBF inode in each cluster containing a FBF chdev 336 for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ ) 337 { 338 chdev_xp = chdev_dir.fbf[channel]; 339 if( chdev_xp != XPTR_NULL ) 340 { 341 chdev_cxy = GET_CXY( chdev_xp ); 342 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp ); 343 if( chdev_cxy == local_cxy ) 344 { 345 vfs_add_child_in_parent( local_cxy, 346 INODE_TYPE_DEV, 347 FS_TYPE_DEVFS, 348 devfs_external_inode_xp, 349 chdev_ptr->name, 350 GET_PTR( chdev_xp ), 351 &inode_xp ); 352 #if DEBUG_DEVFS_INIT 353 cycle = (uint32_t)hal_get_cycles(); 354 if( DEBUG_DEVFS_INIT < cycle ) 355 printk("\n[%s] thread[%x,%x] created <fbf[%d]> inode in cluster %x\n", 356 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 357 #endif 358 } 359 } 360 } 361 362 // create a NIC_RX inode in each cluster containing a NIC_RX chdev 363 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 364 { 365 chdev_xp = chdev_dir.nic_rx[channel]; 366 if( chdev_xp != XPTR_NULL ) 367 { 368 chdev_cxy = GET_CXY( chdev_xp ); 369 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp ); 370 if( chdev_cxy == local_cxy ) 371 { 372 vfs_add_child_in_parent( local_cxy, 373 INODE_TYPE_DEV, 374 FS_TYPE_DEVFS, 375 devfs_external_inode_xp, 376 chdev_ptr->name, 377 GET_PTR( chdev_xp ), 378 &inode_xp ); 379 #if DEBUG_DEVFS_INIT 380 cycle = (uint32_t)hal_get_cycles(); 381 if( DEBUG_DEVFS_INIT < cycle ) 382 printk("\n[%s] thread[%x,%x] created <nic_rx[%d]> inode in cluster %x\n", 383 __FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle ); 384 #endif 385 } 386 } 387 } 388 389 // create a NIC_TX inode in each cluster containing a NIC_TX chdev 390 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) 391 { 392 chdev_xp = chdev_dir.nic_tx[channel]; 393 if( chdev_xp != XPTR_NULL ) 394 { 395 chdev_cxy = GET_CXY( chdev_xp ); 396 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp ); 397 if( chdev_cxy == local_cxy ) 398 { 399 vfs_add_child_in_parent( local_cxy, 400 INODE_TYPE_DEV, 401 FS_TYPE_DEVFS, 402 devfs_external_inode_xp, 403 chdev_ptr->name, 404 GET_PTR( chdev_xp ), 405 &inode_xp ); 458 459 // update child inode "extend" field 460 inode_cxy = GET_CXY( inode_xp ); 461 inode_ptr = GET_PTR( inode_xp ); 462 hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr ); 463 406 464 #if DEBUG_DEVFS_INIT 407 465 cycle = (uint32_t)hal_get_cycles(); … … 462 520 channel = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) ); 463 521 522 // Only TXT devices are associated to a pseudo-file 464 523 assert( ( func == DEV_FUNC_TXT ) , __FUNCTION__, "illegal device func_type"); 465 524 -
trunk/kernel/fs/fatfs.c
r568 r602 2 2 * fatfs.c - FATFS file system API implementation. 3 3 * 4 * Author Alain Greiner (2016,2017 )4 * Author Alain Greiner (2016,2017,2018) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 42 42 ////////////////////////////////////////////////////////////////////////////////////////// 43 43 44 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in vfs.c file45 46 ////////////////////////////////////////////////////////////////////////////////////////// 47 // FATFS specific andstatic functions44 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in kernel_init.c file 45 46 ////////////////////////////////////////////////////////////////////////////////////////// 47 // FATFS specific static functions 48 48 ////////////////////////////////////////////////////////////////////////////////////////// 49 49 … … 89 89 uint32_t res = 0; 90 90 91 if ( little_endian )91 if ( little_endian ) 92 92 { 93 93 for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1]; 94 94 } 95 else 95 else // big_endian 96 96 { 97 97 for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n]; … … 100 100 101 101 } // end fatfs_get_record() 102 103 ////////////////////////////////////////////////////////////////////////////////////////// 104 // This function writes one, two, or four bytes from a 32 bits integer to a memory buffer, 105 // taking into account endianness. 106 ////////////////////////////////////////////////////////////////////////////////////////// 107 // @ offset : first byte of record in buffer. 108 // @ size : record length in bytes (1/2/4). 109 // @ buffer : pointer on buffer base. 110 // @ little endian : the most significant byte has the highest address when true. 111 // @ return the integer value in a 32 bits word. 112 ////////////////////////////////////////////////////////////////////////////////////////// 113 static void fatfs_set_record( uint32_t offset, 114 uint32_t size, 115 uint8_t * buffer, 116 uint32_t little_endian, 117 uint32_t value ) 118 { 119 uint32_t n; 120 121 if ( little_endian ) 122 { 123 for( n = size ; n > 0 ; n-- ) buffer[offset+n-1] = (uint8_t)(value>>((n-1)<<3)); 124 } 125 else // big_endian 126 { 127 for( n = 0 ; n < size ; n++ ) buffer[offset+n] = (uint8_t)(value>>((size-1-n)<<3)); 128 } 129 130 } // end fatfs_set_record() 102 131 103 132 ////////////////////////////////////////////////////////////////////////////////////////// … … 136 165 137 166 name[j] = '\0'; 138 } 167 168 } // fatfs_get_name_from_short() 139 169 140 170 ////////////////////////////////////////////////////////////////////////////////////////// … … 213 243 name[name_offset] = 0; 214 244 215 } // end get_name_from_long() 245 } // end fatfs_get_name_from_long() 246 247 ////////////////////////////////////////////////////////////////////////////////////////// 248 // This static function analyse the <name> input argument, and returns in other 249 // output arguments various informations required to store the name in FATFS directory. 250 // The <name> length cannot be larger than 31 characters : 251 // - Short name (less than 13 characters) require 1 LFN entry. 252 // - Medium names (from 14 to 26 characters require 2 LFN entries. 253 // - Large names (up to 31 characters) require 3 LFN entries. 254 ////////////////////////////////////////////////////////////////////////////////////////// 255 // @ name : [in] complete directory entry name. 256 // @ length : [out] total number of characters in name. 257 // @ nb_lfn : [out] number of LFN entries required to store the name. 258 // @ sfn : [out] a legal SFN name extracted from name / upper case and 8-3 format. 259 // @ checksum : [out] checksum to be stored in SFN. 260 // @ returns 0 on success / returns 1 if the name length is larger than 31 characters. 261 ////////////////////////////////////////////////////////////////////////////////////////// 262 static error_t fatfs_name_format( const char * name, 263 uint32_t * length, 264 uint32_t * nb_lfn, 265 char * sfn, 266 uint8_t * checksum ) 267 { 268 // compute name length 269 uint32_t name_length = strlen( name ); 270 *length = name_length; 271 272 uint32_t suffix_length = 0; 273 uint32_t prefix_length = 0; 274 uint32_t dot_found = 0; 275 uint32_t i; 276 277 // compute prefix and suffix length 278 // only the last '.' is taken into account 279 for ( i=0 ; i<name_length ; i++ ) 280 { 281 if (name[i] == '.' ) 282 { 283 if ( dot_found ) 284 { 285 prefix_length += suffix_length + 1; 286 suffix_length = 0; 287 } 288 else 289 { 290 dot_found = 1; 291 } 292 } 293 else 294 { 295 if ( dot_found) suffix_length++; 296 else prefix_length++; 297 } 298 } 299 300 // build SFN prefix (8bits) 301 if (prefix_length <= 8) 302 { 303 for( i=0 ; i<8 ; i++) 304 { 305 if ( i<prefix_length ) sfn[i] = to_upper( name[i] ); 306 else sfn[i] = 0x20; 307 } 308 } 309 else 310 { 311 for( i=0 ; i<6 ; i++) 312 { 313 sfn[i] = to_upper( name[i] ); 314 } 315 sfn[6] = 0x7E; 316 sfn[7] = 0x31; 317 } 318 319 // build SFN suffix (3 bits) 320 if ( suffix_length == 0 ) 321 { 322 sfn[8] = 0x20; 323 sfn[9] = 0x20; 324 sfn[10] = 0x20; 325 } 326 else if ( suffix_length == 1 ) 327 { 328 sfn[8] = to_upper( name[name_length-1] ); 329 sfn[9] = 0x20; 330 sfn[10] = 0x20; 331 } 332 else if ( suffix_length == 2 ) 333 { 334 sfn[8] = to_upper( name[name_length-2] ); 335 sfn[9] = to_upper( name[name_length-1] ); 336 sfn[10] = 0x20; 337 } 338 else 339 { 340 sfn[8] = to_upper( name[name_length-suffix_length] ); 341 sfn[9] = to_upper( name[name_length-suffix_length+1] ); 342 sfn[10] = to_upper( name[name_length-suffix_length+2] ); 343 } 344 345 // compute 8 bits checksum 346 uint8_t sum = 0; 347 for ( i=0 ; i<11 ; i++ ) 348 { 349 sum = (((sum & 0x01)<<7) | ((sum & 0xFE)>>1)) + sfn[i]; 350 } 351 *checksum = sum; 352 353 // set nb_lfn and length values 354 if ( name_length <= 13 ) 355 { 356 *nb_lfn = 1; 357 return 0; 358 } 359 else if ( name_length <= 26 ) 360 { 361 *nb_lfn = 2; 362 return 0; 363 } 364 else if ( name_length <= 31 ) 365 { 366 *nb_lfn = 3; 367 return 0; 368 } 369 else 370 { 371 return 1; 372 } 373 } // end fatfs_name_format() 374 375 ////////////////////////////////////////////////////////////////////////////////////////// 376 // This static function - atomically - decrements "free_clusters", and updates 377 // the "free_cluster_hint" shared variables in the FATFS context in the FAT cluster. 378 // It scan the FAT to find the first free slot larger than the <cluster> argument, 379 // and set "free_cluster_hint" <= (free - 1). 380 // 381 // WARNING : The free_lock protecting exclusive access to these variables 382 // must be taken by the calling function. 383 ////////////////////////////////////////////////////////////////////////////////////////// 384 // @ cluster : recently allocated cluster index in FAT. 385 ////////////////////////////////////////////////////////////////////////////////////////// 386 static error_t fatfs_free_clusters_decrement( uint32_t cluster ) 387 { 388 fatfs_ctx_t * loc_ctx; // local pointer on local FATFS context 389 fatfs_ctx_t * fat_ctx; // local pointer on FATFS in cluster containing FAT mapper 390 cxy_t mapper_cxy; // cluster identifier for cluster containing FAT mapper 391 xptr_t mapper_xp; // extended pointer on FAT mapper 392 xptr_t hint_xp; // extended pointer on "free_cluster_hint" shared variable 393 xptr_t numb_xp; // extended pointer on "free_clusters" shared variable 394 uint32_t numb; // "free_clusters" variable current value 395 uint32_t page_id; // page index in FAT mapper 396 uint32_t slot_id; // slot index in one page of FAT (1024 slots per page) 397 uint32_t page_max; // max number of pages in FAT mapper 398 xptr_t page_xp; // extended pointer on current page in FAT mapper 399 xptr_t slot_xp; // extended pointer on current slot in FAT mapper 400 401 #if DEBUG_FATFS_FREE_CLUSTERS 402 uint32_t cycle = (uint32_t)hal_get_cycles(); 403 thread_t * this = CURRENT_THREAD; 404 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() ) 405 printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n", 406 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle ); 407 #endif 408 409 // get local pointer on local FATFS context 410 loc_ctx = fs_context[FS_TYPE_FATFS].extend; 411 412 // get cluster containing FAT mapper 413 mapper_xp = loc_ctx->fat_mapper_xp; 414 mapper_cxy = GET_CXY( mapper_xp ); 415 416 // get local pointer on FATFS context in FAT cluster 417 fat_ctx = hal_remote_lpt( XPTR( mapper_cxy , &fs_context[FS_TYPE_FATFS].extend ) ); 418 419 // build extended pointers on free_clusters, and free_cluster_hint 420 hint_xp = XPTR( mapper_cxy , &fat_ctx->free_cluster_hint ); 421 numb_xp = XPTR( mapper_cxy , &fat_ctx->free_clusters ); 422 423 // update "free_clusters" 424 numb = hal_remote_l32( numb_xp ); 425 hal_remote_s32( numb_xp , numb - 1 ); 426 427 // scan FAT mapper to find the first free slot > cluster 428 // and update "free_cluster_hint" as (free - 1) 429 page_id = (cluster + 1) >> 10; 430 slot_id = (cluster + 1) & 0x3FF; 431 page_max = (loc_ctx->fat_sectors_count >> 3); 432 433 // scan FAT mapper / loop on pages 434 while ( page_id < page_max ) 435 { 436 // get current page from mapper 437 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 438 439 if( page_xp == XPTR_NULL ) 440 { 441 printk("\n[ERROR] in %s : cannot access FAT mapper\n", __FUNCTION__ ); 442 return -1; 443 } 444 445 // scan FAT mapper / loop on slots 446 while ( slot_id < 1024 ) 447 { 448 // get extended pointer on current slot 449 slot_xp = ppm_page2base( page_xp ) + (slot_id << 2); 450 451 // test FAT slot value 452 if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER ) 453 { 454 // update "free_cluster_hint" <= (free - 1) 455 hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 ); 456 457 #if DEBUG_FATFS_FREE_CLUSTERS 458 cycle = (uint32_t)hal_get_cycles(); 459 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() ) 460 printk("\n[%s] thread[%x,%x] exit / hint %x / free_clusters %x / cycle %d\n", 461 __FUNCTION__, this->process->pid, this->trdid, 462 hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle ); 463 #endif 464 return 0; 465 } 466 467 // increment slot_id 468 slot_id++; 469 470 } // end loop on slots 471 472 // update loop variables 473 page_id++; 474 slot_id = 0; 475 476 } // end loop on pages 477 478 // return error if no free cluster found 479 printk("\n[ERROR] in %s : No free cluster found\n", __FUNCTION__ ); 480 return -1; 481 482 } // end fatfs_free_clusters_decrement() 483 484 ////////////////////////////////////////////////////////////////////////////////////////// 485 // This static function atomically increments <free_clusters>, and updates 486 // the <free_cluster_hint> shared variables in the FATFS context in the FAT cluster. 487 // If the released cluster index is smaller than the current (hint + 1) value, 488 // it set "free_cluster_hint" <= cluster - 1. 489 // 490 // WARNING : The free_lock protecting exclusive access to these variables 491 // must be taken by the calling function. 492 ////////////////////////////////////////////////////////////////////////////////////////// 493 // @ cluster : recently released cluster index in FAT. 494 ////////////////////////////////////////////////////////////////////////////////////////// 495 static void fatfs_free_clusters_increment( uint32_t cluster ) 496 { 497 fatfs_ctx_t * loc_ctx; // local pointer on local FATFS context 498 fatfs_ctx_t * fat_ctx; // local pointer on FATFS in cluster containing FAT mapper 499 cxy_t fat_cxy; // cluster identifier for cluster containing FAT mapper 500 xptr_t hint_xp; // extended pointer on "free_cluster_hint" shared variable 501 xptr_t numb_xp; // extended pointer on "free_clusters" shared variable 502 uint32_t hint; // "free_cluster_hint" variable current value 503 uint32_t numb; // "free_clusters" variable current value 504 505 // get local pointer on local FATFS context 506 loc_ctx = fs_context[FS_TYPE_FATFS].extend; 507 508 // get cluster containing FAT mapper 509 fat_cxy = GET_CXY( loc_ctx->fat_mapper_xp ); 510 511 // get local pointer on FATFS context in FAT cluster 512 fat_ctx = hal_remote_lpt( XPTR( fat_cxy , &fs_context[FS_TYPE_FATFS].extend ) ); 513 514 // build extended pointers free_lock, free_clusters, and free_cluster_hint 515 hint_xp = XPTR( fat_cxy , &fat_ctx->free_cluster_hint ); 516 numb_xp = XPTR( fat_cxy , &fat_ctx->free_clusters ); 517 518 // get current value of free_cluster_hint and free_clusters 519 hint = hal_remote_l32( hint_xp ); 520 numb = hal_remote_l32( numb_xp ); 521 522 // update free_cluster_hint if required 523 if ( cluster < (hint + 1) ) hal_remote_s32( hint_xp , (cluster - 1) ); 524 525 // update free_clusters 526 hal_remote_s32( numb_xp , numb + 1 ); 527 528 #if DEBUG_FATFS_FREE_CLUSTERS 529 thread_t * this = CURRENT_THREAD; 530 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() ) 531 printk("\n[%s] thread[%x,%x] updates free cluster info : hint %x / number %x\n", 532 __FUNCTION__, this->process->pid, this->trdid, 533 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) ); 534 #endif 535 536 } // end fatfs_free_clusters_increment() 537 538 ////////////////////////////////////////////////////////////////////////////////////////// 539 // This recursive function is called by the generic function fatfs_release_all_clusters() 540 // It release all clusters allocated to a given inode in the FAT mapper. 541 // The removal is done in reverse order of the linked list (from last to first). 542 // It does NOT update the FS on the IOC device. 543 ////////////////////////////////////////////////////////////////////////////////////////// 544 // @ fat_mapper_xp : extended pointer on FAT mapper. 545 // @ cluster : cluster index in FAT. 546 // @ return 0 if success / return -1 if error (cannot access FAT) 547 ////////////////////////////////////////////////////////////////////////////////////////// 548 static error_t fatfs_recursive_release( xptr_t fat_mapper_xp, 549 uint32_t cluster ) 550 { 551 uint32_t next; 552 553 // get next cluster from FAT mapper 554 if ( mapper_remote_get_32( fat_mapper_xp , cluster , &next ) ) return -1; 555 556 #if (DEBUG_FATFS_RELEASE_INODE & 1) 557 thread_t * this = CURRENT_THREAD; 558 if ( DEBUG_FATFS_RELEASE_INODE < (uint32_t)hal_get_cycles() ) 559 printk("\n[%s] thread[%x,%x] access FAT for cluster %x / next %x\n", 560 __FUNCTION__, this->process->pid, this->trdid, cluster, next ); 561 #endif 562 563 if ( next < END_OF_CHAIN_CLUSTER_MIN ) // non terminal case 564 { 565 // call fatfs_recursive_release() on next cluster 566 if ( fatfs_recursive_release( fat_mapper_xp , next ) ) return -1; 567 } 568 569 // update current cluster in FAT mapper 570 if ( mapper_remote_set_32( fat_mapper_xp, cluster , FREE_CLUSTER ) ) return -1; 571 572 // Update free_cluster_hint and free_clusters in FAT context 573 fatfs_free_clusters_increment( cluster ); 574 575 return 0; 576 577 } // end fatfs_recursive_release() 216 578 217 579 … … 220 582 ////////////////////////////////////////////////////////////////////////////////////////// 221 583 222 ////////////////////////////// ////////////////////////////////////////////////////////////584 ////////////////////////////// 223 585 void fatfs_ctx_display( void ) 224 586 { 587 // get pointer on local FATFS context 225 588 vfs_ctx_t * vfs_ctx = &fs_context[FS_TYPE_FATFS]; 226 589 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; 227 590 228 591 printk("\n*** FAT context ***\n" 229 "- fat_sectors = %d\n" 230 "- sector size = %d\n" 231 "- cluster size = %d\n" 232 "- fat_first_lba = %d\n" 233 "- data_first_lba = %d\n" 234 "- root_dir_cluster = %d\n" 235 "- mapper_xp = %l\n", 592 "- fat_sectors = %d\n" 593 "- sector size = %d\n" 594 "- cluster size = %d\n" 595 "- fat_first_lba = %d\n" 596 "- data_first_lba = %d\n" 597 "- root_dir_cluster = %d\n" 598 "- free_clusters = %d\n" 599 "- free_cluster_hint = %d\n" 600 "- fat_mapper_xp = %l\n", 236 601 fatfs_ctx->fat_sectors_count, 237 602 fatfs_ctx->bytes_per_sector, … … 240 605 fatfs_ctx->cluster_begin_lba, 241 606 fatfs_ctx->root_dir_cluster, 607 fatfs_ctx->free_clusters, 608 fatfs_ctx->free_cluster_hint, 242 609 fatfs_ctx->fat_mapper_xp ); 243 } 244 245 ///////////////////////////////////////////// 246 error_t fatfs_get_cluster( mapper_t * mapper, 247 uint32_t first_cluster_id, 610 611 } // end fatfs_ctx_display() 612 613 ////////////////////////////////////////// 614 void fatfs_display_fat( uint32_t page_id, 615 uint32_t nentries ) 616 { 617 uint32_t line; 618 uint32_t maxline; 619 620 // copute numner of lines to display 621 maxline = nentries >> 3; 622 if( nentries & 0x7 ) maxline++; 623 624 // get pointer on local FATFS context 625 vfs_ctx_t * vfs_ctx = &fs_context[FS_TYPE_FATFS]; 626 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; 627 628 // get extended pointer on FAT mapper 629 xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp; 630 631 // get extended pointer and cluster of FAT mapper requested page 632 xptr_t page_xp = mapper_remote_get_page( fat_mapper_xp , page_id ); 633 634 // get extended pointer on requested page base 635 xptr_t base_xp = ppm_page2base( page_xp ); 636 637 printk("\n***** FAT content / page %d *****\n", page_id ); 638 for( line = 0 ; line < maxline ; line++ ) 639 { 640 printk("%x : %X | %X | %X | %X | %X | %X | %X | %X\n", (line<<3), 641 hal_remote_l32( base_xp + ((line<<5) ) ), 642 hal_remote_l32( base_xp + ((line<<5) + 4 ) ), 643 hal_remote_l32( base_xp + ((line<<5) + 8 ) ), 644 hal_remote_l32( base_xp + ((line<<5) + 12 ) ), 645 hal_remote_l32( base_xp + ((line<<5) + 16 ) ), 646 hal_remote_l32( base_xp + ((line<<5) + 20 ) ), 647 hal_remote_l32( base_xp + ((line<<5) + 24 ) ), 648 hal_remote_l32( base_xp + ((line<<5) + 28 ) ) ); 649 } 650 651 } // end fatfs_display_fat() 652 653 /////////////////////////////////////////////////////// 654 error_t fatfs_get_cluster( uint32_t first_cluster_id, 248 655 uint32_t searched_page_index, 249 656 uint32_t * searched_cluster_id ) 250 657 { 251 page_t * current_page_desc;// pointer on current page descriptor252 uint32_t * current_page_buffer;// pointer on current page (array of uint32_t)658 xptr_t current_page_xp; // pointer on current page descriptor 659 uint32_t * buffer; // pointer on current page (array of uint32_t) 253 660 uint32_t current_page_index; // index of current page in FAT 254 661 uint32_t current_page_offset; // offset of slot in current page … … 256 663 uint32_t next_cluster_id; // content of current FAT slot 257 664 258 259 665 assert( (searched_page_index > 0) , 666 "no FAT access required for first page\n"); 260 667 261 668 #if DEBUG_FATFS_GET_CLUSTER 262 uint32_t cycle = (uint32_t)hal_get_cycles(); 669 uint32_t cycle = (uint32_t)hal_get_cycles(); 670 thread_t * this = CURRENT_THREAD; 263 671 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 264 printk("\n[DBG] %s : thread %x enter / first_cluster_id %d / searched_index / cycle %d\n", 265 __FUNCTION__, CURRENT_THREAD, first_cluster_id, searched_page_index, cycle ); 266 #endif 267 268 // get number of FAT slots per page 269 uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2; 270 271 // initialize loop variable 272 current_page_index = first_cluster_id / slots_per_page; 273 current_page_offset = first_cluster_id % slots_per_page; 672 printk("\n[%s] thread[%x,%x] enter / first_cluster_id %d / searched_index / cycle %d\n", 673 __FUNCTION__, this->process->pid, this->trdid, first_cluster_id, searched_page_index, cycle ); 674 #endif 675 676 // get local pointer on local FATFS context 677 fatfs_ctx_t * ctx = fs_context[FS_TYPE_FATFS].extend; 678 679 // get extended pointer and cluster on FAT mapper 680 xptr_t mapper_xp = ctx->fat_mapper_xp; 681 cxy_t mapper_cxy = GET_CXY( mapper_xp ); 682 683 // initialize loop variable (1024 slots per page) 684 current_page_index = first_cluster_id >> 10; 685 current_page_offset = first_cluster_id & 0x3FF; 274 686 page_count_in_file = 0; 275 687 next_cluster_id = 0xFFFFFFFF; … … 279 691 { 280 692 // get pointer on current page descriptor 281 current_page_desc = mapper_get_page( mapper , current_page_index ); 282 283 if( current_page_desc == NULL ) return EIO; 693 current_page_xp = mapper_remote_get_page( mapper_xp , current_page_index ); 694 695 if( current_page_xp == XPTR_NULL ) 696 { 697 // TODO 698 return -1; 699 } 284 700 285 701 // get pointer on buffer for current page 286 xptr_t base_xp = ppm_page2base( XPTR( local_cxy , current_page_desc ));287 current_page_buffer = (uint32_t *)GET_PTR( base_xp );702 xptr_t base_xp = ppm_page2base( current_page_xp ); 703 buffer = (uint32_t *)GET_PTR( base_xp ); 288 704 289 705 // get FAT slot content 290 next_cluster_id = current_page_buffer[current_page_offset];706 next_cluster_id = hal_remote_l32( XPTR( mapper_cxy , &buffer[current_page_offset] ) ); 291 707 292 708 #if (DEBUG_FATFS_GET_CLUSTER & 1) 293 709 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 294 printk("\n[ DBG] %s :traverse FAT / current_page_index = %d\n"710 printk("\n[%s] traverse FAT / current_page_index = %d\n" 295 711 "current_page_offset = %d / next_cluster_id = %d\n", 296 712 __FUNCTION__, current_page_index, current_page_offset , next_cluster_id ); … … 298 714 299 715 // update loop variables 300 current_page_index = next_cluster_id / slots_per_page;301 current_page_offset = next_cluster_id % slots_per_page;716 current_page_index = next_cluster_id >> 10; 717 current_page_offset = next_cluster_id & 0x3FF; 302 718 page_count_in_file++; 303 719 } 304 720 305 if( next_cluster_id == 0xFFFFFFFF ) return EIO;721 if( next_cluster_id == 0xFFFFFFFF ) return -1; 306 722 307 723 #if DEBUG_FATFS_GET_CLUSTER 308 724 cycle = (uint32_t)hal_get_cycles(); 309 725 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 310 printk("\n[ DBG] %s : thread %xexit / searched_cluster_id = %d / cycle %d\n",311 __FUNCTION__, CURRENT_THREAD, next_cluster_id / cycle );726 printk("\n[%s] thread[%x,%x] exit / searched_cluster_id = %d / cycle %d\n", 727 __FUNCTION__, this->process->pid, this->trdid, next_cluster_id / cycle ); 312 728 #endif 313 729 … … 320 736 321 737 /////////////////////////////////////////////////////////////////////////////////////// 322 // Generic API : the following functions are called by the kernel (VFS)738 // Generic API : the following functions are called by the kernel VFS 323 739 // and must be defined by all supported file systems. 324 740 /////////////////////////////////////////////////////////////////////////////////////// … … 342 758 uint8_t * buffer; 343 759 344 #if DEBUG_FATFS_ INIT760 #if DEBUG_FATFS_CTX_INIT 345 761 uint32_t cycle = (uint32_t)hal_get_cycles(); 346 if( DEBUG_FATFS_INIT < cycle ) 347 printk("\n[DBG] %s : thread %x enter for fatfs_ctx = %x / cycle %d\n", 348 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx , cycle ); 349 #endif 350 351 assert( (fatfs_ctx != NULL) , 352 "cannot allocate memory for FATFS context\n" ); 762 if( DEBUG_FATFS_CTX_INIT < cycle ) 763 printk("\n[%s] thread[%x,%x] enter for fatfs_ctx = %x / cycle %d\n", 764 __FUNCTION__ , this->process->pid, this->trdid, fatfs_ctx , cycle ); 765 #endif 766 767 // check argument 768 assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL\n" ); 769 770 // check only cluster 0 does FATFS init 771 assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS\n"); 353 772 354 773 // allocate a 512 bytes buffer to store the boot record … … 357 776 buffer = (uint8_t *)kmem_alloc( &req ); 358 777 359 assert( (buffer != NULL) , 360 "cannot allocate memory for 512 bytes buffer\n" ); 778 if( buffer == NULL ) 779 { 780 printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ ); 781 hal_core_sleep(); 782 } 361 783 362 // load the boot record from device 363 // using a synchronous access to IOC device 784 // load the BOOT record from device 364 785 error = dev_ioc_sync_read( buffer , 0 , 1 ); 365 786 366 assert( (error == 0) , 367 "cannot access boot record\n" ); 368 369 #if (DEBUG_FATFS_INIT & 0x1) 370 if( DEBUG_FATFS_INIT < cycle ) 787 if ( error ) 788 { 789 printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ ); 790 hal_core_sleep(); 791 } 792 793 #if (DEBUG_FATFS_CTX_INIT & 0x1) 794 if( DEBUG_FATFS_CTX_INIT < cycle ) 371 795 { 372 796 uint32_t line; … … 387 811 #endif 388 812 389 // checksector size from boot record813 // get sector size from boot record 390 814 uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 ); 391 392 assert( (sector_size == 512) , 393 "sector size must be 512 bytes\n" ); 394 395 // check cluster size from boot record 815 if ( sector_size != 512 ) 816 { 817 printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ ); 818 hal_core_sleep(); 819 } 820 821 // get cluster size from boot record 396 822 uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 ); 397 398 assert( (nb_sectors == 8) , 399 "cluster size must be 8 sectors\n" ); 400 401 // check number of FAT copies from boot record 823 if ( nb_sectors != 8 ) 824 { 825 printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ ); 826 hal_core_sleep(); 827 } 828 829 // get number of FAT copies from boot record 402 830 uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 ); 403 404 assert( (nb_fats == 1) , 405 "number of FAT copies must be 1\n" ); 406 407 // get & check number of sectors in FAT from boot record 831 if ( nb_fats != 1 ) 832 { 833 printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ ); 834 hal_core_sleep(); 835 } 836 837 // get number of sectors in FAT from boot record 408 838 uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 ); 409 410 assert( ((fat_sectors & 0xF) == 0) , 411 "FAT not multiple of 16 sectors\n"); 412 413 // get and check root cluster from boot record 839 if ( (fat_sectors & 0xF) != 0 ) 840 { 841 printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ ); 842 hal_core_sleep(); 843 } 844 845 // get root cluster from boot record 414 846 uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 ); 415 416 assert( (root_cluster == 2) , 417 "root cluster index must be 2\n"); 847 if ( root_cluster != 2 ) 848 { 849 printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ ); 850 hal_core_sleep(); 851 } 418 852 419 853 // get FAT lba from boot record 420 854 uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 ); 855 856 // get FS_INFO sector lba from boot record 857 uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer , 1 ); 858 859 // load the FS_INFO record from device 860 error = dev_ioc_sync_read( buffer , fs_info_lba , 1 ); 861 862 if ( error ) 863 { 864 printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ ); 865 hal_core_sleep(); 866 } 867 868 // get free clusters number from FS_INFO record 869 uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer , 1 ); 870 if ( free_clusters >= fat_sectors << 7 ) 871 { 872 printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ ); 873 hal_core_sleep(); 874 } 875 876 // get cluster hint from FS_INFO record 877 uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer , 1 ); 878 if ( free_cluster_hint >= fat_sectors << 7 ) 879 { 880 printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ ); 881 hal_core_sleep(); 882 } 421 883 422 884 // release the 512 bytes buffer … … 427 889 // allocate a mapper for the FAT itself 428 890 mapper_t * fat_mapper = mapper_create( FS_TYPE_FATFS ); 429 430 assert( (fat_mapper != NULL) , 431 "no memory for FAT mapper" ); 891 if ( fat_mapper == NULL ) 892 { 893 printk("\n[PANIC] in %s : no memory for FAT mapper\n", __FUNCTION__ ); 894 hal_core_sleep(); 895 } 432 896 433 897 // WARNING : the inode field MUST be NULL for the FAT mapper … … 441 905 fatfs_ctx->cluster_begin_lba = fat_lba + fat_sectors; 442 906 fatfs_ctx->root_dir_cluster = 2; 443 fatfs_ctx->last_allocated_sector = 0; // TODO ???444 fatfs_ctx->last_allocated_index = 0; // TODO ???445 907 fatfs_ctx->fat_mapper_xp = XPTR( local_cxy , fat_mapper ); 446 447 #if DEBUG_FATFS_INIT 908 fatfs_ctx->free_clusters = free_clusters; 909 fatfs_ctx->free_cluster_hint = free_cluster_hint; 910 911 remote_queuelock_init( XPTR( local_cxy , &fatfs_ctx->free_lock ) , LOCK_FATFS_FREE ); 912 913 #if DEBUG_FATFS_CTX_INIT 448 914 cycle = (uint32_t)hal_get_cycles(); 449 if( DEBUG_FATFS_ INIT < cycle )450 printk("\n[ DBG] %s : thread %xexit for fatfs_ctx = %x / cycle %d\n",451 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx, cycle );915 if( DEBUG_FATFS_CTX_INIT < cycle ) 916 printk("\n[%s] thread[%x,%x] exit for fatfs_ctx = %x / cycle %d\n", 917 __FUNCTION__, this->process->pid, this->trdid, fatfs_ctx, cycle ); 452 918 #endif 453 919 … … 463 929 } 464 930 465 ////////////////////////////////////////////// 466 error_t fatfs_ mapper_move_page( page_t * page,467 bool_t to_mapper)931 /////////////////////////////////////////////// 932 error_t fatfs_add_dentry( vfs_inode_t * inode, 933 vfs_dentry_t * dentry ) 468 934 { 469 935 error_t error; 470 vfs_inode_t * inode; 471 mapper_t * mapper; 472 uint32_t index; // page index in mapper 473 uint8_t * buffer; // page base address in mapper 474 uint32_t count; // number of sectors in a page 475 uint32_t lba; // block address on device 476 fatfs_ctx_t * fatfs_ctx; // pointer on local FATFS context 477 478 // get pointer on mapper and page index from page descriptor 479 mapper = page->mapper; 480 index = page->index; 481 482 // get inode pointer from mapper 483 inode = mapper->inode; 484 485 #if DEBUG_FATFS_MOVE 486 uint32_t cycle = (uint32_t)hal_get_cycles(); 487 if( DEBUG_FATFS_MOVE < cycle ) 488 printk("\n[DBG] %s : thread %x enter / page %d / inode %x / mapper %x / cycle %d\n", 489 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle ); 490 #endif 491 492 // get page base address 493 xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) ); 494 buffer = (uint8_t *)GET_PTR( base_xp ); 495 496 // get number of sectors for one page (from FATFS context) 497 fatfs_ctx = (fatfs_ctx_t *)fs_context[FS_TYPE_FATFS].extend; 498 count = fatfs_ctx->sectors_per_cluster; 499 500 // test FAT/normal inode 501 if( inode == NULL ) // it is the FAT mapper 502 { 503 // get lba from page index 504 lba = fatfs_ctx->fat_begin_lba + (count * index); 505 506 #if (DEBUG_FATFS_MOVE & 0x1) 507 if( DEBUG_FATFS_MOVE < cycle ) 508 printk("\n[DBG] %s : access FAT on device / lba = %d\n", __FUNCTION__ , lba ); 509 #endif 510 511 // access device 512 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count ); 513 else error = dev_ioc_write( buffer , lba , count ); 514 515 if( error ) return EIO; 516 } 517 else // it is a normal inode mapper 518 { 519 uint32_t searched_cluster_id; 520 521 // get first_cluster_id from inode extension 522 uint32_t first_cluster_id = (uint32_t)(intptr_t)inode->extend; 523 524 // compute cluster_id 525 if( index == 0 ) // no need to access FAT mapper 936 uint32_t length; // dentry name length 937 uint32_t nb_lfn; // number or required LFN 938 char sfn[11]; // buffer for SFN name 939 uint8_t checksum; // name checksum 940 mapper_t * mapper; // loal pointer on parent inode mapper 941 xptr_t mapper_xp; // extended pointer on parent inode mapper 942 xptr_t child_xp; // extended pointer on child inode 943 cxy_t child_cxy; // child inode cluster 944 vfs_inode_t * child_ptr; // child inode local pointer 945 uint32_t size; // child inode size 946 uint32_t type; // child inode type 947 uint32_t cluster; // child inode cluster index 948 949 #if DEBUG_FATFS_ADD_DENTRY 950 char dir_name[CONFIG_VFS_MAX_NAME_LENGTH]; 951 uint32_t cycle = (uint32_t)hal_get_cycles(); 952 thread_t * this = CURRENT_THREAD; 953 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name ); 954 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 955 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n", 956 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 957 #endif 958 959 // check arguments 960 assert( (inode != NULL) , "inode pointer is NULL\n" ); 961 assert( (dentry != NULL) , "dentry pointer is NULL\n" ); 962 assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" ); 963 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" ); 964 965 // get pointers on directory mapper 966 mapper = inode->mapper; 967 mapper_xp = XPTR( local_cxy , mapper ); 968 969 // get extended pointers on remote child inode 970 child_xp = dentry->child_xp; 971 child_cxy = GET_CXY( child_xp ); 972 child_ptr = GET_PTR( child_xp ); 973 974 // get relevant infos from child inode 975 type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ); 976 size = hal_remote_l32( XPTR( child_cxy , &child_ptr->size ) ); 977 cluster = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( child_cxy , &child_ptr->extend ) ); 978 979 // analyse dentry name 980 error = fatfs_name_format( dentry->name, 981 &length, 982 &nb_lfn, 983 sfn, 984 &checksum ); 985 if ( error ) 986 { 987 printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ ); 988 return -1; 989 } 990 991 // Search end of directory with two embedded loops: 992 // - scan the pages in the mapper 993 // - scan the entries in each page to find NO_MORE_ENTRY 994 995 xptr_t page_xp; // extended pointer on page descriptor 996 xptr_t base_xp; // extended pointer on page base 997 uint8_t * base; // local pointer on page base (array of bytes) 998 uint32_t page_id = 0; // page index in mapper 999 uint32_t offset = 0; // position in page 1000 uint32_t found = 0; // NO_MORE_ENTRY found 1001 1002 // loop on pages in mapper 1003 while ( found == 0 ) 1004 { 1005 // get extended pointer on page descriptor in mapper 1006 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1007 1008 if ( page_xp == XPTR_NULL ) 526 1009 { 527 searched_cluster_id = first_cluster_id; 1010 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ ); 1011 return -1; 528 1012 } 529 else // FAT mapper access required 1013 1014 // get pointer on page base 1015 base_xp = ppm_page2base( page_xp ); 1016 base = GET_PTR( base_xp ); 1017 1018 // loop on directory entries in this page 1019 while ( (offset < 4096) && (found == 0) ) 530 1020 { 531 // get cluster and local pointer on FAT mapper 532 xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp; 533 cxy_t fat_mapper_cxy = GET_CXY( fat_mapper_xp ); 534 mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp ); 535 536 // access FAT mapper 537 if( fat_mapper_cxy == local_cxy ) // FAT mapper is local 1021 if ( fatfs_get_record( LDIR_ORD, (base + offset), 0 ) == NO_MORE_ENTRY ) 538 1022 { 539 540 #if (DEBUG_FATFS_MOVE & 0x1) 541 if( DEBUG_FATFS_MOVE < cycle ) 542 printk("\n[DBG] %s : access local FAT mapper\n" 543 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n", 544 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index ); 545 #endif 546 error = fatfs_get_cluster( fat_mapper_ptr, 547 first_cluster_id, 548 index, 549 &searched_cluster_id ); 1023 found = 1; 1024 } 1025 else 1026 { 1027 offset = offset + 32; 550 1028 } 551 else // FAT mapper is remote 1029 } // end loop on entries 1030 1031 if ( found == 0 ) 1032 { 1033 page_id++; 1034 offset = 0; 1035 } 1036 } // end loop on pages 1037 1038 // Modify the directory mapper: depending on the name length, 1039 // the new child requires to write (3, 4, or 5) directory entries. 1040 // To actually register the new child, we use a 5 steps FSM 1041 // (one state per entry to be written), that is traversed as: 1042 // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE 1043 // At most two pages are modified: 1044 // - the page containing the NO_MORE_ENTRY is always modified 1045 // - the following page can be modified if the name spread on to pages. 1046 1047 char * name = dentry->name; 1048 1049 uint32_t step; // FSM state 1050 1051 if ( nb_lfn == 1 ) step = 3; 1052 else if ( nb_lfn == 2 ) step = 4; 1053 else if ( nb_lfn == 3 ) step = 5; 1054 1055 uint8_t * entry; // pointer on directory entry to be written 1056 uint32_t i; // byte index in one 32 bytes directory 1057 uint32_t c; // character index in name 1058 1059 while ( step ) 1060 { 1061 // when the new child is split on two pages, 1062 // we need to access a new page in mapper 1063 if ( offset >= 4096 ) 1064 { 1065 // copy the modified page to IOC device 1066 fatfs_move_page( page_xp , false ); 1067 1068 // get the next page in FAT mapper 1069 page_xp = mapper_remote_get_page( mapper_xp , page_id + 1 ); 1070 1071 if ( page_xp == XPTR_NULL ) 552 1072 { 553 554 #if (DEBUG_FATFS_MOVE & 0x1) 555 if( DEBUG_FATFS_MOVE < cycle ) 556 printk("\n[DBG] %s : access remote FAT mapper\n" 557 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n", 558 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index ); 559 #endif 560 rpc_fatfs_get_cluster_client( fat_mapper_cxy, 561 fat_mapper_ptr, 562 first_cluster_id, 563 index, 564 &searched_cluster_id, 565 &error ); 1073 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ ); 1074 return -1; 566 1075 } 567 568 if( error ) return EIO; 1076 1077 // get pointer on page base 1078 base_xp = ppm_page2base( page_xp ); 1079 base = GET_PTR( base_xp ); 1080 1081 // update offset 1082 offset = 0; 569 1083 } 570 1084 571 #if (DEBUG_FATFS_MOVE & 0x1) 572 if( DEBUG_FATFS_MOVE < cycle ) 573 printk("\n[DBG] %s : access device for inode %x / cluster_id %d\n", 574 __FUNCTION__ , inode , searched_cluster_id ); 575 #endif 576 577 // get lba from cluster_id 578 lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id ); 579 580 // access device 581 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count ); 582 else error = dev_ioc_write( buffer , lba , count ); 583 584 if( error ) return EIO; 585 } 586 587 #if DEBUG_FATFS_MOVE 1085 // compute directory entry address 1086 entry = base + offset; 1087 1088 #if (DEBUG_FATFS_ADD_DENTRY & 1) 1089 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 1090 printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d\n", 1091 __FUNCTION__, step, offset, nb_lfn ); 1092 #endif 1093 1094 // write 32 bytes (one directory entry) per iteration 1095 switch ( step ) 1096 { 1097 case 5: // write LFN3 entry 1098 { 1099 c = 26; 1100 // scan the 32 bytes in dir_entry 1101 for ( i = 0 ; i < 32 ; i++ ) 1102 { 1103 if (i == 0) 1104 { 1105 if ( nb_lfn == 3) entry[i] = 0x43; 1106 else entry[i] = 0x03; 1107 } 1108 else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1)) || 1109 ((i >= 14) && (i<=25) && ((i&1)==0)) || 1110 ((i >= 28) && (i<=31) && ((i&1)==0)) ) && 1111 ( c < length ) ) 1112 { 1113 entry[i] = name[c]; 1114 c++; 1115 } 1116 else if (i == 11) entry[i] = 0x0F; 1117 else if (i == 13) entry[i] = checksum; 1118 else entry[i] = 0x00; 1119 } 1120 step--; 1121 break; 1122 } 1123 case 4: // write LFN2 entry 1124 { 1125 c = 13; 1126 // scan the 32 bytes in dir_entry 1127 for ( i = 0 ; i < 32 ; i++ ) 1128 { 1129 if (i == 0) 1130 { 1131 if ( nb_lfn == 2) entry[i] = 0x42; 1132 else entry[i] = 0x02; 1133 } 1134 else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1)) || 1135 ((i >= 14) && (i<=25) && ((i&1)==0)) || 1136 ((i >= 28) && (i<=31) && ((i&1)==0)) ) && 1137 ( c < length ) ) 1138 { 1139 entry[i] = name[c]; 1140 c++; 1141 } 1142 else if (i == 11) entry[i] = 0x0F; 1143 else if (i == 13) entry[i] = checksum; 1144 else entry[i] = 0x00; 1145 } 1146 step--; 1147 break; 1148 } 1149 case 3: // Write LFN1 entry 1150 { 1151 c = 0; 1152 // scan the 32 bytes in dir_entry 1153 for ( i = 0 ; i < 32 ; i++ ) 1154 { 1155 if (i == 0) 1156 { 1157 if ( nb_lfn == 1) entry[i] = 0x41; 1158 else entry[i] = 0x01; 1159 } 1160 else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1)) || 1161 ((i >= 14) && (i<=25) && ((i&1)==0)) || 1162 ((i >= 28) && (i<=31) && ((i&1)==0)) ) && 1163 ( c < length ) ) 1164 { 1165 entry[i] = name[c]; 1166 c++; 1167 } 1168 else if (i == 11) entry[i] = 0x0F; 1169 else if (i == 13) entry[i] = checksum; 1170 else entry[i] = 0x00; 1171 } 1172 step--; 1173 break; 1174 } 1175 case 2: // write NORMAL entry 1176 { 1177 // scan the 32 bytes in dir_entry 1178 for ( i = 0 ; i < 32 ; i++ ) 1179 { 1180 if ( i < 11 ) // 8.3 SFN 1181 { 1182 entry[i] = sfn[i]; 1183 } 1184 else if (i == 11) // ATTR 1185 { 1186 if (type == INODE_TYPE_DIR) entry[i] = 0x10; 1187 else entry[i] = 0x20; 1188 } 1189 else if (i == 20) entry[i] = cluster>>16; // cluster.B2 1190 else if (i == 21) entry[i] = cluster>>24; // cluster.B3 1191 else if (i == 26) entry[i] = cluster>>0; // cluster.B0 1192 else if (i == 27) entry[i] = cluster>>8; // cluster.B1 1193 else if (i == 28) entry[i] = size>>0; // size.B0 1194 else if (i == 29) entry[i] = size>>8; // size.B1 1195 else if (i == 30) entry[i] = size>>16; // size.B2 1196 else if (i == 31) entry[i] = size>>24; // size.B3 1197 else entry[i] = 0x00; 1198 } 1199 1200 // update the "extend" field in dentry descriptor 1201 dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5); 1202 1203 step--; 1204 break; 1205 } 1206 case 1: // write NOMORE entry 1207 { 1208 entry [0] = 0x00; 1209 step--; 1210 break; 1211 } 1212 } // end switch step 1213 1214 offset += 32; 1215 1216 } // exit while 1217 1218 // copy the modified page to the IOC device 1219 fatfs_move_page( page_xp , false ); 1220 1221 #if DEBUG_FATFS_ADD_DENTRY 588 1222 cycle = (uint32_t)hal_get_cycles(); 589 if( DEBUG_FATFS_MOVE < cycle ) 590 printk("\n[DBG] %s : thread %x exit / page %d / inode %x / mapper %x / cycle %d\n", 591 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle ); 592 #endif 593 594 #if (DEBUG_FATFS_MOVE & 0x1) 595 if( DEBUG_FATFS_MOVE < cycle ) 596 { 597 uint32_t * tab = (uint32_t *)buffer; 598 uint32_t line , word; 599 printk("\n***** %s : First 64 words of loaded page\n", __FUNCTION__ ); 600 for( line = 0 ; line < 8 ; line++ ) 601 { 602 printk("%X : ", line ); 603 for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] ); 604 printk("\n"); 605 } 606 } 1223 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 1224 printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n", 1225 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 607 1226 #endif 608 1227 609 1228 return 0; 610 1229 611 } // end fatfs_mapper_move_page() 612 613 ///////////////////////////////////////////////////// 614 error_t fatfs_inode_load( vfs_inode_t * parent_inode, 1230 } // end fatfs_add_dentry() 1231 1232 ////////////////////////////////////////////////// 1233 error_t fatfs_remove_dentry( vfs_inode_t * inode, 1234 vfs_dentry_t * dentry ) 1235 { 1236 xptr_t mapper_xp; // extended pointer on mapper 1237 mapper_t * mapper; // local pointer on mapper 1238 xptr_t page_xp; // extended pointer on mapper page descriptor 1239 xptr_t base_xp; // extended pointer on mapper page base 1240 uint8_t * base; // local pointer on mapper page base 1241 1242 #if DEBUG_FATFS_REMOVE_DENTRY 1243 char dir_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1244 uint32_t cycle = (uint32_t)hal_get_cycles(); 1245 thread_t * this = CURRENT_THREAD; 1246 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name ); 1247 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 1248 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n", 1249 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 1250 #endif 1251 1252 // check arguments 1253 assert( (inode != NULL) , "inode pointer is NULL\n" ); 1254 assert( (dentry != NULL) , "dentry pointer is NULL\n" ); 1255 assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" ); 1256 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" ); 1257 1258 // get pointers on directory mapper 1259 mapper = inode->mapper; 1260 mapper_xp = XPTR( local_cxy , mapper ); 1261 1262 // compute number of LFN entries 1263 uint32_t nb_lfn; 1264 uint32_t name_length = strlen( dentry->name ); 1265 1266 if ( name_length <= 13 ) nb_lfn = 1; 1267 else if ( name_length <= 26 ) nb_lfn = 2; 1268 else nb_lfn = 3; 1269 1270 // we must invalidate (2, 3 or 4) 32 bytes entries: 1271 // the NORMAL entry (registered in dentry->extend) and all preceding LFN entries 1272 // At most two pages are modified: 1273 // - the page containing the NORMAL entry is always modified. 1274 // - the preceding page is modified when the name spread on two pages. 1275 1276 // get 32 bytes directory entry index from dentry->extend 1277 uint32_t dentry_id = (uint32_t)(intptr_t)dentry->extend; 1278 1279 // get page index and offset in parent directory mapper 1280 uint32_t page_id = dentry_id >> 7; 1281 uint32_t offset = (dentry_id & 0x7F)<<5; 1282 1283 // get extended pointer on page descriptor from parent directory mapper 1284 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1285 1286 if ( page_xp == XPTR_NULL ) 1287 { 1288 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ ); 1289 return -1; 1290 } 1291 1292 // get pointers on page base 1293 base_xp = ppm_page2base( page_xp ); 1294 base = GET_PTR( base_xp ); 1295 1296 // invalidate NORMAL entry in directory cache 1297 base[offset] = 0xE5; 1298 1299 // invalidate LFN entries 1300 while ( nb_lfn ) 1301 { 1302 if (offset == 0) // we must load page (page_id - 1) 1303 { 1304 1305 // check page_id 1306 assert( (page_id > 0), "page_id and offset cannot be both 0\n" ); 1307 1308 // copy the modified page to the IOC device 1309 fatfs_move_page( page_xp , false ); 1310 1311 // get extended pointer on page descriptor from parent directory mapper 1312 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1313 1314 if ( page_xp == XPTR_NULL ) 1315 { 1316 printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ ); 1317 return -1; 1318 } 1319 1320 // get pointers on page base 1321 base_xp = ppm_page2base( page_xp ); 1322 base = GET_PTR( base_xp ); 1323 1324 // update offset 1325 offset = 4096; 1326 } 1327 1328 offset = offset - 32; 1329 1330 // check for LFN entry 1331 assert( (fatfs_get_record( DIR_ATTR, base + offset, 0 ) == ATTR_LONG_NAME_MASK ), 1332 "this directory entry must be a LFN\n"); 1333 1334 // invalidate LFN entry 1335 base[offset] = 0xE5; 1336 1337 nb_lfn--; 1338 } 1339 1340 // copy the modified page to the IOC device 1341 fatfs_move_page( page_xp , false ); 1342 1343 1344 #if DEBUG_FATFS_REMOVE_DENTRY 1345 cycle = (uint32_t)hal_get_cycles(); 1346 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 1347 printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n", 1348 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 1349 #endif 1350 1351 return 0; 1352 1353 } // end fatfs_remove_dentry 1354 1355 //////////////////////////////////////////////////////////////// 1356 error_t fatfs_child_init( vfs_inode_t * parent_inode, 615 1357 char * name, 616 1358 xptr_t child_inode_xp ) 617 1359 { 618 1360 // Two embedded loops: 619 // - scan the parent mapper pages1361 // - scan the parent directory mapper pages 620 1362 // - scan the directory entries in each 4 Kbytes page 621 1363 622 #if DEBUG_FATFS_LOAD 623 uint32_t cycle = (uint32_t)hal_get_cycles(); 624 if( DEBUG_FATFS_LOAD < cycle ) 625 printk("\n[DBG] %s : thread %x enter for child <%s> in parent inode %x / cycle %d\n", 626 __FUNCTION__ , CURRENT_THREAD , name , parent_inode , cycle ); 627 #endif 628 629 mapper_t * mapper = parent_inode->mapper; 630 631 assert( (mapper != NULL) , "parent mapper undefined\n"); 1364 #if DEBUG_FATFS_CHILD_INIT 1365 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1366 uint32_t cycle = (uint32_t)hal_get_cycles(); 1367 thread_t * this = CURRENT_THREAD; 1368 vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name ); 1369 if( DEBUG_FATFS_CHILD_INIT < cycle ) 1370 printk("\n[%s] thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n", 1371 __FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle ); 1372 #endif 1373 1374 // check parent_inode and child_inode 1375 assert( (parent_inode != NULL) , "parent_inode is NULL\n" ); 1376 assert( (child_inode_xp != XPTR_NULL ) , "child_inode is XPTR_NULL\n" ); 1377 1378 mapper_t * mapper = parent_inode->mapper; 1379 xptr_t mapper_xp = XPTR( local_cxy , mapper ); 1380 1381 // check parent mapper 1382 assert( (mapper != NULL) , "parent mapper is NULL\n"); 632 1383 633 1384 char cname[CONFIG_VFS_MAX_NAME_LENGTH]; // name extracter from each directory entry … … 636 1387 char lfn2[16]; // buffer for one partial cname 637 1388 char lfn3[16]; // buffer for one partial cname 638 page_t * page; // pointer on current page descriptor 639 uint8_t * base; // pointer on current page base 640 uint32_t offset = 0; // byte offset in page 641 uint32_t index = 0; // page index in mapper 1389 xptr_t page_xp; // extended pointer on page descriptor 1390 xptr_t base_xp; // extended pointer on page base 1391 uint8_t * base; // local pointer on page base 642 1392 uint32_t attr; // directory entry ATTR field 643 1393 uint32_t ord; // directory entry ORD field 644 1394 uint32_t seq; // sequence index 645 uint32_t lfn = 0; // LFN entries number 646 uint32_t size = 0; // searched file/dir size (bytes) 647 uint32_t cluster = 0; // searched file/dir cluster index 648 uint32_t is_dir = 0; // searched file/dir type 649 uint32_t dentry; // directory entry index 650 int32_t found = 0; // not found (0) / name found (1) / end of dir (-1) 1395 uint32_t lfn = 0; // LFN entries number 1396 uint32_t size = 0; // searched file/dir size (bytes) 1397 uint32_t cluster = 0; // searched file/dir cluster index 1398 uint32_t is_dir = 0; // searched file/dir type 1399 int32_t found = 0; // not found (0) / name found (1) / end of dir (-1) 1400 uint32_t page_id = 0; // page index in mapper 1401 uint32_t dentry_id = 0; // directory entry index 1402 uint32_t offset = 0; // byte offset in page 651 1403 652 1404 // scan the parent directory mapper … … 654 1406 { 655 1407 // get one page 656 page = mapper_get_page( mapper , index);657 658 assert( (page != NULL) , "bad parent mapper\n");1408 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1409 1410 if( page_xp == XPTR_NULL) return EIO; 659 1411 660 1412 // get page base 661 xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ));662 base = (uint8_t *)GET_PTR( base_xp );663 664 #if (DEBUG_FATFS_ LOAD& 0x1)665 if( DEBUG_FATFS_ LOAD< cycle )1413 base_xp = ppm_page2base( page_xp ); 1414 base = (uint8_t *)GET_PTR( base_xp ); 1415 1416 #if (DEBUG_FATFS_CHILD_INIT & 0x1) 1417 if( DEBUG_FATFS_CHILD_INIT < cycle ) 666 1418 { 667 1419 uint32_t * buf = (uint32_t *)base; 668 1420 uint32_t line , word; 669 printk("\n ***** %s : First 16 dentries for parent inode %x\n",670 __FUNCTION__ , parent_ inode );1421 printk("\n[%s] First 16 dentries for <%s>\n", 1422 __FUNCTION__ , parent_name ); 671 1423 for( line = 0 ; line < 16 ; line++ ) 672 1424 { … … 728 1480 cluster = (fatfs_get_record( DIR_FST_CLUS_HI , base + offset , 1 ) << 16) | 729 1481 (fatfs_get_record( DIR_FST_CLUS_LO , base + offset , 1 ) ) ; 730 dentry = ((index<<12) + offset)>>5;731 is_dir = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);732 size = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );733 found = 1;1482 dentry_id = ((page_id<<12) + offset)>>5; 1483 is_dir = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY); 1484 size = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 ); 1485 found = 1; 734 1486 } 735 1487 offset = offset + 32; 736 1488 lfn = 0; 737 1489 } 738 } // end loop on directory entries 739 index++; 1490 } // end loop on directory entries in page 1491 1492 page_id++; 740 1493 offset = 0; 1494 741 1495 } // end loop on pages 742 1496 … … 746 1500 { 747 1501 748 #if DEBUG_FATFS_ LOAD1502 #if DEBUG_FATFS_CHILD_INIT 749 1503 cycle = (uint32_t)hal_get_cycles(); 750 if( DEBUG_FATFS_LOAD < cycle ) 751 printk("\n[DBG] %s : thread %x exit / child <%s> not found / cycle %d\n", 752 __FUNCTION__ , CURRENT_THREAD, name, cycle ); 753 #endif 754 755 return ENOENT; 756 } 757 else // found searched child name 758 { 759 // get child inode cluster and local pointer 760 cxy_t child_cxy = GET_CXY( child_inode_xp ); 761 vfs_inode_t * child_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp ); 762 763 // update the child inode "type", "size", and "extend" fields 764 vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE; 765 766 hal_remote_s32( XPTR( child_cxy , &child_ptr->type ) , type ); 767 hal_remote_s32( XPTR( child_cxy , &child_ptr->size ) , size ); 768 hal_remote_s32( XPTR( child_cxy , &child_ptr->extend ) , cluster ); 769 770 #if DEBUG_FATFS_LOAD 1504 if( DEBUG_FATFS_CHILD_INIT < cycle ) 1505 printk("\n[%s] thread[%x,%x] exit / child <%s> not found / cycle %d\n", 1506 __FUNCTION__, this->process->pid, this->trdid, name, cycle ); 1507 #endif 1508 1509 return -1; 1510 } 1511 1512 // get child inode cluster and local pointer 1513 cxy_t inode_cxy = GET_CXY( child_inode_xp ); 1514 vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp ); 1515 1516 // get dentry pointers and cluster 1517 xptr_t dentry_xp = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 1518 vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); 1519 cxy_t dentry_cxy = GET_CXY( dentry_xp ); 1520 1521 // dentry descriptor must be in same cluster as parent inode 1522 assert( (dentry_cxy == local_cxy) , "illegal dentry cluster\n" ); 1523 1524 // update the child inode "type", "size", and "extend" fields 1525 vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE; 1526 1527 hal_remote_s32( XPTR( inode_cxy , &inode_ptr->type ) , type ); 1528 hal_remote_s32( XPTR( inode_cxy , &inode_ptr->size ) , size ); 1529 hal_remote_s32( XPTR( inode_cxy , &inode_ptr->extend ) , cluster ); 1530 1531 // update the dentry "extend" field 1532 dentry_ptr->extend = (void *)(intptr_t)dentry_id; 1533 1534 #if DEBUG_FATFS_CHILD_INIT 771 1535 cycle = (uint32_t)hal_get_cycles(); 772 if( DEBUG_FATFS_LOAD < cycle ) 773 printk("\n[DBG] %s : thread %x exit / child <%s> loaded / cycle %d\n", 774 __FUNCTION__ , CURRENT_THREAD, name, cycle ); 775 #endif 776 777 return 0; 778 } 779 } // end fatfs_inode_load() 1536 if( DEBUG_FATFS_CHILD_INIT < cycle ) 1537 printk("\n[%s] thread[%x,%x] exit / child <%s> loaded in <%s> / cycle %d\n", 1538 __FUNCTION__, this->process->pid, this->trdid, name, parent_name, cycle ); 1539 #endif 1540 1541 return 0; 1542 1543 } // end fatfs_child_init() 1544 1545 /////////////////////////////////////////////// 1546 error_t fatfs_sync_inode( vfs_inode_t * inode ) 1547 { 1548 1549 // check inode pointer and cluster index 1550 assert( (inode != NULL) , "inode pointer undefined\n" ); 1551 assert( (inode->mapper != NULL ) , "mapper pointer undefined\n" ); 1552 assert( (inode->type == INODE_TYPE_FILE) , "inode must be a file\n" ); 1553 1554 #if DEBUG_FATFS_SYNC_INODE 1555 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 1556 uint32_t cycle = (uint32_t)hal_get_cycles(); 1557 thread_t * this = CURRENT_THREAD; 1558 vfs_inode_get_name( XPTR( local_cxy , inode ) , name ); 1559 if( DEBUG_FATFS_SYNC_INODE < cycle ) 1560 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n", 1561 __FUNCTION__ , this->process->pid, this->trdid, name, cycle ); 1562 #endif 1563 1564 error_t error; 1565 mapper_t * mapper; 1566 page_t * page; 1567 uint32_t page_id; 1568 1569 // get mapper from inode 1570 mapper = inode->mapper; 1571 1572 // compute max number of pages in mapper from file size 1573 uint32_t size = inode->size; 1574 uint32_t pages = size >> CONFIG_PPM_PAGE_SHIFT; 1575 if( size & CONFIG_PPM_PAGE_MASK ) pages++; 1576 1577 // get pointer on mapper radix tree 1578 grdxt_t * rt = &mapper->rt; 1579 1580 // scan all pages 1581 for( page_id = 0 ; page_id < pages ; page_id++ ) 1582 { 1583 // get page descriptor from mapper 1584 page = grdxt_lookup( rt , page_id ); 1585 1586 // check all existing pages 1587 if ( page != NULL ) 1588 { 1589 if ( page->flags & PG_DIRTY ) 1590 { 1591 1592 #if (DEBUG_FATFS_SYNC_INODE & 1) 1593 if( DEBUG_FATFS_SYNC_INODE < cycle ) 1594 printk("\n[%s] thread[%x,%x] synchronizes page %d from <%s> mapper to IOC device\n", 1595 __FUNCTION__, page_id, name ); 1596 #endif 1597 // build extended pointer on page descriptor 1598 xptr_t page_xp = XPTR( local_cxy , page ); 1599 1600 // move page from mapper to device 1601 error = fatfs_move_page( page_xp , false ); 1602 1603 if ( error ) return -1; 1604 1605 // reset page dirty flag 1606 ppm_page_undo_dirty( page_xp ); 1607 } 1608 } 1609 } // end loop on pages 1610 1611 #if DEBUG_FATFS_SYNC_INODE 1612 cycle = (uint32_t)hal_get_cycles(); 1613 if( DEBUG_FATFS_SYNC_INODE < cycle ) 1614 printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n", 1615 __FUNCTION__ , this->process->pid, this->trdid, name, cycle ); 1616 #endif 1617 1618 return 0; 1619 1620 } // end fatfs_sync_inode() 1621 1622 ////////////////////////////// 1623 error_t fatfs_sync_fat( void ) 1624 { 1625 1626 #if DEBUG_FATFS_SYNC_FAT 1627 uint32_t cycle = (uint32_t)hal_get_cycles(); 1628 thread_t * this = CURRENT_THREAD; 1629 if( DEBUG_FATFS_SYNC_FAT < cycle ) 1630 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 1631 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1632 #endif 1633 1634 uint32_t page_id; 1635 error_t error; 1636 1637 // get FAT mapper pointers an cluster 1638 fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; 1639 xptr_t mapper_xp = fatfs_ctx->fat_mapper_xp; 1640 cxy_t mapper_cxy = GET_CXY( mapper_xp ); 1641 mapper_t * mapper_ptr = GET_PTR( mapper_xp ); 1642 1643 // compute max number of 4 Kbytes pages in FAT mapper 1644 // TODO : this could be improved (see fatfs.h) [AG] 1645 uint32_t pages = fatfs_ctx->fat_sectors_count >> 3; 1646 1647 // get pointers on remote FAT mapper radix tree 1648 grdxt_t * rt_ptr = &mapper_ptr->rt; 1649 xptr_t rt_xp = XPTR( mapper_cxy , rt_ptr ); 1650 1651 // scan all pages 1652 for( page_id = 0 ; page_id < pages ; page_id++ ) 1653 { 1654 // get extended pointer on page descriptor from FAT mapper 1655 xptr_t page_xp = grdxt_remote_lookup( rt_xp , page_id ); 1656 1657 // check all existing pages 1658 if ( page_xp != XPTR_NULL ) 1659 { 1660 page_t * page_ptr = GET_PTR( page_xp ); 1661 uint32_t flags = hal_remote_l32( XPTR( mapper_cxy , &page_ptr->flags ) ); 1662 1663 if ( flags & PG_DIRTY ) 1664 { 1665 1666 #if (DEBUG_FATFS_SYNC_FAT & 1) 1667 if( DEBUG_FATFS_SYNC_FAT < cycle ) 1668 printk("\n[%s] thread[%x,%x] synchronizes page %d from FAT mapper to IOC device\n", 1669 __FUNCTION__, page_id ); 1670 #endif 1671 // move page from mapper to device 1672 error = fatfs_move_page( page_xp , false ); 1673 1674 if ( error ) return -1; 1675 1676 // reset page dirty flag 1677 ppm_page_undo_dirty( page_xp ); 1678 } 1679 } 1680 } // end loop on pages 1681 1682 #if DEBUG_FATFS_SYNC_FAT 1683 cycle = (uint32_t)hal_get_cycles(); 1684 if( DEBUG_FATFS_SYNC_FAT < cycle ) 1685 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 1686 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1687 #endif 1688 1689 return 0; 1690 1691 } // end fatfs_sync_fat() 1692 1693 //////////////////////////////////// 1694 error_t fatfs_sync_free_info( void ) 1695 { 1696 1697 #if DEBUG_FATFS_SYNC_FSINFO 1698 uint32_t cycle = (uint32_t)hal_get_cycles(); 1699 thread_t * this = CURRENT_THREAD; 1700 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1701 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 1702 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1703 #endif 1704 1705 uint8_t * buffer; // dynamically allocated aligned 512 bytes buffer 1706 kmem_req_t req; 1707 error_t error; 1708 1709 // get FS_INFO lba, free_ from FATFS context 1710 fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; 1711 uint32_t lba = fatfs_ctx->fs_info_lba; 1712 uint32_t hint = fatfs_ctx->free_cluster_hint; 1713 uint32_t number = fatfs_ctx->free_clusters; 1714 1715 // allocate buffer to store the FS_INFO sector 1716 req.type = KMEM_512_BYTES; 1717 req.flags = AF_KERNEL | AF_ZERO; 1718 buffer = (uint8_t *)kmem_alloc( &req ); 1719 if( buffer == NULL ) 1720 { 1721 printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ ); 1722 return ENOMEM; 1723 } 1724 1725 // load the FS_INFO sector from device to buffer 1726 error = dev_ioc_read( buffer , lba , 1 ); 1727 if ( error ) 1728 { 1729 printk("\n[PANIC] in %s : cannot read FS_INFO record\n", __FUNCTION__ ); 1730 return EIO; 1731 } 1732 1733 // update buffer 1734 fatfs_set_record( FS_FREE_CLUSTERS , buffer , 1 , number ); 1735 fatfs_set_record( FS_FREE_CLUSTER_HINT , buffer , 1 , hint ); 1736 1737 // write modified FS_INFO sector from buffer to device 1738 error = dev_ioc_write( buffer , lba , 1 ); 1739 if ( error ) 1740 { 1741 printk("\n[PANIC] in %s : cannot write FS_INFO record\n", __FUNCTION__ ); 1742 return EIO; 1743 } 1744 1745 // release the 512 bytes buffer 1746 req.type = KMEM_512_BYTES; 1747 req.ptr = buffer; 1748 kmem_free( &req ); 1749 1750 #if DEBUG_FATFS_SYNC_FSINFO 1751 cycle = (uint32_t)hal_get_cycles(); 1752 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1753 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 1754 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1755 #endif 1756 1757 return 0; 1758 1759 } // end fatfs_sync_fs_info() 1760 1761 ////////////////////////////////////////////////////////// 1762 error_t fatfs_cluster_alloc( uint32_t * searched_cluster ) 1763 { 1764 uint32_t page_id; // page index in mapper 1765 uint32_t slot_id; // slot index in page (1024 slots per page) 1766 uint32_t hint; // first free cluster index in FAT 1767 uint32_t free_clusters; // total number of free clusters 1768 vfs_ctx_t * vfs_ctx; // local pointer on VFS context (same in all clusters) 1769 fatfs_ctx_t * loc_fatfs_ctx; // local pointer on local FATFS context 1770 fatfs_ctx_t * fat_fatfs_ctx; // local pointer on FATFS context in FAT cluster 1771 xptr_t mapper_xp; // extended pointer on FAT mapper 1772 cxy_t mapper_cxy; // Fat mapper cluster identifier 1773 xptr_t page_xp; // extended pointer on current page descriptor in mapper 1774 xptr_t slot_xp; // extended pointer on FAT slot defined by hint 1775 xptr_t lock_xp; // extended pointer on lock protecting free clusters info 1776 xptr_t hint_xp; // extended pointer on free_cluster_hint in FAT cluster 1777 xptr_t numb_xp; // extended pointer on free_clusters_number in FAT cluster 1778 1779 #if DEBUG_FATFS_CLUSTER_ALLOC 1780 uint32_t cycle = (uint32_t)hal_get_cycles(); 1781 thread_t * this = CURRENT_THREAD; 1782 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1783 printk("\n[%s] thread[%x,%x] enter / cycle = %d\n", 1784 __FUNCTION__, this->process->pid, this->trdid, cycle ); 1785 #endif 1786 1787 // get local pointer on VFS context (same in all clusters) 1788 vfs_ctx = &fs_context[FS_TYPE_FATFS]; 1789 1790 // get local pointer on local FATFS context 1791 loc_fatfs_ctx = vfs_ctx->extend; 1792 1793 // get extended pointer and cluster on FAT mapper 1794 mapper_xp = loc_fatfs_ctx->fat_mapper_xp; 1795 mapper_cxy = GET_CXY( mapper_xp ); 1796 1797 // get local pointer on FATFS context in FAT cluster 1798 fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) ); 1799 1800 // build relevant extended pointers in on free clusters info in FAT cluster 1801 lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock ); 1802 hint_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint ); 1803 numb_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters ); 1804 1805 // take the lock protecting free clusters 1806 remote_queuelock_acquire( lock_xp ); 1807 1808 // get hint and free_clusters values from FATFS context 1809 hint = hal_remote_l32( hint_xp ); 1810 free_clusters = hal_remote_l32( numb_xp ); 1811 1812 // get page index & slot index for the first free cluster 1813 page_id = (hint + 1) >> 10; 1814 slot_id = (hint + 1) & 0x3FF; 1815 1816 // get relevant page from mapper 1817 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1818 1819 if( page_xp == XPTR_NULL ) 1820 { 1821 printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ ); 1822 return -1; 1823 } 1824 1825 // build extended pointer on free cluster slot 1826 slot_xp = ppm_page2base( page_xp ) + (slot_id<<2); 1827 1828 #if (DEBUG_FATFS_CLUSTER_ALLOC & 1) 1829 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1830 printk("\n[%s] thread[%x,%x] get free info / hint %x / free_clusters %x\n", 1831 __FUNCTION__, this->process->pid, this->trdid, hint, free_clusters ); 1832 #endif 1833 1834 // check "free_clusters" 1835 if ( free_clusters == 0 ) 1836 { 1837 printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ ); 1838 remote_queuelock_acquire( lock_xp ); 1839 return -1; 1840 } 1841 else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN ) 1842 { 1843 printk("\n[WARNING] in %s : only %n free FATFS clusters\n", 1844 __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN ); 1845 } 1846 1847 // check "hint" 1848 if( hal_remote_l32( slot_xp ) != FREE_CLUSTER ) 1849 { 1850 printk("\n[ERROR] in %s : illegal hint cluster\n", __FUNCTION__ ); 1851 remote_queuelock_acquire( lock_xp ); 1852 return -1; 1853 } 1854 1855 // update allocated cluster in FAT mapper 1856 hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX ); 1857 1858 // update free cluster info 1859 fatfs_free_clusters_decrement( hint + 1 ); 1860 1861 // release free clusters busylock 1862 remote_queuelock_release( lock_xp ); 1863 1864 #if DEBUG_FATFS_CLUSTER_ALLOC 1865 cycle = (uint32_t)hal_get_cycles(); 1866 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1867 printk("\n[%s] thread[%x,%x] exit / cluster %x / cycle %d\n", 1868 __FUNCTION__, this->process->pid, this->trdid, hint + 1, cycle ); 1869 #endif 1870 1871 *searched_cluster = hint + 1; 1872 return 0; 1873 1874 } // end fat_cluster_alloc() 1875 1876 ////////////////////////////////////////////// 1877 error_t fatfs_release_inode( xptr_t inode_xp ) 1878 { 1879 vfs_ctx_t * vfs_ctx; // local pointer on VFS context (same in all clusters). 1880 fatfs_ctx_t * loc_fatfs_ctx; // local pointer on local FATFS context 1881 fatfs_ctx_t * fat_fatfs_ctx; // local pointer on FATFS context in FAT cluster 1882 xptr_t mapper_xp; // extended pointer on FAT mapper 1883 cxy_t mapper_cxy; // Fat mapper cluster identifier 1884 xptr_t lock_xp; // extended pointer on lock protecting free clusters info. 1885 xptr_t first_xp; // extended pointer on inode extension 1886 uint32_t first_cluster; // first cluster index for released inode 1887 vfs_inode_t * inode_ptr; 1888 cxy_t inode_cxy; 1889 1890 // check inode pointer 1891 assert( (inode_xp != XPTR_NULL) , "inode pointer is NULL\n" ); 1892 1893 // get first_cluster from inode extension 1894 inode_ptr = GET_PTR( inode_xp ); 1895 inode_cxy = GET_CXY( inode_xp ); 1896 first_xp = XPTR( inode_cxy , &inode_ptr->extend ); 1897 first_cluster = (uint32_t)(intptr_t)hal_remote_lpt( first_xp ); 1898 1899 // check first cluster index 1900 assert( (first_cluster != 0) , "inode extend is NULL\n" ); 1901 1902 #if DEBUG_FATFS_RELEASE_INODE 1903 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 1904 uint32_t cycle = (uint32_t)hal_get_cycles(); 1905 thread_t * this = CURRENT_THREAD; 1906 vfs_inode_get_name( inode_xp , name ); 1907 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1908 printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster %x / cycle %d\n", 1909 __FUNCTION__ , this->process->pid, this->trdid, name, first_cluster, cycle ); 1910 #endif 1911 1912 // get local pointer on VFS context (same in all clusters) 1913 vfs_ctx = &fs_context[FS_TYPE_FATFS]; 1914 1915 // get local pointer on local FATFS context 1916 loc_fatfs_ctx = vfs_ctx->extend; 1917 1918 // get extended pointer and cluster on FAT mapper 1919 mapper_xp = loc_fatfs_ctx->fat_mapper_xp; 1920 mapper_cxy = GET_CXY( mapper_xp ); 1921 1922 // get local pointer on FATFS context in FAT cluster 1923 fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) ); 1924 1925 // get extended pointer on free clusters lock in FAT cluster 1926 lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock ); 1927 1928 // take lock protecting free clusters 1929 remote_queuelock_acquire( lock_xp ); 1930 1931 // call the recursive function to release all clusters from FAT mapper 1932 if ( fatfs_recursive_release( mapper_xp , first_cluster ) ) 1933 { 1934 printk("\n[ERROR] in %s : cannot update FAT mapper\n", __FUNCTION__ ); 1935 remote_queuelock_release( lock_xp ); 1936 return -1; 1937 } 1938 1939 // release lock protecting free cluster 1940 remote_queuelock_release( lock_xp ); 1941 1942 #if (DEBUG_FATFS_RELEASE_INODE & 1) 1943 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1944 printk("\n[%s] inode <%s> removed from FAT mapper\n", __FUNCTION__, name ); 1945 #endif 1946 1947 // update FAT on IOC device (from FAT mapper) 1948 if ( fatfs_sync_fat() ) 1949 { 1950 printk("\n[ERROR] in %s : cannot update FAT on device\n", __FUNCTION__ ); 1951 return -1; 1952 } 1953 1954 #if (DEBUG_FATFS_RELEASE_INODE & 1) 1955 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1956 printk("\n[%s] inode <%s> removed from FAT on IOC device\n", __FUNCTION__, name ); 1957 #endif 1958 1959 // update FS-INFO sector on IOC device (from FATFS context) 1960 if ( fatfs_sync_free_info() ) 1961 { 1962 printk("\n[ERROR] in %s: cannot update FS_INFO on device\n", __FUNCTION__ ); 1963 return -1; 1964 } 1965 1966 #if DEBUG_FATFS_RELEASE_INODE 1967 cycle = (uint32_t)hal_get_cycles(); 1968 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1969 printk("\n[%s] thread[%x,%x] removed <%s> inode from FATFS / cycle %d\n", 1970 __FUNCTION__ , this->process->pid, this->trdid, name, cycle ); 1971 #endif 1972 1973 return 0; 1974 1975 } // end fatfs_release_inode() 1976 1977 ///////////////////////////////////////// 1978 error_t fatfs_move_page( xptr_t page_xp, 1979 bool_t to_mapper ) 1980 { 1981 error_t error; 1982 vfs_inode_t * inode_ptr; 1983 mapper_t * mapper_ptr; 1984 uint32_t page_id; // page index in mapper 1985 1986 #if DEBUG_FATFS_MOVE_PAGE 1987 uint32_t cycle = (uint32_t)hal_get_cycles(); 1988 thread_t * this = CURRENT_THREAD; 1989 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 1990 #endif 1991 1992 // get page cluster an local pointer 1993 cxy_t page_cxy = GET_CXY( page_xp ); 1994 page_t * page_ptr = GET_PTR( page_xp ); 1995 1996 // get mapper pointer and page index from page descriptor 1997 mapper_ptr = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) ); 1998 page_id = hal_remote_l32( XPTR( page_cxy , &page_ptr->index ) ); 1999 2000 // get pointer on local FATFS context 2001 fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; 2002 2003 // get page base address 2004 xptr_t base_xp = ppm_page2base( page_xp ); 2005 uint8_t * buffer = (uint8_t *)GET_PTR( base_xp ); 2006 2007 // get inode pointer from mapper 2008 inode_ptr = hal_remote_lpt( XPTR( page_cxy , &mapper_ptr->inode ) ); 2009 2010 ////////////////////////////// it is the FAT mapper 2011 if( inode_ptr == NULL ) 2012 { 2013 // get lba from FATFS context and page_id 2014 uint32_t lba = fatfs_ctx->fat_begin_lba + (page_id << 3); 2015 2016 // access device 2017 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 ); 2018 else error = dev_ioc_write( buffer , lba , 8 ); 2019 2020 if( error ) return EIO; 2021 2022 #if (DEBUG_FATFS_MOVE_PAGE & 0x1) 2023 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2024 { 2025 uint32_t * tab = (uint32_t *)buffer; 2026 uint32_t line , word; 2027 printk("\n***** %s : First 64 words of page %d in FAT mapper\n", 2028 __FUNCTION__ , page_id ); 2029 for( line = 0 ; line < 8 ; line++ ) 2030 { 2031 printk("%X : ", line ); 2032 for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] ); 2033 printk("\n"); 2034 } 2035 } 2036 #endif 2037 2038 #if DEBUG_FATFS_MOVE_PAGE 2039 cycle = (uint32_t)hal_get_cycles(); 2040 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2041 { 2042 if (to_mapper) 2043 printk("\n[%s] thread[%x,%x] load page %d of FAT / cycle %d\n", 2044 __FUNCTION__, this->process->pid, this->trdid, page_id, cycle ); 2045 else 2046 printk("\n[%s] thread[%x,%x] sync page %d of FAT / cycle %d\n", 2047 __FUNCTION__, this->process->pid, this->trdid, page_id, cycle ); 2048 } 2049 #endif 2050 2051 } 2052 ///////////////////////// it is an inode mapper 2053 else 2054 { 2055 2056 #if DEBUG_FATFS_MOVE_PAGE 2057 vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name ); 2058 #endif 2059 2060 uint32_t searched_cluster; 2061 uint32_t first_cluster; 2062 2063 // get first_cluster from inode extension 2064 void * extend = hal_remote_lpt( XPTR( page_cxy , &inode_ptr->extend ) ); 2065 first_cluster = (uint32_t)(intptr_t)extend; 2066 2067 // compute searched_cluster 2068 if( page_id == 0 ) // no need to access FAT mapper 2069 { 2070 // searched cluster is first cluster 2071 searched_cluster = first_cluster; 2072 } 2073 else // FAT mapper access required 2074 { 2075 // access FAT mapper to get searched cluster 2076 error = fatfs_get_cluster( first_cluster, 2077 page_id, 2078 &searched_cluster ); 2079 if( error ) return EIO; 2080 } 2081 2082 // get lba from searched_cluster 2083 uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster ); 2084 2085 // access device 2086 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 ); 2087 else error = dev_ioc_write( buffer , lba , 8 ); 2088 2089 if( error ) return EIO; 2090 2091 #if (DEBUG_FATFS_MOVE_PAGE & 0x1) 2092 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2093 { 2094 uint32_t * tab = (uint32_t *)buffer; 2095 uint32_t line , word; 2096 printk("\n***** %s : First 64 words of page %d in <%s> mapper\n", 2097 __FUNCTION__, page_id, name ); 2098 for( line = 0 ; line < 8 ; line++ ) 2099 { 2100 printk("%X : ", line ); 2101 for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] ); 2102 printk("\n"); 2103 } 2104 } 2105 #endif 2106 2107 #if DEBUG_FATFS_MOVE_PAGE 2108 cycle = (uint32_t)hal_get_cycles(); 2109 if(DEBUG_FATFS_MOVE_PAGE < cycle) 2110 { 2111 if(to_mapper) 2112 printk("\n[%s] thread[%x,%x] load page %d of <%s> inode / cycle %d\n", 2113 __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle ); 2114 else 2115 printk("\n[%s] thread[%x,%x] sync page %d of <%s> inode / cycle %d\n", 2116 __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle ); 2117 } 2118 #endif 2119 2120 } 2121 2122 return 0; 2123 2124 } // end fatfs_move_page() 2125 2126 -
trunk/kernel/fs/fatfs.h
r484 r602 3 3 * 4 4 * Author Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017 )5 * Alain Greiner (2016,2017,2018) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 27 27 28 28 #include <hal_kernel_types.h> 29 #include <r wlock.h>29 #include <remote_queuelock.h> 30 30 #include <vfs.h> 31 31 … … 35 35 // 36 36 // The FATFS extensions to the generic VFS are the following: 37 // 37 38 // 1) The vfs_ctx_t "extend" field is a void* pointing on the fatfs_ctx_t structure. 38 39 // This structure contains various general informations such as the total … … 41 42 // cluster index for the root directory. It contains also an extended pointer 42 43 // on the FAT mapper. 43 // 2) The vfs_inode_t "extend" field is a void*, but contains for each inode, 44 // 45 // 2) The vfs_inode_t "extend" contains, for each inode, 44 46 // the first FAT cluster index (after cast to intptr). 47 // 48 // 3) The vfs_dentry_t "extend" field contains, for each dentry, the entry index 49 // in the FATFS directory (32 bytes per FATFS entry). 45 50 /////////////////////////////////////////////////////////////////////////////////////////// 46 51 … … 163 168 struct vfs_ctx_s; 164 169 struct vfs_inode_s; 165 166 /***************************************************************************************** 167 * This structure defines a FATFS specific context (extension to VFS context). 170 struct vfs_dentry_s; 171 172 /***************************************************************************************** 173 * This structure defines a FATFS specific context (extension to VFS context). 174 * This extension is replicated in all clusters. 175 * 176 * WARNING : Almost all fields are constant values, but the <free_cluster_hint> and 177 * <free_clusters> are shared variables. All kernel instances use the variables 178 * in cluster 0, using the <free_lock> remote busy_lock for exclusive access. 168 179 ****************************************************************************************/ 169 180 170 181 typedef struct fatfs_ctx_s 171 182 { 172 uint32_t fat_sectors_count; /*! number of sectors in FAT region */ 173 uint32_t bytes_per_sector; /*! number of bytes per sector */ 174 uint32_t sectors_per_cluster; /*! number of sectors per cluster */ 175 uint32_t fat_begin_lba; /*! lba of FAT region */ 176 uint32_t cluster_begin_lba; /*! lba of data region */ 177 uint32_t root_dir_cluster; /*! cluster index for the root directory */ 178 uint32_t last_allocated_sector; /*! TODO ??? */ 179 uint32_t last_allocated_index; /*! TODO ??? */ 180 xptr_t fat_mapper_xp; /*! FAT mapper (in IO cluster) */ 183 uint32_t fat_sectors_count; /*! number of sectors in FAT region */ 184 uint32_t bytes_per_sector; /*! number of bytes per sector */ 185 uint32_t sectors_per_cluster; /*! number of sectors per cluster */ 186 uint32_t fat_begin_lba; /*! lba of FAT region */ 187 uint32_t cluster_begin_lba; /*! lba of data region */ 188 uint32_t fs_info_lba; /*! lba of FS_INFO sector */ 189 uint32_t root_dir_cluster; /*! cluster index for root directory */ 190 xptr_t fat_mapper_xp; /*! extended pointer on FAT mapper */ 191 uint32_t free_cluster_hint; /*! start point to search free cluster */ 192 uint32_t free_clusters; /*! free clusters number */ 193 remote_queuelock_t free_lock; /*! exclusive access to hint & number */ 181 194 } 182 195 fatfs_ctx_t; … … 186 199 ////////////////////////////////////////////////////////////////////////////////////////// 187 200 188 /****************************************************************************************** 189 * This 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 * We can use a RPC to scan the remote FAT mapper, because the RPC_FIFO will avoid 193 * contention in the cluster containing the FAT mapper, and the RPC latency is not 194 * critical compared to the device access latency. 201 /***************************************************************************************** 202 * This function access the FAT (File Allocation Table), stored in the FAT mapper, and 203 * returns in <searched_cluster> the FATFS cluster index for a given page of a given 204 * inode identified by the <first_cluster> and <page_id> arguments. 205 * It can be called by a thread running in any cluster, as it uses remote access 206 * primitives when the FAT mapper is remote. 195 207 * The FAT is actually an array of uint32_t slots. Each slot in this array contains the 196 208 * index of another slot in this array, to form one linked list for each file stored on … … 198 210 * FATFS cluster on the device. One FATFS cluster is supposed to contain one PPM page. 199 211 * For a given file, the entry point in the FAT is simply the index of the FATFS cluster 200 * containing the first page of the file. The mapper being a cache, this function 201 * automatically updates the FAT mapper from informations stored on device in case of miss. 202 ****************************************************************************************** 203 * @ mapper : local pointer on the FAT mapper. 204 * @ first_cluster : index of the first FATFS cluster allocated to the file. 205 * @ page_index : index of searched page in file. 206 * @ searched_cluster_id : [out] found FATFS cluster index. 207 * @ return 0 if success / return EIO if a FAT mapper miss cannot be solved. 208 *****************************************************************************************/ 209 error_t fatfs_get_cluster( struct mapper_s * mapper, 210 uint32_t first_cluster, 211 uint32_t page_index, 212 uint32_t * searched_cluster_id ); 213 214 /****************************************************************************************** 212 * containing the first page of the file. The FAT mapper being a cache, this function 213 * updates the FAT mapper from informations stored on IOC device in case of miss. 214 ***************************************************************************************** 215 * @ first_cluster : [in] index of first FATFS cluster allocated to the file. 216 * @ page_id : [in] index of searched page in file. 217 * @ searched_cluster : [out] found FATFS cluster index. 218 * @ return 0 if success / return -1 if a FAT mapper miss cannot be solved. 219 ****************************************************************************************/ 220 error_t fatfs_get_cluster( uint32_t first_cluster, 221 uint32_t page_id, 222 uint32_t * searched_cluster ); 223 224 /***************************************************************************************** 215 225 * This function display the content of the FATFS context. 216 **************************************************************************************** */226 ****************************************************************************************/ 217 227 void fatfs_ctx_display( void ); 218 228 229 /***************************************************************************************** 230 * This function displays the content of a part of the File Allocation Table. 231 * It loads the requested page fom device to mapper if required. 232 ***************************************************************************************** 233 * @ page_id : page index in FAT mapper (one page is 4 Kbytes). 234 * @ nentries : number of entries (one entry is 4 bytes). 235 ****************************************************************************************/ 236 void fatfs_display_fat( uint32_t page_id, 237 uint32_t nentries ); 238 239 219 240 220 241 ////////////////////////////////////////////////////////////////////////////////////////// 221 // Generic API: These functions are called by the kernel ,242 // Generic API: These functions are called by the kernel VFS, 222 243 // and must be implemented by all File Systems. 223 244 ////////////////////////////////////////////////////////////////////////////////////////// 224 245 225 /***************************************************************************************** *246 /***************************************************************************************** 226 247 * This fuction allocates memory from local cluster for a FATFS context descriptor. 227 ***************************************************************************************** *248 ***************************************************************************************** 228 249 * @ return a pointer on the created context / return NULL if failure. 229 **************************************************************************************** */250 ****************************************************************************************/ 230 251 fatfs_ctx_t * fatfs_ctx_alloc( void ); 231 252 232 253 /***************************************************************************************** 233 * This function access the boot device, and initialises the FATFS context254 * This function access the boot device, and initialises the local FATFS context 234 255 * from informations contained in the boot record. 235 256 ***************************************************************************************** … … 246 267 247 268 /***************************************************************************************** 248 * This function moves a page from/to the mapper to/from the FATFS file system on device. 249 * It must be called by a thread running in cluster containing the mapper. 250 * The pointer on the mapper and the page index in file are found in the page descriptor. 251 * WARNING : The inode field in the mapper MUST be NULL for the FAT mapper, as this 252 * is used to implement a specific behaviour to access the FAT zone on device. 253 ***************************************************************************************** 254 * @ page : local pointer on page descriptor. 255 * @ to_mapper : transfer direction 256 * @ return 0 if success / return EIO if error. 257 ****************************************************************************************/ 258 error_t fatfs_mapper_move_page( struct page_s * page, 259 bool_t to_mapper ); 260 261 /***************************************************************************************** 262 * This function scan an existing parent directory, identified by the <parent> argument, 263 * to find a directory entry identified by the <name> argument and update the remote 264 * child inode descriptor, identified by the <child_xp> argument. 265 * It set the "type", "size", and "extend" (FAT cluster index) fields in child inode. 269 * This function implements the generic vfs_fs_add_dentry() function for the FATFS. 270 ***************************************************************************************** 271 * This function updates a directory identified by the <inode> argument 272 * to add a new directory entry identified by the <dentry> argument. 273 * All modified pages in directory mapper are synchronously updated on IOC device. 274 * It must be called by a thread running in the cluster containing the inode. 275 * 276 * Implementation note : this function works in two steps: 277 * - It scan the set of 32 bytes FATFS directry entries, using two embedded loops 278 * to find the end of directory (NO_MORE_ENTRY marker). 279 * - Then it writes 3, 4, or 5 directory entries (depending on the name length), using 280 * a 5 steps FSM (one state per entry to be written), updates on IOC device the 281 * modified pages, and updates the dentry extension field, that must contain 282 * the dentry index in FATFS directory. 283 ***************************************************************************************** 284 * @ inode : local pointer on directory inode. 285 * @ dentry : local pointer on dentry. 286 * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device. 287 ****************************************************************************************/ 288 error_t fatfs_add_dentry( struct vfs_inode_s * inode, 289 struct vfs_dentry_s * dentry ); 290 291 /***************************************************************************************** 292 * This function implements the generic vfs_fs_remove_dentry() function for the FATFS. 293 ***************************************************************************************** 294 * This function updates a directory identified by the <inode> argument 295 * to remove a directory entry identified by the <dentry> argument. 296 * All modified pages in directory mapper are synchronously updated on IOC device. 297 * It must be called by a thread running in the cluster containing the inode. 298 * 299 * Implementation note: this function uses the dentry extension to directly access 300 * the NORMAL directory entry and invalidate all involved LFN entries. Then it 301 * updates the modified pages on IOC device. 302 ***************************************************************************************** 303 * @ inode : local pointer on directory inode. 304 * @ dentry : local pointer on dentry. 305 * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device. 306 ****************************************************************************************/ 307 error_t fatfs_remove_dentry( struct vfs_inode_s * inode, 308 struct vfs_dentry_s * dentry ); 309 310 /***************************************************************************************** 311 * This function implements the generic vfs_fs_child_init() function for the FATFS. 312 ***************************************************************************************** 313 * It scan the mapper of an existing parent directory, identified by the <parent> 314 * argument, to find a directory entry identified by the <name> argument. 315 * It updates the existing remote child inode, identified by the <child_xp> argument, 316 * - it set the "type", "size", and "extend" fields in inode descriptor. 317 * - it set the " extend" field in dentry descriptor. 266 318 * It must be called by a thread running in the cluster containing the parent inode. 267 319 ***************************************************************************************** … … 271 323 * @ return 0 if success / return ENOENT if child not found. 272 324 ****************************************************************************************/ 273 error_t fatfs_ inode_load( struct vfs_inode_s * parent_inode,325 error_t fatfs_child_init( struct vfs_inode_s * parent_inode, 274 326 char * name, 275 327 xptr_t child_inode_xp ); 276 328 329 /***************************************************************************************** 330 * This function implements the generic vfs_fs_sync_inode() function for the FATFS. 331 ***************************************************************************************** 332 * It updates the FATFS on the IOC device for a given inode identified by 333 * the <inode> argument. It scan all pages registered in the associated mapper, 334 * and copies from mapper to device each page marked as dirty. 335 * WARNING : The target <inode> cannot be a directory, because all modifications in a 336 * directory * are synchronously done on the IOC device by the two fatfs_add_dentry() 337 * and fatfs_remove_dentry() functions. 338 ***************************************************************************************** 339 * @ inode : local pointer on inode. 340 * @ return 0 if success / return EIO if failure during device access. 341 ****************************************************************************************/ 342 error_t fatfs_sync_inode( struct vfs_inode_s * inode ); 343 344 /***************************************************************************************** 345 * This function implements the generic vfs_fs_sync_fat() function for the FATFS. 346 ***************************************************************************************** 347 * It updates the FATFS on the IOC device for the FAT itself. 348 * It scan all clusters registered in the FAT mapper, and copies from mapper to device 349 * each page marked as dirty. 350 * 351 * TODO : the current implementation check ALL pages in the FAT region, even if most 352 * pages are empty, and not copied in mapper. It is sub-optimal. 353 * - A first solution is to maintain in the FAT context two "dirty_min" and "dirty_max" 354 * variables defining the smallest/largest dirty page index in FAT mapper... 355 ***************************************************************************************** 356 * @ return 0 if success / return EIO if failure during device access. 357 ****************************************************************************************/ 358 error_t fatfs_sync_fat( void ); 359 360 /***************************************************************************************** 361 * This function implements the generic vfs_fs_sync_fsinfo() function for the FATFS. 362 ***************************************************************************************** 363 * It updates the FS_INFO sector on the IOC device. 364 * It copies the <free_cluster_hint> and <free_clusters> variables from 365 * the FATFS context in cluster 0 to the FS_INFO sector on device. 366 ***************************************************************************************** 367 * @ return 0 if success / return EIO if failure during device access. 368 ****************************************************************************************/ 369 error_t fatfs_sync_free_info( void ); 370 371 /***************************************************************************************** 372 * This function implements the generic vfs_fs_cluster_alloc() function for the FATFS. 373 ***************************************************************************************** 374 * It access the FAT (File allocation table), stored in the FAT mapper, and returns 375 * in <searched_cluster> the FATFS cluster index of a free cluster. 376 * It can be called by a thread running in any cluster, as it uses remote access 377 * primitives when the FAT mapper is remote. It takes the "free_lock" stored in the 378 * FATFS context located in the same cluster as the FAT mapper itself, to get exclusive 379 * access to the FAT. It uses (and updates) the <free_cluster_hint> and <free_clusters> 380 * shared variables in this FATFS context. 381 * It updates the FAT mapper, and synchronously updates the FAT region on IOC device. 382 * The FAT mapper being a cache, this function updates the FAT mapper from informations 383 * stored on IOC device in case of miss. 384 ***************************************************************************************** 385 * @ searched_cluster : [out] found FATFS cluster index. 386 * @ return 0 if success / return -1 if no more free clusters on IOC device. 387 ****************************************************************************************/ 388 error_t fatfs_cluster_alloc( uint32_t * searched_cluster ); 389 390 /***************************************************************************************** 391 * This function implements the generic vfs_fs_release_inode() function for the FATFS. 392 ***************************************************************************************** 393 * It releases all clusters allocated to a file/directory identified by the <inode_xp> 394 * argument. All released clusters are marked FREE_CLUSTER in the FAT mapper. 395 * This function calls the recursive function fatfs_cluster_release() to release 396 * the clusters in reverse order of the linked list (from last to first). 397 * When the FAT mapper has been updated, it calls the fatfs_sync_fat() function to 398 * synchronously update all dirty pages in the FAT mapper to the IOC device. 399 * Finally the FS-INFO sector on the IOC device is updated. 400 ***************************************************************************************** 401 * @ inode_xp : extended pointer on inode. 402 * @ return 0 if success / return EIO if failure during device access. 403 ****************************************************************************************/ 404 error_t fatfs_release_inode( xptr_t inode_xp ); 405 406 /***************************************************************************************** 407 * This function implements the generic vfs_fs_move_page() function for the FATFS. 408 ***************************************************************************************** 409 * This function moves a page from/to the mapper to/from the FATFS file system on device. 410 * The page must have been previously allocated and registered in the mapper, but the 411 * page - and the mapper - can be located in another cluster than the calling thread. 412 * The pointer on the mapper and the page index in file are found in the page descriptor. 413 * It is used both for the regular file/directory mappers, and for the FAT mapper. 414 * For the FAT mapper, it access the FATFS to get the location on IOC device. 415 * For a regular file, it access the FAT mapper to get the cluster index on IOC device. 416 * It can be called by any thread running in any cluster. 417 * 418 * WARNING : For the FAT mapper, the inode field in the mapper MUST be NULL, as this 419 * is used to indicate that the corresponding mapper is the FAT mapper. 420 ***************************************************************************************** 421 * @ page_xp : extended pointer on page descriptor. 422 * @ to_mapper : true for device->mapper / false for mapper->device 423 * @ return 0 if success / return EIO if error during device access. 424 ****************************************************************************************/ 425 error_t fatfs_move_page( xptr_t page_xp, 426 bool_t to_mapper ); 427 428 429 430 431 432 277 433 #endif /* _FATFS_H_ */ -
trunk/kernel/fs/ramfs.c
r568 r602 35 35 char * ramfs_root_name ) 36 36 { 37 xptr_t root_inode_xp; // unused37 xptr_t unused_xp; // required by vfs_add_child_in_parent() 38 38 39 39 cxy_t cxy = cluster_random_select(); … … 45 45 parent_inode_xp, 46 46 ramfs_root_name, 47 NULL,48 & root_inode_xp );47 &unused_xp, 48 &unused_xp ); 49 49 } 50 50 -
trunk/kernel/fs/vfs.c
r598 r602 57 57 extern char * lock_type_str[]; // allocated in kernel_init.c 58 58 59 ////////////////////////////////////////////////////////////////////////////////////////// 60 // Context related functions59 /////////////////////////////////////////////////////////////////////////////////////////// 60 // VFS Context related functions 61 61 ////////////////////////////////////////////////////////////////////////////////////////// 62 62 … … 123 123 124 124 ////////////////////////////////////////////////////////////////////////////////////////// 125 // Inoderelated functions125 // VFS inode descriptor related functions 126 126 ////////////////////////////////////////////////////////////////////////////////////////// 127 127 … … 145 145 vfs_fs_type_t fs_type, 146 146 vfs_inode_type_t inode_type, 147 void * extend,148 147 uint32_t attr, 149 148 uint32_t rights, … … 228 227 inode->ctx = ctx; 229 228 inode->mapper = mapper; 230 inode->extend = extend;229 inode->extend = NULL; 231 230 232 231 // initialise inode field in mapper … … 258 257 } // end vfs_inode_create() 259 258 260 //////////////////////////////////////////////// 261 error_t vfs_inode_destroy( vfs_inode_t * inode ) 262 { 263 assert( (inode->refcount == 0) , "inode refcount non zero\n" ); 259 ///////////////////////////////////////////// 260 void vfs_inode_destroy( vfs_inode_t * inode ) 261 { 262 263 // check inode refcount 264 assert( (inode->refcount == 0) , "inode refcount non zero\n" ); 264 265 265 266 // release memory allocated for mapper … … 272 273 kmem_free( &req ); 273 274 274 return 0;275 276 275 } // end vfs_inode_destroy() 277 278 /////////////////////////////////////////////279 error_t vfs_inode_load( vfs_inode_t * parent,280 char * name,281 xptr_t child_xp )282 {283 284 #if DEBUG_VFS_INODE_LOAD285 uint32_t cycle = (uint32_t)hal_get_cycles();286 if( DEBUG_VFS_INODE_LOAD < cycle )287 printk("\n[%s] thread %x enter for <%s> / cycle %d\n",288 __FUNCTION__, CURRENT_THREAD , name , cycle );289 #endif290 291 error_t error = 0;292 293 assert( (parent != NULL) , "parent pointer is NULL\n");294 295 assert( (child_xp != XPTR_NULL) , "child pointer is NULL\n");296 297 // get parent inode FS type298 vfs_fs_type_t fs_type = parent->ctx->type;299 300 // call relevant FS function301 if( fs_type == FS_TYPE_FATFS )302 {303 error = fatfs_inode_load( parent , name , child_xp );304 }305 else if( fs_type == FS_TYPE_RAMFS )306 {307 assert( false , "should not be called for RAMFS\n" );308 }309 else if( fs_type == FS_TYPE_DEVFS )310 {311 assert( false , "should not be called for DEVFS\n" );312 }313 else314 {315 assert( false , "undefined file system type\n" );316 }317 318 #if DEBUG_VFS_INODE_LOAD319 cycle = (uint32_t)hal_get_cycles();320 if( DEBUG_VFS_INODE_LOAD < cycle )321 printk("\n[%s] thread %x exit for <%s> / cycle %d\n",322 __FUNCTION__, CURRENT_THREAD , name , cycle );323 #endif324 325 return error;326 327 } // end vfs_inode_load()328 276 329 277 //////////////////////////////////////////// … … 429 377 } // end vfs_inode_get_name() 430 378 379 /////////////////////////////////////////////////////// 380 error_t vfs_inode_load_all_pages( vfs_inode_t * inode ) 381 { 382 383 assert( (inode != NULL) , "inode pointer is NULL\n" ); 384 385 uint32_t page_id; 386 xptr_t page_xp; 387 388 mapper_t * mapper = inode->mapper; 389 uint32_t size = inode->size; 390 391 assert( (mapper != NULL) , "mapper pointer is NULL\n" ); 392 393 #if DEBUG_VFS_INODE_LOAD_ALL 394 uint32_t cycle = (uint32_t)hal_get_cycles(); 395 thread_t * this = CURRENT_THREAD; 396 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 397 vfs_inode_get_name( XPTR( local_cxy , inode ) , name ); 398 if( DEBUG_VFS_INODE_LOAD_ALL < cycle ) 399 printk("\n[%s] thread[%x,%x] enter for <%s> in cluster %x / cycle %d\n", 400 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle ); 401 #endif 402 403 // compute number of pages 404 uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT; 405 if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++; 406 407 // loop on pages 408 for( page_id = 0 ; page_id < npages ; page_id ++ ) 409 { 410 // If the mage is missing, this function allocates the missing page, 411 // and load the page from IOC device into mapper 412 page_xp = mapper_remote_get_page( XPTR( local_cxy , mapper ), page_id ); 413 414 if( page_xp == XPTR_NULL ) return -1; 415 } 416 417 #if DEBUG_VFS_INODE_LOAD_ALL 418 cycle = (uint32_t)hal_get_cycles(); 419 if( DEBUG_VFS_INODE_LOAD_ALL < cycle ) 420 printk("\n[%s] thread[%x,%x] exit for <%x> in cluster %x / cycle %d\n", 421 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle ); 422 #endif 423 424 return 0; 425 426 } // end vfs_inode_load_all_pages() 427 431 428 //////////////////////////////////////////////////////////////////////////////////////////// 432 // Dentryrelated functions429 // VFS dentry descriptor related functions 433 430 ////////////////////////////////////////////////////////////////////////////////////////// 434 431 … … 480 477 dentry->length = length; 481 478 dentry->parent = parent; 479 dentry->extend = NULL; 482 480 strcpy( dentry->name , name ); 483 481 … … 509 507 cycle = (uint32_t)hal_get_cycles(); 510 508 if( DEBUG_VFS_DENTRY_CREATE < cycle ) 511 printk("\n[%s] thread[%x,%x] exit for <%s> / dentry %x/ cycle %d\n",512 __FUNCTION__, this->process->pid, this->trdid, name, dentry, cycle );509 printk("\n[%s] thread[%x,%x] exit for <%s> / dentry [%x,%x] / cycle %d\n", 510 __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, dentry, cycle ); 513 511 #endif 514 512 … … 517 515 } // end vfs_dentry_create() 518 516 519 //////////////////////////////////////////////// ///520 error_tvfs_dentry_destroy( vfs_dentry_t * dentry )521 { 522 error_t error; 523 524 assert( (dentry->refcount == 0) , __FUNCTION__, "dentry refcount non zero\n" );517 //////////////////////////////////////////////// 518 void vfs_dentry_destroy( vfs_dentry_t * dentry ) 519 { 520 521 // check dentry refcount 522 assert( (dentry->refcount == 0) , "dentry refcount non zero\n" ); 525 523 526 524 // get pointer on parent inode … … 528 526 529 527 // remove this dentry from parent inode htab 530 error = xhtab_remove( XPTR( local_cxy , &parent->children ), 531 dentry->name, 532 XPTR( local_cxy , &dentry->list ) ); 533 534 if( error ) return EINVAL; 528 xhtab_remove( XPTR( local_cxy , &parent->children ), 529 dentry->name, 530 XPTR( local_cxy , &dentry->list ) ); 535 531 536 532 // release memory allocated to dentry … … 540 536 kmem_free( &req ); 541 537 542 return 0; 538 } // end vfs_dentry_destroy() 539 540 ////////////////////////////////////////////// 541 void vfs_dentry_remote_up( xptr_t dentry_xp ) 542 { 543 // get dentry cluster and local pointer 544 cxy_t dentry_cxy = GET_CXY( dentry_xp ); 545 vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); 546 547 hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , 1 ); 543 548 } 544 549 550 //////////////////////////////////////////////// 551 void vfs_dentry_remote_down( xptr_t dentry_xp ) 552 { 553 // get dentry cluster and local pointer 554 cxy_t dentry_cxy = GET_CXY( dentry_xp ); 555 vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); 556 557 hal_remote_atomic_add( XPTR( dentry_cxy , &dentry_ptr->refcount ) , -1 ); 558 } 559 545 560 546 561 547 562 ////////////////////////////////////////////////////////////////////////////////////////// 548 // File descriptor related functions563 // VFS file descriptor related functions 549 564 ////////////////////////////////////////////////////////////////////////////////////////// 550 565 … … 645 660 646 661 ////////////////////////////////////////////////////////////////////////////////////////// 647 // File accessrelated functions662 // "syscalls" API related functions 648 663 ////////////////////////////////////////////////////////////////////////////////////////// 649 664 … … 665 680 uint32_t file_id; // created file descriptor index in reference fd_array 666 681 667 assert( (mode == 0), __FUNCTION__, 668 "the mode parameter is not supported yet\n" ); 682 683 if( mode != 0 ) 684 { 685 printk("\n[ERROR] in %s : the mode parameter is not supported yet\n" ); 686 return -1; 687 } 669 688 670 689 #if DEBUG_VFS_OPEN … … 736 755 uint32_t size ) 737 756 { 738 assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );739 740 757 cxy_t file_cxy; // remote file descriptor cluster 741 758 vfs_file_t * file_ptr; // remote file descriptor local pointer … … 745 762 error_t error; 746 763 764 // check argument 765 assert( (file_xp != XPTR_NULL), "file_xp == XPTR_NULL\n" ); 766 747 767 // get cluster and local pointer on remote file descriptor 748 768 file_cxy = GET_CXY( file_xp ); … … 752 772 inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 753 773 754 assert( (inode_type == INODE_TYPE_FILE) , 755 774 // check inode type 775 assert( (inode_type == INODE_TYPE_FILE), "inode type is not INODE_TYPE_FILE" ); 756 776 757 777 // get mapper pointer and file offset from file descriptor … … 770 790 else 771 791 { 772 rpc_mapper_move_buffer_client( file_cxy, 773 mapper, 774 to_buffer, 775 true, // user buffer 776 file_offset, 777 (uint64_t)(intptr_t)buffer, 778 size, 779 &error ); 792 rpc_mapper_move_user_client( file_cxy, 793 mapper, 794 to_buffer, 795 file_offset, 796 buffer, 797 size, 798 &error ); 780 799 } 781 800 782 if( error ) return -1; 783 else return size; 801 // update file offset in file descriptor 802 hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->offset ) , size ); 803 804 if( error ) 805 { 806 return -1; 807 } 808 809 return size; 784 810 785 811 } // end vfs_user_move() … … 791 817 uint32_t size ) 792 818 { 793 assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );794 795 819 cxy_t file_cxy; // remote file descriptor cluster 796 820 vfs_file_t * file_ptr; // remote file descriptor local pointer 797 vfs_inode_type_t inode_type; 821 vfs_inode_type_t inode_type; // remote file type 798 822 uint32_t file_offset; // current offset in file 799 mapper_t * mapper; 823 mapper_t * mapper_ptr; // remote mapper local pointer 824 xptr_t mapper_xp; // remote mapper extended pointer 800 825 error_t error; 826 827 // check argument 828 assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" ); 801 829 802 830 // get cluster and local pointer on remote file descriptor … … 810 838 if( inode_type == INODE_TYPE_FILE ) 811 839 { 812 // get mapper pointer and file offset from file descriptor840 // get mapper pointers and file offset from file descriptor 813 841 file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) ); 814 mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) ); 842 mapper_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) ); 843 mapper_xp = XPTR( file_cxy , mapper_ptr ); 815 844 816 845 // move data between mapper and buffer 817 if( file_cxy == local_cxy ) 818 { 819 error = mapper_move_kernel( mapper, 820 to_buffer, 821 file_offset, 822 buffer_xp, 823 size ); 824 } 825 else 826 { 827 rpc_mapper_move_buffer_client( file_cxy, 828 mapper, 829 to_buffer, 830 false, // kernel buffer 831 file_offset, 832 buffer_xp, 833 size, 834 &error ); 835 } 836 846 error = mapper_move_kernel( mapper_xp, 847 to_buffer, 848 file_offset, 849 buffer_xp, 850 size ); 837 851 if( error ) return -1; 838 else return 0;839 852 } 840 853 else … … 843 856 return -1; 844 857 } 858 859 return 0; 860 845 861 } // end vfs_kernel_move() 846 862 … … 853 869 xptr_t offset_xp; 854 870 xptr_t lock_xp; 871 xptr_t size_xp; 855 872 cxy_t file_cxy; 856 873 vfs_file_t * file_ptr; … … 858 875 uint32_t new; 859 876 860 assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" ); 877 // check argument 878 assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" ); 861 879 862 880 // get cluster and local pointer on remote file descriptor … … 864 882 file_ptr = GET_PTR( file_xp ); 865 883 866 // build extended pointers on lock and offset 884 // get local pointer on remote inode 885 inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) ); 886 887 // build extended pointers on lock, offset and size 867 888 offset_xp = XPTR( file_cxy , &file_ptr->offset ); 868 889 lock_xp = XPTR( file_cxy , &file_ptr->lock ); 890 size_xp = XPTR( file_cxy , &inode_ptr->size ); 869 891 870 892 // take file descriptor lock … … 881 903 else if ( whence == SEEK_END ) // new = size + offset 882 904 { 883 // get local pointer on remote inode 884 inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) ); 885 886 new = hal_remote_l32( XPTR( file_cxy , &inode_ptr->size ) ) + offset; 905 new = hal_remote_l32( size_xp ) + offset; 887 906 } 888 907 else … … 893 912 } 894 913 914 #if DEBUG_VFS_LSEEK 915 uint32_t cycle = (uint32_t)hal_get_cycles(); 916 thread_t * this = CURRENT_THREAD; 917 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 918 vfs_inode_get_name( XPTR( file_cxy , inode_ptr ) , name ); 919 if( cycle > DEBUG_VFS_LSEEK ) 920 printk("\n[%s] thread[%x,%x] for <%s> / new offset %d / cycle %d\n", 921 __FUNCTION__ , this->process->pid, this->trdid, name, new, cycle ); 922 #endif 923 895 924 // set new offset 896 925 hal_remote_s32( offset_xp , new ); … … 900 929 901 930 // success 902 if ( new_offset != NULL ) 903 *new_offset = new; 931 if ( new_offset != NULL ) *new_offset = new; 904 932 return 0; 905 933 … … 922 950 process_t * process_ptr; // process copy local pointer 923 951 924 assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" ); 925 926 assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , "illegal file_id" );952 // check arguments 953 assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" ); 954 assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , "illegal file_id\n" ); 927 955 928 956 thread_t * this = CURRENT_THREAD; … … 1019 1047 char * path ) 1020 1048 { 1021 assert( false , "not implemented cwd_xp %x, path <%s> \n", 1022 cwd_xp, path ); 1023 return 0; 1024 } 1049 error_t error; 1050 xptr_t inode_xp; // extended pointer on target inode 1051 cxy_t inode_cxy; // target inode cluster identifier 1052 vfs_inode_t * inode_ptr; // target inode local pointer 1053 uint32_t inode_refcount; // target inode refcount 1054 vfs_inode_type_t type; // target inode type 1055 mapper_t * mapper; // pointer on target inode mapper 1056 xptr_t dentry_xp; // extended pointer on target dentry 1057 cxy_t dentry_cxy; // target dentry cluster identifier 1058 vfs_dentry_t * dentry_ptr; // target dentry local pointer 1059 uint32_t dentry_refcount; // target dentry refcount 1060 vfs_inode_t * dentry_parent_ptr; // parent inode local pointer 1061 1062 #if DEBUG_VFS_UNLINK 1063 thread_t * this = CURRENT_THREAD; 1064 uint32_t cycle = (uint32_t)hal_get_cycles(); 1065 if( DEBUG_VFS_UNLINK < cycle ) 1066 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n", 1067 __FUNCTION__, this->process->pid, this->trdid, path, cycle ); 1068 #endif 1069 1070 // get extended pointer on target inode 1071 error = vfs_lookup( cwd_xp , path , 0 , &inode_xp ); 1072 1073 if( error ) return error; 1074 1075 // get inode cluster and local pointer 1076 inode_cxy = GET_CXY( inode_xp ); 1077 inode_ptr = GET_PTR( inode_xp ); 1078 1079 // get inode type, refcount, mapper, dentry_xp 1080 type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) ); 1081 inode_refcount = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) ); 1082 mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) ); 1083 dentry_xp = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 1084 1085 // get dentry cluster, local pointer, refcount, and pointers on parent inode 1086 dentry_ptr = GET_PTR( dentry_xp ); 1087 dentry_cxy = GET_CXY( dentry_xp ); 1088 dentry_refcount = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) ); 1089 dentry_parent_ptr = hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) ); 1090 1091 // check inode & dentry refcount 1092 assert( (inode_refcount == 1), "illegal inode refcount for <%s>\n", path ); 1093 assert( (dentry_refcount == 1), "illegal dentry refcount for <%s>\n", path ); 1094 1095 ///////////////////////////// 1096 if( type == INODE_TYPE_FILE ) 1097 { 1098 // 1. release clusters allocated to file in the FAT mapper 1099 // synchronize the FAT on IOC device 1100 error = vfs_fs_release_inode( inode_xp ); 1101 if( error ) 1102 { 1103 printk("\n[ERROR] in %s : cannot update FAT mapper <%s>\n", path ); 1104 return -1; 1105 } 1106 1107 #if(DEBUG_VFS_UNLINK & 1) 1108 if( DEBUG_VFS_UNLINK < cycle ) 1109 printk("\n[%s] thread[%x,%x] removed <%s> inode from FAT (mapper and IOC device)\n", 1110 __FUNCTION__, this->process->pid, this->trdid, path ); 1111 #endif 1112 1113 // 2. update parent directory in Inode Tree 1114 // synchronize the parent directory on IOC device 1115 if (dentry_cxy == local_cxy) // dentry is local 1116 { 1117 error = vfs_fs_remove_dentry( dentry_parent_ptr, 1118 dentry_ptr ); 1119 } 1120 else // dentry is remote 1121 { 1122 rpc_vfs_fs_remove_dentry_client( dentry_cxy, 1123 dentry_parent_ptr, 1124 dentry_ptr, 1125 &error ); 1126 } 1127 if( error ) 1128 { 1129 printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n", path ); 1130 return -1; 1131 } 1132 1133 #if(DEBUG_VFS_UNLINK & 1) 1134 if( DEBUG_VFS_UNLINK < cycle ) 1135 printk("\n[%s] thread[%x,%x] removed <%s> inode from parent dir (mapper and IOC device)\n", 1136 __FUNCTION__, this->process->pid, this->trdid, path ); 1137 #endif 1138 // 3. remove inode (including mapper & dentry) from Inode Tree 1139 vfs_remove_child_from_parent( inode_xp ); 1140 1141 #if DEBUG_VFS_UNLINK 1142 if( DEBUG_VFS_UNLINK < cycle ) 1143 printk("\n[%s] thread[%x,%x] exit / removed <%s> inode from Inode Tree / cycle %d\n", 1144 __FUNCTION__, this->process->pid, this->trdid, path, cycle ); 1145 #endif 1146 return 0; 1147 } 1148 ///////////////////////////////// 1149 else if( type == INODE_TYPE_DIR ) 1150 { 1151 printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) ); 1152 return -1; 1153 } 1154 //// 1155 else 1156 { 1157 printk("\n[ERROR] in %s : unsupported type %s\n", vfs_inode_type_str( type ) ); 1158 return -1; 1159 } 1160 1161 } // end vfs_unlink() 1025 1162 1026 1163 ////////////////////////////////////// … … 1058 1195 1059 1196 return 0; 1060 } 1197 1198 } // end vfs_stat() 1061 1199 1062 1200 ///////////////////////////////////////////// … … 1172 1310 1173 1311 ////////////////////////////////////////////////////////////////////////////////////////// 1174 // Inode Treefunctions1312 // Distributed Inode Tree access related functions 1175 1313 ////////////////////////////////////////////////////////////////////////////////////////// 1176 1314 … … 1336 1474 } // end vfs_display() 1337 1475 1476 /* 1338 1477 ////////////////////////////////////////////////////////////////////////////////////////// 1339 // This function is used by the vfs_lookup() function.1478 // This static function is used by the vfs_lookup() function. 1340 1479 // It takes an extended pointer on a remote inode (parent directory inode), 1341 1480 // and check access_rights violation for the calling thread. … … 1347 1486 // @ return true if access rights are violated. 1348 1487 ////////////////////////////////////////////////////////////////////////////////////////// 1349 bool_t vfs_access_denied( xptr_t inode_xp,1488 static bool_t vfs_access_denied( xptr_t inode_xp, 1350 1489 uint32_t client_uid, 1351 1490 uint32_t client_gid ) … … 1364 1503 else return true; 1365 1504 } 1505 */ 1366 1506 1367 1507 ////////////////////////////////////////////////////////////////////////////////////////// … … 1465 1605 cxy_t parent_cxy; // cluster for parent inode 1466 1606 vfs_inode_t * parent_ptr; // local pointer on parent inode 1607 xptr_t dentry_xp; // extended pointer on dentry 1467 1608 xptr_t child_xp; // extended pointer on child inode 1468 1609 cxy_t child_cxy; // cluster for child inode 1469 vfs_inode_t * child_ptr; // local pointer on child inode 1610 vfs_inode_t * child_ptr; // local pointer on child inode 1611 vfs_inode_type_t child_type; // child inode type 1470 1612 vfs_fs_type_t fs_type; // File system type 1471 1613 vfs_ctx_t * ctx_ptr; // local pointer on FS context … … 1519 1661 #if (DEBUG_VFS_LOOKUP & 1) 1520 1662 if( DEBUG_VFS_LOOKUP < cycle ) 1521 printk("\n[%s] look for<%s> / last = %d\n",1522 __FUNCTION__ , name, last );1663 printk("\n[%s] thread[%x,%x] look for <%s> in <%s> / last = %d\n", 1664 __FUNCTION__, process->pid, this->trdid, name, pathname, last ); 1523 1665 #endif 1524 1666 … … 1533 1675 #if (DEBUG_VFS_LOOKUP & 1) 1534 1676 if( DEBUG_VFS_LOOKUP < cycle ) 1535 printk("\n[%s] miss <%s> node => try to create it\n",1536 __FUNCTION__ 1677 printk("\n[%s] thread[%x,%x] miss <%s> node => try to create it\n", 1678 __FUNCTION__, process->pid, this->trdid, name ); 1537 1679 #endif 1538 1680 // if a child node is not found in the inode tree, … … 1544 1686 // . if it is not found in the parent mapper: 1545 1687 // - if ( not last or not create ) an error is reported 1546 // - if (last and create and dir) a new directory is created 1547 // - if (last and create and not dir) a new file is created 1688 // - if (last and create) a new file or directory is created 1548 1689 1549 1690 // release lock on parent inode 1550 1691 vfs_inode_unlock( parent_xp ); 1551 1692 1552 // get parent inode FS type1693 // get parent inode cluster and local pointer 1553 1694 parent_cxy = GET_CXY( parent_xp ); 1554 1695 parent_ptr = GET_PTR( parent_xp ); 1555 ctx_ptr = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) ); 1696 1697 // get parent inode FS type 1698 ctx_ptr = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) ); 1556 1699 fs_type = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) ); 1557 1700 1558 1701 // select a cluster for missing inode 1559 1702 child_cxy = cluster_random_select(); 1703 1704 // define child inode type 1705 if( dir ) child_type = INODE_TYPE_DIR; 1706 else child_type = INODE_TYPE_FILE; 1560 1707 1561 1708 // insert a new child dentry/inode in inode tree 1562 1709 error = vfs_add_child_in_parent( child_cxy, 1563 0, // type will be updated later1710 child_type, 1564 1711 fs_type, 1565 1712 parent_xp, 1566 1713 name, 1567 NULL, // fs_type_specific inode extend1714 &dentry_xp, 1568 1715 &child_xp ); 1569 1716 if( error ) 1570 1717 { 1571 printk("\n[ERROR] in %s : cannot create node %s forpath <%s>\n",1718 printk("\n[ERROR] in %s : cannot create node <%s> in path <%s>\n", 1572 1719 __FUNCTION__ , name, pathname ); 1573 return ENOMEM;1720 return -1; 1574 1721 } 1575 1722 1576 // get child inode cluster and local pointer 1577 child_cxy = GET_CXY( child_xp ); 1723 // get child inode local pointer 1578 1724 child_ptr = GET_PTR( child_xp ); 1579 1725 1580 1726 #if (DEBUG_VFS_LOOKUP & 1) 1581 1727 if( DEBUG_VFS_LOOKUP < cycle ) 1582 printk("\n[%s] missing <%s> inode speculatively created / cxy %x / ptr %x\n", 1583 __FUNCTION__ , name , child_cxy, child_ptr ); 1584 #endif 1585 // scan parent mapper to complete the missing inode 1728 printk("\n[%s] thread[%x,%x] created missing inode <%s> in cluster %x\n", 1729 __FUNCTION__, process->pid, this->trdid, name, child_cxy ); 1730 #endif 1731 // scan parent mapper to find the missing dentry, and complete 1732 // the initialisation of dentry and child inode desciptors 1586 1733 if( parent_cxy == local_cxy ) 1734 1587 1735 { 1588 error = vfs_ inode_load( parent_ptr,1589 name,1590 child_xp );1736 error = vfs_fs_child_init( parent_ptr, 1737 name, 1738 child_xp ); 1591 1739 } 1592 1740 else 1593 1741 { 1594 rpc_vfs_ inode_load_client( parent_cxy,1595 parent_ptr,1596 name,1597 child_xp,1598 &error );1742 rpc_vfs_fs_child_init_client( parent_cxy, 1743 parent_ptr, 1744 name, 1745 child_xp, 1746 &error ); 1599 1747 } 1600 1748 1601 1749 if ( error ) // child not found in parent mapper 1602 1750 { 1603 if ( last && create && dir ) // new directory => update inode type1751 if ( last && create ) // add a new dentry in parent 1604 1752 { 1605 hal_remote_s32( XPTR( child_cxy, &child_ptr->type ), INODE_TYPE_DIR ); 1753 error = vfs_new_child_init( parent_xp, 1754 dentry_xp, 1755 child_xp ); 1756 if ( error ) 1757 { 1758 printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n", 1759 __FUNCTION__, name, pathname ); 1760 vfs_remove_child_from_parent( child_xp ); 1761 return -1; 1762 } 1606 1763 1607 1764 #if (DEBUG_VFS_LOOKUP & 1) 1608 1765 if( DEBUG_VFS_LOOKUP < cycle ) 1609 printk("\n[%s] created node <%s> in path %s / type DIR\n",1610 __FUNCTION__ , name, pathname );1766 printk("\n[%s] thread[%x,%x] created inode <%s> in path\n", 1767 __FUNCTION__, process->pid, this->trdid, name ); 1611 1768 #endif 1612 1769 } 1613 else if ( last && create ) // new file => update inode type 1614 { 1615 hal_remote_s32( XPTR( child_cxy, &child_ptr->type ), INODE_TYPE_FILE ); 1616 1617 #if (DEBUG_VFS_LOOKUP & 1) 1618 if( DEBUG_VFS_LOOKUP < cycle ) 1619 printk("\n[%s] created node <%s> in path %s / type FILE\n", 1620 __FUNCTION__ , name, pathname ); 1621 #endif 1622 } 1623 else // not last or not create => remove created node 1770 else // not last or not create => error 1624 1771 { 1625 1772 printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n", … … 1629 1776 } 1630 1777 } 1631 else // child found in parent 1778 else // child found in parent mapper 1632 1779 { 1633 1780 // load child mapper from device if child is a directory (prefetch) … … 1636 1783 if( child_cxy == local_cxy ) 1637 1784 { 1638 error = vfs_ mapper_load_all( child_ptr );1785 error = vfs_inode_load_all_pages( child_ptr ); 1639 1786 } 1640 1787 else 1641 1788 { 1642 rpc_vfs_ mapper_load_all_client( child_cxy,1643 child_ptr,1644 &error );1789 rpc_vfs_inode_load_all_pages_client( child_cxy, 1790 child_ptr, 1791 &error ); 1645 1792 } 1646 1793 if ( error ) … … 1654 1801 #if (DEBUG_VFS_LOOKUP & 1) 1655 1802 if( DEBUG_VFS_LOOKUP < cycle ) 1656 printk("\n[%s] load mapper from device for node <%s> in path %s\n",1657 __FUNCTION__ , name, pathname );1803 printk("\n[%s] thread[%x,%x] loaded from IOC device mapper for <%s> in <%s>\n", 1804 __FUNCTION__ , process->pid, this->trdid, name, pathname ); 1658 1805 #endif 1659 1806 } … … 1668 1815 #if (DEBUG_VFS_LOOKUP & 1) 1669 1816 if( DEBUG_VFS_LOOKUP < cycle ) 1670 printk("\n[%s] found <%s> / inode %x in cluster %x\n",1671 __FUNCTION__ , name , GET_PTR(child_xp), GET_CXY(child_xp) );1817 printk("\n[%s] thread[%x,%x] found <%s> / inode %x in cluster %x\n", 1818 __FUNCTION__, process->pid, this->trdid, name, GET_PTR(child_xp), GET_CXY(child_xp) ); 1672 1819 #endif 1673 1820 child_ptr = GET_PTR( child_xp ); … … 1710 1857 cycle = (uint32_t)hal_get_cycles(); 1711 1858 if( DEBUG_VFS_LOOKUP < cycle ) 1712 printk("\n[%s] thread[%x,%x] exit for <%s>\n" 1713 " parent %x in cluster %x / child %x in cluster %x / cycle %d\n", 1714 __FUNCTION__ , process->pid, this->trdid, pathname, 1715 parent_ptr, parent_cxy, child_ptr, child_cxy, cycle ); 1859 printk("\n[%s] thread[%x,%x] exit for <%s> cycle %d\n", 1860 __FUNCTION__ , process->pid, this->trdid, pathname, cycle ); 1716 1861 #endif 1717 1862 … … 1723 1868 1724 1869 } // end vfs_lookup() 1870 1871 1872 1873 /////////////////////////////////////////////// 1874 error_t vfs_new_child_init( xptr_t parent_xp, 1875 xptr_t dentry_xp, 1876 xptr_t child_xp ) 1877 { 1878 error_t error; 1879 uint32_t cluster; 1880 uint32_t child_type; 1881 uint32_t child_size; 1882 1883 #if DEBUG_VFS_NEW_CHILD_INIT 1884 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1885 char child_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1886 vfs_inode_get_name( parent_xp , parent_name ); 1887 vfs_inode_get_name( child_xp , child_name ); 1888 uint32_t cycle = (uint32_t)hal_get_cycles(); 1889 thread_t * this = CURRENT_THREAD; 1890 if( DEBUG_VFS_NEW_CHILD_INIT < cycle ) 1891 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n", 1892 __FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle ); 1893 #endif 1894 1895 // get parent inode cluster and local pointer 1896 cxy_t parent_cxy = GET_CXY( parent_xp ); 1897 vfs_inode_t * parent_ptr = GET_PTR( parent_xp ); 1898 1899 // get dentry local pointer 1900 vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); 1901 1902 // get child inode cluster and local pointer 1903 cxy_t child_cxy = GET_CXY( child_xp ); 1904 vfs_inode_t * child_ptr = GET_PTR( child_xp ); 1905 1906 // 1. allocate one free cluster to child inode 1907 // depending on the child inode FS type 1908 vfs_ctx_t * ctx = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) ); 1909 1910 error = vfs_fs_cluster_alloc( ctx->type, 1911 &cluster ); 1912 if ( error ) 1913 { 1914 printk("\n[ERROR] in %s : cannot find a free VFS cluster\n", 1915 __FUNCTION__ ); 1916 return -1; 1917 } 1918 1919 #if( DEBUG_VFS_NEW_CHILD_INIT & 1) 1920 if( DEBUG_VFS_NEW_CHILD_INIT < cycle ) 1921 printk("\n[%s] thread[%x,%x] allocated one FAT cluster to <%s>\n", 1922 __FUNCTION__ , this->process->pid, this->trdid, child_name ); 1923 #endif 1924 1925 // 2. update the child inode descriptor 1926 child_type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ); 1927 child_size = (child_type == INODE_TYPE_DIR) ? 4096 : 0; 1928 1929 hal_remote_s32( XPTR( child_cxy , &child_ptr->size ) , child_size ); 1930 hal_remote_spt( XPTR( child_cxy , &child_ptr->extend ) , (void*)(intptr_t)cluster ); 1931 1932 // 3. update the parent inode mapper, and 1933 // update the dentry extension if required 1934 if( local_cxy == parent_cxy ) 1935 { 1936 error = vfs_fs_add_dentry( parent_ptr, 1937 dentry_ptr ); 1938 } 1939 else 1940 { 1941 rpc_vfs_fs_add_dentry_client( parent_cxy, 1942 parent_ptr, 1943 dentry_ptr, 1944 &error ); 1945 } 1946 if ( error ) 1947 { 1948 printk("\n[ERROR] in %s : cannot register child in parent directory\n", 1949 __FUNCTION__ ); 1950 return -1; 1951 } 1952 1953 #if DEBUG_VFS_NEW_CHILD_INIT 1954 cycle = (uint32_t)hal_get_cycles(); 1955 if( DEBUG_VFS_NEW_CHILD_INIT < cycle ) 1956 printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%> / cycle %d\n", 1957 __FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle ); 1958 #endif 1959 1960 return 0; 1961 1962 } // end vfs_new_child_init() 1725 1963 1726 1964 //////////////////////////////////////////// … … 1794 2032 1795 2033 1796 ////////////////////////////////////////////////////////////// 1797 error_t vfs_add_child_in_parent( cxy_t child_ cxy,1798 vfs_inode_type_t inode_type,2034 //////////////////////////////////////////////////////////////////// 2035 error_t vfs_add_child_in_parent( cxy_t child_inode_cxy, 2036 vfs_inode_type_t child_inode_type, 1799 2037 vfs_fs_type_t fs_type, 1800 xptr_t parent_ xp,2038 xptr_t parent_inode_xp, 1801 2039 char * name, 1802 void * extend,1803 xptr_t * child_ xp )2040 xptr_t * dentry_xp, 2041 xptr_t * child_inode_xp ) 1804 2042 { 1805 2043 error_t error; 1806 xptr_t dentry_xp; // extended pointer on created dentry 1807 xptr_t inode_xp; // extended pointer on created inode 1808 cxy_t parent_cxy; // parent inode cluster identifier 1809 vfs_inode_t * parent_ptr; // parent inode local pointer 2044 xptr_t new_dentry_xp; // extended pointer on created dentry 2045 vfs_dentry_t * new_dentry_ptr; // created dentry local pointer 2046 xptr_t new_inode_xp; // extended pointer on created child inode 2047 cxy_t parent_inode_cxy; // parent inode cluster identifier 2048 vfs_inode_t * parent_inode_ptr; // parent inode local pointer 1810 2049 1811 2050 // get parent inode cluster and local pointer 1812 parent_ cxy = GET_CXY( parent_xp );1813 parent_ ptr = GET_PTR( parent_xp );2051 parent_inode_cxy = GET_CXY( parent_inode_xp ); 2052 parent_inode_ptr = GET_PTR( parent_inode_xp ); 1814 2053 1815 2054 #if DEBUG_VFS_ADD_CHILD 2055 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 2056 vfs_inode_get_name( parent_inode_xp , parent_name ); 1816 2057 uint32_t cycle = (uint32_t)hal_get_cycles(); 1817 2058 thread_t * this = CURRENT_THREAD; 1818 2059 if( DEBUG_VFS_ADD_CHILD < cycle ) 1819 printk("\n[%s] thread[%x,%x] enter for <%s> / child_cxy %x / parent_cxy %x / cycle %d\n",1820 __FUNCTION__, this->process->pid, this->trdid, name, 1821 child_cxy, parent_cxy, (uint32_t)hal_get_cycles() );2060 printk("\n[%s] thread[%x,%x] enter / child <%s> cxy %x / parent <%s> cxy %x / cycle %d\n", 2061 __FUNCTION__, this->process->pid, this->trdid, name, child_inode_cxy, 2062 parent_name, parent_inode_cxy, (uint32_t)hal_get_cycles() ); 1822 2063 #endif 1823 2064 1824 2065 // 1. create dentry 1825 if( parent_ cxy == local_cxy ) // parent cluster is the local cluster2066 if( parent_inode_cxy == local_cxy ) // parent cluster is the local cluster 1826 2067 { 1827 2068 error = vfs_dentry_create( fs_type, 1828 2069 name, 1829 parent_ ptr,1830 & dentry_xp );2070 parent_inode_ptr, 2071 &new_dentry_xp ); 1831 2072 } 1832 2073 else // parent cluster is remote 1833 2074 { 1834 rpc_vfs_dentry_create_client( parent_ cxy,2075 rpc_vfs_dentry_create_client( parent_inode_cxy, 1835 2076 fs_type, 1836 2077 name, 1837 parent_ ptr,1838 & dentry_xp,2078 parent_inode_ptr, 2079 &new_dentry_xp, 1839 2080 &error ); 1840 2081 } … … 1843 2084 { 1844 2085 printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n", 1845 __FUNCTION__ , name , parent_cxy ); 1846 return ENOMEM; 1847 } 2086 __FUNCTION__ , name , parent_inode_cxy ); 2087 return -1; 2088 } 2089 2090 // get dentry local pointer 2091 new_dentry_ptr = GET_PTR( new_dentry_xp ); 1848 2092 1849 2093 #if(DEBUG_VFS_ADD_CHILD & 1) 1850 2094 if( DEBUG_VFS_ADD_CHILD < cycle ) 1851 2095 printk("\n[%s] thread[%x,%x] / dentry <%s> created in cluster %x\n", 1852 __FUNCTION__, this->process->pid, this->trdid, name, parent_ cxy );2096 __FUNCTION__, this->process->pid, this->trdid, name, parent_inode_cxy ); 1853 2097 #endif 1854 2098 … … 1859 2103 uint32_t gid = 0; 1860 2104 1861 if( child_ cxy == local_cxy ) // child cluster is the local cluster1862 { 1863 error = vfs_inode_create( dentry_xp,2105 if( child_inode_cxy == local_cxy ) // child cluster is the local cluster 2106 { 2107 error = vfs_inode_create( new_dentry_xp, 1864 2108 fs_type, 1865 inode_type, 1866 extend, 2109 child_inode_type, 1867 2110 attr, 1868 2111 mode, 1869 2112 uid, 1870 2113 gid, 1871 & inode_xp );2114 &new_inode_xp ); 1872 2115 } 1873 2116 else // child cluster is remote 1874 2117 { 1875 rpc_vfs_inode_create_client( child_ cxy,1876 dentry_xp,2118 rpc_vfs_inode_create_client( child_inode_cxy, 2119 new_dentry_xp, 1877 2120 fs_type, 1878 inode_type, 1879 extend, 2121 child_inode_type, 1880 2122 attr, 1881 2123 mode, 1882 2124 uid, 1883 2125 gid, 1884 & inode_xp,2126 &new_inode_xp, 1885 2127 &error ); 1886 2128 } … … 1889 2131 { 1890 2132 printk("\n[ERROR] in %s : cannot create inode in cluster %x\n", 1891 __FUNCTION__ , child_ cxy );2133 __FUNCTION__ , child_inode_cxy ); 1892 2134 1893 vfs_dentry_t * dentry = GET_PTR( dentry_xp ); 1894 if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry ); 1895 else rpc_vfs_dentry_destroy_client( parent_cxy , dentry , &error ); 1896 return ENOMEM; 2135 if( parent_inode_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr ); 2136 else rpc_vfs_dentry_destroy_client( parent_inode_cxy , new_dentry_ptr ); 2137 return -1; 1897 2138 } 1898 2139 … … 1900 2141 if( DEBUG_VFS_ADD_CHILD < cycle ) 1901 2142 printk("\n[%s] thread[%x,%x] / inode <%s> created in cluster %x\n", 1902 __FUNCTION__ , this->process->pid, this->trdid, name , child_ cxy );1903 #endif 1904 1905 // 3. update extended pointer on inode in dentry1906 cxy_t dentry_cxy = GET_CXY( dentry_xp );1907 vfs_ dentry_t * dentry_ptr = GET_PTR( dentry_xp );1908 hal_remote_s64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) , inode_xp );2143 __FUNCTION__ , this->process->pid, this->trdid, name , child_inode_cxy ); 2144 #endif 2145 2146 // 3. update "child_xp" field in dentry and increment refcounts 2147 hal_remote_s64( XPTR( parent_inode_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp ); 2148 vfs_inode_remote_up( new_inode_xp ); 2149 vfs_dentry_remote_up( new_dentry_xp ); 1909 2150 1910 2151 #if DEBUG_VFS_ADD_CHILD … … 1915 2156 #endif 1916 2157 1917 // success : return extended pointer on child inode 1918 *child_xp = inode_xp; 2158 // return extended pointer on dentry & child inode 2159 *dentry_xp = new_dentry_xp; 2160 *child_inode_xp = new_inode_xp; 1919 2161 return 0; 1920 2162 1921 // FIXME update the refcount fields in both inode and dentry1922 1923 2163 } // end vfs_add_child_in_parent() 1924 2164 1925 //////////////////////////////////////////////////// ///1926 error_tvfs_remove_child_from_parent( xptr_t inode_xp )2165 //////////////////////////////////////////////////// 2166 void vfs_remove_child_from_parent( xptr_t inode_xp ) 1927 2167 { 1928 2168 cxy_t inode_cxy; … … 1931 2171 cxy_t dentry_cxy; 1932 2172 vfs_dentry_t * dentry_ptr; 1933 error_t error;1934 2173 1935 2174 // get inode cluster and local pointer … … 1937 2176 inode_ptr = GET_PTR( inode_xp ); 1938 2177 1939 // get cluster and pointers of associated dentry2178 // get associated dentry cluster and pointers 1940 2179 dentry_xp = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 1941 2180 dentry_cxy = GET_CXY( dentry_xp ); 1942 2181 dentry_ptr = GET_PTR( dentry_xp ); 1943 2182 1944 // FIXME update the refcount fields in both inode and dentry 2183 // check dentry refcount 2184 assert( ( hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->refcount ) ) == 1 ), 2185 "dentry refcount must be 1\n" ); 2186 2187 // check inode refcount 2188 assert( ( hal_remote_l32( XPTR( inode_cxy , &inode_ptr->refcount ) ) == 1 ), 2189 "inode refcount must be 1\n" ); 2190 2191 // decrement refcount for inode and dentry 2192 vfs_inode_remote_down( inode_xp ); 2193 vfs_dentry_remote_down( dentry_xp ); 1945 2194 1946 2195 // delete dentry 1947 2196 if( dentry_cxy == local_cxy ) 1948 2197 { 1949 error =vfs_dentry_destroy( dentry_ptr );2198 vfs_dentry_destroy( dentry_ptr ); 1950 2199 } 1951 2200 else 1952 2201 { 1953 2202 rpc_vfs_dentry_destroy_client( dentry_cxy, 1954 dentry_ptr, 1955 &error ); 1956 } 1957 if( error ) return EINVAL; 2203 dentry_ptr ); 2204 } 1958 2205 1959 2206 // delete inode … … 1965 2212 { 1966 2213 rpc_vfs_inode_destroy_client( inode_cxy, 1967 inode_ptr, 1968 &error ); 1969 } 1970 if( error ) return EINVAL; 1971 1972 return 0; 2214 inode_ptr ); 2215 } 1973 2216 1974 2217 } // end vfs_remove_child_from_parent() 1975 2218 1976 2219 ////////////////////////////////////////////////////////////////////////////////////////// 1977 // Mapper related functions2220 // API used by VFS to access a specific FS 1978 2221 ////////////////////////////////////////////////////////////////////////////////////////// 1979 2222 1980 /////////////////////////////////////////// /1981 error_t vfs_ mapper_move_page( page_t * page,1982 2223 /////////////////////////////////////////// 2224 error_t vfs_fs_move_page( xptr_t page_xp, 2225 bool_t to_mapper ) 1983 2226 { 1984 2227 error_t error = 0; 1985 2228 1986 assert( (page != NULL) , "page pointer is NULL\n" ); 1987 1988 mapper_t * mapper = page->mapper; 1989 1990 assert( (mapper != NULL) , "no mapper for page\n" ); 1991 1992 #if DEBUG_VFS_MAPPER_MOVE 1993 uint32_t cycle = (uint32_t)hal_get_cycles(); 1994 thread_t * this = CURRENT_THREAD; 1995 if( DEBUG_VFS_MAPPER_MOVE < cycle ) 1996 printk("\n[%s] thread[%x,%x] enter for page %d / mapper %x / inode %x / cycle %d\n", 1997 __FUNCTION__, this->process->pid, this->trdid, page->index, mapper, mapper->inode, cycle ); 1998 #endif 2229 assert( (page_xp != XPTR_NULL) , "page pointer is NULL\n" ); 2230 2231 page_t * page_ptr = GET_PTR( page_xp ); 2232 cxy_t page_cxy = GET_CXY( page_xp ); 2233 2234 // get local pointer on page mapper 2235 mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) ); 2236 2237 assert( (mapper != NULL) , "no mapper for page\n" ); 2238 2239 // get FS type 2240 vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->type ) ); 2241 2242 // call relevant FS function 2243 if( fs_type == FS_TYPE_FATFS ) 2244 { 2245 error = fatfs_move_page( page_xp , to_mapper ); 2246 } 2247 else if( fs_type == FS_TYPE_RAMFS ) 2248 { 2249 assert( false , "should not be called for RAMFS\n" ); 2250 } 2251 else if( fs_type == FS_TYPE_DEVFS ) 2252 { 2253 assert( false , "should not be called for DEVFS\n" ); 2254 } 2255 else 2256 { 2257 assert( false , "undefined file system type\n" ); 2258 } 2259 2260 return error; 2261 2262 } // end vfs_fs_move_page() 2263 2264 //////////////////////////////////////////////// 2265 error_t vfs_fs_add_dentry( vfs_inode_t * inode, 2266 vfs_dentry_t * dentry ) 2267 { 2268 error_t error = 0; 2269 2270 assert( (inode != NULL) , "inode pointer is NULL\n" ); 2271 assert( (dentry != NULL) , "dentry pointer is NULL\n" ); 2272 2273 mapper_t * mapper = inode->mapper; 2274 2275 assert( (mapper != NULL) , "mapper pointer is NULL\n" ); 1999 2276 2000 2277 // get FS type … … 2004 2281 if( fs_type == FS_TYPE_FATFS ) 2005 2282 { 2006 // enter mapper in write mode 2007 rwlock_wr_acquire( &mapper->lock ); 2008 2009 // move page to mapper 2010 error = fatfs_mapper_move_page( page , to_mapper ); 2011 2012 // exit mapper in write mode 2013 rwlock_wr_release( &mapper->lock ); 2283 error = fatfs_add_dentry( inode , dentry ); 2014 2284 } 2015 2285 else if( fs_type == FS_TYPE_RAMFS ) … … 2026 2296 } 2027 2297 2028 #if DEBUG_VFS_MAPPER_MOVE2029 cycle = (uint32_t)hal_get_cycles();2030 if( DEBUG_VFS_MAPPER_MOVE < cycle )2031 printk("\n[%s] thread[%x,%x] exit for page %d / mapper %x / inode %x / cycle %d\n",2032 __FUNCTION__, this->process->pid, this->trdid, page->index, mapper, mapper->inode, cycle );2033 #endif2034 2035 2298 return error; 2036 2299 2037 } // end vfs_move_page() 2038 2039 ////////////////////////////////////////////////// 2040 error_t vfs_mapper_load_all( vfs_inode_t * inode ) 2041 { 2042 assert( (inode != NULL) , "inode pointer is NULL\n" ); 2043 2044 uint32_t index; 2045 page_t * page; 2300 } // end vfs_fs_add_dentry() 2301 2302 /////////////////////////////////////////////////// 2303 error_t vfs_fs_remove_dentry( vfs_inode_t * inode, 2304 vfs_dentry_t * dentry ) 2305 { 2306 error_t error = 0; 2307 2308 assert( (inode != NULL) , "inode pointer is NULL\n" ); 2309 assert( (dentry != NULL) , "dentry pointer is NULL\n" ); 2046 2310 2047 2311 mapper_t * mapper = inode->mapper; 2048 uint32_t size = inode->size;2049 2312 2050 2313 assert( (mapper != NULL) , "mapper pointer is NULL\n" ); 2051 2314 2052 #if DEBUG_VFS_MAPPER_LOAD 2053 uint32_t cycle = (uint32_t)hal_get_cycles(); 2054 thread_t * this = CURRENT_THREAD; 2055 if( DEBUG_VFS_MAPPER_MOVE < cycle ) 2056 printk("\n[%s] thread[%x,%x] enter for inode %x in cluster %x / cycle %d\n", 2057 __FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle ); 2058 #endif 2059 2060 // compute number of pages 2061 uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT; 2062 if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++; 2063 2064 // loop on pages 2065 for( index = 0 ; index < npages ; index ++ ) 2066 { 2067 // this function allocates the missing page in mapper, 2068 // and call the vfs_mapper_move_page() to load the page from device 2069 page = mapper_get_page( mapper , index ); 2070 2071 if( page == NULL ) return EIO; 2072 } 2073 2074 #if DEBUG_VFS_MAPPER_LOAD 2075 cycle = (uint32_t)hal_get_cycles(); 2076 if( DEBUG_VFS_MAPPER_MOVE < cycle ) 2077 printk("\n[%s] thread[%x,%x] exit for inode %x in cluster %x / cycle %d\n", 2078 __FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle ); 2079 #endif 2080 2081 return 0; 2082 2083 } // end vfs_mapper_load_all() 2084 2315 // get FS type 2316 vfs_fs_type_t fs_type = mapper->type; 2317 2318 // call relevant FS function 2319 if( fs_type == FS_TYPE_FATFS ) 2320 { 2321 error = fatfs_remove_dentry( inode , dentry ); 2322 } 2323 else if( fs_type == FS_TYPE_RAMFS ) 2324 { 2325 assert( false , "should not be called for RAMFS\n" ); 2326 } 2327 else if( fs_type == FS_TYPE_DEVFS ) 2328 { 2329 assert( false , "should not be called for DEVFS\n" ); 2330 } 2331 else 2332 { 2333 assert( false , "undefined file system type\n" ); 2334 } 2335 2336 return error; 2337 2338 } // end vfs_fs_remove_dentry() 2339 2340 //////////////////////////////////////////////// 2341 error_t vfs_fs_child_init( vfs_inode_t * parent, 2342 char * name, 2343 xptr_t child_xp ) 2344 { 2345 error_t error = 0; 2346 2347 // check arguments 2348 assert( (parent != NULL) , "parent pointer is NULL\n"); 2349 assert( (child_xp != XPTR_NULL) , "child pointer is NULL\n"); 2350 2351 // get parent inode FS type 2352 vfs_fs_type_t fs_type = parent->ctx->type; 2353 2354 // call relevant FS function 2355 if( fs_type == FS_TYPE_FATFS ) 2356 { 2357 error = fatfs_child_init( parent , name , child_xp ); 2358 } 2359 else if( fs_type == FS_TYPE_RAMFS ) 2360 { 2361 assert( false , "should not be called for RAMFS\n" ); 2362 } 2363 else if( fs_type == FS_TYPE_DEVFS ) 2364 { 2365 assert( false , "should not be called for DEVFS\n" ); 2366 } 2367 else 2368 { 2369 assert( false , "undefined file system type\n" ); 2370 } 2371 2372 return error; 2373 2374 } // end vfs_fs_child_init() 2375 2376 ///////////////////////////////////////////////// 2377 error_t vfs_fs_cluster_alloc( uint32_t fs_type, 2378 uint32_t * cluster ) 2379 { 2380 error_t error = 0; 2381 2382 // call relevant FS function 2383 if( fs_type == FS_TYPE_FATFS ) 2384 { 2385 error = fatfs_cluster_alloc( cluster ); 2386 } 2387 else if( fs_type == FS_TYPE_RAMFS ) 2388 { 2389 assert( false , "should not be called for RAMFS\n" ); 2390 } 2391 else if( fs_type == FS_TYPE_DEVFS ) 2392 { 2393 assert( false , "should not be called for DEVFS\n" ); 2394 } 2395 else 2396 { 2397 assert( false , "undefined file system type\n" ); 2398 } 2399 2400 return error; 2401 2402 } // end vfs_fs_alloc_cluster() 2403 2404 //////////////////////////////////////////////// 2405 error_t vfs_fs_release_inode( xptr_t inode_xp ) 2406 { 2407 error_t error = 0; 2408 2409 assert( (inode_xp != XPTR_NULL) , "inode pointer is NULL\n") 2410 2411 vfs_inode_t * inode_ptr = GET_PTR( inode_xp ); 2412 cxy_t inode_cxy = GET_CXY( inode_xp ); 2413 2414 // get local pointer on page mapper 2415 mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) ); 2416 2417 assert( (mapper != NULL) , "mapper pointer is NULL\n") 2418 2419 // get FS type from mapper 2420 vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->type ) ); 2421 2422 // call relevant FS function 2423 if( fs_type == FS_TYPE_FATFS ) 2424 { 2425 error = fatfs_release_inode( inode_xp ); 2426 } 2427 else if( fs_type == FS_TYPE_RAMFS ) 2428 { 2429 assert( false , "should not be called for RAMFS\n" ); 2430 } 2431 else if( fs_type == FS_TYPE_DEVFS ) 2432 { 2433 assert( false , "should not be called for DEVFS\n" ); 2434 } 2435 else 2436 { 2437 assert( false , "undefined file system type\n" ); 2438 } 2439 2440 return error; 2441 2442 } // end vfs_fs_release_inode() 2443 2444 -
trunk/kernel/fs/vfs.h
r598 r602 78 78 * This structure defines a VFS context, that contains informations common to all inodes 79 79 * and dentries for a given file system. As it is declared as a global variable in the 80 * kdata segment, it is handled as private by each OS intance in a given cluster. 80 * kdata segment (fs_context[] array), it is replicated in all clusters. 81 * The <extend> field is a pointer on the FS specific context extension. 82 * This extension is dynamically allocated by kernel_init in all clusters. 83 * In each cluster, both this VFS context and the FS specific context are handled as 84 * private by the local OS intance. 81 85 *****************************************************************************************/ 82 86 … … 252 256 253 257 254 /*****************************************************************************************/ 255 /******************** VFS global functions ***********************************************/ 256 /*****************************************************************************************/ 257 258 259 /****************************************************************************************** 260 * This function mount a given file system type for a given process TODO. 261 *****************************************************************************************/ 262 error_t vfs_mount_fs_root( struct device_s * device, 263 uint32_t fs_type, 264 struct process_s * process ); 265 266 267 /*****************************************************************************************/ 268 /******************* VFS Context related functions ****************************************/ 269 /*****************************************************************************************/ 258 /****************************************************************************************** 259 * These functions access / modify a VFS context. 260 *****************************************************************************************/ 270 261 271 262 /****************************************************************************************** … … 311 302 312 303 313 /*****************************************************************************************/ 314 /********************* Inode related functions *******************************************/ 315 /*****************************************************************************************/ 304 /****************************************************************************************** 305 * These low-level functions access / modify a VFS inode descriptor 306 *****************************************************************************************/ 307 308 /****************************************************************************************** 309 * This function returns a printable string for the inode type. 310 *****************************************************************************************/ 311 const char * vfs_inode_type_str( vfs_inode_type_t type ); 316 312 317 313 /****************************************************************************************** … … 325 321 * @ fs_type : file system type. 326 322 * @ inode_type : inode type. 327 * @ extend : local pointer on vs_type_specific extension.328 323 * @ attr : inode attributes. 329 324 * @ rights : inode access rights. … … 336 331 vfs_fs_type_t fs_type, 337 332 vfs_inode_type_t inode_type, 338 void * extend,339 333 uint32_t attr, 340 334 uint32_t rights, … … 344 338 345 339 /****************************************************************************************** 346 * This function releases memory allocated to an inode descriptor. 347 * It must be executed by a thread running in the cluster containing the inode, 348 * and the inode refcount must be zero. If the client thread is not running in the owner 349 * cluster, you must use the rpc_vfs_inode_destroy_client() function. 340 * This function releases memory allocated to an inode descriptor, including 341 * all memory allocated to the mapper (both mapper descriptor and radix tree). 342 * The mapper should not contain any dirty page (shold be synchronized before deletion), 343 * and the inode refcount must be zero. 344 * It must be executed by a thread running in the cluster containing the inode. 345 * Use the rpc_vfs_inode_destroy_client() function if required. 350 346 ****************************************************************************************** 351 347 * @ inode : local pointer on inode descriptor. 352 * @ return 0 if success / return EINVAL if error. 353 *****************************************************************************************/ 354 error_t vfs_inode_destroy( vfs_inode_t * inode ); 355 356 /****************************************************************************************** 357 * This function scan an existing parent inode directory, identified by the <parent> 358 * argument to find a directory entry identified by the <name> argument, and update 359 * the remote child inode, identified by the <child_xp> argument. 360 * Depending on the file system type, it calls the relevant, FS specific function, 361 * to scan the directory, and set the "type", "size", and "extend" fields. 362 * It must be called by a thread running in the cluster containing the parent inode. 363 ****************************************************************************************** 364 * @ parent : local pointer on parent inode (directory). 365 * @ name : child name. 366 * @ child_xp : extended pointer on remote child inode (file or directory) 367 * @ return 0 if success / return ENOENT if not found. 368 *****************************************************************************************/ 369 error_t vfs_inode_load( vfs_inode_t * parent, 370 char * name, 371 xptr_t child_xp ); 348 *****************************************************************************************/ 349 void vfs_inode_destroy( vfs_inode_t * inode ); 372 350 373 351 /****************************************************************************************** … … 399 377 /****************************************************************************************** 400 378 * This function takes the main lock of a remote inode. 401 * This lock protect all inode fiel s, including the children dentries.379 * This lock protect all inode fields, including the children dentries. 402 380 ***************************************************************************************** 403 381 * @ inode_xp : extended pointer on the remote inode. … … 424 402 char * name ); 425 403 426 427 /*****************************************************************************************/ 428 /***************** Dentry related functions **********************************************/ 429 /*****************************************************************************************/ 404 /****************************************************************************************** 405 * This function accesses successively all pages of a file identified by the <inode>, 406 * argument, to force misses, and load all pages into mapper. 407 * The target inode can be a directory or a file, but this function is mainly used 408 * to prefetch a complete directory to the mapper. 409 * It must be executed by a thread running in the cluster containing the inode. 410 * This function does NOT take any lock. 411 ****************************************************************************************** 412 * @ inode : local pointer on inode. 413 * @ return 0 if success / return -1 if device access failure. 414 *****************************************************************************************/ 415 error_t vfs_inode_load_all_pages( vfs_inode_t * inode ); 416 417 418 /****************************************************************************************** 419 * These low-level functions access / modify a VFS dentry descriptor 420 *****************************************************************************************/ 430 421 431 422 /****************************************************************************************** … … 449 440 /****************************************************************************************** 450 441 * This function releases memory allocated to a dentry descriptor. 451 * It must be executed by a thread running in the cluster containing the dentry,452 * and the dentry refcount must be zero. If the client thread is not running in the owner453 * cluster, you must use the rpc_dentry_destroy_client() function.442 * The dentry refcount must be zero. 443 * It must be executed by a thread running in the cluster containing the dentry. 444 * Use the rpc_vfs_dentry_destroy_client() function if required. 454 445 ****************************************************************************************** 455 446 * @ dentry : local pointer on dentry descriptor. 456 * @ return 0 if success / return EINVAL if error. 457 *****************************************************************************************/ 458 error_t vfs_dentry_destroy( vfs_dentry_t * dentry ); 447 *****************************************************************************************/ 448 void vfs_dentry_destroy( vfs_dentry_t * dentry ); 459 449 460 450 /****************************************************************************************** … … 466 456 467 457 468 /***************************************************************************************** /469 /************************ File descriptor related functions ******************************/ 470 /*****************************************************************************************/458 /****************************************************************************************** 459 * These low-level functions access / modify a VFS file descriptor 460 *****************************************************************************************/ 471 461 472 462 /****************************************************************************************** … … 505 495 506 496 507 /*****************************************************************************************/ 508 /******************* Inode-Tree related functions ****************************************/ 509 /*****************************************************************************************/ 510 511 /****************************************************************************************** 512 * This function returns a printable string for the inode type. 513 *****************************************************************************************/ 514 const char * vfs_inode_type_str( vfs_inode_type_t type ); 497 /****************************************************************************************** 498 * These functions access / modify the distributed VFS Inode Treee 499 *****************************************************************************************/ 515 500 516 501 /****************************************************************************************** … … 555 540 * This function creates a new couple dentry/inode, and insert it in the Inode-Tree. 556 541 * It can be executed by any thread running in any cluster (can be different from both 557 * the child cluster and the parent cluster), as it uses the rpc_dentry_create_client() 558 * and rpc_inode_create client() if required. This is done in three steps: 559 * 1) The dentry is created in the cluster containing the existing <parent_xp> inode. 560 * The new dentry name is defined by the <name> argument. 561 * 2) The inode and its associated mapper are created in cluster identified by <child_cxy>. 562 * The new inode and the parent inode can have different FS types. 563 * 3) The "child_xp" field in created dentry (pointing on the created inode) is updated. 564 ****************************************************************************************** 565 * @ child_cxy : target cluster for child inode. 566 * @ inode_type : new inode type 567 * @ fs_type : new inode FS type. 568 * @ parent_xp : extended pointer on parent inode. 569 * @ name : new directory entry name. 570 * @ extend : fs_type_specific inode extension. 571 * @ child_xp : [out] buffer for extended pointer on child inode. 572 * @ return 0 if success / ENOMEM if dentry or inode cannot be created. 573 *****************************************************************************************/ 574 error_t vfs_add_child_in_parent( cxy_t child_cxy, 575 vfs_inode_type_t inode_type, 542 * the child cluster and the parent cluster), as it uses RPCs if required. 543 * Only the distributed Inode Tree is modified: Even for a new file, this function 544 * does NOT modify the parent mapper, and does NOT update the FS on IOC device. 545 * 546 * [Implementation] 547 * As there are cross-references between the inode and the associated dentry, this 548 * function implement a three steps scenario : 549 * 1) The dentry descriptor is created in the cluster containing the existing <parent_xp> 550 * inode, and is only partially initialized : "fs_type", "name", "parent_xp" fields. 551 * 2) The inode and its associated mapper are created in cluster identified by <child_cxy>, 552 * and initialised. The new inode and the parent inode can have different FS types. 553 * 3) The "child_xp" field in dentry (pointing on the created inode) is updated, 554 * and the refcount is incremented for both the inode and the dentry. 555 ****************************************************************************************** 556 * @ child_inode_cxy : [in] target cluster for child inode. 557 * @ child_inode_type : [in] child inode type 558 * @ fs_type : [in] child inode FS type. 559 * @ parent_inode_xp : [in] extended pointer on parent inode. 560 * @ name : [in] new directory entry name. 561 * @ dentry_xp : [out] buffer for extended pointer on dentry 562 * @ child_inode_xp : [out] buffer for extended pointer on child inode. 563 * @ return 0 if success / -1 if dentry or inode cannot be created. 564 *****************************************************************************************/ 565 error_t vfs_add_child_in_parent( cxy_t child_inodecxy, 566 vfs_inode_type_t chilg_inode_type, 576 567 vfs_fs_type_t fs_type, 577 xptr_t parent_xp, 578 char * name, 579 void * extend, 580 xptr_t * child_xp ); 581 582 /****************************************************************************************** 583 * This function removes a couple dentry/inode from the Inode-Tree, and remove it from 584 * the external device. 568 xptr_t parent_inode_xp, 569 char * name, 570 xptr_t * dentry_xp, 571 xptr_t * child_inode_xp ); 572 573 /****************************************************************************************** 574 * This function removes a couple dentry/inode from the Inode-Tree. 575 * Both the inode and dentry references counters must be 1. 576 * It can be executed by any thread running in any cluster (can be different from both 577 * the inode cluster and the dentry cluster), as it uses RPCs if required. 585 578 ****************************************************************************************** 586 579 * @ child_xp : extended pointer on removed inode. 587 580 *****************************************************************************************/ 588 error_t vfs_remove_child_from_parent( xptr_t inode_xp ); 581 void vfs_remove_child_from_parent( xptr_t inode_xp ); 582 583 /****************************************************************************************** 584 * This function is called by the vfs_lookup() function when a new dentry/inode must 585 * be created from scratch and introduced in both the Inode Tree and the IOC device. 586 * The dentry and inode descriptors have been created by the caller: 587 * - It allocates one cluster from the relevant FS, and updates the File Allocation 588 * Table (both the FAT mapper, and the IOC device). 589 * - It set the "size", and "extend" fields in child inode descriptor. 590 * - It updates the parent directory to introduce the new child in the parent directory 591 * inode descriptor (radix tree), in theparent inode mapper, and on IOC device. 592 * - It set the "extend" field in dentry descriptor. 593 * It can be called by a thread running in any cluster. 594 ****************************************************************************************** 595 * @ parent_xp : extended pointer on parent inode descriptor. 596 * @ dentry_xp : extended pointer on new dentry descriptor. 597 * @ child_xp : extended pointer on child inode descriptor. 598 * @ return 0 if success / -1 if failure. 599 *****************************************************************************************/ 600 error_t vfs_new_child_init( xptr_t parent_xp, 601 xptr_t dentry_xp, 602 xptr_t child_xp ); 589 603 590 604 /****************************************************************************************** … … 597 611 void vfs_display( xptr_t inode_xp ); 598 612 599 600 601 602 603 /*****************************************************************************************/ 604 /****************** File access API ******************************************************/ 605 /*****************************************************************************************/ 613 /****************************************************************************************** 614 * This function mount a given file system type for a given process 615 * TODO non implemented yet [AG]. 616 *****************************************************************************************/ 617 error_t vfs_mount_fs_root( struct device_s * device, 618 uint32_t fs_type, 619 struct process_s * process ); 620 621 622 623 /****************************************************************************************** 624 * These functions define the VFS "syscalls" API (user commands) 625 *****************************************************************************************/ 626 627 /****************************************************************************************** 628 * This function moves <size> bytes between a remote file mapper, identified by the 629 * <file_xp> argument, and a - possibly distributed - user space <buffer>, taken into 630 * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>. 631 * It is called by the sys_read() and sys_write() functions. 632 ****************************************************************************************** 633 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false. 634 * @ file_xp : extended pointer on the remote file descriptor. 635 * @ buffer : user space pointer on buffer (can be physically distributed). 636 * @ size : requested number of bytes from offset. 637 * @ returns number of bytes actually moved if success / -1 if error. 638 *****************************************************************************************/ 639 int vfs_user_move( bool_t to_buffer, 640 xptr_t file_xp, 641 void * buffer, 642 uint32_t size ); 643 644 /****************************************************************************************** 645 * This function moves <size> bytes between a remote file mapper, identified by the 646 * <file_xp> argument, and a - possibly remote - kernel <buffer_xp>, taken into 647 * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>. 648 * It is called by the elf_load_process() function. 649 ****************************************************************************************** 650 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false. 651 * @ file_xp : extended pointer on the remote file descriptor. 652 * @ buffer_xp : user space pointer on buffer (can be physically distributed). 653 * @ size : requested number of bytes from offset. 654 * @ returns 0 if success / -1 if error. 655 *****************************************************************************************/ 656 error_t vfs_kernel_move( bool_t to_buffer, 657 xptr_t file_xp, 658 xptr_t buffer_xp, 659 uint32_t size ); 606 660 607 661 /****************************************************************************************** … … 619 673 * @ process : local pointer on local process descriptor copy. 620 674 * @ path : file pathname (absolute or relative to current directory). 621 * @ flags : defined above.622 * @ mode : access rights (as defined by chmod) 675 * @ flags : defined in vfs_file_t structure. 676 * @ mode : access rights (as defined by chmod). 623 677 * @ file_xp : [out] buffer for extended pointer on created remote file descriptor. 624 678 * @ file_id : [out] buffer for created file descriptor index in reference fd_array. … … 631 685 xptr_t * file_xp, 632 686 uint32_t * file_id ); 633 634 /******************************************************************************************635 * This function moves <size> bytes between a remote file mapper, identified by the636 * <file_xp> argument, and a - possibly distributed - user space <buffer>, taken into637 * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>.638 * It is called by the sys_read() and sys_write() functions.639 ******************************************************************************************640 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.641 * @ file_xp : extended pointer on the remote file descriptor.642 * @ buffer : user space pointer on buffer (can be physically distributed).643 * @ size : requested number of bytes from offset.644 * @ returns number of bytes actually moved if success / -1 if error.645 *****************************************************************************************/646 int vfs_user_move( bool_t to_buffer,647 xptr_t file_xp,648 void * buffer,649 uint32_t size );650 651 /******************************************************************************************652 * This function moves <size> bytes between a remote file mapper, identified by the653 * <file_xp> argument, and a - possibly remote - kernel <buffer_xp>, taken into654 * account the offset in <file_xp>. The transfer direction is defined by <to_buffer>.655 * It is called by the elf_load_process() function.656 ******************************************************************************************657 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false.658 * @ file_xp : extended pointer on the remote file descriptor.659 * @ buffer_xp : user space pointer on buffer (can be physically distributed).660 * @ size : requested number of bytes from offset.661 * @ returns 0 if success / -1 if error.662 *****************************************************************************************/663 error_t vfs_kernel_move( bool_t to_buffer,664 xptr_t file_xp,665 xptr_t buffer_xp,666 uint32_t size );667 687 668 688 /****************************************************************************************** … … 685 705 686 706 /****************************************************************************************** 687 * This function close the - non-replicated- file descriptor identified by the <file_xp>707 * This function close the - non-replicated - file descriptor identified by the <file_xp> 688 708 * and <file_id> arguments. 689 709 * 1) All entries in the fd_array copies are directly reset by the calling thread, … … 700 720 701 721 /****************************************************************************************** 702 * This function remove from the file system a directory entry identified by the 703 * <cwd_xp> & <path> arguments. 722 * This function is called by the kernel to create in the file system a new directory 723 * entry identified by the <cwd_xp> & <path_1>, linked to the node identified by the 724 * <cwd_xp> & <path_2> arguments. It can be any type of node. 725 * If the link is successful, the link count of the target node is incremented. 726 * <path_1> and <path_2> share equal access rights to the underlying object. 727 * Both the IOC device and the Inode Tree are modified. 728 ****************************************************************************************** 729 * @ cwd_xp : extended pointer on current working directory file descriptor. 730 * @ path_1 : new pathname (absolute or relative to current directory). 731 * @ path_1 : existing pathname (absolute or relative to current directory). 732 * @ returns 0 if success / -1 if error. 733 *****************************************************************************************/ 734 error_t vfs_link( xptr_t cwd_xp, 735 char * path_1, 736 char * path_2 ); 737 738 /****************************************************************************************** 739 * This function is called by the kernel to remove from the file system a directory entry 740 * identified by the <cwd_xp> & <path> arguments. The target node can be any type of node. 741 * The link count of the target node is decremented. If the removed link is the last, 742 * the target node is deleted. 743 * Both the IOC device and the Inode Tree are modified. 704 744 ****************************************************************************************** 705 745 * @ cwd_xp : extended pointer on the current working directory file descriptor. … … 747 787 char * path, 748 788 uint32_t mode ); 749 750 /******************************************************************************************751 * This function remove a directory identified by the <cwd_xp / path> arguments752 * from the file system.753 * TODO not implemented yet...754 ******************************************************************************************755 * @ cwd_xp : extended pointer on the current working directory file descriptor.756 * @ path : pathname (absolute or relative to current directory).757 * @ returns 0 if success / -1 if error.758 *****************************************************************************************/759 error_t vfs_rmdir( xptr_t cwd_xp,760 char * path );761 789 762 790 /****************************************************************************************** … … 797 825 798 826 799 /*****************************************************************************************/ 800 /****************** Mapper access API ****************************************************/ 801 /*****************************************************************************************/ 802 803 /****************************************************************************************** 804 * This function makes an I/O operation to move one page to/from device from/to the mapper. 827 828 /****************************************************************************************** 829 * These functions define the VFS "FS" API (to a specific File System) 830 *****************************************************************************************/ 831 832 /****************************************************************************************** 833 * This function updates the mapper associated to a directory inode identified by the 834 * <parent> argument, to add a new entry identified by the <dentry> argument. 835 * The directory inode descriptor and the dentry descriptor are in the same cluster. 836 * Depending on the file system type, it calls the proper, FS specific function. 837 * It ulso pdates the dentry descriptor and/or the inode descriptor extensions 838 * as required by the specific file system type. 839 * Finally, it synchronously updates the parent directory on IOC device. 840 * 841 * It must be executed by a thread running in the cluster containing the parent directory. 842 * It can be the RPC_VFS_VS_ADD_DENTRY. This function does NOT take any lock. 843 ****************************************************************************************** 844 * @ parent : local pointer on parent (directory) inode. 845 * @ dentry : local pointer on dentry containing name. 846 * @ return 0 if success / return -1 if device access failure. 847 *****************************************************************************************/ 848 error_t vfs_fs_add_dentry( vfs_inode_t * parent, 849 vfs_dentry_t * dentry ); 850 851 /****************************************************************************************** 852 * This function updates the mapper associated to a directory inode identified by the 853 * <parent> argument, to remove an entry identified by the <dentry> argument. 854 * The directory inode descriptor and the dentry descriptor are in the same cluster. 855 * Depending on the file system type, it calls the proper, FS specific function. 856 * Finally, it synchronously updates the parent directory on IOC device. 857 * 858 * It must be executed by a thread running in the cluster containing the parent directory. 859 * It can be the RPC_VFS_VS_REMOVE_DENTRY. This function does NOT take any lock. 860 ****************************************************************************************** 861 * @ parent : local pointer on parent (directory) inode. 862 * @ dentry : local pointer on dentry containing name. 863 * @ return 0 if success / return -1 if device access failure. 864 *****************************************************************************************/ 865 error_t vfs_fs_remove_dentry( vfs_inode_t * parent, 866 vfs_dentry_t * dentry ); 867 868 /****************************************************************************************** 869 * This function scan the mapper of an an existing parent inode directory, identified by 870 * the <parent> argument to find a directory entry identified by the <name> argument, 871 * and updates both the child inode descriptor, identified by the <child_xp> argument, 872 * and the associated dentry descriptor : 873 * - It set the "size", and "extend" fields in inode descriptor. 874 * - It set the "extend" field in dentry descriptor. 875 * It is called by the vfs_lookup() function in case of miss. 876 * 877 * Depending on the file system type, it calls the relevant, FS specific function. 878 * It must be called by a thread running in the cluster containing the parent inode. 879 * This function does NOT take any lock. 880 ****************************************************************************************** 881 * @ parent : local pointer on parent inode (directory). 882 * @ name : child name. 883 * @ child_xp : extended pointer on remote child inode (file or directory) 884 * @ return 0 if success / return ENOENT if not found. 885 *****************************************************************************************/ 886 error_t vfs_fs_child_init( vfs_inode_t * parent, 887 char * name, 888 xptr_t child_xp ); 889 890 /***************************************************************************************** 891 * This function updates the FS on the IOC device for a given inode identified by 892 * the <inode> argument. It scan all pages registered in the associated mapper, 893 * and copies from mapper to device each page marked as dirty. 894 * WARNING : The target <inode> cannot be a directory, because all modifications in a 895 * directory are synchronously done on the IOC device by the two vfs_fs_add_dentry() 896 * and vfs_fs_remove_dentry() functions. 897 * 898 * Depending on the file system type, it calls the relevant, FS specific function. 899 * It must be called by a thread running in the inode cluster. 900 ***************************************************************************************** 901 * @ inode : local pointer on inode. 902 * @ return 0 if success / return EIO if failure during device access. 903 ****************************************************************************************/ 904 error_t vfs_fs_sync_inode( struct vfs_inode_s * inode ); 905 906 /***************************************************************************************** 907 * This function updates the FS on the IOC device for the FAT itself. 908 * It scan all clusters registered in the FAT mapper, and copies to device 909 * each page marked as dirty. 910 * 911 * Depending on the file system type, it calls the relevant, FS specific function. 912 * It can be called by a thread running in any cluster. 913 ***************************************************************************************** 914 * @ return 0 if success / return EIO if failure during device access. 915 ****************************************************************************************/ 916 error_t vfs_fs_sync_fat( void ); 917 918 /***************************************************************************************** 919 * This function updates the free clusters info on the IOC device. 920 * 921 * Depending on the file system type, it calls the relevant, FS specific function. 922 * It can be called by a thread running in any cluster. 923 ***************************************************************************************** 924 * @ return 0 if success / return EIO if failure during device access. 925 ****************************************************************************************/ 926 error_t vfs_fs_sync_free_info( void ); 927 928 /****************************************************************************************** 929 * This function allocates a free cluster from the FS identified by the <fs_type> 930 * argument. It updates the selected FS File Allocation Table. 931 * 932 * Depending on the file system type, it calls the relevant, FS specific function. 933 * It can be called by a thread running in any cluster. 934 ****************************************************************************************** 935 * @ fs_type : [in] File System type. 936 * @ cluster : [out] cluster index in File system. 937 * @ return 0 if success / return -1 if no free cluster 938 *****************************************************************************************/ 939 error_t vfs_fs_cluster_alloc( uint32_t fs_type, 940 uint32_t * cluster ); 941 942 /****************************************************************************************** 943 * This function makes all I/O operations required to release all clusters allocated 944 * on IOC device to a given inode, identified by the <inode_xp> argument. 945 * Depending on the file system type, it calls the proper, FS specific function. 946 * It is called by the vfs_unlink() function. 947 * It can be executed by a thread running in any cluster. 948 * This function does NOT take any lock. 949 ****************************************************************************************** 950 * @ inode_xp : extended pointer on inode. 951 * @ return 0 if success / return -1 if device access failure. 952 *****************************************************************************************/ 953 error_t vfs_fs_release_inode( xptr_t inode_xp ); 954 955 /****************************************************************************************** 956 * This function makes the I/O operation to move one page identified by the <page_xp> 957 * argument to/from the IOC device from/to the mapper, as defined by <to_mapper>. 958 * Depending on the file system type, it calls the proper, FS specific function. 805 959 * It is used in case of MISS on the mapper, or when a dirty page in the mapper must 806 960 * be updated in the File System. 807 * Depending on the file system type, it calls the proper, FS specific function.808 * It must be executed by a thread running in the cluster containing the mapper.809 961 * The mapper pointer is obtained from the page descriptor. 810 * It takes the mapper lock before launching the IO operation. 811 ****************************************************************************************** 812 * @ page : local pointer on the page descriptor. 962 * It can be executed by any thread running in any cluster. 963 * This function does NOT take any lock. 964 ****************************************************************************************** 965 * @ page_xp : extended pointer on the page descriptor. 813 966 * @ to_mapper : transfer direction. 814 * @ returns 0 if success / return EINVAL if it cannot access the external device. 815 *****************************************************************************************/ 816 error_t vfs_mapper_move_page( struct page_s * page, 817 bool_t to_mapper ); 818 819 /****************************************************************************************** 820 * This function makes the I/O operations required to move, from device to mapper, 821 * all pages covering a given inode, identified by the <inode> argument. The target 822 * inode can be a directory or a file, but this function is mainly used to load (prefetch) 823 * a complete directory to the mapper. 824 * Depending on the file system type, it calls the proper, FS specific function. 825 * It must be executed by a thread running in the cluster containing the mapper. 826 * The mapper pointer is obtained from the inode descriptor. 827 * It takes the mapper lock before launching the IO operation. 828 ****************************************************************************************** 829 * @ inode : local pointer on inode. 830 * @ return 0 if success / return EIO if device access failure. 831 *****************************************************************************************/ 832 error_t vfs_mapper_load_all( vfs_inode_t * inode ); 967 * @ returns 0 if success / return -1 if device access failure. 968 *****************************************************************************************/ 969 error_t vfs_fs_move_page( xptr_t page_xp, 970 bool_t to_mapper ); 833 971 834 972
Note: See TracChangeset
for help on using the changeset viewer.