diff mbox

[1/1] KVM: make get dirty log ioctl return the first dirty page's position

Message ID 20100224174544.64a67b3a.yoshikawa.takuya@oss.ntt.co.jp (mailing list archive)
State New, archived
Headers show

Commit Message

Takuya Yoshikawa Feb. 24, 2010, 8:45 a.m. UTC
None
diff mbox

Patch

diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt
index d170cb4..7ebfd7c 100644
--- a/Documentation/kvm/api.txt
+++ b/Documentation/kvm/api.txt
@@ -201,7 +201,7 @@  Capability: basic
 Architectures: x86
 Type: vm ioctl
 Parameters: struct kvm_dirty_log (in/out)
-Returns: 0 on success, -1 on error
+Returns: first dirty page position on success, -1 on error
 
 /* for KVM_GET_DIRTY_LOG */
 struct kvm_dirty_log {
@@ -215,8 +215,10 @@  struct kvm_dirty_log {
 
 Given a memory slot, return a bitmap containing any pages dirtied
 since the last call to this ioctl.  Bit 0 is the first page in the
-memory slot.  Ensure the entire structure is cleared to avoid padding
-issues.
+memory slot.  The return value ensures that the contents of the
+bitmap whose indexes, when you access as unsigned long array, are
+less than this are clean.  Ensure the entire structure is cleared
+to avoid padding issues.
 
 4.8 KVM_SET_MEMORY_ALIAS
 
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 26e0e08..ae78301 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1828,7 +1828,7 @@  out:
 }
 
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
-		struct kvm_dirty_log *log)
+			       struct kvm_dirty_log *log)
 {
 	int r;
 	int n;
@@ -1843,7 +1843,7 @@  int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 		goto out;
 
 	r = kvm_get_dirty_log(kvm, log, &is_dirty);
-	if (r)
+	if (r < 0)
 		goto out;
 
 	/* If nothing is dirty, don't bother messing with page tables. */
@@ -1853,7 +1853,6 @@  int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
 		memset(memslot->dirty_bitmap, 0, n);
 	}
-	r = 0;
 out:
 	mutex_unlock(&kvm->slots_lock);
 	spin_unlock(&kvm->arch.dirty_log_lock);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 794c94b..6ffd6f2 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -1065,7 +1065,7 @@  int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
  * Get (and clear) the dirty memory log for a memory slot.
  */
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
-				      struct kvm_dirty_log *log)
+			       struct kvm_dirty_log *log)
 {
 	struct kvm_memory_slot *memslot;
 	struct kvm_vcpu *vcpu;
@@ -1076,7 +1076,7 @@  int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 	mutex_lock(&kvm->slots_lock);
 
 	r = kvm_get_dirty_log(kvm, log, &is_dirty);
-	if (r)
+	if (r < 0)
 		goto out;
 
 	/* If nothing is dirty, don't bother messing with page tables. */
@@ -1093,7 +1093,6 @@  int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 		memset(memslot->dirty_bitmap, 0, n);
 	}
 
-	r = 0;
 out:
 	mutex_unlock(&kvm->slots_lock);
 	return r;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 8f09959..640ce77 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -136,7 +136,7 @@  int kvm_dev_ioctl_check_extension(long ext)
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 			       struct kvm_dirty_log *log)
 {
-	return 0;
+	return -ENOSYS;
 }
 
 long kvm_arch_vm_ioctl(struct file *filp,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e25a522..8068ee9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2694,13 +2694,14 @@  static int kvm_vm_ioctl_reinject(struct kvm *kvm,
 
 /*
  * Get (and clear) the dirty memory log for a memory slot.
+ * Return the first dirty page position on success.
  */
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
-				      struct kvm_dirty_log *log)
+			       struct kvm_dirty_log *log)
 {
 	int r, n, i;
 	struct kvm_memory_slot *memslot;
-	unsigned long is_dirty = 0;
+	bool is_dirty;
 	unsigned long *dirty_bitmap = NULL;
 
 	mutex_lock(&kvm->slots_lock);
@@ -2722,8 +2723,12 @@  int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 		goto out;
 	memset(dirty_bitmap, 0, n);
 
-	for (i = 0; !is_dirty && i < n/sizeof(long); i++)
-		is_dirty = memslot->dirty_bitmap[i];
+	for (i = 0, is_dirty = false; i < n/sizeof(long); i++) {
+		if (memslot->dirty_bitmap[i]) {
+			is_dirty = true;
+			break;
+		}
+	}
 
 	/* If nothing is dirty, don't bother messing with page tables. */
 	if (is_dirty) {
@@ -2747,7 +2752,7 @@  int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 		kfree(old_slots);
 	}
 
-	r = 0;
+	r = i;
 	if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n))
 		r = -EFAULT;
 out_free:
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 548f925..4b715c9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -769,7 +769,6 @@  int kvm_get_dirty_log(struct kvm *kvm,
 	struct kvm_memory_slot *memslot;
 	int r, i;
 	int n;
-	unsigned long any = 0;
 
 	r = -EINVAL;
 	if (log->slot >= KVM_MEMORY_SLOTS)
@@ -782,17 +781,18 @@  int kvm_get_dirty_log(struct kvm *kvm,
 
 	n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
 
-	for (i = 0; !any && i < n/sizeof(long); ++i)
-		any = memslot->dirty_bitmap[i];
+	for (i = 0; i < n/sizeof(long); ++i) {
+		if (memslot->dirty_bitmap[i]) {
+			*is_dirty = 1;
+			break;
+		}
+	}
 
 	r = -EFAULT;
 	if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
 		goto out;
 
-	if (any)
-		*is_dirty = 1;
-
-	r = 0;
+	r = i;
 out:
 	return r;
 }
@@ -1592,7 +1592,7 @@  static long kvm_vm_ioctl(struct file *filp,
 		if (copy_from_user(&log, argp, sizeof log))
 			goto out;
 		r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
-		if (r)
+		if (r < 0)
 			goto out;
 		break;
 	}
@@ -1693,7 +1693,7 @@  static long kvm_vm_compat_ioctl(struct file *filp,
 		log.dirty_bitmap = compat_ptr(compat_log.dirty_bitmap);
 
 		r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
-		if (r)
+		if (r < 0)
 			goto out;
 		break;
 	}