From nobody Wed Feb 11 04:19:38 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1770719610; cv=none; d=zohomail.com; s=zohoarc; b=Kb6NAj8RdG2Yfefc9Sv9Dy/DB0QWmQwb6D9HK28nvG0GKGiEjSQG1JRvpvWrNm1brsGdEuV2Pv3WXqKsGMBfZf68ZVKzftS6oOluRqIW+km1BL9TFHCXJvPIdGVI/zXi2lefK322Z7DLDSQUbGqwHuLgxMWYD6E8lC0f1+0dXag= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1770719610; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=EeDHSAJE1btH0yxDSPP7iJ6ByZ0M3+JxGI6VJZpjGzw=; b=g8W5Edclrtc3EPc3RRPQz+k9hUvlMWwwaXls8GnSvS92bVrTjx8053XMM5FBE9EJDTrcJBNonlXZ8yJnj7W9akDDUmyjowkj9Rtc9hRaBME6CrW4HJ3PulxMo3IrUCOgRmtHBDOu5FlPvYfPRHGOw9qzEWtkKc2VtAZ06p/RWUY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1770719610453124.78623468705052; Tue, 10 Feb 2026 02:33:30 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id E86544417A; Tue, 10 Feb 2026 05:33:29 -0500 (EST) Received: from [172.19.199.6] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 47B114425E; Tue, 10 Feb 2026 05:31:51 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 1139A419E9; Tue, 10 Feb 2026 05:13:18 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id E43CF4419C for ; Tue, 10 Feb 2026 05:11:12 -0500 (EST) Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-573-v4kNin-HMVeCg-TxzFQYbw-1; Tue, 10 Feb 2026 05:11:11 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 887B7195608D for ; Tue, 10 Feb 2026 10:11:10 +0000 (UTC) Received: from speedmetal.lan (unknown [10.44.22.2]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D409C30001A5 for ; Tue, 10 Feb 2026 10:11:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1770718272; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EeDHSAJE1btH0yxDSPP7iJ6ByZ0M3+JxGI6VJZpjGzw=; b=JWyYIuU72TEHYmtGk9GY7PqcjM5gdwCziGbwstm8RxGeTWdxnlNSUArCWP9Tia9rg3OCRw WwQkAPJRuXLzXc69iiJDcuLPhaUF6IqkOh1/sOAj4NhI8RaPEnO6lktMC19QagLzqBfgbT erWaocwyN8Qb5ioGVlEm7KEFAtbmVcI= X-MC-Unique: v4kNin-HMVeCg-TxzFQYbw-1 X-Mimecast-MFC-AGG-ID: v4kNin-HMVeCg-TxzFQYbw_1770718270 To: devel@lists.libvirt.org Subject: [PATCH v2 4/4] qemu: Implement support for persistent reservation migration control Date: Tue, 10 Feb 2026 11:11:02 +0100 Message-ID: <5d32506229cd410b30cb6849326c82026fb3a038.1770718214.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: S1h9yLX1aj8mkHvKLBNIIykpPP3t6vmuRlRDqu_EB0U_1770718270 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: L4TPQDU6TWSAYWB2FU4AI632DCFIPKAJ X-Message-ID-Hash: L4TPQDU6TWSAYWB2FU4AI632DCFIPKAJ X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Peter Krempa via Devel Reply-To: Peter Krempa X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1770719611027154100 Content-Type: text/plain; charset="utf-8" From: Peter Krempa The 'migration' attribute for the '' element allows to control the persistent reservation migration feature independently of the machine type default. Add the XML plumbing and qemu support. We consider it ABI for now since it influences qemu migration protocol. Signed-off-by: Peter Krempa --- docs/formatdomain.rst | 3 +++ src/conf/domain_conf.c | 21 +++++++++++++++++++ src/conf/schemas/storagecommon.rng | 5 +++++ src/conf/storage_source_conf.c | 10 +++++++++ src/conf/storage_source_conf.h | 2 ++ src/qemu/qemu_command.c | 4 ++++ src/qemu/qemu_validate.c | 16 ++++++++++++++ ...irtio-scsi-reservations.x86_64-latest.args | 2 +- .../disk-virtio-scsi-reservations.xml | 2 +- 9 files changed, 63 insertions(+), 2 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 87644ad42a..dfc0e94ec3 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -3186,6 +3186,9 @@ paravirtualized driver is specified via the ``disk`` = element. the socket, and finally ``mode`` which accepts one value ``client`` specifying the role of hypervisor. It's recommended to allow libvirt manage the persistent reservations. + :since:`Since 12.1.0` the ``migration`` (values ``yes``, ``no``) con= trols + whether the hypervisor should attempt to migrate persistent reservat= ions + during migration. ``initiator`` :since:`Since 4.7.0`, the ``initiator`` element is supported for a disk ``type`` "network" that is using a ``source`` element with the diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e88dc62520..09cd562d3a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -20999,6 +20999,27 @@ virDomainDiskDefCheckABIStability(virDomainDiskDef= *src, return false; } + /* While not guest visible it influences the qemu migration stream so + * we need to keep it identical */ + if (src->src->pr || dst->src->pr) { + virTristateBool srcmig =3D VIR_TRISTATE_BOOL_ABSENT; + virTristateBool dstmig =3D VIR_TRISTATE_BOOL_ABSENT; + + if (src->src->pr) + srcmig =3D src->src->pr->migration; + + if (dst->src->pr) + dstmig =3D dst->src->pr->migration; + + if (srcmig !=3D dstmig) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target disk reservations 'migration' propert= y %1$s does not match source %2$s"), + virTristateBoolTypeToString(dstmig), + virTristateBoolTypeToString(srcmig)); + return false; + } + } + if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio)) return false; diff --git a/src/conf/schemas/storagecommon.rng b/src/conf/schemas/storagec= ommon.rng index 14704c737e..450d53131f 100644 --- a/src/conf/schemas/storagecommon.rng +++ b/src/conf/schemas/storagecommon.rng @@ -104,6 +104,11 @@ + + + + + diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index d7b9bdfecb..e5f20fba80 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -331,6 +331,11 @@ virStoragePRDefParseXML(xmlXPathContextPtr ctxt) &prd->managed) < 0) goto cleanup; + if (virXMLPropTristateBool(ctxt->node, "migration", + VIR_XML_PROP_NONZERO, + &prd->migration) < 0) + goto cleanup; + type =3D virXPathString("string(./source[1]/@type)", ctxt); path =3D virXPathString("string(./source[1]/@path)", ctxt); mode =3D virXPathString("string(./source[1]/@mode)", ctxt); @@ -385,6 +390,11 @@ virStoragePRDefFormat(virBuffer *buf, { virBufferAsprintf(buf, "managed)); + + if (prd->migration !=3D VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(buf, " migration=3D'%s'", + virTristateBoolTypeToString(prd->migration)); + if (prd->path && (prd->managed =3D=3D VIR_TRISTATE_BOOL_NO || !migratable)) { virBufferAddLit(buf, ">\n"); diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index 22c35d420d..d3a9b0e7a2 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -236,6 +236,8 @@ struct _virStoragePRDef { virTristateBool managed; char *path; + virTristateBool migration; + /* manager object alias */ char *mgralias; }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 069211e139..c09c883a28 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1692,6 +1692,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, g_autofree char *usbdiskalias =3D NULL; const virDomainDeviceInfo *deviceinfo =3D &disk->info; g_autoptr(virJSONValue) statistics =3D NULL; + virTristateBool migrate_pr =3D VIR_TRISTATE_BOOL_ABSENT; virDomainDeviceInfo usbSCSIinfo =3D { .type =3D VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE, .addr.drive =3D { .diskbus =3D VIR_DOMAIN_DISK_BUS_USB }, @@ -1717,6 +1718,8 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, case VIR_DOMAIN_DISK_BUS_SCSI: if (disk->device =3D=3D VIR_DOMAIN_DISK_DEVICE_LUN) { driver =3D "scsi-block"; + if (disk->src->pr) + migrate_pr =3D disk->src->pr->migration; } else { if (disk->device =3D=3D VIR_DOMAIN_DISK_DEVICE_CDROM) { driver =3D "scsi-cd"; @@ -1938,6 +1941,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, "S:rerror", rpolicy, "A:stats-intervals", &statistics, "T:dpofua", disk->dpofua, /* SCSI-only, ensu= red by validation */ + "T:migrate-pr", migrate_pr, /* 'scsi-block' = only, ensured by validation */ NULL) < 0) return NULL; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 0bad299996..2ca38db9f1 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3226,6 +3226,22 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDom= ainDiskDef *disk, } } + if (disk->src->pr && + disk->src->pr->migration !=3D VIR_TRISTATE_BOOL_ABSENT) { + if (disk->device !=3D VIR_DOMAIN_DISK_DEVICE_LUN || + disk->bus !=3D VIR_DOMAIN_DISK_BUS_SCSI) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent reservation migration supported o= nly with 'lun' disks on 'scsi' bus")); + return -1; + } + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_= PR)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent reservation migration not support= ed by this qemu")); + return -1; + } + } + if (disk->rotation_rate) { if (disk->bus !=3D VIR_DOMAIN_DISK_BUS_SCSI && disk->bus !=3D VIR_DOMAIN_DISK_BUS_IDE && diff --git a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-lat= est.args b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-lates= t.args index cbc2a0f398..f1d7a450ee 100644 --- a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args +++ b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args @@ -33,7 +33,7 @@ XDG_CONFIG_HOME=3D/var/lib/libvirt/qemu/domain--1-QEMUGue= st1/.config \ -device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"l= un":0,"drive":"libvirt-2-storage","id":"scsi0-0-0-0","bootindex":1}' \ -object '{"qom-type":"pr-manager-helper","id":"pr-helper-libvirt-1-storage= ","path":"/path/to/qemu-pr-helper.sock"}' \ -blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest2","pr= -manager":"pr-helper-libvirt-1-storage","node-name":"libvirt-1-storage","re= ad-only":false}' \ --device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"l= un":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1"}' \ +-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"l= un":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1","migrate-pr":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","add= r":"0x4"}' \ -sandbox on,obsolete=3Ddeny,elevateprivileges=3Ddeny,spawn=3Ddeny,resource= control=3Ddeny \ diff --git a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml b/test= s/qemuxmlconfdata/disk-virtio-scsi-reservations.xml index 9c55d6ec3e..7f9160ff3a 100644 --- a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml +++ b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml @@ -28,7 +28,7 @@ - + --=20 2.53.0