Commit 871d2f079661323a7645b388eb5ae8d7eeb3117c

Authored by aliguori
1 parent 7526aa2d

Fix some issues with QEMUFile

This patch allows QEMUFile's read and write operations to return 
negative error codes.  This is necessary to detect things like closed 
streams during live migration.

It also removes unused code for QEMUFileFD write path.  Finally, it 
makes sure to avoid attempting to flush an output buffer if the file
is only being used for input.  This was spotted by Uri Lublin.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5474 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 82 additions and 45 deletions
... ... @@ -11,8 +11,8 @@
11 11 * The pos argument can be ignored if the file is only being used for
12 12 * streaming. The handler should try to write all of the data it can.
13 13 */
14   -typedef void (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
15   - int64_t pos, int size);
  14 +typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
  15 + int64_t pos, int size);
16 16  
17 17 /* Read a chunk of data from a file at the given position. The pos argument
18 18 * can be ignored if the file is only be used for streaming. The number of
... ... @@ -64,6 +64,7 @@ unsigned int qemu_get_be16(QEMUFile *f);
64 64 unsigned int qemu_get_be32(QEMUFile *f);
65 65 uint64_t qemu_get_be64(QEMUFile *f);
66 66 int qemu_file_rate_limit(QEMUFile *f);
  67 +int qemu_file_has_error(QEMUFile *f);
67 68  
68 69 /* Try to send any outstanding data. This function is useful when output is
69 70 * halted due to rate limiting or EAGAIN errors occur as it can be used to
... ...
... ... @@ -6197,12 +6197,15 @@ struct QEMUFile {
6197 6197 QEMUFileCloseFunc *close;
6198 6198 QEMUFileRateLimit *rate_limit;
6199 6199 void *opaque;
  6200 + int is_write;
6200 6201  
6201 6202 int64_t buf_offset; /* start of buffer when writing, end of buffer
6202 6203 when reading */
6203 6204 int buf_index;
6204 6205 int buf_size; /* 0 when writing */
6205 6206 uint8_t buf[IO_BUF_SIZE];
  6207 +
  6208 + int has_error;
6206 6209 };
6207 6210  
6208 6211 typedef struct QEMUFileFD
... ... @@ -6211,34 +6214,6 @@ typedef struct QEMUFileFD
6211 6214 QEMUFile *file;
6212 6215 } QEMUFileFD;
6213 6216  
6214   -static void fd_put_notify(void *opaque)
6215   -{
6216   - QEMUFileFD *s = opaque;
6217   -
6218   - /* Remove writable callback and do a put notify */
6219   - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
6220   - qemu_file_put_notify(s->file);
6221   -}
6222   -
6223   -static void fd_put_buffer(void *opaque, const uint8_t *buf,
6224   - int64_t pos, int size)
6225   -{
6226   - QEMUFileFD *s = opaque;
6227   - ssize_t len;
6228   -
6229   - do {
6230   - len = write(s->fd, buf, size);
6231   - } while (len == -1 && errno == EINTR);
6232   -
6233   - if (len == -1)
6234   - len = -errno;
6235   -
6236   - /* When the fd becomes writable again, register a callback to do
6237   - * a put notify */
6238   - if (len == -EAGAIN)
6239   - qemu_set_fd_handler2(s->fd, NULL, NULL, fd_put_notify, s);
6240   -}
6241   -
6242 6217 static int fd_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
6243 6218 {
6244 6219 QEMUFileFD *s = opaque;
... ... @@ -6269,7 +6244,7 @@ QEMUFile *qemu_fopen_fd(int fd)
6269 6244 return NULL;
6270 6245  
6271 6246 s->fd = fd;
6272   - s->file = qemu_fopen_ops(s, fd_put_buffer, fd_get_buffer, fd_close, NULL);
  6247 + s->file = qemu_fopen_ops(s, NULL, fd_get_buffer, fd_close, NULL);
6273 6248 return s->file;
6274 6249 }
6275 6250  
... ... @@ -6278,12 +6253,13 @@ typedef struct QEMUFileStdio
6278 6253 FILE *outfile;
6279 6254 } QEMUFileStdio;
6280 6255  
6281   -static void file_put_buffer(void *opaque, const uint8_t *buf,
  6256 +static int file_put_buffer(void *opaque, const uint8_t *buf,
6282 6257 int64_t pos, int size)
6283 6258 {
6284 6259 QEMUFileStdio *s = opaque;
6285 6260 fseek(s->outfile, pos, SEEK_SET);
6286 6261 fwrite(buf, 1, size, s->outfile);
  6262 + return size;
6287 6263 }
6288 6264  
6289 6265 static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
... ... @@ -6331,11 +6307,12 @@ typedef struct QEMUFileBdrv
6331 6307 int64_t base_offset;
6332 6308 } QEMUFileBdrv;
6333 6309  
6334   -static void bdrv_put_buffer(void *opaque, const uint8_t *buf,
6335   - int64_t pos, int size)
  6310 +static int bdrv_put_buffer(void *opaque, const uint8_t *buf,
  6311 + int64_t pos, int size)
6336 6312 {
6337 6313 QEMUFileBdrv *s = opaque;
6338 6314 bdrv_pwrite(s->bs, s->base_offset + pos, buf, size);
  6315 + return size;
6339 6316 }
6340 6317  
6341 6318 static int bdrv_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
... ... @@ -6384,18 +6361,29 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
6384 6361 f->get_buffer = get_buffer;
6385 6362 f->close = close;
6386 6363 f->rate_limit = rate_limit;
  6364 + f->is_write = 0;
6387 6365  
6388 6366 return f;
6389 6367 }
6390 6368  
  6369 +int qemu_file_has_error(QEMUFile *f)
  6370 +{
  6371 + return f->has_error;
  6372 +}
  6373 +
6391 6374 void qemu_fflush(QEMUFile *f)
6392 6375 {
6393 6376 if (!f->put_buffer)
6394 6377 return;
6395 6378  
6396   - if (f->buf_index > 0) {
6397   - f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
6398   - f->buf_offset += f->buf_index;
  6379 + if (f->is_write && f->buf_index > 0) {
  6380 + int len;
  6381 +
  6382 + len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
  6383 + if (len > 0)
  6384 + f->buf_offset += f->buf_index;
  6385 + else
  6386 + f->has_error = 1;
6399 6387 f->buf_index = 0;
6400 6388 }
6401 6389 }
... ... @@ -6407,13 +6395,16 @@ static void qemu_fill_buffer(QEMUFile *f)
6407 6395 if (!f->get_buffer)
6408 6396 return;
6409 6397  
6410   - len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
6411   - if (len < 0)
6412   - len = 0;
  6398 + if (f->is_write)
  6399 + abort();
6413 6400  
6414   - f->buf_index = 0;
6415   - f->buf_size = len;
6416   - f->buf_offset += len;
  6401 + len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
  6402 + if (len > 0) {
  6403 + f->buf_index = 0;
  6404 + f->buf_size = len;
  6405 + f->buf_offset += len;
  6406 + } else if (len != -EAGAIN)
  6407 + f->has_error = 1;
6417 6408 }
6418 6409  
6419 6410 int qemu_fclose(QEMUFile *f)
... ... @@ -6434,11 +6425,19 @@ void qemu_file_put_notify(QEMUFile *f)
6434 6425 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
6435 6426 {
6436 6427 int l;
6437   - while (size > 0) {
  6428 +
  6429 + if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
  6430 + fprintf(stderr,
  6431 + "Attempted to write to buffer while read buffer is not empty\n");
  6432 + abort();
  6433 + }
  6434 +
  6435 + while (!f->has_error && size > 0) {
6438 6436 l = IO_BUF_SIZE - f->buf_index;
6439 6437 if (l > size)
6440 6438 l = size;
6441 6439 memcpy(f->buf + f->buf_index, buf, l);
  6440 + f->is_write = 1;
6442 6441 f->buf_index += l;
6443 6442 buf += l;
6444 6443 size -= l;
... ... @@ -6449,7 +6448,14 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
6449 6448  
6450 6449 void qemu_put_byte(QEMUFile *f, int v)
6451 6450 {
  6451 + if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
  6452 + fprintf(stderr,
  6453 + "Attempted to write to buffer while read buffer is not empty\n");
  6454 + abort();
  6455 + }
  6456 +
6452 6457 f->buf[f->buf_index++] = v;
  6458 + f->is_write = 1;
6453 6459 if (f->buf_index >= IO_BUF_SIZE)
6454 6460 qemu_fflush(f);
6455 6461 }
... ... @@ -6458,6 +6464,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
6458 6464 {
6459 6465 int size, l;
6460 6466  
  6467 + if (f->is_write)
  6468 + abort();
  6469 +
6461 6470 size = size1;
6462 6471 while (size > 0) {
6463 6472 l = f->buf_size - f->buf_index;
... ... @@ -6479,6 +6488,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
6479 6488  
6480 6489 int qemu_get_byte(QEMUFile *f)
6481 6490 {
  6491 + if (f->is_write)
  6492 + abort();
  6493 +
6482 6494 if (f->buf_index >= f->buf_size) {
6483 6495 qemu_fill_buffer(f);
6484 6496 if (f->buf_index >= f->buf_size)
... ... @@ -6671,6 +6683,9 @@ int qemu_savevm_state_begin(QEMUFile *f)
6671 6683 se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
6672 6684 }
6673 6685  
  6686 + if (qemu_file_has_error(f))
  6687 + return -EIO;
  6688 +
6674 6689 return 0;
6675 6690 }
6676 6691  
... ... @@ -6693,6 +6708,9 @@ int qemu_savevm_state_iterate(QEMUFile *f)
6693 6708 if (ret)
6694 6709 return 1;
6695 6710  
  6711 + if (qemu_file_has_error(f))
  6712 + return -EIO;
  6713 +
6696 6714 return 0;
6697 6715 }
6698 6716  
... ... @@ -6734,6 +6752,9 @@ int qemu_savevm_state_complete(QEMUFile *f)
6734 6752  
6735 6753 qemu_put_byte(f, QEMU_VM_EOF);
6736 6754  
  6755 + if (qemu_file_has_error(f))
  6756 + return -EIO;
  6757 +
6737 6758 return 0;
6738 6759 }
6739 6760  
... ... @@ -6758,8 +6779,12 @@ int qemu_savevm_state(QEMUFile *f)
6758 6779 ret = qemu_savevm_state_complete(f);
6759 6780  
6760 6781 out:
6761   - if (saved_vm_running)
  6782 + if (qemu_file_has_error(f))
  6783 + ret = -EIO;
  6784 +
  6785 + if (!ret && saved_vm_running)
6762 6786 vm_start();
  6787 +
6763 6788 return ret;
6764 6789 }
6765 6790  
... ... @@ -6815,6 +6840,10 @@ static int qemu_loadvm_state_v2(QEMUFile *f)
6815 6840 /* always seek to exact end of record */
6816 6841 qemu_fseek(f, cur_pos + record_len, SEEK_SET);
6817 6842 }
  6843 +
  6844 + if (qemu_file_has_error(f))
  6845 + return -EIO;
  6846 +
6818 6847 return 0;
6819 6848 }
6820 6849  
... ... @@ -6913,6 +6942,9 @@ out:
6913 6942 qemu_free(le);
6914 6943 }
6915 6944  
  6945 + if (qemu_file_has_error(f))
  6946 + ret = -EIO;
  6947 +
6916 6948 return ret;
6917 6949 }
6918 6950  
... ... @@ -7224,6 +7256,10 @@ static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
7224 7256 default:
7225 7257 return -EINVAL;
7226 7258 }
  7259 +
  7260 + if (qemu_file_has_error(f))
  7261 + return -EIO;
  7262 +
7227 7263 return 0;
7228 7264 }
7229 7265  
... ...