在 2021/6/21 15:29, Peter Krempa 写道:
On Sat, Jun 19, 2021 at 17:53:04 +0800, huangy81(a)chinatelecom.cn
wrote:
> From: Hyman Huang(黄勇) <huangy81(a)chinatelecom.cn>
>
> QEMU has introduced a dirty ring feature, this patch add corresponding
> feature named 'dirty-ring', which enable dirty ring feature when
> starting vm.
>
> To enable the feature, libvirt add "-accel dirty-ring-size=xxx"
> to QEMU command line, the following XML needs to be added to
> the guest's domain description:
>
> <features>
> <kvm>
> <dirty-ring state='on' size='xxx'>
> </kvm>
> </features>
>
> If property "state=on" but property "size" not be configured,
set
> default ring size with 4096.
>
> Since dirty ring can only be enabled by specifying "-accel" option
> and do not support the legacy style, it seems that there's no
> other way to work around this, so we use "-accel" option to specify
> accelerator instead of "-machine" when building qemu commandline.
>
> Details about the qemu "-accel" option:
>
https://lore.kernel.org/qemu-devel/3aa73987-40e8-3619-0723-9f17f73850bd@r...
>
> Three things this patch has done:
Note we require that patches are kept small and self contained. You
describe 3 things this patch is doing ant thus it almost implies as
it could be split 3-ways ...
> 1. switch the option "-machine accel" to "-accel" when
specifying
> accelerator type once libvirt build QEMU command line.
this definitely belongs to a separate patch.
>>
> 2. Since this patch change the output of building commandline, qemuxml2argvtest
> should also been modified so that test cases can be executed
> successfully, we modify test cases involved from qemu-2.9.0 to
Note that the oldest supported qemu is now qemu-2.11
ok, i'll fix it.
> qemu-6.1.0
>
> 3. Introduce dirty_ring_size in struct "_virDomainDef" to hold the
> ring size configured by user, and pass dirty_ring_size when building qemu
> commandline if dirty ring feature enabled.
This requires at least a 2 way split.
1) patch adding the definition, docs and XML parser/formatter
2) actual qemu impl.
ok, i'll split it next version.
>
> Signed-off-by: Hyman Huang(黄勇) <huangy81(a)chinatelecom.cn>
> ---
[...]
> @@ -17574,6 +17575,9 @@ virDomainFeaturesDefParse(virDomainDef *def,
> if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
> int feature;
> virTristateSwitch value;
> + xmlNodePtr node = NULL;
> +
> + node = ctxt->node;
> if ((n = virXPathNodeSet("./features/kvm/*", ctxt, &nodes))
< 0)
> return -1;
>
> @@ -17590,12 +17594,40 @@ virDomainFeaturesDefParse(virDomainDef *def,
> case VIR_DOMAIN_KVM_HIDDEN:
> case VIR_DOMAIN_KVM_DEDICATED:
> case VIR_DOMAIN_KVM_POLLCONTROL:
> + case VIR_DOMAIN_KVM_DIRTY_RING:
Don't integrate this with other cases ... >
> if (virXMLPropTristateSwitch(nodes[i], "state",
> VIR_XML_PROP_REQUIRED,
> &value) < 0)
> return -1;
Preferably rather duplicate this parsing ....
>
> def->kvm_features[feature] = value;
> +
> + /* only for dirty ring case */
> + if (((virDomainKVM) feature) == VIR_DOMAIN_KVM_DIRTY_RING
&&
> + value == VIR_TRISTATE_SWITCH_ON) {
To avoid this condition.
> + ctxt->node = nodes[i];
> +
> + if (virXMLPropString(ctxt->node, "size")) {
> + if (virXPathUInt("string(./@size)", ctxt,
> + &def->dirty_ring_size) < 0)
{
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("invalid number of dirty ring
size"));
> + return -1;
> + }
> +
> + if ((def->dirty_ring_size &
(def->dirty_ring_size - 1)) ||
Zero checks on integers should be explicit.
> + def->dirty_ring_size < 1024 ||
> + def->dirty_ring_size > 65536) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("dirty ring must be power of 2
"
> + "and ranges [1024,
65536]"));
> + return -1;
> + }
> + } else {
> + /* ring size not configured, set with default value 4096
*/
> + def->dirty_ring_size = 4096;
Assigning defaults in the parser isn't current state of things.
Preferably this belongs to a post-parse callback.
get it.
> + }
> + }
> break;
>
> case VIR_DOMAIN_KVM_LAST:
[...]
> @@ -21627,6 +21660,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src,
> case VIR_DOMAIN_KVM_HIDDEN:
> case VIR_DOMAIN_KVM_DEDICATED:
> case VIR_DOMAIN_KVM_POLLCONTROL:
> + case VIR_DOMAIN_KVM_DIRTY_RING:
> if (src->kvm_features[i] != dst->kvm_features[i]) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> _("State of KVM feature '%s'
differs: "
The abi-stability check should also check the size.
> @@ -27614,6 +27648,15 @@ virDomainDefFormatFeatures(virBuffer *buf,
> def->kvm_features[j]));
> break;
>
> + case VIR_DOMAIN_KVM_DIRTY_RING:
> + if (def->kvm_features[j])
Make the comparison with VIR_TRISTATE_SWITCH_ABSENT explicit here.
> + virBufferAsprintf(&childBuf, "<%s
state='%s' size='%d'/>\n",
> + virDomainKVMTypeToString(j),
> + virTristateSwitchTypeToString(
> + def->kvm_features[j]),
Don't linebreak the argument to virTristateSwitchTypeToString even if it
exceeds the line lenght. It's unreadable this way.
indeed, seems weird,
i'll fix it
> + def->dirty_ring_size);
> + break;
> +
> case VIR_DOMAIN_KVM_LAST:
> break;
> }
[...]
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index ea51369..80142b2 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -6587,6 +6587,9 @@ qemuBuildCpuCommandLine(virCommand *cmd,
> virBufferAddLit(&buf, ",kvm-poll-control=on");
> break;
>
> + case VIR_DOMAIN_KVM_DIRTY_RING:
> + break;
> +
> case VIR_DOMAIN_KVM_LAST:
> break;
> }
> @@ -6758,29 +6761,41 @@ qemuBuildNameCommandLine(virCommand *cmd,
> return 0;
> }
>
> +static void
> +qemuBuildAccelCommandLineTcgOptions(void)
> +{
> + /* TODO: build command line tcg accelerator
> + * property like tb-size */
Is this patch incomplete? In case you don't want to support this for TCG
you should forbid it in validation rather than silently ignoring it.
ok, i'll
forbid it next version.
> +}
> +
> +static void
> +qemuBuildAccelCommandLineKvmOptions(virBuffer *buf,
> + const virDomainDef *def)
> +{
> + if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON
&&
> + def->kvm_features[VIR_DOMAIN_KVM_DIRTY_RING] == VIR_TRISTATE_SWITCH_ON)
{
> + virBufferAsprintf(buf, ",dirty-ring-size=%d",
def->dirty_ring_size);
> + }
> +}
> +
> static int
> -qemuBuildMachineCommandLine(virCommand *cmd,
> - virQEMUDriverConfig *cfg,
> - const virDomainDef *def,
> - virQEMUCaps *qemuCaps,
> - qemuDomainObjPrivate *priv)
> +qemuBuildAccelCommandLine(virCommand *cmd,
> + const virDomainDef *def)
> {
> - virTristateSwitch vmport = def->features[VIR_DOMAIN_FEATURE_VMPORT];
> - virTristateSwitch smm = def->features[VIR_DOMAIN_FEATURE_SMM];
> - virCPUDef *cpu = def->cpu;
> + /* the '-machine' options for accelerator are legacy,
> + * using the '-accel' options by default */
> g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
> - size_t i;
> -
> - virCommandAddArg(cmd, "-machine");
> - virBufferAdd(&buf, def->os.machine, -1);
> + virCommandAddArg(cmd, "-accel");
This MUST be a separate commit it's a fully separate change which
requires separate justification.
ok.
>
> switch ((virDomainVirtType)def->virtType) {
> case VIR_DOMAIN_VIRT_QEMU:
> - virBufferAddLit(&buf, ",accel=tcg");
> + virBufferAddLit(&buf, "tcg");
> + qemuBuildAccelCommandLineTcgOptions();
> break;
>
> case VIR_DOMAIN_VIRT_KVM:
> - virBufferAddLit(&buf, ",accel=kvm");
> + virBufferAddLit(&buf, "kvm");
> + qemuBuildAccelCommandLineKvmOptions(&buf, def);
> break;
>
> case VIR_DOMAIN_VIRT_KQEMU:
> @@ -6808,6 +6823,61 @@ qemuBuildMachineCommandLine(virCommand *cmd,
> return -1;
> }
>
> + virCommandAddArgBuffer(cmd, &buf);
> + return 0;
> +}
> +
> +static int
> +qemuBuildMachineCommandLine(virCommand *cmd,
> + virQEMUDriverConfig *cfg,
> + const virDomainDef *def,
> + virQEMUCaps *qemuCaps,
> + qemuDomainObjPrivate *priv)
> +{
> + virTristateSwitch vmport = def->features[VIR_DOMAIN_FEATURE_VMPORT];
> + virTristateSwitch smm = def->features[VIR_DOMAIN_FEATURE_SMM];
> + virCPUDef *cpu = def->cpu;
> + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
> + size_t i;
> +
> + virCommandAddArg(cmd, "-machine");
> + virBufferAdd(&buf, def->os.machine, -1);
> +
> + /* QEMU lower than 2.9.0 do not support '-accel'
> + * fallback to '-machine accel' */
We don't support those qemu versions. This is the reason why you must
split the patch. A refactor like this has nothing to do with the feature
addition and should be justified and reviewed separately.
ok. i'll post a patch
just changing the way of build commandline before
the dirty ring feature patchset.
> + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ACCEL)) {
> + switch ((virDomainVirtType)def->virtType) {
> + case VIR_DOMAIN_VIRT_QEMU:
> + virBufferAddLit(&buf, ",accel=tcg");
> + break;
> + case VIR_DOMAIN_VIRT_KVM:
> + virBufferAddLit(&buf, ",accel=kvm");
> + break;
> + case VIR_DOMAIN_VIRT_KQEMU:
[...]
> @@ -10402,6 +10472,11 @@ qemuBuildCommandLine(virQEMUDriver *driver,
> if (qemuBuildMachineCommandLine(cmd, cfg, def, qemuCaps, priv) < 0)
> return NULL;
>
> + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ACCEL)) {
> + if (qemuBuildAccelCommandLine(cmd, def) < 0)
> + return NULL;
> + }
> +
> qemuBuildTSEGCommandLine(cmd, def);
>
> if (qemuBuildCpuCommandLine(cmd, driver, def, qemuCaps) < 0)