Features/QOM-QAPI integration

From QEMU
Revision as of 10:43, 3 December 2020 by Paolo Bonzini (talk | contribs) (Created page with "Separating configuration of QOM objects from their run-time state, and express the configuration as a QAPI struct. == Implementation == New input visitor function (the imple...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Separating configuration of QOM objects from their run-time state, and express the configuration as a QAPI struct.

Implementation

New input visitor function (the implementation in QObjectInputVisitor visits QLIST_FIRST(&qiv->stack)->h)

bool visit_struct_foreach_member(Visitor *v, void (*cb)(void *opaque, const char *name, Visitor *v, Error **errp),
                                 void *opaque, Error **errp);

New ObjectClass function pointer "configure" replaces the visitor step of user_creatable_add_type

void (*configure)(Object *obj, Visitor *v, Error **errp);

The object_configure function wraps the "configure" function pointer and falls back to properties for anything that isn't consumed by the classes:

bool object_configure(Object *obj, Visitor *v, Error **errp) {
    Error *local_err = NULL;
    visit_start_struct(v, NULL, NULL, 0, &local_err);
    if (local_err) {
        goto out;
    }
    foreach super class from Object to object_get_class(obj) {
        if (oc->configure) {
            oc->configure(obj, v, &local_err);
            if (local_err) {
                goto out;
            }
        }
    }
    if (!visit_struct_foreach_member(v, object_property_set, obj, errp)) {
        return false;
    }
out:
    if (local_err) {
        error_propagate(errp, local_err);
    } else {
        visit_check_struct(v, &local_err);
    }
    visit_end_struct(v, NULL);
    return local_err != NULL;
}

user_creatable_add_type uses object_configure to set properties

    obj = object_new(type);
    if (!object_configure(obj, v, &local_err)) {
        goto out;
    }
    if (id != NULL) {
        ...
    }

Conversion

Conversion from writable properties to options struct adds a definition of oc->configure, such as:

struct RngEgd {
    RngBackend parent;
    CharBackend chr;
    RngEgdOptions config;
};
void qapi_RngEgd_configure(Object *obj, Visitor *v, Error **errp)
{
    RngEgd *s = RNG_EGD(obj);
    visit_type_RngEgdOptions(v, NULL, &s->config, errp);
}
...
oc->configure = qapi_RngEgd_configure;

The qapi_RngEgd_configure function could be later generated by QAPI, for example from:

{ 'object': 'RngEgd',
  'configuration': {
       'chardev': 'str'
  }
}

The above QAPI declaration could also generate a constructor function for use in C code, for example:

RngEgd *object_new_configure(const char *type, void (*v)(Visitor *v, const char *name, void **ptr, Error **errp),
                             void *data, Error **errp)
{
    Object *o;
    QObject *ret = NULL;
    Error *local_err = NULL;
    Visitor *qiv, *qov;
    qov = qobject_output_visitor_new(&ret);
    v(qov, NULL, &data, &local_err);
    visit_free(qov);
    if (local_err) {
        error_propagate(errp, local_err);
        return NULL;
    }
    qiv = qobject_input_visitor_new(ret);
    o = object_new(type);
    object_configure(o, qiv, &local_err);
    visit_free(qiv);
    if (local_err) {
        error_propagate(errp, local_err);
        object_unref(o);
        return NULL;
    }
    return o;
}
static inline RngEgd *rng_egd_new(RngOptions *opt, Error **errp)
{
    return RNG_EGD(object_new_configure(TYPE_RNG_EGD, visit_type_RngEgdOptions, opt, errp));
}

Properties still exist, but they are mostly read-only. For example, rng_egd_get_chardev remains exactly the same but rng_egd_set_chardev goes away. They also keep their role in releasing resources on "object-del" (though it's visible mostly in devices, and not for example in rng-egd because it uses a string property for "chardev").

Properties are _not_ exposed to QAPI (not yet at least). Properties will be of one of three kinds:

  • read-only 1:1 mapping to configuration fields (e.g. rng-random.filename)
  • read-only 1:1 mapping to runtime state fields (e.g. rng-egd.chardev)
  • writable, with side effects (e.g. throttle-group.limits)

Writable 1:1 mapping to runtime state fields are probably rare enough that we can treat them the same as the third case.

QAPI can express the first two. The third must remain in C code for now.