aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2014-07-21 06:26:58 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-07-28 19:47:44 -0400
commit07a338236fdcd6caf41541dcdf879f5758020ab1 (patch)
treefd6dadad36b3c75547ca33e0006a0a00d212fe75
parentf469f02dc6fa67f6c6a7d91400d08b9339147aed (diff)
PM / Hibernate: Add memory_rtree_find_bit function
Add a function to find a bit in the radix tree for a given pfn. Also add code to the memory bitmap wrapper functions to use the radix tree together with the existing memory bitmap implementation. On read accesses compare the results of both bitmaps to make sure the radix tree behaves the same way. Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-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/**