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.