* [Qemu-devel] [PATCH v2 0/2] qga: flush explicitly when needed
@ 2015-11-24 18:04 marcandre.lureau
2015-11-24 18:04 ` [Qemu-devel] [PATCH v2 1/2] " marcandre.lureau
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: marcandre.lureau @ 2015-11-24 18:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau, mdroth
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Without this change, a write() followed by a read() may lose the
previously written content, as shown in the following test.
v1->v2:
- replace guchar with unsigned char
- fix implicitly/explictly
- comment space fix
Marc-André Lureau (2):
qga: flush explicitly when needed
tests: add file-write-read test
qga/commands-posix.c | 22 ++++++++++++
tests/test-qga.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 115 insertions(+), 2 deletions(-)
--
2.5.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v2 1/2] qga: flush explicitly when needed
2015-11-24 18:04 [Qemu-devel] [PATCH v2 0/2] qga: flush explicitly when needed marcandre.lureau
@ 2015-11-24 18:04 ` marcandre.lureau
2015-11-24 20:56 ` 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:47 ` [Qemu-devel] [PATCH for-2.5 v2 0/2] qga: flush explicitly when needed Eric Blake
2 siblings, 1 reply; 8+ messages in thread
From: marcandre.lureau @ 2015-11-24 18:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau, mdroth
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;
+ }
+
buf = g_base64_decode(buf_b64, &buf_len);
if (!has_count) {
--
2.5.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] tests: add file-write-read test
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 18:04 ` 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
2 siblings, 1 reply; 8+ messages in thread
From: marcandre.lureau @ 2015-11-24 18:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau, mdroth
From: Marc-André Lureau <marcandre.lureau@redhat.com>
This test exhibits a POSIX behaviour regarding switching between write
and read. It's undefined result if the application doesn't ensure a
flush between the two operations (with glibc, the flush can be implicit
when the buffer size is relatively small). The previous commit fixes
this test.
Related to:
https://bugzilla.redhat.com/show_bug.cgi?id=1210246
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-qga.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 93 insertions(+), 2 deletions(-)
diff --git a/tests/test-qga.c b/tests/test-qga.c
index 6473846..3b99d9d 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -352,10 +352,10 @@ static void test_qga_network_get_interfaces(gconstpointer fix)
static void test_qga_file_ops(gconstpointer fix)
{
const TestFixture *fixture = fix;
- const guchar helloworld[] = "Hello World!\n";
+ const unsigned char helloworld[] = "Hello World!\n";
const char *b64;
gchar *cmd, *path, *enc;
- guchar *dec;
+ unsigned char *dec;
QDict *ret, *val;
int64_t id, eof;
gsize count;
@@ -496,6 +496,96 @@ static void test_qga_file_ops(gconstpointer fix)
g_free(cmd);
}
+static void test_qga_file_write_read(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ const unsigned char helloworld[] = "Hello World!\n";
+ const char *b64;
+ gchar *cmd, *enc;
+ QDict *ret, *val;
+ int64_t id, eof;
+ gsize count;
+
+ /* open */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
+ " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ id = qdict_get_int(ret, "return");
+ QDECREF(ret);
+
+ enc = g_base64_encode(helloworld, sizeof(helloworld));
+ /* write */
+ cmd = g_strdup_printf("{'execute': 'guest-file-write',"
+ " 'arguments': { 'handle': %" PRId64 ","
+ " 'buf-b64': '%s' } }", id, enc);
+ ret = qmp_fd(fixture->fd, cmd);
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ g_assert_cmpint(eof, ==, 0);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* read (check implicit flush) */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, 0);
+ g_assert(eof);
+ g_assert_cmpstr(b64, ==, "");
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* seek to 0 */
+ cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
+ " 'arguments': { 'handle': %" PRId64 ", "
+ " 'offset': %d, 'whence': %d } }",
+ id, 0, SEEK_SET);
+ ret = qmp_fd(fixture->fd, cmd);
+ qmp_assert_no_error(ret);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "position");
+ eof = qdict_get_bool(val, "eof");
+ g_assert_cmpint(count, ==, 0);
+ g_assert(!eof);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* read */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ g_assert(eof);
+ g_assert_cmpstr(b64, ==, enc);
+ QDECREF(ret);
+ g_free(cmd);
+ g_free(enc);
+
+ /* close */
+ cmd = g_strdup_printf("{'execute': 'guest-file-close',"
+ " 'arguments': {'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ QDECREF(ret);
+ g_free(cmd);
+}
+
static void test_qga_get_time(gconstpointer fix)
{
const TestFixture *fixture = fix;
@@ -762,6 +852,7 @@ int main(int argc, char **argv)
g_test_add_data_func("/qga/get-memory-blocks", &fix,
test_qga_get_memory_blocks);
g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops);
+ g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
g_test_add_data_func("/qga/fsfreeze-status", &fix,
--
2.5.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/2] tests: add file-write-read test
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
0 siblings, 0 replies; 8+ messages in thread
From: Eric Blake @ 2015-11-24 20:46 UTC (permalink / raw)
To: marcandre.lureau, qemu-devel; +Cc: mdroth
[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]
On 11/24/2015 11:04 AM, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> This test exhibits a POSIX behaviour regarding switching between write
> and read. It's undefined result if the application doesn't ensure a
> flush between the two operations (with glibc, the flush can be implicit
> when the buffer size is relatively small). The previous commit fixes
> this test.
>
> Related to:
> https://bugzilla.redhat.com/show_bug.cgi?id=1210246
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> tests/test-qga.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 93 insertions(+), 2 deletions(-)
> +
> + /* seek to 0 */
> + cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
> + " 'arguments': { 'handle': %" PRId64 ", "
> + " 'offset': %d, 'whence': %d } }",
> + id, 0, SEEK_SET);
If my patch goes in first, you'll want this to be s/SEEK_SET/0/ to
match. (If yours goes in first, I'll spin a v2 of my patch to cover all
sites in the testsuite that need munging).
https://lists.gnu.org/archive/html/qemu-devel/2015-11/msg05454.html
With that figured out,
Reviewed-by: Eric Blake <eblake@redhat.com>
--
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 --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH for-2.5 v2 0/2] qga: flush explicitly when needed
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 18:04 ` [Qemu-devel] [PATCH v2 2/2] tests: add file-write-read test marcandre.lureau
@ 2015-11-24 20:47 ` Eric Blake
2 siblings, 0 replies; 8+ messages in thread
From: Eric Blake @ 2015-11-24 20:47 UTC (permalink / raw)
To: marcandre.lureau, qemu-devel; +Cc: mdroth
[-- Attachment #1: Type: text/plain, Size: 952 bytes --]
On 11/24/2015 11:04 AM, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Without this change, a write() followed by a read() may lose the
> previously written content, as shown in the following test.
>
> v1->v2:
> - replace guchar with unsigned char
> - fix implicitly/explictly
> - comment space fix
Counts as a bug fix, so I'm suggesting that this series goes in 2.5;
although the behavior itself has been broken for a longer time so it is
not critical if it stalls until 2.6.
>
> Marc-André Lureau (2):
> qga: flush explicitly when needed
> tests: add file-write-read test
>
> qga/commands-posix.c | 22 ++++++++++++
> tests/test-qga.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 115 insertions(+), 2 deletions(-)
>
--
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 --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] qga: flush explicitly when needed
2015-11-24 18:04 ` [Qemu-devel] [PATCH v2 1/2] " marcandre.lureau
@ 2015-11-24 20:56 ` Eric Blake
2015-11-24 22:19 ` Michael Roth
0 siblings, 1 reply; 8+ messages in thread
From: Eric Blake @ 2015-11-24 20:56 UTC (permalink / raw)
To: marcandre.lureau, qemu-devel; +Cc: mdroth
[-- 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 --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] qga: flush explicitly when needed
2015-11-24 20:56 ` Eric Blake
@ 2015-11-24 22:19 ` Michael Roth
2015-11-24 22:28 ` Eric Blake
0 siblings, 1 reply; 8+ messages in thread
From: Michael Roth @ 2015-11-24 22:19 UTC (permalink / raw)
To: Eric Blake, marcandre.lureau, qemu-devel
Quoting Eric Blake (2015-11-24 14:56:15)
> 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?
I think that would be prudent. !gfh->writing doesn't imply gfh->reading,
and failed calls to qmp_guest_file_read() should probably not set
gfh->writing to true either.
Maybe something like:
gfh->rw_state = RW_STATE_NEW | RW_STATE_READING | RW_STATE_WRITING, skip the
fseek()/fflush() on RW_NEW, and only move to RW_STATE_READING/WRITING when
fread()/fwrite(), respectively, actually succeed?
I guess that still leaves the possibility of writes failing after reads
on non-seekable files. Are such files always directional? Otherwise that
means there are cases where it's impossible to implement the
requirements of the spec.
>
> --
> Eric Blake eblake redhat com +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] qga: flush explicitly when needed
2015-11-24 22:19 ` Michael Roth
@ 2015-11-24 22:28 ` Eric Blake
0 siblings, 0 replies; 8+ messages in thread
From: Eric Blake @ 2015-11-24 22:28 UTC (permalink / raw)
To: Michael Roth, marcandre.lureau, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 2361 bytes --]
On 11/24/2015 03:19 PM, Michael Roth wrote:
>> 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?
>
> I think that would be prudent. !gfh->writing doesn't imply gfh->reading,
> and failed calls to qmp_guest_file_read() should probably not set
> gfh->writing to true either.
>
> Maybe something like:
>
> gfh->rw_state = RW_STATE_NEW | RW_STATE_READING | RW_STATE_WRITING, skip the
> fseek()/fflush() on RW_NEW, and only move to RW_STATE_READING/WRITING when
> fread()/fwrite(), respectively, actually succeed?
Additionally, if guest-file-seek succeeds, reset state to RW_STATE_NEW
(any user-triggered seek satisfies the requirement so that we don't need
our implicit seek).
>
> I guess that still leaves the possibility of writes failing after reads
> on non-seekable files. Are such files always directional? Otherwise that
> means there are cases where it's impossible to implement the
> requirements of the spec.
Remember, /dev/tty is commonly opened for both reading and writing - but
via separate fds (you read from fd 0, write to fd 1) - and it is the
console or terminal emulator that sets up the initial things (you seldom
see scripts directly attempting a bi-directional 'exec <> /dev/tty'. I
think we'll be okay on that front. Or if we're paranoid, then have
guest-file-seek inspect errno - if seek failed due to ESPIPE, then the
file is non-seekable, stdio shouldn't be buffering anyways, and we can
just blindly force RW_STATE_NEW in that case (the real reason for
fflush/fseek between read/write transitions is for 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 --]
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-11-24 22:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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
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).