Patchwork [v5,04/12] rdma: introduce qemu_get_max_size()

login
register
mail settings
Submitter mrhines@linux.vnet.ibm.com
Date April 21, 2013, 9:17 p.m.
Message ID <1366579081-6857-5-git-send-email-mrhines@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/238259/
State New
Headers show

Comments

mrhines@linux.vnet.ibm.com - April 21, 2013, 9:17 p.m.
From: "Michael R. Hines" <mrhines@us.ibm.com>

This functions allows you to perform your own per-QEMUFileOps
calculation for the value of 'max_size'.

For RDMA, this calculation artificially limits migration throughput
and needs to be done differently for high-throughput links.

Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
---
 include/migration/qemu-file.h |   12 ++++++++++++
 migration.c                   |    3 ++-
 savevm.c                      |   19 +++++++++++++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)
Eric Blake - April 22, 2013, 8:20 p.m.
On 04/21/2013 03:17 PM, mrhines@linux.vnet.ibm.com wrote:
> From: "Michael R. Hines" <mrhines@us.ibm.com>
> 
> This functions allows you to perform your own per-QEMUFileOps
> calculation for the value of 'max_size'.
> 
> For RDMA, this calculation artificially limits migration throughput
> and needs to be done differently for high-throughput links.
> 
> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
> ---

>  
> +size_t qemu_get_max_size(QEMUFile *f, uint64_t transferred_bytes,
> +                         uint64_t time_spent, uint64_t max_downtime)
> +{
> +    if (time_spent) {
> +        mbps = (((double) transferred_bytes * 8.0) / 
> +            ((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
> +    } else {
> +        mbps = -1.0;
> +    }
> +
> +    if (f->ops->get_max_size) {
> +        return f->ops->get_max_size(f, f->opaque, 
> +            transferred_bytes, time_spent, max_downtime);
> +    }
> +
> +    return ((double) (transferred_bytes / time_spent)) * 
> +                    max_downtime / 1000000;

Cast to double is too late; you've already suffered from integer
division truncation when you compute (transferred_bytes/time_spent).
mrhines@linux.vnet.ibm.com - April 22, 2013, 8:59 p.m.
On 04/22/2013 04:20 PM, Eric Blake wrote:
> On 04/21/2013 03:17 PM, mrhines@linux.vnet.ibm.com wrote:
>> From: "Michael R. Hines" <mrhines@us.ibm.com>
>>
>> This functions allows you to perform your own per-QEMUFileOps
>> calculation for the value of 'max_size'.
>>
>> For RDMA, this calculation artificially limits migration throughput
>> and needs to be done differently for high-throughput links.
>>
>> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
>> ---
>>   
>> +size_t qemu_get_max_size(QEMUFile *f, uint64_t transferred_bytes,
>> +                         uint64_t time_spent, uint64_t max_downtime)
>> +{
>> +    if (time_spent) {
>> +        mbps = (((double) transferred_bytes * 8.0) /
>> +            ((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
>> +    } else {
>> +        mbps = -1.0;
>> +    }
>> +
>> +    if (f->ops->get_max_size) {
>> +        return f->ops->get_max_size(f, f->opaque,
>> +            transferred_bytes, time_spent, max_downtime);
>> +    }
>> +
>> +    return ((double) (transferred_bytes / time_spent)) *
>> +                    max_downtime / 1000000;
> Cast to double is too late; you've already suffered from integer
> division truncation when you compute (transferred_bytes/time_spent).
>

Good catch, thank you.

Patch

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 70eb9bd..1803aeb 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -57,12 +57,22 @@  typedef int (QEMUFileGetFD)(void *opaque);
 typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
                                            int iovcnt, int64_t pos);
 
+/*
+ * This function allows override of how to calculate max_size
+ * after each iteration.
+ */
+typedef size_t (QEMUFileMaxSizeFunc)(QEMUFile *f, void *opaque,
+                               uint64_t transferred_bytes,
+                               uint64_t time_spent,
+                               uint64_t max_downtime);
+
 typedef struct QEMUFileOps {
     QEMUFilePutBufferFunc *put_buffer;
     QEMUFileGetBufferFunc *get_buffer;
     QEMUFileCloseFunc *close;
     QEMUFileGetFD *get_fd;
     QEMUFileWritevBufferFunc *writev_buffer;
+    QEMUFileMaxSizeFunc *get_max_size;
 } QEMUFileOps;
 
 QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
@@ -81,6 +91,8 @@  void qemu_put_byte(QEMUFile *f, int v);
  */
 void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size);
 double qemu_get_mbps(void);
+size_t qemu_get_max_size(QEMUFile *f, uint64_t transferred_bytes,
+                         uint64_t time_spent, uint64_t max_downtime);
 
 
 static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
diff --git a/migration.c b/migration.c
index e2d73c4..48b5174 100644
--- a/migration.c
+++ b/migration.c
@@ -545,7 +545,8 @@  static void *migration_thread(void *opaque)
             uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes;
             uint64_t time_spent = current_time - initial_time - sleep_time;
             double bandwidth = transferred_bytes / time_spent;
-            max_size = bandwidth * migrate_max_downtime() / 1000000;
+            max_size = qemu_get_max_size(s->file, transferred_bytes, 
+                    time_spent, migrate_max_downtime());
 
             DPRINTF("transferred %" PRIu64 " time_spent %" PRIu64
                     " bandwidth %g max_size %" PRId64 "\n",
diff --git a/savevm.c b/savevm.c
index 6fcad19..60776e5 100644
--- a/savevm.c
+++ b/savevm.c
@@ -647,6 +647,25 @@  int qemu_get_fd(QEMUFile *f)
     return -1;
 }
 
+size_t qemu_get_max_size(QEMUFile *f, uint64_t transferred_bytes,
+                         uint64_t time_spent, uint64_t max_downtime)
+{
+    if (time_spent) {
+        mbps = (((double) transferred_bytes * 8.0) / 
+            ((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
+    } else {
+        mbps = -1.0;
+    }
+
+    if (f->ops->get_max_size) {
+        return f->ops->get_max_size(f, f->opaque, 
+            transferred_bytes, time_spent, max_downtime);
+    }
+
+    return ((double) (transferred_bytes / time_spent)) * 
+                    max_downtime / 1000000;
+}
+
 /** Closes the file
  *
  * Returns negative error value if any error happened on previous operations or