All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: Ladi Prosek <lprosek@redhat.com>
Cc: "Daniel P. Berrange" <berrange@redhat.com>,
	qemu-devel <qemu-devel@nongnu.org>,
	mdroth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH] qga: implement guest-file-ioctl
Date: Thu, 02 Feb 2017 12:05:30 +0100	[thread overview]
Message-ID: <87h94c6ef9.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <CABdb737yd8ookNxet=Rp7b6-fux6iiBiS7KrrddtZ2EZVPFKqg@mail.gmail.com> (Ladi Prosek's message of "Wed, 1 Feb 2017 14:41:01 +0100")

Ladi Prosek <lprosek@redhat.com> writes:

> On Wed, Feb 1, 2017 at 12:03 PM, Daniel P. Berrange <berrange@redhat.com> wrote:
>> On Wed, Feb 01, 2017 at 11:50:43AM +0100, Ladi Prosek wrote:
>>> On Wed, Feb 1, 2017 at 11:20 AM, Daniel P. Berrange <berrange@redhat.com> wrote:
>>> > On Wed, Feb 01, 2017 at 11:06:46AM +0100, Ladi Prosek wrote:
>>> >> Analogous to guest-file-read and guest-file-write, this commit adds
>>> >> support for issuing IOCTLs to files in the guest. With the goal of
>>> >> abstracting away the differences between Posix ioctl() and Win32
>>> >> DeviceIoControl() to provide one unified API, the schema distinguishes
>>> >> between input and output buffer sizes (as required by Win32) and
>>> >> allows the caller to supply either a 'buffer', pointer to which will
>>> >> be passed to the Posix ioctl(), or an integer argument, passed to
>>> >> ioctl() directly.
>>> >
>>> > What is the intended usage scenario for this ?
>>>
>>> My specific case is extracting a piece of data from Windows guests.
>>> Guest driver exposes a file object with a well-known IOCTL code to
>>> return a data structure from the kernel.
>>
>> Please provide more information about what you're trying to do.
>>
>> If we can understand the full details it might suggest a different
>> approach that exposing a generic ioctl passthrough facility.
>
> The end goal is to be able to create a Window crash dump file from a
> running (or crashed, but running is more interesting because Windows
> can't do that by itself) Windows VM. To do that without resorting to
> hacks, the host application driving this needs to get the crash dump
> header, which Windows provides in its KeInitializeCrashDumpHeader
> kernel API.
>
> I believe that the most natural way to do this is to have
> 1) a driver installed in the guest providing a way to call
> KeInitializeCrashDumpHeader from user space
> 2) an agent in the guest, running in user space, calling the driver
> and passing the result back to the host
>
> Now 2) may as well be an existing agent, such as the QEMU guest agent,
> and that's why I am here :)

Makes sense.

> KeInitializeCrashDumpHeader returns an opaque byte array, happens to
> be 8192 bytes at the moment. My first choice for the kernel-user
> interface in the guest is IOCTL because what I'm trying to get across
> is a block, a "datagram", not a stream, and I have the option for
> easily adding more functionality later by adding more IOCTL codes with
> the file object still representing "the driver".

ioctl() is the traditional way to do something like this.

In Linux, you might well be asked to do a pseudo-file in /sys instead.

> I could use regular file I/O as well. I would either have to devise a
> protocol for talking to the driver, have a way of delimiting messages,
> re-syncing the channel etc.,

Way too much trouble.

>                              or make a slight semantic shift and
> instead of the file object representing the driver, it would represent
> this one particular function of the driver. Opening the file and
> reading from it until eof would yield the crash dump header.

Or even simpler: read(fd, buf, n) always returns the first @n bytes of
the crash dump header.  If you want to detect a size that doesn't match
your expectations, pass a slightly larger buffer.

>>> > The size of arguments that need to be provided to ioctl()s vary on
>>> > the architecture of the guest kernel that's running, which cannot be
>>> > assumed to be the same as the architecture of the QEMU binary. ie
>>> > you can be running i686 kernel in an x86_64 QEMU.  So it feels like
>>> > it is going to be hard for applications to reliably use this feature
>>> > unless they have more information about the guest OS, that is not
>>> > currently provided by QEMU guest agent. So it feels like this design
>>> > is not likely to be satisfactory to me.
>>>
>>> I can turn this around and say that guest-file-read and
>>> guest-file-write shouldn't exist because applications can't reliably
>>> know what the format of files on the guest is.
>>
>> No that's not the same thing at all. From the POV of the QEMU API, the
>> contents of the files do not matter - it is just a byte stream and the
>> guest agent API lets you read it in the same way no matter what is in
>> the files, or what OS is running. There's no need to know anything about
>> the guest OS in order to successfully read/write the entire file.
>
> Ok, so there are two different aspects that should probably be
> separated. The actual semantics of IOCTL calls is equivalent to the
> semantics of files in general. For files it's stream in, stream out
> (and seeking and such). For IOCTL it's a buffer in, buffer out (and a
> return code). The content is file specific, IOCTL code specific,
> whatever. Definitely not guest agent's business to interpret it. Here
> I think my analogy holds.

"Everything is a file".  Many times we made something not a file we
regretted it later.

>> The ioctl design you've proposed here is different because you need to
>> know precise operating system details before you can use the API. I
>> think that's really flawed.
>
> Yes, maybe. Maybe the concept of the IOCTL syscall is just too
> different across the guest operating systems supported by the agent. I
> tried to abstract away the differences between Posix and Windows.
> Perhaps I didn't do it right or there's more OSes to worry about. Yes,
> in theory the data passed to or from IOCTL may contain pointers and
> not be easily remotable. But it's not common. Files can also be opened
> with all kinds of obscure flags on different OSes, many of which are
> not supported by guest-file-open.

ioctl() is an ugly low-level interface, which makes it awkward to pass
through QGA.

Your point that we strip away details of the file I/O interfaces for QGA
is valid.  I wouldn't rule out the possibility of a suitably limited
ioctl() pass through out of hand.  But we'd probably want more than one
use case to demonstrate that it's useful despite the limitations.

>> It would be possible to design a ioctl API that is more usable if you
>> didn't try to do generic passthrough of arbitrary ioctl commands. Instead
>> provide a QAPI schema that uses a union to provide strongly typed arguments
>> for the ioctl commands you care about using. Or completely separate QAPI
>> commands instead of multiplexing everything into an ioctl command.
>
> I can add a QAPI command for my specific use case if it's acceptable,
> that's not a problem. Although at that point I would probably just go
> back to my plan b and use regular file I/O and guest-file-read. I just
> wanted to be as generic as possible to benefit other use cases as well
> and I ended up with what's basically my stab at RPC ioctl.

I appreciate you trying to provide something that's generally useful
instead of just hacking up a one-off that works four your special
problem.

Of course, designing a generally useful thing can sometimes be more
trouble than it's worth.  Use your judgement.

  parent reply	other threads:[~2017-02-02 11:05 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-01 10:06 [Qemu-devel] [PATCH] qga: implement guest-file-ioctl Ladi Prosek
2017-02-01 10:20 ` Daniel P. Berrange
2017-02-01 10:50   ` Ladi Prosek
2017-02-01 11:03     ` Daniel P. Berrange
2017-02-01 13:41       ` Ladi Prosek
2017-02-01 14:43         ` Eric Blake
2017-02-01 15:43           ` Ladi Prosek
2017-02-01 20:24           ` Paolo Bonzini
2017-02-02 11:05         ` Markus Armbruster [this message]
2017-02-06 15:37         ` Denis V. Lunev
2017-02-06 15:50           ` Daniel P. Berrange
2017-02-06 15:50           ` Ladi Prosek
2017-02-06 16:10             ` Alexey Kostyushko
2017-02-07 13:16               ` Ladi Prosek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87h94c6ef9.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=lprosek@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.