mirror of https://github.com/xqemu/xqemu.git
migration: ensure qemu_fflush() always writes full data amount
The QEMUFile writev_buffer / put_buffer functions are expected to write out the full set of requested data, blocking until complete. The qemu_fflush() caller does not expect to deal with partial writes. Clarify the function comments and add a sanity check to the code to catch mistaken implementations. Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Message-Id: <1461751518-12128-5-git-send-email-berrange@redhat.com> Signed-off-by: Amit Shah <amit.shah@redhat.com>
This commit is contained in:
parent
a8ec4437cd
commit
baf51e7739
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
/* This function writes a chunk of data to a file at the given position.
|
/* This function writes a chunk of data to a file at the given position.
|
||||||
* The pos argument can be ignored if the file is only being used for
|
* The pos argument can be ignored if the file is only being used for
|
||||||
* streaming. The handler should try to write all of the data it can.
|
* streaming. The handler must write all of the data or return a negative
|
||||||
|
* errno value.
|
||||||
*/
|
*/
|
||||||
typedef ssize_t (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
|
typedef ssize_t (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
|
||||||
int64_t pos, size_t size);
|
int64_t pos, size_t size);
|
||||||
|
@ -54,7 +55,8 @@ typedef int (QEMUFileCloseFunc)(void *opaque);
|
||||||
typedef int (QEMUFileGetFD)(void *opaque);
|
typedef int (QEMUFileGetFD)(void *opaque);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function writes an iovec to file.
|
* This function writes an iovec to file. The handler must write all
|
||||||
|
* of the data or return a negative errno value.
|
||||||
*/
|
*/
|
||||||
typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
|
typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
|
||||||
int iovcnt, int64_t pos);
|
int iovcnt, int64_t pos);
|
||||||
|
|
|
@ -108,11 +108,13 @@ bool qemu_file_is_writable(QEMUFile *f)
|
||||||
* Flushes QEMUFile buffer
|
* Flushes QEMUFile buffer
|
||||||
*
|
*
|
||||||
* If there is writev_buffer QEMUFileOps it uses it otherwise uses
|
* If there is writev_buffer QEMUFileOps it uses it otherwise uses
|
||||||
* put_buffer ops.
|
* put_buffer ops. This will flush all pending data. If data was
|
||||||
|
* only partially flushed, it will set an error state.
|
||||||
*/
|
*/
|
||||||
void qemu_fflush(QEMUFile *f)
|
void qemu_fflush(QEMUFile *f)
|
||||||
{
|
{
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
ssize_t expect = 0;
|
||||||
|
|
||||||
if (!qemu_file_is_writable(f)) {
|
if (!qemu_file_is_writable(f)) {
|
||||||
return;
|
return;
|
||||||
|
@ -120,21 +122,27 @@ void qemu_fflush(QEMUFile *f)
|
||||||
|
|
||||||
if (f->ops->writev_buffer) {
|
if (f->ops->writev_buffer) {
|
||||||
if (f->iovcnt > 0) {
|
if (f->iovcnt > 0) {
|
||||||
|
expect = iov_size(f->iov, f->iovcnt);
|
||||||
ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
|
ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (f->buf_index > 0) {
|
if (f->buf_index > 0) {
|
||||||
|
expect = f->buf_index;
|
||||||
ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
|
ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
f->pos += ret;
|
f->pos += ret;
|
||||||
}
|
}
|
||||||
|
/* We expect the QEMUFile write impl to send the full
|
||||||
|
* data set we requested, so sanity check that.
|
||||||
|
*/
|
||||||
|
if (ret != expect) {
|
||||||
|
qemu_file_set_error(f, ret < 0 ? ret : -EIO);
|
||||||
|
}
|
||||||
f->buf_index = 0;
|
f->buf_index = 0;
|
||||||
f->iovcnt = 0;
|
f->iovcnt = 0;
|
||||||
if (ret < 0) {
|
|
||||||
qemu_file_set_error(f, ret);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
|
void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
|
||||||
|
|
Loading…
Reference in New Issue