Patchwork [04/12] arch_init: introduce ram_page_save()

login
register
mail settings
Submitter Lei Li
Date July 25, 2013, 8:18 p.m.
Message ID <1374783499-2550-5-git-send-email-lilei@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/261951/
State New
Headers show

Comments

Lei Li - July 25, 2013, 8:18 p.m.
Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 arch_init.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)
mrhines@linux.vnet.ibm.com - Aug. 2, 2013, 7:40 p.m.
On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   arch_init.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 58 insertions(+), 0 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index a8b91ee..a418071 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -699,6 +699,64 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
>       return remaining_size;
>   }
>
> +/* This is the last block from where we have sent data for local migration */
> +static RAMBlock *last_block_local;
> +static ram_addr_t last_offset_local;
> +
> +static int ram_page_save(QEMUFile *f)
> +{
> +    RAMBlock *block = last_block_local;
> +    ram_addr_t offset = last_offset_local;
> +    MemoryRegion *mr = block->mr;
> +    int bytes_sent = 0;
> +
> +    if (!block) {
> +        block = QTAILQ_FIRST(&ram_list.blocks);
> +    }
> +
> +    do {
> +        mr = block->mr;
> +        uint8_t *p;
> +        int cont = (block == last_block_local) ? RAM_SAVE_FLAG_CONTINUE : 0;
> +
> +        p = memory_region_get_ram_ptr(mr) + offset;
> +
> +        if (is_zero_page(p)) {
> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
> +            if (!cont) {
> +                qemu_put_byte(f, strlen(block->idstr));
> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
> +                                strlen(block->idstr));
> +            }
> +            qemu_put_byte(f, *p);
> +            bytes_sent = 1;
> +        } else {
> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
> +            if (!cont) {
> +                qemu_put_byte(f, strlen(block->idstr));
> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
> +                                strlen(block->idstr));
> +            }
> +            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> +            bytes_sent = TARGET_PAGE_SIZE;
> +        }
> +
> +        offset += TARGET_PAGE_SIZE;
> +        if (offset >= block->length) {
> +            offset = 0;
> +            block = QTAILQ_NEXT(block, next);
> +            if (!block) {
> +                block = QTAILQ_FIRST(&ram_list.blocks);
> +            }
> +        }
> +    } while (block != last_block_local || offset != last_offset_local);
> +
> +    last_block_local = block;
> +    last_offset_local = offset;
> +
> +    return bytes_sent;
> +}
> +
>   static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
>   {
>       int ret, rc = 0;

Seems like there's a lot of duplicate code.

We have new hooks to override the way memory is saved in arch_init.c

See the QEMUFileOps......... save_page() / before_ram_iterate() / 
after_ram_iterate()

You might need to introduce a new "load_page()" pointer in QEMUFileOps.

Then all this code can be private to migration-local.c

- Michael
Lei Li - Aug. 5, 2013, 2:49 a.m.
On 08/03/2013 03:40 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   arch_init.c |   58 
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 files changed, 58 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index a8b91ee..a418071 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -699,6 +699,64 @@ static uint64_t ram_save_pending(QEMUFile *f, 
>> void *opaque, uint64_t max_size)
>>       return remaining_size;
>>   }
>>
>> +/* This is the last block from where we have sent data for local 
>> migration */
>> +static RAMBlock *last_block_local;
>> +static ram_addr_t last_offset_local;
>> +
>> +static int ram_page_save(QEMUFile *f)
>> +{
>> +    RAMBlock *block = last_block_local;
>> +    ram_addr_t offset = last_offset_local;
>> +    MemoryRegion *mr = block->mr;
>> +    int bytes_sent = 0;
>> +
>> +    if (!block) {
>> +        block = QTAILQ_FIRST(&ram_list.blocks);
>> +    }
>> +
>> +    do {
>> +        mr = block->mr;
>> +        uint8_t *p;
>> +        int cont = (block == last_block_local) ? 
>> RAM_SAVE_FLAG_CONTINUE : 0;
>> +
>> +        p = memory_region_get_ram_ptr(mr) + offset;
>> +
>> +        if (is_zero_page(p)) {
>> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
>> +            if (!cont) {
>> +                qemu_put_byte(f, strlen(block->idstr));
>> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
>> +                                strlen(block->idstr));
>> +            }
>> +            qemu_put_byte(f, *p);
>> +            bytes_sent = 1;
>> +        } else {
>> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
>> +            if (!cont) {
>> +                qemu_put_byte(f, strlen(block->idstr));
>> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
>> +                                strlen(block->idstr));
>> +            }
>> +            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
>> +            bytes_sent = TARGET_PAGE_SIZE;
>> +        }
>> +
>> +        offset += TARGET_PAGE_SIZE;
>> +        if (offset >= block->length) {
>> +            offset = 0;
>> +            block = QTAILQ_NEXT(block, next);
>> +            if (!block) {
>> +                block = QTAILQ_FIRST(&ram_list.blocks);
>> +            }
>> +        }
>> +    } while (block != last_block_local || offset != last_offset_local);
>> +
>> +    last_block_local = block;
>> +    last_offset_local = offset;
>> +
>> +    return bytes_sent;
>> +}
>> +
>>   static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
>>   {
>>       int ret, rc = 0;
>
> Seems like there's a lot of duplicate code.
>
> We have new hooks to override the way memory is saved in arch_init.c
>
> See the QEMUFileOps......... save_page() / before_ram_iterate() / 
> after_ram_iterate()
>
> You might need to introduce a new "load_page()" pointer in QEMUFileOps.
>
> Then all this code can be private to migration-local.c

Hi Michael,

This implementation was based on the tree that rdma migration you added have
not been merged...

Yes, Paolo also suggested that reuses the rdma hooks and I am trying to figure
it out. Your comments really helps, thanks for your suggestions!
  

>
> - Michael
>
>
>

Patch

diff --git a/arch_init.c b/arch_init.c
index a8b91ee..a418071 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -699,6 +699,64 @@  static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
     return remaining_size;
 }
 
+/* This is the last block from where we have sent data for local migration */
+static RAMBlock *last_block_local;
+static ram_addr_t last_offset_local;
+
+static int ram_page_save(QEMUFile *f)
+{
+    RAMBlock *block = last_block_local;
+    ram_addr_t offset = last_offset_local;
+    MemoryRegion *mr = block->mr;
+    int bytes_sent = 0;
+
+    if (!block) {
+        block = QTAILQ_FIRST(&ram_list.blocks);
+    }
+
+    do {
+        mr = block->mr;
+        uint8_t *p;
+        int cont = (block == last_block_local) ? RAM_SAVE_FLAG_CONTINUE : 0;
+
+        p = memory_region_get_ram_ptr(mr) + offset;
+
+        if (is_zero_page(p)) {
+            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
+            if (!cont) {
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
+            }
+            qemu_put_byte(f, *p);
+            bytes_sent = 1;
+        } else {
+            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
+            if (!cont) {
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
+            }
+            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+            bytes_sent = TARGET_PAGE_SIZE;
+        }
+
+        offset += TARGET_PAGE_SIZE;
+        if (offset >= block->length) {
+            offset = 0;
+            block = QTAILQ_NEXT(block, next);
+            if (!block) {
+                block = QTAILQ_FIRST(&ram_list.blocks);
+            }
+        }
+    } while (block != last_block_local || offset != last_offset_local);
+
+    last_block_local = block;
+    last_offset_local = offset;
+
+    return bytes_sent;
+}
+
 static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
 {
     int ret, rc = 0;