Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-13 Thread Marcelo Tosatti
On Thu, Aug 09, 2012 at 10:00:16AM +0200, Paolo Bonzini wrote:
 Il 09/08/2012 09:28, liu ping fan ha scritto:
   VCPU threadI/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.

The idea, written on that plan, was:

- RCU protects memory maps.
- Object reference protects device in the window between 4. and 5.

The unplug/remove path should:

1) Lock memmap_lock for write (if not using RCU).
2) Remove any memmap entries (which is possible due to write lock on
memmap_lock. Alternatively wait for an RCU grace period). Device should
not be visible after that.
3) Lock dev-lock.
4) Wait until references are removed (no new references can be made
since device is not visible).
5) Remove device. 

So its a combination of both dev-lock and reference counter.

Note: a first step can be only parallel execution of MMIO lookups
(actually that is a very good first target). dev-lock above would be 
qemu_big_lock in that first stage, then _only devices which are 
performance sensitive need to be converted_.

 But the RCU critical section should not include the whole processing of
 MMIO, only the walk of the memory map.

Yes.

 And in general I think this is a bit too tricky... I understand not
 adding refcounting to all of bottom halves, timers, etc., but if you are
 using a device you should have explicit ref/unref pairs.
 
 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
--
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


Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-13 Thread Marcelo Tosatti
On Fri, Aug 10, 2012 at 02:42:58PM +0800, liu ping fan wrote:
 On Thu, Aug 9, 2012 at 4:00 PM, Paolo Bonzini pbonz...@redhat.com wrote:
  Il 09/08/2012 09:28, liu ping fan ha scritto:
   VCPU threadI/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.
 
  But the RCU critical section should not include the whole processing of
  MMIO, only the walk of the memory map.
 
 Yes, you are right.  And I think cur_map_get() can be broken into the
 style lock,  ref++, phys_page_find(); unlock.  easily.
 
  And in general I think this is a bit too tricky... I understand not
  adding refcounting to all of bottom halves, timers, etc., but if you are
  using a device you should have explicit ref/unref pairs.
 
 Actually, there are pairs -- when dev enter mem view, inc ref; and
 when it leave, dec ref.
 But as Avi has pointed out, the mr-refcnt introduce complicate and no
 gain. So I will discard this design

The plan that you refer that has been relatively well thought out, IIRC. 
Instead of designing something, i would try to understand/improve on
that.

 Thanks and regards,
 pingfan
 
  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
--
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


Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-10 Thread liu ping fan
On Thu, Aug 9, 2012 at 4:00 PM, Paolo Bonzini pbonz...@redhat.com wrote:
 Il 09/08/2012 09:28, liu ping fan ha scritto:
  VCPU threadI/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.

 But the RCU critical section should not include the whole processing of
 MMIO, only the walk of the memory map.

Yes, you are right.  And I think cur_map_get() can be broken into the
style lock,  ref++, phys_page_find(); unlock.  easily.

 And in general I think this is a bit too tricky... I understand not
 adding refcounting to all of bottom halves, timers, etc., but if you are
 using a device you should have explicit ref/unref pairs.

Actually, there are pairs -- when dev enter mem view, inc ref; and
when it leave, dec ref.
But as Avi has pointed out, the mr-refcnt introduce complicate and no
gain. So I will discard this design

Thanks and regards,
pingfan

 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


Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-09 Thread liu ping fan
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 threadI/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 threadI/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


Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-09 Thread Paolo Bonzini
Il 09/08/2012 09:28, liu ping fan ha scritto:
  VCPU threadI/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.

But the RCU critical section should not include the whole processing of
MMIO, only the walk of the memory map.

And in general I think this is a bit too tricky... I understand not
adding refcounting to all of bottom halves, timers, etc., but if you are
using a device you should have explicit ref/unref pairs.

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


Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-08 Thread Paolo Bonzini
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 threadI/O thread
=
get MMIO request
rcu_read_lock()
walk memory map
   qdev_unmap()
   lock_devtree()
   ...
   unlock_devtree
   unref dev - refcnt=0, free enqueued
ref()
rcu_read_unlock()
   free()
dangling pointer!

If you defer the unref, you have instead

VCPU threadI/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


Re: [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views

2012-08-08 Thread Avi Kivity
On 08/08/2012 12:52 PM, Paolo Bonzini 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 threadI/O thread
 =
 get MMIO request
 rcu_read_lock()
 walk memory map
qdev_unmap()
lock_devtree()
...
unlock_devtree
unref dev - refcnt=0, free enqueued
 ref()
 rcu_read_unlock()
free()
 dangling pointer!

unref should follow either synchronize_rcu(), or be in a call_rcu()
callback (deferring the unref).  IMO synchronize_rcu() is sufficient
here, unplug is a truly slow path, esp. on real hardware.


-- 
error compiling committee.c: too many arguments to function
--
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