Markus Armbruster <arm...@redhat.com> writes:

> It's not just tests.  QAPI-related headers have deteriorated, and pull
> in too much.  I'll try to clean this up.  Thanks!

While some cleanup is certainly possible and probably useful, I don't
think I can completely solve the problem that way.

Not counting tests, we have two or three QAPI schemas, depending on how
you count:

* QEMU's main schema qapi/qapi-schema.json

  This schema defines qemu-system-FOO's QMP (plus types used for QOM
  properties and such, but that's detail we can ignore here).

* The storage daemon's schema storage-daemon/qapi/qapi-schema.json

  This is a strict subset the main schema, not a schema on its own.

  qemu-storage-daemon wants to provide a subset of qemu-system-FOO's
  QMP.  We get this as follows.

  qapi/qapi-schema.json contains nothing but include directives.
  storage-daemon/qapi/qapi-schema.json contains nothing but a subset of
  the same include directives.  The exact same code gets generated for
  these modules both times.  We always use the copy generated for the
  main schema's modules, and ignore the one generated for the storage
  daemon.  Different code gets generated for command & event
  registration, and QMP introspection.  The storage daemon uses the code
  generated for its subset.  This is a bit of a hack.

* The guest agent's schema qga/qapi-schema.json

  This schema defines qemu-ga's QMP.

Each program generally uses at most one QAPI schema.  Easy.

The exception is the guest agent.  It might have initially used just its
own QAPI schema as well, but today, it also uses parts of the main
schema.  That's because the main schema has grown tentacles into common
code.

Example: qemu-ga with -m vsock-listen prefixes its -p argument with
"vsock:" and parses the result with socket_parse().  While we can
quibble about the details here, sharing vsock address syntax and parser
between guest agent and QEMU proper makes sense.  The address structure
/ abstract syntax is defined in the main schema's qapi/sockets.json.
The address parser is declared in qemu/sockets.h, and pulls in the main
schema's qapi/qapi-types-sockets.h.

Trying to limit qemu-ga to just its own schema would make no sense.  We
*want* to share things defined in a (shared) QAPI schema.

Note that while qemu-ga C code pulls in (generated) main schema stuff,
its QAPI schema so far does not.  However, reuse of utility types like
SocketAddress or OnOffAuto from the main schema might become interesting
some day.

The QAPI generator supports more than one schema per program, although
kind of half-heartedly.  There's -p to set a prefix, which is prepended
to filenames and symbols.  But there's no systematic effort to do the
latter.  We slap it to symbols whenever we run into a collision.

Example: your patch slaps it to the generated QapiFeature enum and its
members.

Example: we don't slap it to command handlers.  If two schemas both
define command 'frobnicate', we generate a prototype qmp_frobnicate()
for both, and expect the handwritten code to supply a function suitable
for both.

We can continue slapping the prefix to symbols whenever we run into a
collision, i.e. go with your patch.  Feels like the pragmatic choice to
not block your series.

But could we do better in the long run?

Back when we created the guest agent schema, QAPI schemas were
monolithic: a single schema file, generating a single qapi-types.h and
so forth.

Today, a schema can be modular, i.e. split into multiple modules, each
generating its own qapi-types-MODULE.h and so forth.

We exploit this to have a single schema both for qemu-system-FOO's QMP
and qemu-storage-daemon's QMP, albeit in a hacky way.

What if QAPI provided cleaner means for generating multiple QMPs from a
single schema?

Then we could have a single schema, and no worries about collisions.

I'm not asking you to try this.  It's just an idea I wrote up so I don't
forget it again.


Reply via email to