aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-12-21 10:20:16 -0500
committerGleb Natapov <gleb@redhat.com>2012-12-23 03:17:38 -0500
commit116c14c0191f3378e6567af296529ac287e85aa2 (patch)
tree98b6f582d2d2f83da21918a95bfea48f1d37d84e /virt
parent871a069db9f29938071b3d214cb964980071ffbf (diff)
kvm: Fix memory slot generation updates
Previous patch "kvm: Minor memory slot optimization" (b7f69c555ca43) overlooked the generation field of the memory slots. Re-using the original memory slots left us with with two slightly different memory slots with the same generation. To fix this, make update_memslots() take a new parameter to specify the last generation. This also makes generation management more explicit to avoid such problems in the future. Reported-by: Takuya Yoshikawa <yoshikawa_takuya_b1@lab.ntt.co.jp> Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index bd31096e3698..14cbae83be64 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -672,7 +672,8 @@ static void sort_memslots(struct kvm_memslots *slots)
672 slots->id_to_index[slots->memslots[i].id] = i; 672 slots->id_to_index[slots->memslots[i].id] = i;
673} 673}
674 674
675void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new) 675void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new,
676 u64 last_generation)
676{ 677{
677 if (new) { 678 if (new) {
678 int id = new->id; 679 int id = new->id;
@@ -684,7 +685,7 @@ void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new)
684 sort_memslots(slots); 685 sort_memslots(slots);
685 } 686 }
686 687
687 slots->generation++; 688 slots->generation = last_generation + 1;
688} 689}
689 690
690static int check_memory_region_flags(struct kvm_userspace_memory_region *mem) 691static int check_memory_region_flags(struct kvm_userspace_memory_region *mem)
@@ -819,7 +820,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
819 slot = id_to_memslot(slots, mem->slot); 820 slot = id_to_memslot(slots, mem->slot);
820 slot->flags |= KVM_MEMSLOT_INVALID; 821 slot->flags |= KVM_MEMSLOT_INVALID;
821 822
822 update_memslots(slots, NULL); 823 update_memslots(slots, NULL, kvm->memslots->generation);
823 824
824 old_memslots = kvm->memslots; 825 old_memslots = kvm->memslots;
825 rcu_assign_pointer(kvm->memslots, slots); 826 rcu_assign_pointer(kvm->memslots, slots);
@@ -867,7 +868,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
867 memset(&new.arch, 0, sizeof(new.arch)); 868 memset(&new.arch, 0, sizeof(new.arch));
868 } 869 }
869 870
870 update_memslots(slots, &new); 871 update_memslots(slots, &new, kvm->memslots->generation);
871 old_memslots = kvm->memslots; 872 old_memslots = kvm->memslots;
872 rcu_assign_pointer(kvm->memslots, slots); 873 rcu_assign_pointer(kvm->memslots, slots);
873 synchronize_srcu_expedited(&kvm->srcu); 874 synchronize_srcu_expedited(&kvm->srcu);