device-core: use RCU for list of children of a bus

This fixes the race between device emulation code that tries to find
a child device to dispatch the request to (e.g a scsi disk),
and hotplug of a new device to that bus.

Note that this doesn't convert all the readers of the list
but only these that might go over that list without BQL held.

This is a very small first step to make this code thread safe.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20200913160259.32145-5-mlevitsk@redhat.com>
[Use RCU_READ_LOCK_GUARD in more places, adjust testcase now that
 the delay in DEVICE_DELETED due to RCU is more consistent. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20201006123904.610658-9-mlevitsk@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Maxim Levitsky 2020-10-06 15:38:59 +03:00 committed by Paolo Bonzini
parent 7bed89958b
commit 2d24a64661
5 changed files with 63 additions and 29 deletions

View file

@ -3,6 +3,8 @@
#include "qemu/queue.h"
#include "qemu/bitmap.h"
#include "qemu/rcu.h"
#include "qemu/rcu_queue.h"
#include "qom/object.h"
#include "hw/hotplug.h"
#include "hw/resettable.h"
@ -238,6 +240,7 @@ struct BusClass {
};
typedef struct BusChild {
struct rcu_head rcu;
DeviceState *child;
int index;
QTAILQ_ENTRY(BusChild) sibling;
@ -258,6 +261,12 @@ struct BusState {
int max_index;
bool realized;
int num_children;
/*
* children is a RCU QTAILQ, thus readers must use RCU to access it,
* and writers must hold the big qemu lock
*/
QTAILQ_HEAD(, BusChild) children;
QLIST_ENTRY(BusState) sibling;
ResettableState reset;