qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paul Brook <paul@codesourcery.com>
To: Amit Shah <amit.shah@redhat.com>
Cc: Juan Quintela <quintela@redhat.com>,
	qemu-devel@nongnu.org, Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v8 7/7] virtio-console: Enable port throttling when chardev is slow to consume data
Date: Mon, 6 Dec 2010 13:23:50 +0000	[thread overview]
Message-ID: <201012061323.51074.paul@codesourcery.com> (raw)
In-Reply-To: <20101206101101.GG11457@amit-x200.redhat.com>

> > As with the DMA interface added a while ago, I believe it's important to
> > get these APIs right.  Quick hacks to support limited use-cases just end
> > up needing a complete rewrite (or even worse multiple concurrent
> > APIs/implementations) once we actually start using them seriously.
> 
> Sure.  My proposal is for qemu_chr_write() to succeed all the time.  If
> the backend can block, and the caller can handle it, it can get a
> -EAGAIN (or WSAEWOULDBLOCK) return.  When the backend becomes writable,
> the chardev can call the ->writes_unblocked() callback for that caller.
> Individual callers need not bother about re-submitting partial writes,
> since the buffering can be done in common code in one place
> (qemu-char.c).

That's only OK if you assume it's OK to buffer all but one byte of the 
transmit request.

> > I'm extremely reluctant to add a new layer of buffering that is not
> > visible to ether the kernel or the device.  In practice we still need to
> > be able to split oversize requests, so handling small split requests
> > should be pretty much free.
> 
> So do you propose to propagate this -EAGAIN error all the way to the
> guest?  That won't work for older virtio guests (for virtio, host and
> guest changes will be needed).

Huh? That doesn't make any sense. The guest is already using an asyncronous 
submission mechanism.  
With a virtio device the status of a buffer becomes indeterminate once it has 
been placed into the queue. Only when it is removed from the queue do we know 
that it has completed.  The device may transfer all or part of that buffer at 
any time in between.
 
> > > > b) Store the data on the side somewhere. Tell the device all data has
> > > > been sent, and arrange for this data to be flushed before accepting
> > > > any more data. This is bad because it allows the guest to allocate
> > > > arbitrarily large[1] buffers on the host. i.e. a fairly easily
> > > > exploitable DoS attack.
> > > 
> > > With virtio-serial, this is what's in use.  The buffer is limited to
> > > the length of the vq (which is a compile-time constant) and there also
> > > is the virtio_serial_throttle_port() call that tells the guest to not
> > > send any more data to the host till the char layer indicates it's OK
> > > to send more data.
> > 
> > No.
> > 
> > Firstly you're assuming all users are virtio based. That may be all you
> > care about, but is not acceptable if you want to get this code merged.
> 
> OK, but it's assumed that once a -EAGAIN is returned, the caller will
> take appropriate actions to restrict the data sent.  Especially,
> send_all has:
> 
>     if (chr->write_blocked) {
>         /*
>          * We don't handle this situation: the caller should not send
>          * us data while we're blocked.
>          *
>          * We could buffer this data here but that'll only encourage
>          * bad behaviour on part of the callers.

>          */
>         return -1;
>     }

If you're being draconian about this then do it properly and make this an 
abort. Otherwise return -EAGAIN. Returning a random error seems like the worst 
of both worlds.  Your code results in spurious guest errors (or lost data) 
with real indication that this is actually a qemu device emulation bug.
 
> > Secondly, the virtqueue only restricts the number of direct ring buffer
> > entries. It does not restrict the quantity of data each ring entry points
> > to.
> 
> But that's entirely in guest memory, so it's limited to the amount of
> RAM that has been allocated to the guest.

Exactly. The guest can cause ram_size * nr_ports of additional host memory to 
be allocated.  Not acceptable. 

> > > > c) Return a partial write to the guest. The guest already has to
> > > > handle retries due to EAGAIN, and DMA capable devices already have
> > > > to handle partial mappings, so this doesn't seem too onerous a
> > > > requirement. This is not a new concept, it's the same as the unix
> > > > write(2)/send(2) functions.
> > > 
> > > This isn't possible with the current vq design.
> > 
> > You need to fix that then.  I'm fairly sure it must be possible as
> > virtio-blk has to handle similar problems.
> 
> This was one of the items that was debated during the lead-up to
> virtio-serial merge:  whether a write() call in the guest means data has
> been flushed out to the host chardev or if the guest has just passed it
> on to the host to take care of it.  We merged the latter approach.

Ensuring that data has actually reached the endpoint (v.s. being in a queue 
for transmission at the next available point) is a different problem, and 
probably one better solved by higher level protocols.


Char devices are fundamentally stream based devices with no frame boundaries 
(or alternatively a fixed frame size of 1 byte).

Your device only reports progress to the guest in virtqueue-entry sized 
chunks. However that places no real restrictions on how the data is passed to 
the host. You can choose to pass a single queue entry to the host in several 
smaller chunks, or even pass several queue entries to the host in a single 
request.

Paul

  reply	other threads:[~2010-12-06 13:23 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-01  9:54 [Qemu-devel] [PATCH v8 0/7] char: non-blocking writes, virtio-console flow control Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 1/7] virtio-console: Factor out common init between console and generic ports Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 2/7] char: Add a QemuChrHandlers struct to initialise chardev handlers Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 3/7] char: Introduce char_set/remove_fd_handlers() Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 4/7] char: Add framework for a 'write unblocked' callback Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 5/7] char: Update send_all() to handle nonblocking chardev write requests Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 6/7] char: Equip the unix/tcp backend to handle nonblocking writes Amit Shah
2010-12-01  9:54 ` [Qemu-devel] [PATCH v8 7/7] virtio-console: Enable port throttling when chardev is slow to consume data Amit Shah
2010-12-01 11:30   ` Paul Brook
2010-12-01 11:48     ` Amit Shah
2010-12-01 11:59       ` Paul Brook
2010-12-01 12:12         ` Amit Shah
2010-12-01 13:08           ` Paul Brook
2010-12-02  9:21             ` Amit Shah
2010-12-02 17:31               ` Paul Brook
2010-12-06  6:55                 ` Amit Shah
2010-12-06  9:35                   ` Paul Brook
2010-12-06 10:11                     ` Amit Shah
2010-12-06 13:23                       ` Paul Brook [this message]
2010-12-07  7:11                         ` Amit Shah
2010-12-08 12:56                           ` Paul Brook
2010-12-08 14:25                             ` Amit Shah
2010-12-08 16:54                               ` Paul Brook

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=201012061323.51074.paul@codesourcery.com \
    --to=paul@codesourcery.com \
    --cc=amit.shah@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).