On Wed, Aug 8, 2012 at 5:52 PM, Paolo Bonzini <pbonz...@redhat.com> wrote:
> Il 08/08/2012 08:25, Liu Ping Fan ha scritto:
>> +void qdev_unplug_complete(DeviceState *dev, Error **errp)
>> +{
>> +    /* isolate from mem view */
>> +    qdev_unmap(dev);
>> +    qemu_lock_devtree();
>> +    /* isolate from device tree */
>> +    qdev_unset_parent(dev);
>> +    qemu_unlock_devtree();
>> +    object_unref(OBJECT(dev));
>
> Rather than deferring the free, you should defer the unref.  Otherwise
> the following can happen when you have "real" RCU access to the memory
> map on the read-side:
>
>     VCPU thread                    I/O thread
> =====================================================================
>     get MMIO request
>     rcu_read_lock()
>     walk memory map
>                                    qdev_unmap()
>                                    lock_devtree()
>                                    ...
>                                    unlock_devtree
>                                    unref dev -> refcnt=0, free enqueued
>     ref()

No ref() for dev here, while we have ref to flatview+radix in my patches.
I use rcu to protect radix+flatview+mr refered. As to dev, its ref has
inc when it is added into mem view -- that is
memory_region_add_subregion -> memory_region_get() {
if(atomic_add_and_return()) dev->ref++  }.
So not until reclaimer of mem view, the dev's ref is hold by mem view.
In a short word, rcu protect mem view, while device is protected by refcnt.

>     rcu_read_unlock()
>                                    free()
>     <dangling pointer!>
>
> If you defer the unref, you have instead
>
>     VCPU thread                    I/O thread
> =====================================================================
>     get MMIO request
>     rcu_read_lock()
>     walk memory map
>                                    qdev_unmap()
>                                    lock_devtree()
>                                    ...
>                                    unlock_devtree
>                                    unref is enqueued
>     ref() -> refcnt = 2
>     rcu_read_unlock()
>                                    unref() -> refcnt=1
>     unref() -> refcnt = 1
>
> So this also makes patch 14 unnecessary.
>
> Paolo
>
>> +}
>
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to