diff options
-rw-r--r-- | kernel/power/snapshot.c | 84 |
1 files changed, 81 insertions, 3 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 5a0eafdbac79..0b7f93498077 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -720,6 +720,56 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, | |||
720 | return 0; | 720 | return 0; |
721 | } | 721 | } |
722 | 722 | ||
723 | /* | ||
724 | * memory_rtree_find_bit - Find the bit for pfn in the memory | ||
725 | * bitmap | ||
726 | * | ||
727 | * Walks the radix tree to find the page which contains the bit for | ||
728 | * pfn and returns the bit position in **addr and *bit_nr. | ||
729 | */ | ||
730 | static int memory_rtree_find_bit(struct memory_bitmap *bm, unsigned long pfn, | ||
731 | void **addr, unsigned int *bit_nr) | ||
732 | { | ||
733 | struct mem_zone_bm_rtree *curr, *zone; | ||
734 | struct rtree_node *node; | ||
735 | int i, block_nr; | ||
736 | |||
737 | zone = NULL; | ||
738 | |||
739 | /* Find the right zone */ | ||
740 | list_for_each_entry(curr, &bm->zones, list) { | ||
741 | if (pfn >= curr->start_pfn && pfn < curr->end_pfn) { | ||
742 | zone = curr; | ||
743 | break; | ||
744 | } | ||
745 | } | ||
746 | |||
747 | if (!zone) | ||
748 | return -EFAULT; | ||
749 | |||
750 | /* | ||
751 | * We have a zone. Now walk the radix tree to find the leave | ||
752 | * node for our pfn. | ||
753 | */ | ||
754 | node = zone->rtree; | ||
755 | block_nr = (pfn - zone->start_pfn) >> BM_BLOCK_SHIFT; | ||
756 | |||
757 | for (i = zone->levels; i > 0; i--) { | ||
758 | int index; | ||
759 | |||
760 | index = block_nr >> ((i - 1) * BM_RTREE_LEVEL_SHIFT); | ||
761 | index &= BM_RTREE_LEVEL_MASK; | ||
762 | BUG_ON(node->data[index] == 0); | ||
763 | node = (struct rtree_node *)node->data[index]; | ||
764 | } | ||
765 | |||
766 | /* Set return values */ | ||
767 | *addr = node->data; | ||
768 | *bit_nr = (pfn - zone->start_pfn) & BM_BLOCK_MASK; | ||
769 | |||
770 | return 0; | ||
771 | } | ||
772 | |||
723 | static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) | 773 | static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) |
724 | { | 774 | { |
725 | void *addr; | 775 | void *addr; |
@@ -729,6 +779,10 @@ static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
729 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); | 779 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
730 | BUG_ON(error); | 780 | BUG_ON(error); |
731 | set_bit(bit, addr); | 781 | set_bit(bit, addr); |
782 | |||
783 | error = memory_rtree_find_bit(bm, pfn, &addr, &bit); | ||
784 | BUG_ON(error); | ||
785 | set_bit(bit, addr); | ||
732 | } | 786 | } |
733 | 787 | ||
734 | static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) | 788 | static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) |
@@ -740,6 +794,13 @@ static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) | |||
740 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); | 794 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
741 | if (!error) | 795 | if (!error) |
742 | set_bit(bit, addr); | 796 | set_bit(bit, addr); |
797 | else | ||
798 | return error; | ||
799 | |||
800 | error = memory_rtree_find_bit(bm, pfn, &addr, &bit); | ||
801 | if (!error) | ||
802 | set_bit(bit, addr); | ||
803 | |||
743 | return error; | 804 | return error; |
744 | } | 805 | } |
745 | 806 | ||
@@ -752,25 +813,42 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
752 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); | 813 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
753 | BUG_ON(error); | 814 | BUG_ON(error); |
754 | clear_bit(bit, addr); | 815 | clear_bit(bit, addr); |
816 | |||
817 | error = memory_rtree_find_bit(bm, pfn, &addr, &bit); | ||
818 | BUG_ON(error); | ||
819 | clear_bit(bit, addr); | ||
755 | } | 820 | } |
756 | 821 | ||
757 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | 822 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) |
758 | { | 823 | { |
759 | void *addr; | 824 | void *addr; |
760 | unsigned int bit; | 825 | unsigned int bit; |
761 | int error; | 826 | int error, error2; |
827 | int v; | ||
762 | 828 | ||
763 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); | 829 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
764 | BUG_ON(error); | 830 | BUG_ON(error); |
765 | return test_bit(bit, addr); | 831 | v = test_bit(bit, addr); |
832 | |||
833 | error2 = memory_rtree_find_bit(bm, pfn, &addr, &bit); | ||
834 | BUG_ON(error2); | ||
835 | |||
836 | WARN_ON_ONCE(v != test_bit(bit, addr)); | ||
837 | |||
838 | return v; | ||
766 | } | 839 | } |
767 | 840 | ||
768 | static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn) | 841 | static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn) |
769 | { | 842 | { |
770 | void *addr; | 843 | void *addr; |
771 | unsigned int bit; | 844 | unsigned int bit; |
845 | int present; | ||
846 | |||
847 | present = !memory_bm_find_bit(bm, pfn, &addr, &bit); | ||
848 | |||
849 | WARN_ON_ONCE(present != !memory_rtree_find_bit(bm, pfn, &addr, &bit)); | ||
772 | 850 | ||
773 | return !memory_bm_find_bit(bm, pfn, &addr, &bit); | 851 | return present; |
774 | } | 852 | } |
775 | 853 | ||
776 | /** | 854 | /** |