From: Stefan Weil <sw@weilnetz.de>
To: Andrew Baumann <Andrew.Baumann@microsoft.com>, qemu-devel@nongnu.org
Cc: Jason Wang <jasowang@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 2/2] tap-win32: disable broken async write path
Date: Wed, 18 Nov 2015 08:39:37 +0100 [thread overview]
Message-ID: <564C2B39.7080500@weilnetz.de> (raw)
In-Reply-To: <1447787363-15216-3-git-send-email-Andrew.Baumann@microsoft.com>
Am 17.11.2015 um 20:09 schrieb Andrew Baumann:
> The code under the TUN_ASYNCHRONOUS_WRITES path makes two incorrect
> assumptions about the behaviour of the WriteFile API for overlapped
> file handles. First, WriteFile does not update the
> lpNumberOfBytesWritten parameter when the overlapped parameter is
> non-NULL (the number of bytes written is known only when the operation
> completes). Second, the buffer shouldn't be touched (or freed) until
> the operation completes. This led to at least one bug where
> tap_win32_write returned zero bytes written, which in turn caused
> further writes ("receives") to be disabled for that device.
>
> This change disables the asynchronous write path, while keeping most
> of the code around in case someone sees value in resurrecting it. It
> also adds some conditional debug output, similar to the read path.
>
> Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> ---
> Although this version of the patch tries to be minimally invasive and
> keep the code around, I'm not sure if there is much value in fixing
> this -- I haven't checked, but would expect that the write to a tap
> device is just a fairly fast buffer copy. If you would prefer a patch
> that simply removes the async write support entirely, that should be
> easy to do.
>
> net/tap-win32.c | 48 +++++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 37 insertions(+), 11 deletions(-)
>
> diff --git a/net/tap-win32.c b/net/tap-win32.c
> index 5e5d6db..02a3b0d 100644
> --- a/net/tap-win32.c
> +++ b/net/tap-win32.c
> @@ -77,7 +77,12 @@
>
> //#define DEBUG_TAP_WIN32
>
> -#define TUN_ASYNCHRONOUS_WRITES 1
> +/* FIXME: The asynch write path appears to be broken at
> + * present. WriteFile() ignores the lpNumberOfBytesWritten parameter
> + * for overlapped writes, with the result we return zero bytes sent,
> + * and after handling a single packet, receive is disabled for this
> + * interface. */
> +/* #define TUN_ASYNCHRONOUS_WRITES 1 */
>
> #define TUN_BUFFER_SIZE 1560
> #define TUN_MAX_BUFFER_COUNT 32
> @@ -461,26 +466,47 @@ static int tap_win32_write(tap_win32_overlapped_t *overlapped,
> BOOL result;
> DWORD error;
>
> +#ifdef TUN_ASYNCHRONOUS_WRITES
> result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
> &write_size, FALSE);
>
> if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
> WaitForSingleObject(overlapped->write_event, INFINITE);
> +#endif
>
> result = WriteFile(overlapped->handle, buffer, size,
> - &write_size, &overlapped->write_overlapped);
> + NULL, &overlapped->write_overlapped);
> +
> +#ifdef TUN_ASYNCHRONOUS_WRITES
> + /* FIXME: we can't sensibly set write_size here, without waiting
> + * for the IO to complete! Moreover, we can't return zero,
> + * because that will disable receive on this interface, and we
> + * also can't assume it will succeed and return the full size,
> + * because that will result in the buffer being reclaimed while
> + * the IO is in progress. */
> +#error Async writes are broken. Please disable TUN_ASYNCHRONOUS_WRITES.
> +#else /* !TUN_ASYNCHRONOUS_WRITES */
> + if (!result) {
> + error = GetLastError();
> + if (error == ERROR_IO_PENDING) {
> + result = GetOverlappedResult(overlapped->handle,
> + &overlapped->write_overlapped,
> + &write_size, TRUE);
> + }
> + }
> +#endif
>
> if (!result) {
> - switch (error = GetLastError())
> - {
> - case ERROR_IO_PENDING:
> -#ifndef TUN_ASYNCHRONOUS_WRITES
> - WaitForSingleObject(overlapped->write_event, INFINITE);
> +#ifdef DEBUG_TAP_WIN32
> + LPVOID msgbuf;
Does this also work ...
char *msgbuf;
> + error = GetLastError();
> + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
> + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
> + (LPTSTR)&msgbuf, 0, NULL);
... and remove the type cast here? If it works without compiler
warnings, I'd prefer that variant.
> + fprintf(stderr, "Tap-Win32: Error WriteFile %d - %s\n", error, msgbuf);
> + LocalFree(msgbuf);
> #endif
> - break;
> - default:
> - return -1;
> - }
> + return 0;
> }
>
> return write_size;
Otherwise, the patch looks good, but I currently cannot test it.
Stefan
next prev parent reply other threads:[~2015-11-18 7:39 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-17 19:09 [Qemu-devel] [PATCH 0/2] net/tap-win32 bugfixes Andrew Baumann
2015-11-17 19:09 ` [Qemu-devel] [PATCH 1/2] tap-win32: skip unexpected nodes during registry enumeration Andrew Baumann
2015-11-18 7:25 ` Stefan Weil
2015-11-17 19:09 ` [Qemu-devel] [PATCH 2/2] tap-win32: disable broken async write path Andrew Baumann
2015-11-18 7:39 ` Stefan Weil [this message]
2015-11-18 18:33 ` Andrew Baumann
2015-11-18 2:07 ` [Qemu-devel] [PATCH 0/2] net/tap-win32 bugfixes Jason Wang
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=564C2B39.7080500@weilnetz.de \
--to=sw@weilnetz.de \
--cc=Andrew.Baumann@microsoft.com \
--cc=jasowang@redhat.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 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).