Changeset 82cb6768 in mainline
- Timestamp:
- 2012-04-10T20:01:46Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f2a3e57
- Parents:
- b73530a
- Location:
- uspace/lib/ext4
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_balloc.c
rb73530a r82cb6768 569 569 } 570 570 571 int ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t fblock) 571 int ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, 572 uint32_t fblock, bool *free) 572 573 { 573 574 int rc; … … 595 596 } 596 597 597 boolfree = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group);598 599 if ( free) {598 *free = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group); 599 600 if (*free) { 600 601 ext4_bitmap_set_bit(bitmap_block->data, index_in_group); 601 602 bitmap_block->dirty = true; … … 610 611 } 611 612 612 if (!free) { 613 rc = EINVAL; 613 if (!(*free)) { 614 614 goto terminate; 615 615 } -
uspace/lib/ext4/libext4_balloc.h
rb73530a r82cb6768 41 41 uint32_t , uint32_t); 42 42 extern int ext4_balloc_alloc_block(ext4_inode_ref_t *, uint32_t *); 43 extern int ext4_balloc_try_alloc_block(ext4_inode_ref_t *, uint32_t );43 extern int ext4_balloc_try_alloc_block(ext4_inode_ref_t *, uint32_t, bool *); 44 44 45 45 #endif -
uspace/lib/ext4/libext4_extent.c
rb73530a r82cb6768 192 192 if (entries_count == 0) { 193 193 // this leaf is empty 194 EXT4FS_DBG("EMPTY LEAF");194 // EXT4FS_DBG("EMPTY LEAF"); 195 195 *extent = NULL; 196 196 return; … … 379 379 uint32_t fblock = ext4_extent_index_get_leaf(index); 380 380 381 EXT4FS_DBG("fblock = \%u", fblock);381 // EXT4FS_DBG("fblock = \%u", fblock); 382 382 383 383 rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD); … … 543 543 // Put loaded blocks 544 544 // From 1 -> 0 is a block with inode data 545 for (uint16_t i = 1; i < path->depth; ++i) {545 for (uint16_t i = 1; i <= path->depth; ++i) { 546 546 if (path[i].block) { 547 547 block_put(path[i].block); … … 553 553 554 554 return rc; 555 } 556 557 static int ext4_extent_append_extent(ext4_inode_ref_t *inode_ref, 558 ext4_extent_path_t *path, ext4_extent_path_t **last_path_item, 559 uint32_t iblock) 560 { 561 int rc; 562 563 ext4_extent_path_t *path_ptr = *last_path_item; 564 565 uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header); 566 uint16_t limit = ext4_extent_header_get_max_entries_count(path_ptr->header); 567 568 // Trivial way - no splitting 569 if (entries < limit) { 570 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 571 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 572 ext4_extent_set_block_count(path_ptr->extent, 0); 573 ext4_extent_set_first_block(path_ptr->extent, iblock); 574 ext4_extent_set_start(path_ptr->extent, 0); 575 path_ptr->block->dirty = true; 576 577 return EOK; 578 } 579 580 uint32_t block_size = 581 ext4_superblock_get_block_size(inode_ref->fs->superblock); 582 583 // Trivial tree - grow 584 if (path_ptr == path) { 585 586 // EXT4FS_DBG("splitting extent root"); 587 588 uint32_t new_fblock; 589 rc = ext4_balloc_alloc_block(inode_ref, &new_fblock); 590 if (rc != EOK) { 591 EXT4FS_DBG("error in block allocation"); 592 return rc; 593 } 594 595 // EXT4FS_DBG("allocated new node \%u", new_fblock); 596 597 block_t *block; 598 rc = block_get(&block, inode_ref->fs->device, 599 new_fblock, BLOCK_FLAGS_NOREAD); 600 if (rc != EOK) { 601 EXT4FS_DBG("error in block_get"); 602 return rc; 603 } 604 605 memset(block->data, 0, block_size); 606 607 // Move data from root to the new block 608 memcpy(block->data, inode_ref->inode->blocks, 609 EXT4_INODE_BLOCKS * sizeof(uint32_t)); 610 611 path_ptr++; 612 path_ptr->block = block; 613 path_ptr->header = (ext4_extent_header_t *)block->data; 614 path_ptr->depth = ext4_extent_header_get_depth(path_ptr->header); 615 path_ptr->index = NULL; 616 617 uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header); 618 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 619 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 620 uint16_t limit = (block_size - sizeof(ext4_extent_header_t)) / 621 sizeof(ext4_extent_t); 622 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 623 624 // Modify root (in inode) 625 path->depth = 1; 626 path->extent = NULL; 627 path->index = EXT4_EXTENT_FIRST_INDEX(path->header); 628 629 ext4_extent_header_set_depth(path->header, path_ptr->depth + 1); 630 ext4_extent_header_set_entries_count(path->header, 1); 631 632 ext4_extent_index_set_first_block(path->index, 0); 633 ext4_extent_index_set_leaf(path->index, new_fblock); 634 635 path_ptr->block->dirty = true; 636 path->block->dirty = true; 637 638 *last_path_item = path_ptr; 639 640 return EOK; 641 } 642 643 assert(false); 644 645 // start splitting 646 uint32_t fblock = 0; 647 648 path_ptr--; 649 650 while (path_ptr > path) { 651 652 rc = ext4_balloc_alloc_block(inode_ref, &fblock); 653 if (rc != EOK) { 654 return rc; 655 } 656 657 block_t *block; 658 rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD); 659 if (rc != EOK) { 660 ext4_balloc_free_block(inode_ref, fblock); 661 return rc; 662 } 663 664 // Init block 665 memset(block->data, 0, block_size); 666 667 // Not modified 668 block_put(path_ptr->block); 669 path_ptr->block = block; 670 671 path_ptr->header = block->data; 672 673 if (path_ptr->depth) { 674 path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header); 675 } else { 676 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header); 677 } 678 } 679 680 return EOK; 555 681 } 556 682 … … 564 690 uint32_t block_size = ext4_superblock_get_block_size(sb); 565 691 692 // Calculate number of new logical block 566 693 uint32_t new_block_idx = 0; 567 694 if (inode_size > 0) { … … 572 699 } 573 700 701 // Load the nearest leaf (with extent) 574 702 ext4_extent_path_t *path; 575 703 rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path); … … 584 712 } 585 713 586 // if extent == NULL -> add extent to empty leaf 714 uint32_t phys_block = 0; 715 716 // Add new extent to the node 587 717 if (path_ptr->extent == NULL) { 588 589 EXT4FS_DBG("NULL extent");590 591 ext4_extent_t *ext = EXT4_EXTENT_FIRST(path_ptr->header);592 ext4_extent_set_block_count(ext, 0);593 594 ext4_extent_header_set_entries_count(path_ptr->header, 1);595 596 path_ptr->extent = ext;597 } 598 599 uint32_t phys_block;600 601 if (ext4_extent_get_block_count(path_ptr->extent) == 0) {602 603 EXT4FS_DBG("no blocks in extent"); 604 605 // Add first block to the extent606 607 rc = ext4_balloc_alloc_block(inode_ref, &phys_block); 608 if (rc != EOK) {609 EXT4FS_DBG("error in allocation"); 718 goto append_extent; 719 } 720 721 uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent); 722 uint16_t block_limit = (1 << 15); 723 724 if (block_count < block_limit) { 725 726 if (block_count == 0) { 727 728 rc = ext4_balloc_alloc_block(inode_ref, &phys_block); 729 if (rc != EOK) { 730 // TODO error, cleanup 731 assert(false); 732 } 733 734 ext4_extent_set_first_block(path_ptr->extent, new_block_idx); 735 ext4_extent_set_start(path_ptr->extent, phys_block); 736 ext4_extent_set_block_count(path_ptr->extent, 1); 737 738 path_ptr->block->dirty = true; 739 610 740 goto finish; 611 } 612 613 ext4_extent_set_block_count(path_ptr->extent, 1); 614 ext4_extent_set_start(path_ptr->extent, phys_block); 615 ext4_extent_set_first_block(path_ptr->extent, new_block_idx); 616 617 path_ptr->block->dirty = true; 618 741 } else { 742 743 phys_block = ext4_extent_get_start(path_ptr->extent); 744 phys_block += ext4_extent_get_block_count(path_ptr->extent); 745 746 bool free; 747 rc = ext4_balloc_try_alloc_block(inode_ref, phys_block, &free); 748 if (rc != EOK) { 749 // TODO error 750 assert(false); 751 } 752 753 if (! free) { 754 // target is not free 755 // EXT4FS_DBG("target not free, \%u", phys_block); 756 goto append_extent; 757 } 758 759 760 ext4_extent_set_block_count(path_ptr->extent, block_count + 1); 761 762 path_ptr->block->dirty = true; 763 764 goto finish; 765 } 766 } 767 768 assert(false); 769 770 append_extent: 771 772 phys_block = 0; 773 // Allocate and insert insert new block 774 rc = ext4_balloc_alloc_block(inode_ref, &phys_block); 775 if (rc != EOK) { 776 EXT4FS_DBG("error in block allocation, rc = \%d", rc); 619 777 goto finish; 620 621 } else { 622 // try allocate succeeding extent block 623 624 EXT4FS_DBG("existing extent"); 625 626 uint16_t blocks = ext4_extent_get_block_count(path_ptr->extent); 627 628 if (blocks < (1 << 15)) { 629 // there is place for more blocks 630 631 EXT4FS_DBG("appending block to existing extent"); 632 633 uint64_t last = ext4_extent_get_start(path_ptr->extent) + blocks - 1; 634 635 rc = ext4_balloc_try_alloc_block(inode_ref, last + 1); 636 if (rc == EOK) { 637 path_ptr->block->dirty = true; 638 ext4_extent_set_block_count(path_ptr->extent, blocks + 1); 639 phys_block = last + 1; 640 goto finish; 641 } 642 643 if (rc != EINVAL) { 644 goto finish; 645 } 646 } 647 648 // Add new extent 649 // TODO 650 assert(false); 651 } 652 778 } 779 780 // EXT4FS_DBG("allocated \%u", phys_block); 781 782 rc = ext4_extent_append_extent(inode_ref, path, &path_ptr, new_block_idx); 783 if (rc != EOK) { 784 ext4_balloc_free_block(inode_ref, phys_block); 785 goto finish; 786 } 787 788 ext4_extent_set_block_count(path_ptr->extent, 1); 789 ext4_extent_set_first_block(path_ptr->extent, new_block_idx); 790 ext4_extent_set_start(path_ptr->extent, phys_block); 791 792 path_ptr->block->dirty = true; 653 793 654 794 finish: … … 657 797 *fblock = phys_block; 658 798 799 // EXT4FS_DBG("iblock = \%u, fblock = \%u", new_block_idx, phys_block); 800 659 801 // Put loaded blocks 660 802 // From 1 -> 0 is a block with inode data 661 for (uint16_t i = 1; i < path->depth; ++i) {803 for (uint16_t i = 1; i <= path->depth; ++i) { 662 804 if (path[i].block) { 663 805 block_put(path[i].block);
Note:
See TracChangeset
for help on using the changeset viewer.