FreeCalypso > hg > freecalypso-sw
comparison gsm-fw/services/ffs/reclaim.c @ 216:0eb85790c0ed
gsm-fw/services/ffs: reclaim.c compiles
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 06 Jan 2014 07:23:36 +0000 |
parents | ef7d7da61c56 |
children | 2beb88a3d528 |
comparison
equal
deleted
inserted
replaced
215:517dd86b45b1 | 216:0eb85790c0ed |
---|---|
6 * | 6 * |
7 * $Id: reclaim.c 1.4.1.28 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ | 7 * $Id: reclaim.c 1.4.1.28 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ |
8 * | 8 * |
9 ******************************************************************************/ | 9 ******************************************************************************/ |
10 | 10 |
11 #ifndef TARGET | 11 #include "ffs.h" |
12 #include "ffs.cfg" | 12 #include "core.h" |
13 #endif | 13 #include "drv.h" |
14 | 14 #include "ffstrace.h" |
15 #include "ffs/ffs.h" | |
16 #include "ffs/board/core.h" | |
17 #include "ffs/board/drv.h" | |
18 #include "ffs/board/ffstrace.h" | |
19 | 15 |
20 #include <stdlib.h> // rand() | 16 #include <stdlib.h> // rand() |
21 | 17 |
22 /****************************************************************************** | 18 /****************************************************************************** |
23 * Inodes Reclaim | 19 * Inodes Reclaim |
503 | 499 |
504 iref_t data_block_reclaim(bref_t b, int candidate) | 500 iref_t data_block_reclaim(bref_t b, int candidate) |
505 { | 501 { |
506 iref_t i, n, j; | 502 iref_t i, n, j; |
507 blocksize_t used_old, lost_old; | 503 blocksize_t used_old, lost_old; |
508 int org_res_space, result = 0; | 504 int org_res_space, result = 0; |
509 iref_t org_block_files_reserved; | 505 iref_t org_block_files_reserved; |
510 offset_t lower, upper; | 506 offset_t lower, upper; |
511 struct inode_s *ip; | 507 struct inode_s *ip; |
512 static int is_reclaim_running = 0; | 508 static int is_reclaim_running = 0; |
513 | 509 |
514 tw(tr(TR_BEGIN, TrDReclaim, "data_block_reclaim(%d) {\n", b)); | 510 tw(tr(TR_BEGIN, TrDReclaim, "data_block_reclaim(%d) {\n", b)); |
515 | 511 |
516 // In case of no free blocks (after sudden power off) or if the file | 512 // In case of no free blocks (after sudden power off) or if the file |
517 // system is near full we risk to be reentered (infinity recursively | 513 // system is near full we risk to be reentered (infinity recursively |
518 // loop) and we can not allow that, so just return. | 514 // loop) and we can not allow that, so just return. |
519 if (is_reclaim_running == 1) { | 515 if (is_reclaim_running == 1) { |
520 tw(tr(TR_END, TrDReclaim, "} (reenteret skip reclaim) 0\n")); | 516 tw(tr(TR_END, TrDReclaim, "} (reenteret skip reclaim) 0\n")); |
521 return EFFS_RECLAIMLOOP; | 517 return EFFS_RECLAIMLOOP; |
522 } | 518 } |
523 | 519 |
524 is_reclaim_running = 1; | 520 is_reclaim_running = 1; |
525 | 521 |
526 // If there are more objects in this block than there are remaining | 522 // If there are more objects in this block than there are remaining |
527 // free inodes, we have to make an inodes_reclaim() first. | 523 // free inodes, we have to make an inodes_reclaim() first. |
528 tw(tr(TR_FUNC, TrDReclaim, | 524 tw(tr(TR_FUNC, TrDReclaim, |
529 "block_objects, fs.inodes_max, inodes: used, free\n")); | 525 "block_objects, fs.inodes_max, inodes: used, free\n")); |
539 tw(tr(TR_FUNC, TrInode, "NOTE: Will run out of free inodes...\n")); | 535 tw(tr(TR_FUNC, TrInode, "NOTE: Will run out of free inodes...\n")); |
540 inodes_reclaim(); | 536 inodes_reclaim(); |
541 } | 537 } |
542 | 538 |
543 // Allocate a new block. NOTE: we don't return an error because if we | 539 // Allocate a new block. NOTE: we don't return an error because if we |
544 // get in the situation where we don't have any free blocks this is the | 540 // get in the situation where we don't have any free blocks this is the |
545 // only way to recover. | 541 // only way to recover. |
546 if ((result = block_alloc(1, BF_DATA)) < 0) { | 542 if ((result = block_alloc(1, BF_DATA)) < 0) { |
547 tw(tr(TR_FUNC, TrAll, "WARNING: block_alloc failed\n")); | 543 tw(tr(TR_FUNC, TrAll, "WARNING: block_alloc failed\n")); |
548 } | 544 } |
549 | 545 |
550 BLOCK_RECLAIM_TEST(BLOCK_RECLAIM_ALLOC, "Oops after ffs_block_alloc()"); | 546 BLOCK_RECLAIM_TEST(BLOCK_RECLAIM_ALLOC, "Oops after ffs_block_alloc()"); |
551 | 547 |
552 // If there are any objects at all to reclaim... | 548 // If there are any objects at all to reclaim... |
553 if (bstat[b].objects > 0) | 549 if (bstat[b].objects > 0) |
554 { | 550 { |
555 BLOCK_RECOVER_TEST_INIT(BLOCK_RECOVER_OBJECTS, "Dummy") | 551 BLOCK_RECOVER_TEST_INIT(BLOCK_RECOVER_OBJECTS, "Dummy") |
556 // Save the current journal state | 552 // Save the current journal state |
557 if (journal_push() != EFFS_OK) { | 553 if (journal_push() != EFFS_OK) { |
558 is_reclaim_running = 0; // NOTEME: change to goto? | 554 is_reclaim_running = 0; // NOTEME: change to goto? |
559 return EFFS_CORRUPTED; | 555 return EFFS_CORRUPTED; |
560 } | 556 } |
572 upper = offset2location(dev.binfo[b].offset + dev.blocksize); | 568 upper = offset2location(dev.binfo[b].offset + dev.blocksize); |
573 | 569 |
574 tw(tr(TR_FUNC, TrDReclaim, "Block addr range = 0x%X..0x%X\n", | 570 tw(tr(TR_FUNC, TrDReclaim, "Block addr range = 0x%X..0x%X\n", |
575 location2offset(lower), location2offset(upper))); | 571 location2offset(lower), location2offset(upper))); |
576 | 572 |
577 // This is the only time we are allowed to use the reserved | 573 // This is the only time we are allowed to use the reserved |
578 org_block_files_reserved= fs.block_files_reserved; | 574 org_block_files_reserved= fs.block_files_reserved; |
579 fs.block_files_reserved = 0; | 575 fs.block_files_reserved = 0; |
580 | 576 |
581 org_res_space = fs.reserved_space; | 577 org_res_space = fs.reserved_space; |
582 fs.reserved_space = RESERVED_NONE; | 578 fs.reserved_space = RESERVED_NONE; |
583 | 579 |
584 ip = inode_addr(1); | 580 ip = inode_addr(1); |
585 for (i = 1, n = 0; i < fs.inodes_max; i++, ip++) | 581 for (i = 1, n = 0; i < fs.inodes_max; i++, ip++) |
586 { | 582 { |
587 BLOCK_RECOVER_TEST(BLOCK_RECOVER_OBJECTS, "Oops before relocate all objects"); | 583 BLOCK_RECOVER_TEST(BLOCK_RECOVER_OBJECTS, "Oops before relocate all objects"); |
588 // Ensure object is valid and within the block to be reclaimed | 584 // Ensure object is valid and within the block to be reclaimed |
589 if (is_object_valid(ip) && | 585 if (is_object_valid(ip) && |
590 lower <= ip->location && ip->location < upper) | 586 lower <= ip->location && ip->location < upper) |
591 { | 587 { |
592 if ((result = object_relocate(i)) < 0) { | 588 if ((result = object_relocate(i)) < 0) { |
644 | 640 |
645 n++; | 641 n++; |
646 } | 642 } |
647 } | 643 } |
648 | 644 |
649 fs.block_files_reserved = org_block_files_reserved; // Restore | 645 fs.block_files_reserved = org_block_files_reserved; // Restore |
650 fs.reserved_space = org_res_space; | 646 fs.reserved_space = org_res_space; |
651 | 647 |
652 tw(tr(TR_FUNC, TrDReclaim, "Reclaimed %d objects\n", n)); | 648 tw(tr(TR_FUNC, TrDReclaim, "Reclaimed %d objects\n", n)); |
653 if (result >= 0) | 649 if (result >= 0) |
654 result = n; // We return number of objects relocated | 650 result = n; // We return number of objects relocated |
655 | 651 |
657 // We did not finish, so restore the old bstat[].used of the block. | 653 // We did not finish, so restore the old bstat[].used of the block. |
658 bstat[b].used = used_old; | 654 bstat[b].used = used_old; |
659 tw(tr(TR_FUNC, TrAll, | 655 tw(tr(TR_FUNC, TrAll, |
660 "WARNING: data_block_reclaim() not completed\n")); | 656 "WARNING: data_block_reclaim() not completed\n")); |
661 result = EFFS_DBR; | 657 result = EFFS_DBR; |
662 } | 658 } |
663 | 659 |
664 // Restore the saved journal state | 660 // Restore the saved journal state |
665 if (journal_pop() != EFFS_OK) { | 661 if (journal_pop() != EFFS_OK) { |
666 is_reclaim_running = 0; // NOTEME: change to goto? | 662 is_reclaim_running = 0; // NOTEME: change to goto? |
667 return EFFS_CORRUPTED; | 663 return EFFS_CORRUPTED; |
668 } | 664 } |
669 } | 665 } |
670 BLOCK_RECLAIM_TEST(BLOCK_RECLAIM_NO_CLEAN, "Oops before clean old data block"); | 666 BLOCK_RECLAIM_TEST(BLOCK_RECLAIM_NO_CLEAN, "Oops before clean old data block"); |
671 | 667 |
672 if (result >= 0) { | 668 if (result >= 0) { |
673 // Clean the block (remove all inodes that refer to this block) | 669 // Clean the block (remove all inodes that refer to this block) |
674 block_flags_write(b, BF_CLEANING); | 670 block_flags_write(b, BF_CLEANING); |
675 block_clean(b); | 671 block_clean(b); |
676 | 672 |
677 statistics_update_drec(used_old - lost_old, lost_old, candidate); | 673 statistics_update_drec(used_old - lost_old, lost_old, candidate); |
678 | 674 |
679 BLOCK_RECLAIM_TEST(BLOCK_RECLAIM_CLEANING, "Oops before free old data block"); | 675 BLOCK_RECLAIM_TEST(BLOCK_RECLAIM_CLEANING, "Oops before free old data block"); |
680 | 676 |
681 // Free the old block | 677 // Free the old block |
682 block_free(b); | 678 block_free(b); |
683 } | 679 } |
684 | 680 |
685 is_reclaim_running = 0; | 681 is_reclaim_running = 0; |
686 | 682 |
687 tw(tr(TR_END, TrDReclaim, "} (data_block_reclaim) %d\n", result)); | 683 tw(tr(TR_END, TrDReclaim, "} (data_block_reclaim) %d\n", result)); |
688 ttw(ttr(TTrRec, "} %d" NL, result)); | 684 ttw(ttr(TTrRec, "} %d" NL, result)); |
689 | 685 |
690 return result; | 686 return result; |
782 // levelling. Also, the global age limits are updated. FIXME: Should we | 778 // levelling. Also, the global age limits are updated. FIXME: Should we |
783 // avoid having ffs_initialize() do a block_reclaim() because it delays reboot?. | 779 // avoid having ffs_initialize() do a block_reclaim() because it delays reboot?. |
784 int blocks_reclaim(void) | 780 int blocks_reclaim(void) |
785 { | 781 { |
786 bref_t b, n, b_lost_space; | 782 bref_t b, n, b_lost_space; |
787 int blocks_free = 0, lost_space; | 783 int blocks_free = 0, lost_space; |
788 | 784 int free_space, b_free_space; |
789 int free_space, b_free_space; | |
790 | 785 |
791 tw(tr(TR_BEGIN, TrBlock, "blocks_reclaim() {\n")); | 786 tw(tr(TR_BEGIN, TrBlock, "blocks_reclaim() {\n")); |
792 ttw(str(TTrRec, "blocks_reclaim() {" NL)); | 787 ttw(str(TTrRec, "blocks_reclaim() {" NL)); |
793 | 788 |
794 // Testing of fs.testflags is for the sake of testing block_commit() | 789 // Testing of fs.testflags is for the sake of testing block_commit() |
800 for (b = 0, n = 0; b < dev.numblocks; b++) { | 795 for (b = 0, n = 0; b < dev.numblocks; b++) { |
801 if (is_block_flag(b, BF_LOST)) { | 796 if (is_block_flag(b, BF_LOST)) { |
802 block_reclaim(b); | 797 block_reclaim(b); |
803 n++; | 798 n++; |
804 } | 799 } |
805 if (is_block(b, BF_IS_FREE)) { | 800 if (is_block(b, BF_IS_FREE)) { |
806 blocks_free++; | 801 blocks_free++; |
807 } | 802 } |
808 } | 803 } |
809 } | 804 } |
810 | 805 |
811 // If the number of free blocks is less than fs.blocks_free_min we | 806 // If the number of free blocks is less than fs.blocks_free_min we |
812 // call data_block_reclaim(). We will reclaim the block with most lost | 807 // call data_block_reclaim(). We will reclaim the block with most lost |
813 // space. This should only happend if we got a sudden power off/reset | 808 // space. This should only happend if we got a sudden power off/reset |
814 // while we reclaimed a block. | 809 // while we reclaimed a block. |
815 if (blocks_free < fs.blocks_free_min) { | 810 if (blocks_free < fs.blocks_free_min) { |
816 lost_space = 0; | 811 lost_space = 0; |
817 free_space = 0; | 812 free_space = 0; |
818 | 813 |
819 // We most never reclaim the block with most free space because this | 814 // We most never reclaim the block with most free space because this |
820 // is the only block we can relocate the objects to. | 815 // is the only block we can relocate the objects to. |
821 for (b = 0; b < dev.numblocks; b++) { | 816 for (b = 0; b < dev.numblocks; b++) { |
822 if (is_block_flag(b, BF_DATA)) { | 817 if (is_block_flag(b, BF_DATA)) { |
823 if ((dev.blocksize - bstat[b].used) > free_space) { | 818 if ((dev.blocksize - bstat[b].used) > free_space) { |
824 free_space = dev.blocksize - bstat[b].used; | 819 free_space = dev.blocksize - bstat[b].used; |
825 b_free_space = b; | 820 b_free_space = b; |
826 } | |
827 } | |
828 } | 821 } |
829 tw(tr(TR_FUNC, TrBlock, "most free space: %d in block: %d \n", | 822 } |
830 free_space, b_free_space)); | 823 } |
831 | 824 tw(tr(TR_FUNC, TrBlock, "most free space: %d in block: %d \n", |
832 for (b = 0; b < dev.numblocks; b++) { | 825 free_space, b_free_space)); |
833 if (is_block_flag(b, BF_DATA) && b != b_free_space) { | 826 |
834 if (bstat[b].lost > lost_space) { | 827 for (b = 0; b < dev.numblocks; b++) { |
835 lost_space = bstat[b].lost; | 828 if (is_block_flag(b, BF_DATA) && b != b_free_space) { |
836 b_lost_space = b; | 829 if (bstat[b].lost > lost_space) { |
837 } | 830 lost_space = bstat[b].lost; |
838 } | 831 b_lost_space = b; |
839 } | 832 } |
840 tw(tr(TR_FUNC, TrBlock, "most lost space: %d in block: %d \n", | 833 } |
841 lost_space, b_lost_space)); | |
842 | |
843 data_block_reclaim(b_lost_space, MOST_LOST); | |
844 } | 834 } |
835 tw(tr(TR_FUNC, TrBlock, "most lost space: %d in block: %d \n", | |
836 lost_space, b_lost_space)); | |
837 | |
838 data_block_reclaim(b_lost_space, MOST_LOST); | |
839 } | |
845 tw(tr(TR_END, TrBlock, "} %d\n", n)); | 840 tw(tr(TR_END, TrBlock, "} %d\n", n)); |
846 ttw(ttr(TTrRec, "} %d" NL, n)); | 841 ttw(ttr(TTrRec, "} %d" NL, n)); |
847 | 842 |
848 return n; | 843 return n; |
849 } | 844 } |
863 return fs.initerror; | 858 return fs.initerror; |
864 } | 859 } |
865 | 860 |
866 // Testing of fs.testflags is for the sake of testing block_commit() | 861 // Testing of fs.testflags is for the sake of testing block_commit() |
867 if ((fs.testflags & BLOCK_COMMIT_BASE) != 0 && | 862 if ((fs.testflags & BLOCK_COMMIT_BASE) != 0 && |
868 fs.testflags != BLOCK_COMMIT_OLD_FREE) { | 863 fs.testflags != BLOCK_COMMIT_OLD_FREE) { |
869 tw(tr(TR_FUNC, TrBlock, "Bailing out because fs.testflags = 0x%X\n", | 864 tw(tr(TR_FUNC, TrBlock, "Bailing out because fs.testflags = 0x%X\n", |
870 fs.testflags)); | 865 fs.testflags)); |
871 } | 866 } |
872 else { | 867 else { |
873 // We must read block's age before we erase it. | 868 // We must read block's age before we erase it. |