From: Stefan Hajnoczi <stefanha@gmail.com>
To: Liu Ping Fan <qemulist@gmail.com>
Cc: Peter Maydell <peter.maydell@linaro.org>,
Anthony Liguori <aliguori@us.ibm.com>,
Jan Kiszka <jan.kiszka@siemens.com>,
Marcelo Tosatti <mtosatti@redhat.com>,
qemu-devel@nongnu.org,
Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>,
Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 2/5] hostmem: make hostmem global and RAM hotunplg safe
Date: Thu, 11 Apr 2013 12:11:18 +0200 [thread overview]
Message-ID: <20130411101118.GC9165@stefanha-thinkpad.redhat.com> (raw)
In-Reply-To: <1364804434-7980-3-git-send-email-qemulist@gmail.com>
On Mon, Apr 01, 2013 at 04:20:31PM +0800, Liu Ping Fan wrote:
> From: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
>
> The hostmem listener will translate gpa to hva quickly. Make it
> global, so other component can use it.
> Also this patch adopt MemoryRegionOps's ref/unref interface to
> make it survive the RAM hotunplug.
>
> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
> ---
> hw/dataplane/hostmem.c | 130 +++++++++++++++++++++++++++++++++--------------
> hw/dataplane/hostmem.h | 19 ++------
> 2 files changed, 95 insertions(+), 54 deletions(-)
>
> diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c
> index 380537e..86c02cd 100644
> --- a/hw/dataplane/hostmem.c
> +++ b/hw/dataplane/hostmem.c
> @@ -13,6 +13,12 @@
>
> #include "exec/address-spaces.h"
> #include "hostmem.h"
> +#include "qemu/main-loop.h"
> +
> +/* lock to protect the access to cur_hostmem */
> +static QemuMutex hostmem_lock;
> +static HostMem *cur_hostmem;
> +static HostMem *next_hostmem;
>
> static int hostmem_lookup_cmp(const void *phys_, const void *region_)
> {
> @@ -28,16 +34,49 @@ static int hostmem_lookup_cmp(const void *phys_, const void *region_)
> }
> }
>
> +static void hostmem_ref(HostMem *hostmem)
> +{
> + assert(__sync_add_and_fetch(&hostmem->ref, 1) > 0);
man 3 assert:
"If the macro NDEBUG was defined at the moment <assert.h> was last
included, the macro assert() generates no code, and hence does nothing
at all."
Never rely on a side-effect within an assert() call. Store the return
value into a local variable and test the local in the assert().
Also, these sync gcc builtins are not available on all platforms or gcc
versions. We need to be a little careful to avoid breaking builds here.
Maybe __sync_add_and_fetch() is fine but I wanted to mention it because
I've had trouble with these in the past.
I suggest using glib atomics instead, if possible.
> +}
> +
> +void hostmem_unref(HostMem *hostmem)
> +{
> + int i;
> + HostMemRegion *hmr;
> +
> + if (!__sync_sub_and_fetch(&hostmem->ref, 1)) {
> + for (i = 0; i < hostmem->num_current_regions; i++) {
> + hmr = &hostmem->current_regions[i];
> + /* Fix me, when memory hotunplug implement
> + * assert(hmr->mr_ops->unref)
> + */
Why this fixme? Can you resolve it by making ->unref() return bool from
the start of this patch series?
> + if (hmr->mr->ops && hmr->mr->ops->unref) {
> + hmr->mr->ops->unref();
> + }
> + }
> + g_free(hostmem->current_regions);
> + g_free(hostmem);
> + }
> +}
> +
> /**
> * Map guest physical address to host pointer
> + * also inc refcnt of *mr, caller need to unref later
> */
> -void *hostmem_lookup(HostMem *hostmem, hwaddr phys, hwaddr len, bool is_write)
> +void *hostmem_lookup(hwaddr phys, hwaddr len, MemoryRegion **mr, bool is_write)
A cleaner approach is to keep the hostmem_foo(HostMem *) functions and
have a global interface without the HostMem*. That way the global
wrapper focusses on acquiring cur_hostmem while the existing functions
stay unchanged and focus on performing the actual operation.
> {
> HostMemRegion *region;
> void *host_addr = NULL;
> hwaddr offset_within_region;
> + HostMem *hostmem;
> +
> + assert(mr);
> + *mr = NULL;
> + qemu_mutex_lock(&hostmem_lock);
> + hostmem = cur_hostmem;
> + hostmem_ref(hostmem);
> + qemu_mutex_unlock(&hostmem_lock);
>
> - qemu_mutex_lock(&hostmem->current_regions_lock);
Why is it safe to drop this lock? The memory API could invoke callbacks
in another thread which causes us to update regions.
> region = bsearch(&phys, hostmem->current_regions,
> hostmem->num_current_regions,
> sizeof(hostmem->current_regions[0]),
> @@ -52,28 +91,33 @@ void *hostmem_lookup(HostMem *hostmem, hwaddr phys, hwaddr len, bool is_write)
> if (len <= region->size - offset_within_region) {
> host_addr = region->host_addr + offset_within_region;
> }
> -out:
> - qemu_mutex_unlock(&hostmem->current_regions_lock);
> + *mr = region->mr;
> + memory_region_ref(*mr);
How does this protect against the QEMU thread hot unplugging while we
are searching hostmem->current_regions[]? Our mr would be stale and the
ref operation would corrupt memory if mr has already been freed!
>
> +out:
> + hostmem_unref(hostmem);
> return host_addr;
> }
>
> +static void hostmem_listener_begin(MemoryListener *listener)
> +{
> + next_hostmem = g_new0(HostMem, 1);
> + next_hostmem->ref = 1;
> +}
> +
> /**
> * Install new regions list
> */
> static void hostmem_listener_commit(MemoryListener *listener)
> {
> - HostMem *hostmem = container_of(listener, HostMem, listener);
> + HostMem *tmp;
>
> - qemu_mutex_lock(&hostmem->current_regions_lock);
> - g_free(hostmem->current_regions);
> - hostmem->current_regions = hostmem->new_regions;
> - hostmem->num_current_regions = hostmem->num_new_regions;
> - qemu_mutex_unlock(&hostmem->current_regions_lock);
> + tmp = cur_hostmem;
> + qemu_mutex_lock(&hostmem_lock);
In hostmem_lookup() you accessed cur_hostmem inside the lock. Does the
lock protect cur_hostmem or not?
> + cur_hostmem = next_hostmem;
> + qemu_mutex_unlock(&hostmem_lock);
> + hostmem_unref(tmp);
>
> - /* Reset new regions list */
> - hostmem->new_regions = NULL;
> - hostmem->num_new_regions = 0;
> }
>
> /**
I gave up here. The approach you are trying to take isn't clear in this
patch. I've pointed out some inconsistencies but they make it hard to
review more since I don't understand what you're trying to do.
Please split patches into logical steps and especially document
locks/refcounts to explain their scope - what do they protect?
Stefan
next prev parent reply other threads:[~2013-04-11 10:11 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-01 8:20 [Qemu-devel] [PATCH 0/5] proposal to make hostmem listener RAM unplug safe Liu Ping Fan
2013-04-01 8:20 ` [Qemu-devel] [PATCH 1/5] memory: add ref/unref interface for MemroyRegionOps Liu Ping Fan
2013-04-11 9:49 ` Stefan Hajnoczi
2013-04-12 4:12 ` liu ping fan
2013-04-01 8:20 ` [Qemu-devel] [PATCH 2/5] hostmem: make hostmem global and RAM hotunplg safe Liu Ping Fan
2013-04-02 6:11 ` li guang
2013-04-11 10:09 ` Paolo Bonzini
2013-04-12 6:46 ` liu ping fan
2013-04-12 8:21 ` Stefan Hajnoczi
2013-04-11 10:11 ` Stefan Hajnoczi [this message]
2013-04-11 10:26 ` Paolo Bonzini
2013-04-12 3:55 ` liu ping fan
2013-04-12 8:38 ` Stefan Hajnoczi
2013-04-12 10:03 ` Paolo Bonzini
2013-04-15 1:42 ` liu ping fan
2013-04-15 6:38 ` Paolo Bonzini
2013-04-01 8:20 ` [Qemu-devel] [PATCH 3/5] vring: use hostmem's RAM safe api Liu Ping Fan
2013-04-11 10:15 ` Stefan Hajnoczi
2013-04-12 4:49 ` liu ping fan
2013-04-12 8:41 ` Stefan Hajnoczi
2013-04-01 8:20 ` [Qemu-devel] [PATCH 4/5] virtio-blk: release reference to RAM's memoryRegion Liu Ping Fan
2013-04-02 5:58 ` li guang
2013-04-12 4:44 ` liu ping fan
2013-04-11 10:20 ` Stefan Hajnoczi
2013-04-12 4:48 ` liu ping fan
2013-04-12 8:45 ` Stefan Hajnoczi
2013-04-12 9:05 ` liu ping fan
2013-04-16 7:57 ` Stefan Hajnoczi
2013-04-16 8:12 ` Paolo Bonzini
2013-04-01 8:20 ` [Qemu-devel] [PATCH 5/5] hostmem: init/finalize hostmem listener Liu Ping Fan
2013-04-11 10:02 ` Paolo Bonzini
2013-04-11 12:08 ` liu ping fan
2013-04-11 13:14 ` Paolo Bonzini
2013-06-13 4:38 ` [Qemu-devel] about atexit() (was: [PATCH 5/5] hostmem: init/finalize hostmem listener) Amos Kong
2013-06-13 8:51 ` liu ping fan
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=20130411101118.GC9165@stefanha-thinkpad.redhat.com \
--to=stefanha@gmail.com \
--cc=aliguori@us.ibm.com \
--cc=jan.kiszka@siemens.com \
--cc=mtosatti@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=qemulist@gmail.com \
--cc=vasilis.liaskovitis@profitbricks.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).