Changeset d0d7afb in mainline for uspace/lib/ext4/libext4_directory.c
- Timestamp:
- 2012-03-01T19:56:31Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c30a015
- Parents:
- d8269dc
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_directory.c
rd8269dc rd0d7afb 314 314 315 315 int ext4_directory_add_entry(ext4_filesystem_t *fs, ext4_inode_ref_t * parent, 316 const char * entry_name, ext4_inode_ref_t *child)316 const char *name, ext4_inode_ref_t *child) 317 317 { 318 318 int rc; 319 319 320 EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, entry_name); 321 322 uint16_t name_len = strlen(entry_name); 320 EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, name); 323 321 324 322 // Index adding (if allowed) … … 326 324 ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) { 327 325 328 rc = ext4_directory_dx_add_entry(fs, parent, child, name _len, entry_name);326 rc = ext4_directory_dx_add_entry(fs, parent, child, name); 329 327 330 328 // Check if index is not corrupted … … 347 345 // Linear algorithm 348 346 349 ext4_directory_iterator_t it; 350 rc = ext4_directory_iterator_init(&it, fs, parent, 0); 351 if (rc != EOK) { 352 return rc; 353 } 354 347 EXT4FS_DBG("Linear algorithm"); 348 349 uint32_t iblock, fblock; 355 350 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock); 356 uint16_t required_len = 8 + name_len + (4 - name_len % 4); 357 358 while (it.current != NULL) { 359 uint32_t entry_inode = ext4_directory_entry_ll_get_inode(it.current); 360 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(it.current); 361 362 if ((entry_inode == 0) && (rec_len >= required_len)) { 363 364 ext4_directory_write_entry(fs->superblock, it.current, rec_len, 365 child, entry_name, name_len); 366 it.current_block->dirty = true; 367 return ext4_directory_iterator_fini(&it); 368 } 369 370 if (entry_inode != 0) { 371 uint16_t used_name_len = ext4_directory_entry_ll_get_name_length( 372 fs->superblock, it.current); 373 374 uint16_t used_space = 8 + used_name_len; 375 if ((used_name_len % 4) != 0) { 376 used_space += 4 - (used_name_len % 4); 377 } 378 uint16_t free_space = rec_len - used_space; 379 380 EXT4FS_DBG("rec_len = \%u, used_space = \%u, free space = \%u", rec_len, used_space, free_space); 381 382 if (free_space >= required_len) { 383 384 // Cut tail of current entry 385 ext4_directory_entry_ll_set_entry_length(it.current, used_space); 386 387 // SEEK manually 388 uint32_t local_offset = (it.current_offset % block_size); 389 local_offset += used_space; 390 ext4_directory_entry_ll_t *new_entry = it.current_block->data + local_offset; 391 392 // We are sure, that both entries are in the same data block 393 // dirtyness will be set now 394 395 ext4_directory_write_entry(fs->superblock, new_entry, 396 free_space, child, entry_name, name_len); 397 it.current_block->dirty = true; 398 return ext4_directory_iterator_fini(&it); 399 } 400 401 } 402 403 rc = ext4_directory_iterator_next(&it); 404 if (rc != EOK) { 405 return rc; 406 } 407 } 408 409 // Destroy iterator 410 ext4_directory_iterator_fini(&it); 351 uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode); 352 uint32_t total_blocks = inode_size / block_size; 353 354 uint32_t name_len = strlen(name); 355 356 bool success = false; 357 for (iblock = 0; iblock < total_blocks; ++iblock) { 358 359 rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, iblock, &fblock); 360 if (rc != EOK) { 361 return rc; 362 } 363 364 block_t *block; 365 rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE); 366 if (rc != EOK) { 367 return rc; 368 } 369 370 rc = ext4_directory_try_insert_entry(fs->superblock, block, child, name, name_len); 371 if (rc == EOK) { 372 success = true; 373 } 374 375 rc = block_put(block); 376 if (rc != EOK) { 377 return rc; 378 } 379 380 if (success) { 381 return EOK; 382 } 383 } 384 411 385 412 386 EXT4FS_DBG("NO FREE SPACE - needed to allocate block"); 413 387 414 uint32_t fblock;415 uint32_t iblock;416 388 rc = ext4_directory_append_block(fs, parent, &fblock, &iblock); 417 389 if (rc != EOK) { … … 428 400 // Fill block with zeroes 429 401 memset(new_block->data, 0, block_size); 430 431 402 ext4_directory_entry_ll_t *block_entry = new_block->data; 432 433 ext4_directory_write_entry(fs->superblock, block_entry, block_size, 434 child, entry_name, name_len); 403 ext4_directory_write_entry(fs->superblock, block_entry, block_size, child, name, name_len); 435 404 436 405 new_block->dirty = true; … … 556 525 } 557 526 527 int ext4_directory_try_insert_entry(ext4_superblock_t *sb, 528 block_t *target_block, ext4_inode_ref_t *child, 529 const char *name, uint32_t name_len) 530 { 531 uint32_t block_size = ext4_superblock_get_block_size(sb); 532 uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len; 533 if ((required_len % 4) != 0) { 534 required_len += 4 - (required_len % 4); 535 } 536 537 ext4_directory_entry_ll_t *dentry = target_block->data; 538 ext4_directory_entry_ll_t *stop = target_block->data + block_size; 539 540 while (dentry < stop) { 541 542 uint32_t inode = ext4_directory_entry_ll_get_inode(dentry); 543 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry); 544 545 if ((inode == 0) && (rec_len >= required_len)) { 546 ext4_directory_write_entry(sb, dentry, rec_len, child, name, name_len); 547 target_block->dirty = true; 548 return EOK; 549 } 550 551 if (inode != 0) { 552 uint16_t used_name_len = 553 ext4_directory_entry_ll_get_name_length(sb, dentry); 554 555 uint16_t used_space = 556 sizeof(ext4_fake_directory_entry_t) + used_name_len; 557 if ((used_name_len % 4) != 0) { 558 used_space += 4 - (used_name_len % 4); 559 } 560 uint16_t free_space = rec_len - used_space; 561 562 if (free_space >= required_len) { 563 564 // Cut tail of current entry 565 ext4_directory_entry_ll_set_entry_length(dentry, used_space); 566 ext4_directory_entry_ll_t *new_entry = 567 (void *)dentry + used_space; 568 ext4_directory_write_entry(sb, new_entry, 569 free_space, child, name, name_len); 570 571 target_block->dirty = true; 572 return EOK; 573 } 574 } 575 576 dentry = (void *)dentry + rec_len; 577 } 578 579 return ENOSPC; 580 } 581 558 582 559 583 /**
Note:
See TracChangeset
for help on using the changeset viewer.