[libvirt] [PATCH 13/21] qemu: migration: src: qemuNBDTunnelAcceptAndPipe
John Ferlan
jferlan at redhat.com
Mon Dec 14 16:35:41 UTC 2015
On 11/18/2015 01:13 PM, Pavel Boldin wrote:
> Add qemuNBDTunnelAcceptAndPipe function that is called to handle POLLIN
> on the UNIX socket connection from the QEMU's NBD server.
>
> The function creates a pipe of a remote stream connected to the QEMU
> NBD Unix socket on destination and a local stream connected to
> the incoming connection from the source QEMU's NBD.
>
> Signed-off-by: Pavel Boldin <pboldin at mirantis.com>
> ---
> src/qemu/qemu_migration.c | 134 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 132 insertions(+), 2 deletions(-)
>
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 0682fd8..0f35c13 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -3987,6 +3987,9 @@ struct _qemuMigrationSpec {
>
> #define TUNNEL_SEND_BUF_SIZE 65536
>
> +typedef struct _qemuMigrationPipe qemuMigrationPipe;
> +typedef qemuMigrationPipe *qemuMigrationPipePtr;
> +
> typedef struct _qemuMigrationIOThread qemuMigrationIOThread;
> typedef qemuMigrationIOThread *qemuMigrationIOThreadPtr;
> struct _qemuMigrationIOThread {
> @@ -3997,9 +4000,124 @@ struct _qemuMigrationIOThread {
> virError err;
> int wakeupRecvFD;
> int wakeupSendFD;
> + qemuMigrationPipePtr pipes;
> + virConnectPtr dconn;
> + unsigned char uuid[VIR_UUID_BUFLEN];
> +};
> +
> +struct _qemuMigrationPipe {
> + qemuMigrationPipePtr next;
> + qemuMigrationIOThreadPtr data;
> + virStreamPtr local;
> + virStreamPtr remote;
> };
>
> static void
> +qemuMigrationPipeClose(qemuMigrationPipePtr pipe, bool abort)
> +{
> + virStreamEventUpdateCallback(pipe->local, 0);
> + virStreamEventUpdateCallback(pipe->remote, 0);
> +
> + if (abort) {
> + virStreamAbort(pipe->local);
> + virStreamAbort(pipe->remote);
> + } else {
> + virStreamFinish(pipe->local);
> + virStreamFinish(pipe->remote);
> + }
> +
> + virObjectUnref(pipe->local);
> + virObjectUnref(pipe->remote);
> +}
> +
Norm seems to be 2 blank lines between functions. There's only one here.
> +static qemuMigrationPipePtr
> +qemuMigrationPipeCreate(virStreamPtr local, virStreamPtr remote)
> +{
> + qemuMigrationPipePtr pipe = NULL;
> +
> + if (VIR_ALLOC(pipe) < 0)
> + goto error;
> +
> + pipe->local = local;
> + pipe->remote = remote;
> +
> + return pipe;
> +
> + error:
> + virStreamEventRemoveCallback(local);
> + virStreamEventRemoveCallback(remote);
> + VIR_FREE(pipe);
> + return NULL;
> +}
> +
but two here...
> +
> +static int
> +qemuNBDTunnelAcceptAndPipe(qemuMigrationIOThreadPtr data)
> +{
> + int fd, ret;
> + virStreamPtr local = NULL, remote = NULL;
> + qemuMigrationPipePtr pipe = NULL;
> +
> + while ((fd = accept(data->unixSock, NULL, NULL)) < 0) {
> + if (errno == EAGAIN || errno == EINTR)
> + continue;
> + virReportSystemError(
> + errno, "%s", _("failed to accept connection from qemu"));
> + goto abrt;
> + }
> +
> + if (!(local = virStreamNew(data->dconn, VIR_STREAM_NONBLOCK)))
> + goto abrt;
> +
> + if (!(remote = virStreamNew(data->dconn, VIR_STREAM_NONBLOCK)))
> + goto abrt;
> +
> + ret = virDomainMigrateOpenTunnel(data->dconn,
> + remote,
> + data->uuid,
> + VIR_MIGRATE_TUNNEL_NBD);
> +
> + if (ret < 0)
> + goto abrt;
> +
> + if (virFDStreamOpen(local, fd) < 0)
> + goto abrt;
> +
> + if (!(pipe = qemuMigrationPipeCreate(local, remote)))
> + goto abrt;
> +
> + pipe->data = data;
> + pipe->next = data->pipes;
> + data->pipes = pipe;
Didn't think too long about this insertion code, but how many times can
this happen? It's the removal code which removes them all at one time
that's just has me wondering.
> +
> + return 0;
> +
> + abrt:
> + VIR_FORCE_CLOSE(fd);
> + virStreamAbort(local);
> + virStreamAbort(remote);
> +
> + virObjectUnref(local);
> + virObjectUnref(remote);
> + return -1;
> +}
> +
back to just one blank line.
> +static void
> +qemuMigrationPipesStop(qemuMigrationPipePtr pipe, bool abort)
> +{
> + qemuMigrationPipePtr tmp;
> +
> + while (pipe) {
> + tmp = pipe->next;
> +
> + qemuMigrationPipeClose(pipe, abort);
> + VIR_FREE(pipe);
> +
> + pipe = tmp;
> + }
> +}
> +
And again only 1 line...
> +static void
> qemuMigrationIOFunc(void *arg)
> {
> qemuMigrationIOThreadPtr data = arg;
> @@ -4081,9 +4199,14 @@ qemuMigrationIOFunc(void *arg)
> break;
> }
> }
> +
> + if (fds[2].revents & (POLLIN | POLLERR | POLLHUP) &&
> + qemuNBDTunnelAcceptAndPipe(data) < 0)
> + goto abrt;
This would only seem to be necessary if we have a dconn && uuid set...
> }
>
> virStreamFinish(data->qemuStream);
> + qemuMigrationPipesStop(data->pipes, false);
>
> VIR_FORCE_CLOSE(data->qemuSock);
> VIR_FREE(buffer);
> @@ -4097,6 +4220,7 @@ qemuMigrationIOFunc(void *arg)
> err = NULL;
> }
> virStreamAbort(data->qemuStream);
> + qemuMigrationPipesStop(data->pipes, true);
> if (err) {
> virSetError(err);
> virFreeError(err);
Looks like we can get to error: from within the polling loop, but we
don't use qemuMigrationPipesStop there
> @@ -4114,7 +4238,9 @@ qemuMigrationIOFunc(void *arg)
>
>
> static qemuMigrationIOThreadPtr
> -qemuMigrationStartTunnel(virStreamPtr qemuStream)
> +qemuMigrationStartTunnel(virStreamPtr qemuStream,
> + virConnectPtr dconn,
> + unsigned char uuid[VIR_UUID_BUFLEN])
Again the "const unsigned char *uuid"
So what happens when we don't have nbd disks to migrate? Do we really
need to have dconn and uuid? Seems that is the assumption...
> {
> qemuMigrationIOThreadPtr io = NULL;
> int wakeupFD[2] = { -1, -1 };
> @@ -4132,6 +4258,8 @@ qemuMigrationStartTunnel(virStreamPtr qemuStream)
> io->qemuSock = io->unixSock = -1;
> io->wakeupRecvFD = wakeupFD[0];
> io->wakeupSendFD = wakeupFD[1];
> + io->dconn = dconn;
> + memcpy(io->uuid, uuid, VIR_UUID_BUFLEN);
>
> if (virThreadCreate(&io->thread, true,
> qemuMigrationIOFunc,
> @@ -4337,7 +4465,9 @@ qemuMigrationRun(virQEMUDriverPtr driver,
> VIR_WARN("unable to provide data for graphics client relocation");
>
> if (spec->fwdType != MIGRATION_FWD_DIRECT) {
> - if (!(iothread = qemuMigrationStartTunnel(spec->fwd.stream)))
> + if (!(iothread = qemuMigrationStartTunnel(spec->fwd.stream,
> + dconn,
> + mig->uuid)))
So this will only matter if we have mig->nbd, migrate_flags &
(*DISK|*INC), true? An assumption that's not always true I would think.
And thus the 'need' to start things up with that enabled is unnecessary.
Seems you'd want to keep qemuMigrationStartTunnel as is, then if/when we
known we're going to have this functionality have a "set" function for
dconn && uuid... prior to of course setting the nbd_tunnel* in iothread.
John
FWIW: I'm going to stop here. I've got a backlog of other things to look
at right now and it seems the next one makes things even a bit more
complicated... Plus as I said in my .0 response - starting at patch 16
I wasn't able to apply the changes.
> goto cancel;
>
> if (nmigrate_disks &&
>
More information about the libvir-list
mailing list