On Tue, Feb 10, 2026 at 11:28:07PM +0800, Zhao Liu wrote:
Hi Daniel,
On Tue, Feb 10, 2026 at 10:12:38AM +0000, Daniel P. Berrangé wrote:
Date: Tue, 10 Feb 2026 10:12:38 +0000 From: "Daniel P. Berrangé" <berrange@redhat.com> Subject: Re: [PATCH v2 00/21] qom: introduce property flags to track external user input
On Tue, Feb 10, 2026 at 11:23:27AM +0800, Zhao Liu wrote:
Hi,
This is the v2 trying to introduce property flags to detect user's property setting (from CLI/QMP/HMP). I dropped RFC tag since previous RFC v1 [1].
This says what the series is proposing, but IMHO what is more important here is explaining why this either desirable or appropriate to add as general facility in QOM.
Yes, sorry this cover letter I wrote is overly simplified.
This series tries to control the property access against external user. USER_SET is the base to track external user's behavior, and DEPRECATED & INTERNAL flags provide different levels of access control.
Though the DEPRECATED flag does not inherently restrict access, I think such a warning also serves as a form of control.
The idea of restricting external access to properties is from previous discussions [*] about internal properties.
[*]: How to mark internal properties: https://lore.kernel.org/qemu-devel/2f526570-7ab0-479c-967c-b3f95f9f19e3@redh...
Since that disscussion, currently all properties expected to be "internal" have an “x-” prefix — while this approach can work, it clearly confuses the original meaning of “x-”, which actually means "unstable".
Therefore, I think the optimal approach is to provide the capability to restrict external access to the property — that is, to implement the "true" internal property.
Based on this, it seems impossible to implement an internal property without tracking user input in the QOM?
So the main thing that pushes us into using QOM for internal properties is the machine type compatibility code. eg where we bulk set stuff using compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); That logic is all QOM based. Using QOM isn't our exclusive approach, as we have machine types sometimes setting object fields directly. eg static void pc_i440fx_machine_7_0_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_7_1_options(m); pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); } but that only works for properties against the machine type, not compat properties against devices, since we have no direct access to the other classes/instances. If we want to be able to control hardware compat, without exposing something as a user facing tunable, then internal-only QOM props seems inescapable. I do still wonder if we genuinely need internal-only QOM props for machine type compat ? Whether using a public 'x-' prefixed property or an internal only property, we're constrained by the need to retain the behaviour semantics for as long as the machine type exists. I don't see an internal only property giving us significantly more freedom here. We can already rename a 'x-' property however we want with no notice, as long as the machine type doesn't change behaviour.
The idea that code should take different action for a given fixed value, based on whether the value was set by the user, or left on the default, makes me very uncomfortable.
There have been a number of situations where something that was initially a boolean flag, actually needed to be a tri-state instead, to provide semantics like "On", "Off", "Auto".
This "user set" flag could support such behaviour indirectly, but since "user set" is an internal concept we'd still be only exposing a boolean externally, while using a tri-state internally. That does not give the full flexibility of a tri-state, because internally if we wanted to have the default to be "yes", it offers no way for the mgmt app to put it back to "auto".
For properties that are not booleans, it is much less obvious to me whether we actually need a distinct "not set" concept at all.
USER_SET primarily serves the INTERNAL and DEPRECATED flags. However, its another function is to indicates whether the external user has touched the property.
But, Hmm, I think "auto" and USER_SET don't have conflict?
IIUC, "auto" means the user requests that QEMU make the decision itself. However, just like my patch 19 cleanup of “lbr-fmt”, that property explicitly requires users to provide a valid value. Even we have "auto" for uint64, "auto" can't address this case.
I just meant "auto" as one possible "default" behaviour where a traditional boolean was in use, not for all possible types. The right answer for a default is contextually dependent. For a uint64, a default value would involve some sentinal value, or it could involve a pair of related properties. For example, we have host-phys-bits=on phys-bits=NNN as a pair that work together, so you don't need a magic phys-bits value to represent "use host value".
Similarly, the x86 CPU's topology IDs (used for hotplug) - "thread-id"/ "core-id"/"module-id"..., also require the user to set valid and accurate values; they cannot be replaced with "auto".
Again I wasn't suggestnig an "auto" value for every scenario, that was just an example in a "bool" context. An ID value of "0" is a traditional default for numeric values, which is fine assuming you don't need to dinstinguish 0 as a valid value, from 0 as an invalid value needing user input.
I also think the ideal situation is not to distinguish between external and internal - however, exposing properties to external users makes code evolution painful...
I don't think it does. Code evolution is painful as long as the machine type using the prop needs to exist with fixed semantics, whether it is internal or public with x- prefix. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|