From: Eric Blake <eblake@redhat.com>
To: marcandre.lureau@redhat.com, qemu-devel@nongnu.org
Cc: mdroth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH v2 1/2] qga: flush explicitly when needed
Date: Tue, 24 Nov 2015 13:56:15 -0700 [thread overview]
Message-ID: <5654CEEF.1040102@redhat.com> (raw)
In-Reply-To: <1448388281-18691-2-git-send-email-marcandre.lureau@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 3154 bytes --]
On 11/24/2015 11:04 AM, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> According to the specification:
> http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html
>
> "the application shall ensure that output is not directly followed by
> input without an intervening call to fflush() or to a file positioning
> function (fseek(), fsetpos(), or rewind()), and input is not directly
> followed by output without an intervening call to a file positioning
> function, unless the input operation encounters end-of-file."
>
> Without this change, a write() followed by a read() may lose the
> previously written content, as shown in the following test.
>
> Fixes:
> https://bugzilla.redhat.com/show_bug.cgi?id=1210246
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> qga/commands-posix.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index 0ebd473..d0228ce 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -219,6 +219,7 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
> typedef struct GuestFileHandle {
> uint64_t id;
> FILE *fh;
> + bool writing;
> QTAILQ_ENTRY(GuestFileHandle) next;
> } GuestFileHandle;
>
> @@ -460,6 +461,17 @@ struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
> }
>
> fh = gfh->fh;
> +
> + /* explicitly flush when switching from writing to reading */
> + if (gfh->writing) {
> + int ret = fflush(fh);
> + if (ret == EOF) {
> + error_setg_errno(errp, errno, "failed to flush file");
> + return NULL;
> + }
> + gfh->writing = false;
> + }
> +
> buf = g_malloc0(count+1);
> read_count = fread(buf, 1, count, fh);
> if (ferror(fh)) {
> @@ -496,6 +508,16 @@ GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
> }
>
> fh = gfh->fh;
> +
> + if (!gfh->writing) {
> + int ret = fseek(fh, 0, SEEK_CUR);
> + if (ret == -1) {
> + error_setg_errno(errp, errno, "failed to seek file");
> + return NULL;
> + }
> + gfh->writing = true;
> + }
Hmm. This always attempts fseek() on the first write() to a file, even
if the file is not also open for read. While guest-file-open is most
likely used on regular files (and therefore seekable), I'm worried that
we might have a client that is attempting to use it on terminal files or
other non-seekable file names. Since the fseek() on first write is
unconditional, that means we would now fail to let a user write to such
a file, even if they could previously do so. Should we add more logic
to only do the fseek() after a previous write (as in a tri-state
variable of untouched, last written, last read), so that we aren't
breaking one-pass usage of non-seekable files?
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
next prev parent reply other threads:[~2015-11-24 20:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-24 18:04 [Qemu-devel] [PATCH v2 0/2] qga: flush explicitly when needed marcandre.lureau
2015-11-24 18:04 ` [Qemu-devel] [PATCH v2 1/2] " marcandre.lureau
2015-11-24 20:56 ` Eric Blake [this message]
2015-11-24 22:19 ` Michael Roth
2015-11-24 22:28 ` Eric Blake
2015-11-24 18:04 ` [Qemu-devel] [PATCH v2 2/2] tests: add file-write-read test marcandre.lureau
2015-11-24 20:46 ` Eric Blake
2015-11-24 20:47 ` [Qemu-devel] [PATCH for-2.5 v2 0/2] qga: flush explicitly when needed Eric Blake
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=5654CEEF.1040102@redhat.com \
--to=eblake@redhat.com \
--cc=marcandre.lureau@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.