On Tue, Aug 26, 2014 at 06:03:46PM -0400, John Ferlan wrote:


On 08/26/2014 01:03 AM, Martin Kletzander wrote:
On Mon, Aug 25, 2014 at 08:38:09PM -0400, John Ferlan wrote:
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 287a3f3..740b6ec 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3862,6 +3862,9 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
            virBufferAddLit(&opt, "virtio-blk-device");
        } else {
            virBufferAddLit(&opt, "virtio-blk-pci");
+            if (disk->iothread > 0)
+                virBufferAsprintf(&opt, ",iothread=libvirtIothread%u",
+                                  disk->iothread);

You are using the def->iothread only to format it with virtio disks,
but ... [1]

        }
        qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps);
        if (disk->event_idx &&
@@ -6614,6 +6617,31 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
}


+bool
+qemuDomainIothreadsAvailable(virDomainDefPtr def,
+                             virQEMUCapsPtr qemuCaps,
+                             virDomainDiskDefPtr disk)
+{
+    bool inuse;
+    const char *src = virDomainDiskGetSource(disk);
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD) ||
+        !def->iothreadmap) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("IOThreads not supported for this QEMU "
+                         "for disk '%s'"), src);
+        return false;
+    }
+    if (virBitmapGetBit(def->iothreadmap, disk->iothread, &inuse) || inuse) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("IOThread '%u' for disk '%s' is already "
+                         "being used"), disk->iothread, src);

Some disks may not have source set (empty cdrom drive), so it should
probably be NULLSTR(src), but I think ""IOThread '%u' used multiple
times" is more than enough.

This leads me to a code simplification idea.  If you checked
QEMU_CAPS_OBJECT_IOTHREAD when creating the iothread objects it's
enough to make virBitmapGetBit() handle NULL bitmap carefully and then
just virBitmapGetBit() the bit the same way.  And if the message does
not output the disk name (src), this whole function can be thrown away
and instead of doing:

 if (!qemuDomainIothreadsAvailable(def, qemuCaps, disk))
     goto error;

you'd do:

 if (virBitmapGetBit(def->iothreadmap, disk->iothread, &tmp) || tmp)
     virReportError(...);


I looked at the above code simplification idea and I wasn't able to see
what you were driving at.  Maybe it's my current code myopia... There's
a ditty about not being able to see the forest through the trees that
may apply for me. Maybe I'm missing something obvious - I dunno...

Beyond the obvious of if any other code passes a NULL Bitmap, the
existing code will fail miserably... Modifying GetBit/SetBit/ClearBit in
order to handle a NULL iothreadmap doesn't help the case where iothread
== 0 which I think could be the more common case.


Oh, yes, I missed a case, but anyway, nothing is wrong with reporting
it when building the command-line.  Looking back at my ideas, it seems
like a copy-paste from insomnia-driven programming book.

I've adjusted where the checks are made to within the BuildDriveDevStr
code. That way both the hotplug and regular startup will make the same
check.


Great, that way it's still in building a command-line, but applies for
hotplug too.

Just an idea, though, not a requirement ;)  If you keep it in a
separate function, though, I'd suggest checking the range and
reporting specific error, because when testing I got for example this
error:

 "IOThread '3' for disk '(null)' is already being used"

even though it clearly wasn't; I just had only 1 or 2 I/O threads
created.

+        return false;
+    }
+    return true;
+}
+
+
static int
qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
                                virCommandPtr cmd,
@@ -8055,6 +8083,13 @@ qemuBuildCommandLine(virConnectPtr conn,
                           disk->src->driverName, disk->src->path);
            goto error;
        }
+
+        /* Check iothreads relationship */
+        if (disk->iothread > 0) {
+            if (!qemuDomainIothreadsAvailable(def, qemuCaps, disk))
+                goto error;
+            ignore_value(virBitmapSetBit(def->iothreadmap, disk->iothread));
+        }
    }


[1] ... here you check it for all disks.  And it's kept in the domain
definition for all disks as well.  Maybe removing it from unsupported
disks and checking(+building) the iothreadmap could be done in
qemuDomainDefPostParse().


I'm not sure using a PostParse will work properly, especially in the
hotplug case where the disk xml is not added to the configuration yet -
the live add is attempted first and if it succeeds, then the bitmap
would need to be updated. If the configuration is to be saved, then the
on-disk config is updated. I assume that for hotplug the domain def
passed along is the "live" one that already has the map filled in for
any disks that were properly vetted at startup time.  Without the "live"
map being updated, one could add 'n' live disks to the same IOThread and
that has seemingly nothing to do with PostParse - although I may have
misfollowed things.

The other part of PostParse that's difficult is that the DevicePostParse
would probably be the place to check whether the device itself is valid
because while 'virtio' bus could be set, when does 'pci' get set?

I also note qemuDomainDefPostParse() uses virCapsPtr and not
virQEMUCapsPtr and it's seemingly tasked to primarily add things that
will be needed by the guest due to "other" found devices in the guest
XML and not to peruse through the ndisks looking to fill in a bitmap or
check for all the right configuration setting options for iothreads.

Just wasn't clear enough whether it "should be" used for this purpose.
I'm not against using it - just wasn't completely sure.


Yes, PostParse shouldn't be doing that, the iothreadmap is easier to
be created when starting the machine.  Then it's clear that live
machines have iothreadmap and persistent definitions don't.  I was
just curious whether it would make sense to error out earlier (when
defining the XML) rather then later (when starting the machine).
Unfortunately I covered that simple piece of information in a crusty
hardly readable shell.

[...]
So v2 is coming to a mailbox near you soon...


Looking forward!

Martin

Attachment: signature.asc
Description: Digital signature

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to