• M
    qdev: Fix latent bug with compat_props and onboard devices · 1a3ec8c1
    Markus Armbruster 提交于
    Compatibility properties started life as a qdev property thing: we
    supported them only for qdev properties, and implemented them with the
    machinery backing command line option -global.
    
    Recent commit fa0cb34d put them to use (tacitly) with memory
    backend objects (subtypes of TYPE_MEMORY_BACKEND).  To make that
    possible, we first moved the work of applying them from the -global
    machinery into TYPE_DEVICE's .instance_post_init() method
    device_post_init(), in commits ea9ce893 and b66bbee3, then made
    it available to TYPE_MEMORY_BACKEND's .instance_post_init() method
    host_memory_backend_post_init() as object_apply_compat_props(), in
    commit 1c3994f6.
    
    Note the code smell: we now have function name starting with object_
    in hw/core/qdev.c.  It has to be there rather than in qom/, because it
    calls qdev_get_machine() to find the current accelerator's and
    machine's compat_props.
    
    Turns out calling qdev_get_machine() there is problematic.  If we
    qdev_create() from a machine's .instance_init() method, we call
    device_post_init() and thus qdev_get_machine() before main() can
    create "/machine" in QOM.  qdev_get_machine() tries to get it with
    container_get(), which "helpfully" creates it as "container" object,
    and returns that.  object_apply_compat_props() tries to paper over the
    problem by doing nothing when the value of qdev_get_machine() isn't a
    TYPE_MACHINE.  But the damage is done already: when main() later
    attempts to create the real "/machine", it fails with "attempt to add
    duplicate property 'machine' to object (type 'container')", and
    aborts.
    
    Since no machine .instance_init() calls qdev_create() so far, the bug
    is latent.  But since I want to do that, I get to fix the bug first.
    
    Observe that object_apply_compat_props() doesn't actually need the
    MachineState, only its the compat_props member of its MachineClass and
    AccelClass.  This permits a simple fix: register MachineClass and
    AccelClass compat_props with the object_apply_compat_props() machinery
    right after these classes get selected.
    
    This is actually similar to how things worked before commits
    ea9ce893 and b66bbee3, except we now register much earlier.  The
    old code registered them only after the machine's .instance_init()
    ran, which would've broken compatibility properties for any devices
    created there.
    
    Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
    Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
    Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
    Message-Id: <20190308131445.17502-2-armbru@redhat.com>
    Reviewed-by: NMichael S. Tsirkin <mst@redhat.com>
    1a3ec8c1
accel.c 4.5 KB