Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b050b015 authored by Marcelo Tosatti's avatar Marcelo Tosatti
Browse files

KVM: use SRCU for dirty log

parent bc6678a3
Loading
Loading
Loading
Loading
+41 −8
Original line number Diff line number Diff line
@@ -2415,27 +2415,60 @@ static int kvm_vm_ioctl_reinject(struct kvm *kvm,
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
				      struct kvm_dirty_log *log)
{
	int r;
	int n;
	int r, n, i;
	struct kvm_memory_slot *memslot;
	int is_dirty = 0;
	unsigned long is_dirty = 0;
	unsigned long *dirty_bitmap = NULL;

	down_write(&kvm->slots_lock);

	r = kvm_get_dirty_log(kvm, log, &is_dirty);
	if (r)
	r = -EINVAL;
	if (log->slot >= KVM_MEMORY_SLOTS)
		goto out;

	memslot = &kvm->memslots->memslots[log->slot];
	r = -ENOENT;
	if (!memslot->dirty_bitmap)
		goto out;

	n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;

	r = -ENOMEM;
	dirty_bitmap = vmalloc(n);
	if (!dirty_bitmap)
		goto out;
	memset(dirty_bitmap, 0, n);

	for (i = 0; !is_dirty && i < n/sizeof(long); i++)
		is_dirty = memslot->dirty_bitmap[i];

	/* If nothing is dirty, don't bother messing with page tables. */
	if (is_dirty) {
		struct kvm_memslots *slots, *old_slots;

		spin_lock(&kvm->mmu_lock);
		kvm_mmu_slot_remove_write_access(kvm, log->slot);
		spin_unlock(&kvm->mmu_lock);
		memslot = &kvm->memslots->memslots[log->slot];
		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
		memset(memslot->dirty_bitmap, 0, n);

		slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
		if (!slots)
			goto out_free;

		memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
		slots->memslots[log->slot].dirty_bitmap = dirty_bitmap;

		old_slots = kvm->memslots;
		rcu_assign_pointer(kvm->memslots, slots);
		synchronize_srcu_expedited(&kvm->srcu);
		dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap;
		kfree(old_slots);
	}

	r = 0;
	if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n))
		r = -EFAULT;
out_free:
	vfree(dirty_bitmap);
out:
	up_write(&kvm->slots_lock);
	return r;