[libvirt] [PATCH v3 2/2] libxl: add tunnelled migration support
Joao Martins
joao.m.martins at oracle.com
Thu Feb 16 16:14:19 UTC 2017
On 02/16/2017 02:57 PM, John Ferlan wrote:
> On 02/16/2017 09:26 AM, Joao Martins wrote:
>> On 02/16/2017 11:47 AM, John Ferlan wrote:
>>> FYI: Couple of Coverity issues resulted from these patches.
>>>
>>>> int
>>>> +libxlDomainMigrationPrepareTunnel3(virConnectPtr dconn,
>>>> + virStreamPtr st,
>>>> + virDomainDefPtr *def,
>>>> + const char *cookiein,
>>>> + int cookieinlen,
>>>> + unsigned int flags)
>>>> +{
>>>> + libxlMigrationCookiePtr mig = NULL;
>>>> + libxlDriverPrivatePtr driver = dconn->privateData;
>>>> + virDomainObjPtr vm = NULL;
>>>> + libxlMigrationDstArgs *args = NULL;
>>>> + virThread thread;
>>>> + bool taint_hook = false;
>>>> + libxlDomainObjPrivatePtr priv = NULL;
>>>> + char *xmlout = NULL;
>>>> + int dataFD[2] = { -1, -1 };
>>>> + int ret = -1;
>>>> +
>>>> + if (libxlDomainMigrationPrepareAny(dconn, def, cookiein, cookieinlen,
>>>> + &mig, &xmlout, &taint_hook) < 0)
>>>
>>> Coverity notes that '@mig' will be leaked in this case when "if
>>> (!cookiein || !cookieinlen) {" is true in libxlMigrationEatCookie and
>>> failures from libxlDomainMigrationPrepareAny don't free it.
>>
>> /nods. This diff should do then? It covers both cases I think.
>
> What about:
>
> args->migcookie = mig;
>
>
> and then successful virThreadCreate(&thread, false,
> libxlDoMigrateReceive, args) where 'args' is unref'd, but the cookie
> isn't free'd.
>
> Certainly you wouldn't want to free the cookie and then let the thread
> use it!
\facepalm - you're right.
> So I think the libxlMigrationCookieFree needs to be done in the error:
> label and in the thread cleanup. Also after you assign @mig to
> migcookie, set 'mig = NULL';
Yeap, let me send that in a follow-up patch shortly.
The thread cleanup you mean libxlDoMigrateReceive right? There I think we could
simply move unref args to cleanup label (which would free the cookie). But
probably should go into a separate patch as it seems to be an issue to all
migration paths.
>> diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c
>> index ba1ca5c..6a7d458 100644
>> --- a/src/libxl/libxl_migration.c
>> +++ b/src/libxl/libxl_migration.c
>> @@ -637,6 +637,7 @@ libxlDomainMigrationPrepareTunnel3(virConnectPtr dconn,
>> }
>>
>> done:
>> + libxlMigrationCookieFree(mig);
>> if (vm)
>> virObjectUnlock(vm);
>>
>>
>>
>>>> + goto error;
>>>> +
>>>> + if (!(vm = virDomainObjListAdd(driver->domains, *def,
>>>> + driver->xmlopt,
>>>> + VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
>>>> + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
>>>> + NULL)))
>>>> + goto error;
>>>> +
>>>> + *def = NULL;
>>>> + priv = vm->privateData;
>>>> +
>>>> + if (taint_hook) {
>>>> + /* Domain XML has been altered by a hook script. */
>>>> + priv->hookRun = true;
>>>> + }
>>>> +
>>>> + /*
>>>> + * The data flow of tunnel3 migration in the dest side:
>>>> + * stream -> pipe -> recvfd of libxlDomainStartRestore
>>>> + */
>>>> + if (pipe(dataFD) < 0)
>>>> + goto error;
>>>> +
>>>> + /* Stream data will be written to pipeIn */
>>>> + if (virFDStreamOpen(st, dataFD[1]) < 0)
>>>> + goto error;
>>>> + dataFD[1] = -1; /* 'st' owns the FD now & will close it */
>>>> +
>>>> + if (libxlMigrationDstArgsInitialize() < 0)
>>>> + goto error;
>>>> +
>>>> + if (!(args = virObjectNew(libxlMigrationDstArgsClass)))
>>>> + goto error;
>>>> +
>>>> + args->conn = dconn;
>>>> + args->vm = vm;
>>>> + args->flags = flags;
>>>> + args->migcookie = mig;
>>>> + /* Receive from pipeOut */
>>>> + args->recvfd = dataFD[0];
>>>> + args->nsocks = 0;
>>>> + if (virThreadCreate(&thread, false, libxlDoMigrateReceive, args) < 0) {
>>>> + virReportError(VIR_ERR_OPERATION_FAILED, "%s",
>>>> + _("Failed to create thread for receiving migration data"));
>>>> + goto error;
>>>> + }
>>>> +
>>>> + ret = 0;
>>>> + goto done;
>>>> +
>>>> + error:
>>>> + VIR_FORCE_CLOSE(dataFD[1]);
>>>> + VIR_FORCE_CLOSE(dataFD[0]);
>>>> + virObjectUnref(args);
>>>> + /* Remove virDomainObj from domain list */
>>>> + if (vm) {
>>>> + virDomainObjListRemove(driver->domains, vm);
>>>> + vm = NULL;
>>>> + }
>>>> +
>>>> + done:
>>>> + if (vm)
>>>> + virObjectUnlock(vm);
>>>> +
>>>> + return ret;
>>>> +}
>>>
>>> [...]
>>>
>>>> +
>>>> +static int
>>>> +libxlMigrationStartTunnel(libxlDriverPrivatePtr driver,
>>>> + virDomainObjPtr vm,
>>>> + unsigned long flags,
>>>> + virStreamPtr st,
>>>> + struct libxlTunnelControl *tc)
>>>> +{
>>>> + libxlTunnelMigrationThread *arg = NULL;
>>>> + int ret = -1;
>>>> +
>>>> + if (VIR_ALLOC(tc) < 0)
>>>> + goto out;
>>>> +
>>>> + tc->dataFD[0] = -1;
>>>> + tc->dataFD[1] = -1;
>>>> + if (pipe(tc->dataFD) < 0) {
>>>> + virReportError(errno, "%s", _("Unable to make pipes"));
>>>
>>> Coverity notes that failures would cause a leak for @tc (I assume here
>>> and of course if virThreadCreate fails. Perhaps the 'best' way to
>>> handle that would be to set tc = NULL after ThreadCreate success and
>>> just call libxlMigrationStopTunnel in "out:"...
>>
>> But libxlMigrationStopTunnel is always called (hence should be freeing @tc),
>> whether libxlMigrationStartTunnel failed or not. How about this?
>>
>> @@ -907,8 +908,9 @@ libxlMigrationStartTunnel(libxlDriverPrivatePtr driver,
>> virDomainObjPtr vm,
>> unsigned long flags,
>> virStreamPtr st,
>> - struct libxlTunnelControl *tc)
>> + struct libxlTunnelControl **tnl)
>> {
>> + struct libxlTunnelControl *tc = *tnl;
>
> This doesn't do much... since @tc would be allocated below and *tnl
> wouldn't be updated... Thus, the following is better:
>
> if (VIR_ALLOC(tc) < 0)
> goto out;
> *tnl = tc;
>
OK.
>> libxlTunnelMigrationThread *arg = NULL;
>> int ret = -1;
>>
>> @@ -1045,7 +1047,7 @@ libxlDoMigrateP2P(libxlDriverPrivatePtr driver,
>>
>> VIR_DEBUG("Perform3 uri=%s", NULLSTR(uri_out));
>> if (flags & VIR_MIGRATE_TUNNELLED)
>> - ret = libxlMigrationStartTunnel(driver, vm, flags, st, tc);
>> + ret = libxlMigrationStartTunnel(driver, vm, flags, st, &tc);
>> else
>> ret = libxlDomainMigrationPerform(driver, vm, NULL, NULL,
>> uri_out, NULL, flags);
>>
More information about the libvir-list
mailing list