From: Juan Quintela <quintela@redhat.com>
To: "Gonglei (Arei)" <arei.gonglei@huawei.com>
Cc: "chenliang (T)" <chenliang88@huawei.com>,
"owasserm@redhat.com" <owasserm@redhat.com>,
"Huangweidong (C)" <weidong.huang@huawei.com>,
"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
"Dr. David Alan Gilbert" <dgilbert@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v3] XBZRLE: Fix qemu crash when resize the xbzrle cache
Date: Tue, 25 Feb 2014 16:24:54 +0100 [thread overview]
Message-ID: <87sir7z03d.fsf@elfo.mitica> (raw)
In-Reply-To: <33183CC9F5247A488A2544077AF19020815C8B93@SZXEMA503-MBS.china.huawei.com> (Gonglei's message of "Sat, 22 Feb 2014 08:52:06 +0000")
"Gonglei (Arei)" <arei.gonglei@huawei.com> wrote:
> Resizing the xbzrle cache during migration causes qemu-crash,
> because the main-thread and migration-thread modify the xbzrle
> cache size concurrently without lock-protection.
>
> Signed-off-by: ChenLiang <chenliang88@huawei.com>
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Sorry for the late review.
> ---
> Changes against the previous version:
> *Remove the temporary variable cache in the xbzrle_cache_resize.
>
> arch_init.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 55 insertions(+), 3 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index 80574a0..003640f 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -164,26 +164,69 @@ static struct {
> uint8_t *encoded_buf;
> /* buffer for storing page content */
> uint8_t *current_buf;
> - /* Cache for XBZRLE */
> + /* Cache for XBZRLE, Protected by lock. */
> PageCache *cache;
> + QemuMutex lock;
> } XBZRLE = {
> .encoded_buf = NULL,
> .current_buf = NULL,
> .cache = NULL,
> + /* use the lock carefully */
> + .lock = {PTHREAD_MUTEX_INITIALIZER},
> };
Have you tried to compile for windows? I think this would make it
break. We need to init it with qemu_mutex_init() in ram_save_setup()
after the call to cache_init()?
> /* buffer used for XBZRLE decoding */
> static uint8_t *xbzrle_decoded_buf;
>
> +static void XBZRLE_cache_lock(void)
> +{
> + qemu_mutex_lock(&XBZRLE.lock);
> +}
> +
if we change this to:
if (migrate_use_xbzrle())
qemu_mutex_lock(&XBZRLE.lock);
On both cache operations, we would remove the overhead in the no XBRLE
case, right?
> +static void XBZRLE_cache_unlock(void)
> +{
> + qemu_mutex_unlock(&XBZRLE.lock);
> +}
> +
> int64_t xbzrle_cache_resize(int64_t new_size)
> {
> + PageCache *new_cache, *old_cache;
> +
> if (new_size < TARGET_PAGE_SIZE) {
> return -1;
> }
>
> + XBZRLE_cache_lock();
> if (XBZRLE.cache != NULL) {
> - return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) *
> - TARGET_PAGE_SIZE;
> + /* check XBZRLE.cache again later */
> + XBZRLE_cache_unlock();
> + if (pow2floor(new_size) == migrate_xbzrle_cache_size()) {
> + return pow2floor(new_size);
> + }
> + new_cache = cache_init(new_size / TARGET_PAGE_SIZE,
> + TARGET_PAGE_SIZE);
> + if (!new_cache) {
> + DPRINTF("Error creating cache\n");
> + return -1;
> + }
> +
> + XBZRLE_cache_lock();
> + /* the XBZRLE.cache may have be destroyed, check it again */
> + if (XBZRLE.cache != NULL) {
> + old_cache = XBZRLE.cache;
> + XBZRLE.cache = new_cache;
> + new_cache = NULL;
> + }
> + XBZRLE_cache_unlock();
> +
> + if (NULL == new_cache) {
> + cache_fini(old_cache);
> + } else {
> + cache_fini(new_cache);
> + }
> + } else {
> + XBZRLE_cache_unlock();
> }
Can we change this to:
if (pow2floor(new_size) == migrate_xbzrle_cache_size()) {
return pow2floor(new_size);
}
new_cache = cache_init(new_size / TARGET_PAGE_SIZE,
TARGET_PAGE_SIZE);
if (!new_cache) {
DPRINTF("Error creating cache\n");
return -1;
}
XBZRLE_cache_lock();
/* the XBZRLE.cache may have be destroyed, check it again */
if (XBZRLE.cache != NULL) {
cache_to_free = XBZRLE.cache;
XBZRLE.cache = new_cache;
} else {
cache_to_free = new_cache;
}
XBZRLE_cache_unlock();
cache_fini(cache_to_free);
I think that looking is clearer this way. BTW, we are losing
_everything_ that is on the cache if we resize it. I don't know if that
is what we want. If we have a big cache, and make it bigger because we
are having too many misses, just dropping the whole cache looks like a
bad idea :-(
And my understanding is that we should do a:
migrate_get_current()->xbzrle_cache_size = new_size;
independently of what CACHE is equal or different from NULL?
(this was already wrong before your patch, just asking because you are
looking at the code).
Thanks, Juan.
next prev parent reply other threads:[~2014-02-25 15:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-22 8:52 [Qemu-devel] [PATCH v3] XBZRLE: Fix qemu crash when resize the xbzrle cache Gonglei (Arei)
2014-02-25 15:24 ` Juan Quintela [this message]
2014-02-26 9:10 ` Gonglei (Arei)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87sir7z03d.fsf@elfo.mitica \
--to=quintela@redhat.com \
--cc=arei.gonglei@huawei.com \
--cc=chenliang88@huawei.com \
--cc=dgilbert@redhat.com \
--cc=owasserm@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=weidong.huang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).