[libvirt] [PATCH v2 1/8] domain_conf: Introduce chardev hotplug helpers
Martin Kletzander
mkletzan at redhat.com
Fri Jun 21 08:27:36 UTC 2013
On 06/06/2013 02:29 PM, Michal Privoznik wrote:
> For now, only these three helpers are needed:
> virDomainChrFind - to find a duplicate chardev within VM def
> virDomainChrInsert - wrapper for inserting a new chardev into VM def
> virDomainChrRemove - wrapper for removing chardev from VM def
>
> There is, however, one internal helper as well:
> virDomainChrGetDomainPtrs which sets given pointers to one of
> vmdef->{parallels,serials,consoles,channels} based on passed
> chardev type.
> ---
> src/conf/domain_conf.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++
> src/conf/domain_conf.h | 11 ++++
> src/libvirt_private.syms | 4 ++
> 3 files changed, 175 insertions(+)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index a16ebd1..37f0ce9 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -10056,6 +10056,166 @@ virDomainLeaseRemove(virDomainDefPtr def,
> return virDomainLeaseRemoveAt(def, i);
> }
>
> +static bool
> +virDomainChrEquals(virDomainChrDefPtr src,
> + virDomainChrDefPtr tgt)
> +{
> + if (!src || !tgt)
> + return src == tgt;
> +
> + if (!virDomainChrSourceDefIsEqual(&src->source, &tgt->source))
> + return false;
> +
> + if (src->targetTypeAttr != tgt->targetTypeAttr)
> + return false;
> +
> + if (!src->targetTypeAttr)
> + return true;
> +
> + switch ((enum virDomainChrChannelTargetType) src->targetType) {
There should be one more check and switch above this one to
differentiate according to src->deviceType and tgt->deviceType.
> + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
> + return STREQ_NULLABLE(src->target.name, tgt->target.name);
> + break;
> + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
> + if (!src->target.addr || !tgt->target.addr)
> + return src->target.addr == tgt->target.addr;
> + return memcmp(src->target.addr, tgt->target.addr,
> + sizeof(*src->target.addr)) == 0;
> + break;
> +
> + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
> + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
> + default:
No need for default case in here.
> + return true;
> + }
> +}
> +
> +virDomainChrDefPtr
> +virDomainChrFind(virDomainDefPtr def,
> + virDomainChrDefPtr target)
> +{
> + size_t i;
> +
> + for (i = 0; i < def->nparallels; i++) {
> + virDomainChrDefPtr chr = def->parallels[i];
> +
> + if (virDomainChrEquals(chr, target))
> + return chr;
> + }
> +
> + for (i = 0; i < def->nserials; i++) {
> + virDomainChrDefPtr chr = def->serials[i];
> +
> + if (virDomainChrEquals(chr, target))
> + return chr;
> + }
> +
> +
> + for (i = 0; i < def->nconsoles; i++) {
> + virDomainChrDefPtr chr = def->consoles[i];
> +
> + if (virDomainChrEquals(chr, target))
> + return chr;
> + }
> +
> + for (i = 0; i < def->nchannels; i++) {
> + virDomainChrDefPtr chr = def->channels[i];
> +
> + if (virDomainChrEquals(chr, target))
> + return chr;
> + }
> +
You're iterating over all devices in the domain, but you can check which
ones to check based on target->deviceType.
> + return NULL;
> +}
> +
> +int
> +virDomainChrGetDomainPtrs(virDomainDefPtr vmdef,
> + virDomainChrDefPtr chr,
> + virDomainChrDefPtr ***arrPtr,
> + size_t **cntPtr)
> +{
> + switch ((enum virDomainChrDeviceType) chr->deviceType) {
> + case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
> + *arrPtr = &vmdef->parallels;
> + *cntPtr = &vmdef->nparallels;
> + break;
> +
> + case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
> + *arrPtr = &vmdef->serials;
> + *cntPtr = &vmdef->nserials;
> + break;
> +
> + case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
> + *arrPtr = &vmdef->consoles;
> + *cntPtr = &vmdef->nconsoles;
> + break;
> +
> + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
> + *arrPtr = &vmdef->channels;
> + *cntPtr = &vmdef->nchannels;
> + break;
> +
> + default:
I'd rather cast the switch argument, put a TYPE_LAST here and you don't
have to report the error then.
> + virReportError(VIR_ERR_OPERATION_INVALID,
> + _("Unsupported device type '%d'"),
> + chr->deviceType);
> + return -1;
> + }
> + return 0;
> +}
> +
And with this function, you can iterate over those devices in
virDomainChrFind even more clearly.
> +int virDomainChrInsert(virDomainDefPtr vmdef,
> + virDomainChrDefPtr chr)
> +{
> + virDomainChrDefPtr **arrPtr;
> + size_t *cntPtr;
> +
> + if (virDomainChrGetDomainPtrs(vmdef, chr, &arrPtr, &cntPtr) < 0)
> + return -1;
> +
> + if (VIR_REALLOC_N(*arrPtr, *cntPtr + 1) < 0) {
> + virReportOOMError();
> + return -1;
> + }
> +
> + (*arrPtr)[*cntPtr] = chr;
> + (*cntPtr)++;
> +
VIR_APPEND_ELEMENT could make this a bit shorter and readable.
> + return 0;
> +}
> +
> +int virDomainChrRemove(virDomainDefPtr vmdef,
> + virDomainChrDefPtr chr)
> +{
> + virDomainChrDefPtr **arrPtr;
> + size_t i, *cntPtr;
> +
> + if (virDomainChrGetDomainPtrs(vmdef, chr, &arrPtr, &cntPtr) < 0)
> + return -1;
> +
> + for (i = 0; i < *cntPtr; i++) {
> + virDomainChrDefPtr tmp = (*arrPtr)[i];
> +
> + if (virDomainChrEquals(tmp, chr))
> + break;
> + }
> +
> + if (i == *cntPtr)
> + return -1;
> +
This is another part of code you can de-duplicate since it is similar to
the virDomainChrFind (and deals with the problem mentioned there).
> + virDomainChrDefFree((*arrPtr)[i]);
> + if (*cntPtr > 1) {
> + memmove(*arrPtr + i,
> + *arrPtr + i + 1,
> + sizeof(**arrPtr) * (*cntPtr - (i + 1)));
> + ignore_value(VIR_REALLOC_N(*arrPtr, *cntPtr - 1));
> + } else {
> + VIR_FREE(*arrPtr);
> + }
> + (*cntPtr)--;
> +
And for this you should be able to use the VIR_DELETE_ELEMENT macro.
> + return 0;
> +}
>
> char *
> virDomainDefGetDefaultEmulator(virDomainDefPtr def,
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 3a71d6c..6d650ff 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -2355,6 +2355,17 @@ virDomainLeaseDefPtr
> virDomainLeaseRemove(virDomainDefPtr def,
> virDomainLeaseDefPtr lease);
>
> +int virDomainChrGetDomainPtrs(virDomainDefPtr vmdef,
s/ /\n/
> + virDomainChrDefPtr chr,
> + virDomainChrDefPtr ***arrPtr,
> + size_t **cntPtr);
> +virDomainChrDefPtr virDomainChrFind(virDomainDefPtr def,
dtto
> + virDomainChrDefPtr target);
> +int virDomainChrInsert(virDomainDefPtr vmdef,
dtto
> + virDomainChrDefPtr chr);
> +int virDomainChrRemove(virDomainDefPtr vmdef,
dtto
> + virDomainChrDefPtr chr);
> +
> int virDomainSaveXML(const char *configDir,
pre-existing, but could be fixed.
> virDomainDefPtr def,
> const char *xml);
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index b93629f..b9ba731 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -77,6 +77,10 @@ virDomainChrConsoleTargetTypeToString;
> virDomainChrDefForeach;
> virDomainChrDefFree;
> virDomainChrDefNew;
> +virDomainChrFind;
> +virDomainChrGetDomainPtrs;
> +virDomainChrInsert;
> +virDomainChrRemove;
> virDomainChrSerialTargetTypeFromString;
> virDomainChrSerialTargetTypeToString;
> virDomainChrSourceDefCopy;
>
Martin
More information about the libvir-list
mailing list