qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
@ 2014-03-29  7:52 arei.gonglei
  2014-03-29 13:53 ` Eric Blake
  0 siblings, 1 reply; 7+ messages in thread
From: arei.gonglei @ 2014-03-29  7:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: ChenLiang, weidong.huang, quintela, dgilbert, owasserm, Gonglei,
	mrhines, pbonzini

From: ChenLiang <chenliang88@huawei.com>

xbzrle_encode_buffer checks the value in the ram repeatedly.
It is risk if runs xbzrle_encode_buffer on changing data.
And it is not necessary.

Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: ChenLiang <chenliang88@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 xbzrle.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/xbzrle.c b/xbzrle.c
index fbcb35d..e2c7595 100644
--- a/xbzrle.c
+++ b/xbzrle.c
@@ -82,6 +82,8 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
         if (d + 2 > dlen) {
             return -1;
         }
+        i++;
+        nzrun_len++;
         /* not aligned to sizeof(long) */
         res = (slen - i) % sizeof(long);
         while (res && old_buf[i] != new_buf[i]) {
@@ -118,6 +120,8 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
         memcpy(dst + d, nzrun_start, nzrun_len);
         d += nzrun_len;
         nzrun_len = 0;
+        i++;
+        zrun_len++;
     }
 
     return d;
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
  2014-03-29  7:52 [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly arei.gonglei
@ 2014-03-29 13:53 ` Eric Blake
  2014-03-29 14:15   ` 陈梁
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Blake @ 2014-03-29 13:53 UTC (permalink / raw)
  To: arei.gonglei, qemu-devel
  Cc: ChenLiang, weidong.huang, quintela, dgilbert, owasserm, mrhines,
	pbonzini

[-- Attachment #1: Type: text/plain, Size: 1469 bytes --]

On 03/29/2014 01:52 AM, arei.gonglei@huawei.com wrote:
> From: ChenLiang <chenliang88@huawei.com>
> 
> xbzrle_encode_buffer checks the value in the ram repeatedly.
> It is risk if runs xbzrle_encode_buffer on changing data.
> And it is not necessary.
> 
> Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Signed-off-by: ChenLiang <chenliang88@huawei.com>
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> ---
>  xbzrle.c | 4 ++++
>  1 file changed, 4 insertions(+)

Insufficient.  Observe what we did at line 52 when looking for the zero-run:

>>         /* word at a time for speed */
>>         if (!res) {
>>             while (i < slen &&
>>                    (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {

This dereferences 8 bytes at new_buf[i] (on a 64-bit machine)...

>>                 i += sizeof(long);
>>                 zrun_len += sizeof(long);
>>             }
>> 
>>             /* go over the rest */
>>             while (i < slen && old_buf[i] == new_buf[i]) {

...and this also dereferences those same bytes.  But your argument is
that new_buf[i] is volatile.

You MUST read new_buf[i] into a temporary variable, and if the first
read found a difference, then the "go over the rest" analysis must be on
that temporary, rather than going back to reading directly from new_buf.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
  2014-03-29 13:53 ` Eric Blake
@ 2014-03-29 14:15   ` 陈梁
  2014-03-29 14:26     ` Eric Blake
  2014-03-31  9:40     ` Dr. David Alan Gilbert
  0 siblings, 2 replies; 7+ messages in thread
From: 陈梁 @ 2014-03-29 14:15 UTC (permalink / raw)
  To: Eric Blake
  Cc: ChenLiang, weidong.huang, arei.gonglei, quintela, qemu-devel,
	dgilbert, owasserm, 陈梁, mrhines, pbonzini



> On 03/29/2014 01:52 AM, arei.gonglei@huawei.com wrote:
>> From: ChenLiang <chenliang88@huawei.com>
>> 
>> xbzrle_encode_buffer checks the value in the ram repeatedly.
>> It is risk if runs xbzrle_encode_buffer on changing data.
>> And it is not necessary.
>> 
>> Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Signed-off-by: ChenLiang <chenliang88@huawei.com>
>> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
>> ---
>> xbzrle.c | 4 ++++
>> 1 file changed, 4 insertions(+)
> 
> Insufficient.  Observe what we did at line 52 when looking for the zero-run:
> 
>>>        /* word at a time for speed */
>>>        if (!res) {
>>>            while (i < slen &&
>>>                   (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
> 
> This dereferences 8 bytes at new_buf[i] (on a 64-bit machine)...
> 
>>>                i += sizeof(long);
>>>                zrun_len += sizeof(long);
>>>            }
>>> 
>>>            /* go over the rest */
>>>            while (i < slen && old_buf[i] == new_buf[i]) {
> 
> ...and this also dereferences those same bytes.  But your argument is
> that new_buf[i] is volatile.
> 
> You MUST read new_buf[i] into a temporary variable, and if the first
> read found a difference, then the "go over the rest" analysis must be on
> that temporary, rather than going back to reading directly from new_buf.
> 
It is ok, we just need to guarantee that the pages in cache are same to the page in dest side. 
Don‘t care about whether they are same to src side. Because the modified pages during this
time will be sent at next time.
> -- 
> Eric Blake   eblake redhat com    +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
  2014-03-29 14:15   ` 陈梁
@ 2014-03-29 14:26     ` Eric Blake
       [not found]       ` <C734EB68-7CC7-4028-BD08-0FC54819FD21@icloud.com>
  2014-03-31  9:40     ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 7+ messages in thread
From: Eric Blake @ 2014-03-29 14:26 UTC (permalink / raw)
  To: 陈梁
  Cc: ChenLiang, weidong.huang, quintela, qemu-devel, dgilbert,
	owasserm, arei.gonglei, mrhines, pbonzini

[-- Attachment #1: Type: text/plain, Size: 2052 bytes --]

On 03/29/2014 08:15 AM, 陈梁 wrote:

>>
>> Insufficient.  Observe what we did at line 52 when looking for the zero-run:
>>
>>>>        /* word at a time for speed */
>>>>        if (!res) {
>>>>            while (i < slen &&
>>>>                   (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
>>
>> This dereferences 8 bytes at new_buf[i] (on a 64-bit machine)...
>>
>>>>                i += sizeof(long);
>>>>                zrun_len += sizeof(long);
>>>>            }
>>>>
>>>>            /* go over the rest */
>>>>            while (i < slen && old_buf[i] == new_buf[i]) {
>>
>> ...and this also dereferences those same bytes.  But your argument is
>> that new_buf[i] is volatile.
>>
>> You MUST read new_buf[i] into a temporary variable, and if the first
>> read found a difference, then the "go over the rest" analysis must be on
>> that temporary, rather than going back to reading directly from new_buf.
>>
> It is ok, we just need to guarantee that the pages in cache are same to the page in dest side. 
> Don‘t care about whether they are same to src side. Because the modified pages during this
> time will be sent at next time.

No, it is not okay - if you are reading the same bytes from new_buf, and
new_buf is volatile, then you MUST read each byte of new_buf exactly
once.  Consider this sequence:

old_buf contains

00 00 00 00 00 00 00 00

new_buf initially contains

00 00 00 00 00 00 00 01

so the zrun detection spots that the two buffers are different on the
8-byte read.  But then another thread modifies new_buf to be all zeros.
 Now the "go over the rest" loop does 8 reads, expecting to find a
difference, but it can't find one.

You really need to do the "go over the rest" loop on an 8-byte temporary
variable.  Ever since your patch made new_buf be a volatile buffer,
rather than a static copy, you MUST visit each byte of new_buf exactly once.


-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
       [not found]         ` <F822EA2B-2483-446F-A92C-662B381D1B81@icloud.com>
@ 2014-03-29 15:33           ` Eric Blake
  0 siblings, 0 replies; 7+ messages in thread
From: Eric Blake @ 2014-03-29 15:33 UTC (permalink / raw)
  To: 陈梁
  Cc: ChenLiang, weidong.huang, quintela, qemu-devel, dgilbert,
	owasserm, arei.gonglei, mrhines, pbonzini

[-- Attachment #1: Type: text/plain, Size: 1424 bytes --]

On 03/29/2014 09:00 AM, 陈梁 wrote:

>>> You really need to do the "go over the rest" loop on an 8-byte temporary
>>> variable.  Ever since your patch made new_buf be a volatile buffer,
>>> rather than a static copy, you MUST visit each byte of new_buf exactly once.
>>>
>> hmm, thanks. get it. Maybe we can do it like this

> sorry, it should like this
> 
>         /* word at a time for speed */
>         if (!res) {
>             while (i < slen &&
>                    (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
>                 i += sizeof(long);
>                 zrun_len += sizeof(long);
>             }
> 
>             /* go over the rest */
>             //while (i < slen && old_buf[i] == new_buf[i]) {
>             //    zrun_len++;
>             //    i++;
>             //}
>         }

No, that's not right either.  Once you have made a decision based on
something you have read, you must proceed with that decision.  In the
case, you broke out of the while loop because you found a difference.
Now you must report the location of that difference, as of the time
where you read it and without re-reading from new_buf.  The ONLY viable
solution is to read the contents of new_buf into a temporary, then do
all subsequent actions on that temporary.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
       [not found]         ` <F5241465-1514-4695-8EE0-F781549403FF@icloud.com>
@ 2014-03-29 15:38           ` Eric Blake
  0 siblings, 0 replies; 7+ messages in thread
From: Eric Blake @ 2014-03-29 15:38 UTC (permalink / raw)
  To: 陈梁
  Cc: ChenLiang, weidong.huang, quintela, qemu-devel, dgilbert,
	owasserm, arei.gonglei, mrhines, pbonzini

[-- Attachment #1: Type: text/plain, Size: 1314 bytes --]

On 03/29/2014 09:12 AM, 陈梁 wrote:

>        /* word at a time for speed */
>        if (!res) {
>            while (i < slen &&
>                   (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
>                i += sizeof(long);
>                zrun_len += sizeof(long);
>            }
> 
>            /* go over the rest */
>            //while (i < slen && old_buf[i] == new_buf[i]) {
>            //    zrun_len++;
>            //    i++;
>            //}
>        }
>        i += sizeof(long);
>        nzrun_len += sizeof(long);

That does not produce a minimal compression (it treats all 8 bytes as
different, even if 7 of them were the same).  It might be a viable
solution if the extra overhead of the additional bytes sent over the
wire is less than the overhead saved by not re-checking the temporary
variable to determine a better compression.  But I'm not convinced - it
seems that reading memory into a register, then doing multiple
operations on that cached value, will be a win (that is, minimal
compression matters, because time spent transmitting bytes over the
network is slower than time spent calculating how to avoid bytes to
transmit).

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly
  2014-03-29 14:15   ` 陈梁
  2014-03-29 14:26     ` Eric Blake
@ 2014-03-31  9:40     ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 7+ messages in thread
From: Dr. David Alan Gilbert @ 2014-03-31  9:40 UTC (permalink / raw)
  To: ????
  Cc: ChenLiang, weidong.huang, quintela, qemu-devel, arei.gonglei,
	mrhines, pbonzini

* ???? (chenliang0016@icloud.com) wrote:

> It is ok, we just need to guarantee that the pages in cache are same to the page in dest side. 
> Don??t care about whether they are same to src side. Because the modified pages during this
> time will be sent at next time.

It's an interesting, if unusual, observation; it means we can send
completely bogus data at this point because we know it will get
overwritten later; I think the requirements are:

  1) That we meet the protocol (which seems to require that the run lengths are
     not allowed to be 0)
  2) That we don't get stuck in any loops or go over the end of the page
     (I think this means we have to be careful of those byte loops within
     the word-at-a-time cases)
  3) The page that ends up in our xbzrle cache must match the destination
     page, since the next cycle of xbzrle will use it as reference.

Dave
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-03-31  9:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-29  7:52 [Qemu-devel] [PATCH] xbzrle: don't check the value in the vm ram repeatedly arei.gonglei
2014-03-29 13:53 ` Eric Blake
2014-03-29 14:15   ` 陈梁
2014-03-29 14:26     ` Eric Blake
     [not found]       ` <C734EB68-7CC7-4028-BD08-0FC54819FD21@icloud.com>
     [not found]         ` <F822EA2B-2483-446F-A92C-662B381D1B81@icloud.com>
2014-03-29 15:33           ` Eric Blake
     [not found]         ` <F5241465-1514-4695-8EE0-F781549403FF@icloud.com>
2014-03-29 15:38           ` Eric Blake
2014-03-31  9:40     ` Dr. David Alan Gilbert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).