aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/power/snapshot.c84
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 */
730static 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
723static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) 773static 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
734static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) 788static 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
757static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) 822static 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
768static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn) 841static 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/**