From nobody Sun Feb 8 19:59:42 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562947603; cv=none; d=zoho.com; s=zohoarc; b=XQmDFvl8AaCSsgqFNkh/PD/aeq7qhJGquYqYKYdRoR6cABsCUj9D6O+6MgUuSboumawGNEevGsM4NypoCPA+dWQ+xH3yEeWjS9C8H0Hz/C2zNKy5qyea7Th7pQYMuGnCiYnWdod5NzlXtZ+KF1B9vAltaBokIujZ4PkLih6jYTI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562947603; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=r86Xl1BQdWkwQpK8T2LclczErs6op+af9gN2HJMxq1E=; b=nDR6JaNwT8gglJ7AzmLx1pVdzp7rv6l2jrJeEk+MKnsmmhT4sUZtOEDUPMFUlC7rapp1OtiyDUWHr/o1WP82sO05ZYOe6Gab+yX8qUiGc9rm3CTIVUCvJNMSFKg2EhUfhTw5AOL5sx5NFEdxurGwYTP/TMqJKk9l+I1gq8t+gSU= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1562947603426227.24765661789615; Fri, 12 Jul 2019 09:06:43 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E169388313; Fri, 12 Jul 2019 16:06:41 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BC48F60142; Fri, 12 Jul 2019 16:06:41 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 6D93D183300F; Fri, 12 Jul 2019 16:06:41 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x6CG6e1F016571 for ; Fri, 12 Jul 2019 12:06:40 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0D97B60C73; Fri, 12 Jul 2019 16:06:40 +0000 (UTC) Received: from angien.brq.redhat.com (unknown [10.43.2.229]) by smtp.corp.redhat.com (Postfix) with ESMTP id 666B360C70; Fri, 12 Jul 2019 16:06:37 +0000 (UTC) From: Peter Krempa To: libvir-list@redhat.com Date: Fri, 12 Jul 2019 18:05:51 +0200 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: Peter Krempa Subject: [libvirt] [PATCH 10/25] qemu: domain: Store blockjob data in the status XML X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 12 Jul 2019 16:06:42 +0000 (UTC) Content-Type: text/plain; charset="utf-8" We need to store the block job state in the status XML so that we can properly recover any data when reconnecting after startup and also in the end to be able to do any transition of the backing chain that happened while libvirt was not connected to the monitor. First step is to note the name, type, state and corresponding disk into the status XML. We also need to make sure that a broken blockjob does not make libvirt to lose the VM, thus many of the errors are just mark the job as invalid. Later on we'll cancel all invalid jobs. Signed-off-by: Peter Krempa Reviewed-by: J=C3=A1n Tomko --- src/qemu/qemu_domain.c | 123 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 5af8f3b30c..59225c3ca9 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -32,6 +32,7 @@ #include "qemu_migration_params.h" #include "qemu_security.h" #include "qemu_extdevice.h" +#include "qemu_blockjob.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" @@ -2312,17 +2313,57 @@ qemuDomainObjPrivateXMLFormatAutomaticPlacement(vir= BufferPtr buf, } +static int +qemuDomainObjPrivateXMLFormatBlockjobIterator(void *payload, + const void *name ATTRIBUTE_U= NUSED, + void *data) +{ + VIR_AUTOCLEAN(virBuffer) attrBuf =3D VIR_BUFFER_INITIALIZER; + VIR_AUTOCLEAN(virBuffer) childBuf =3D VIR_BUFFER_INITIALIZER; + qemuBlockJobDataPtr job =3D payload; + virBufferPtr buf =3D data; + const char *state =3D qemuBlockjobStateTypeToString(job->state); + const char *newstate =3D NULL; + + if (job->newstate !=3D -1) + newstate =3D qemuBlockjobStateTypeToString(job->newstate); + + virBufferSetChildIndent(&childBuf, buf); + + virBufferEscapeString(&attrBuf, " name=3D'%s'", job->name); + virBufferEscapeString(&attrBuf, " type=3D'%s'", qemuBlockjobTypeToStri= ng(job->type)); + virBufferEscapeString(&attrBuf, " state=3D'%s'", state); + virBufferEscapeString(&attrBuf, " newstate=3D'%s'", newstate); + virBufferEscapeString(&childBuf, "%s", job->errmsg); + + if (job->disk) + virBufferEscapeString(&childBuf, "\n", job->disk= ->dst); + + return virXMLFormatElement(buf, "blockjob", &attrBuf, &childBuf); +} + + static int qemuDomainObjPrivateXMLFormatBlockjobs(virBufferPtr buf, virDomainObjPtr vm) { - virBuffer attrBuf =3D VIR_BUFFER_INITIALIZER; + qemuDomainObjPrivatePtr priv =3D vm->privateData; + VIR_AUTOCLEAN(virBuffer) attrBuf =3D VIR_BUFFER_INITIALIZER; + VIR_AUTOCLEAN(virBuffer) childBuf =3D VIR_BUFFER_INITIALIZER; bool bj =3D qemuDomainHasBlockjob(vm, false); virBufferAsprintf(&attrBuf, " active=3D'%s'", virTristateBoolTypeToString(virTristateBoolFromBool(= bj))); - return virXMLFormatElement(buf, "blockjobs", &attrBuf, NULL); + virBufferSetChildIndent(&childBuf, buf); + + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) && + virHashForEach(priv->blockjobs, + qemuDomainObjPrivateXMLFormatBlockjobIterator, + &childBuf) < 0) + return -1; + + return virXMLFormatElement(buf, "blockjobs", &attrBuf, &childBuf); } @@ -2662,16 +2703,90 @@ qemuDomainObjPrivateXMLParseAutomaticPlacement(xmlX= PathContextPtr ctxt, static int -qemuDomainObjPrivateXMLParseBlockjobs(qemuDomainObjPrivatePtr priv, +qemuDomainObjPrivateXMLParseBlockjobData(virDomainObjPtr vm, + xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + VIR_XPATH_NODE_AUTORESTORE(ctxt); + virDomainDiskDefPtr disk =3D NULL; + VIR_AUTOUNREF(qemuBlockJobDataPtr) job =3D NULL; + VIR_AUTOFREE(char *) name =3D NULL; + VIR_AUTOFREE(char *) typestr =3D NULL; + int type; + VIR_AUTOFREE(char *) statestr =3D NULL; + int state =3D QEMU_BLOCKJOB_STATE_FAILED; + VIR_AUTOFREE(char *) diskdst =3D NULL; + VIR_AUTOFREE(char *) newstatestr =3D NULL; + int newstate =3D -1; + bool invalidData =3D false; + + ctxt->node =3D node; + + if (!(name =3D virXPathString("string(./@name)", ctxt))) { + VIR_WARN("malformed block job data for vm '%s'", vm->def->name); + return 0; + } + + /* if the job name is known we need to register such a job so that we = can + * clean it up */ + if (!(typestr =3D virXPathString("string(./@type)", ctxt)) || + (type =3D qemuBlockjobTypeFromString(typestr)) < 0) { + type =3D QEMU_BLOCKJOB_TYPE_NONE; + invalidData =3D true; + } + + if (!(job =3D qemuBlockJobDataNew(type, name))) + return -1; + + if (!(statestr =3D virXPathString("string(./@state)", ctxt)) || + (state =3D qemuBlockjobStateTypeFromString(statestr)) < 0) + invalidData =3D true; + + if ((newstatestr =3D virXPathString("string(./@newstate)", ctxt)) && + (newstate =3D qemuBlockjobStateTypeFromString(newstatestr)) < 0) + invalidData =3D true; + + if ((diskdst =3D virXPathString("string(./disk/@dst)", ctxt)) && + !(disk =3D virDomainDiskByName(vm->def, diskdst, false))) + invalidData =3D true; + + job->state =3D state; + job->newstate =3D newstate; + job->errmsg =3D virXPathString("string(./errmsg)", ctxt); + job->invalidData =3D invalidData; + + if (qemuBlockJobRegister(job, vm, disk) < 0) + return -1; + + return 0; +} + + +static int +qemuDomainObjPrivateXMLParseBlockjobs(virDomainObjPtr vm, + qemuDomainObjPrivatePtr priv, xmlXPathContextPtr ctxt) { + VIR_AUTOFREE(xmlNodePtr *) nodes =3D NULL; + ssize_t nnodes =3D 0; VIR_AUTOFREE(char *) active =3D NULL; int tmp; + size_t i; if ((active =3D virXPathString("string(./blockjobs/@active)", ctxt)) && (tmp =3D virTristateBoolTypeFromString(active)) > 0) priv->reconnectBlockjobs =3D tmp; + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) { + if ((nnodes =3D virXPathNodeSet("./blockjobs/blockjob", ctxt, &nod= es)) < 0) + return -1; + + for (i =3D 0; i < nnodes; i++) { + if (qemuDomainObjPrivateXMLParseBlockjobData(vm, nodes[i], ctx= t) < 0) + return -1; + } + } + return 0; } @@ -3029,7 +3144,7 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, qemuDomainObjPrivateXMLParsePR(ctxt, &priv->prDaemonRunning); - if (qemuDomainObjPrivateXMLParseBlockjobs(priv, ctxt) < 0) + if (qemuDomainObjPrivateXMLParseBlockjobs(vm, priv, ctxt) < 0) goto error; qemuDomainStorageIdReset(priv); --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list