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,8 +11,8 @@
11 * The pos argument can be ignored if the file is only being used for 11 * The pos argument can be ignored if the file is only being used for
12 * streaming. The handler should try to write all of the data it can. 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 /* Read a chunk of data from a file at the given position. The pos argument 17 /* Read a chunk of data from a file at the given position. The pos argument
18 * can be ignored if the file is only be used for streaming. The number of 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,6 +64,7 @@ unsigned int qemu_get_be16(QEMUFile *f);
64 unsigned int qemu_get_be32(QEMUFile *f); 64 unsigned int qemu_get_be32(QEMUFile *f);
65 uint64_t qemu_get_be64(QEMUFile *f); 65 uint64_t qemu_get_be64(QEMUFile *f);
66 int qemu_file_rate_limit(QEMUFile *f); 66 int qemu_file_rate_limit(QEMUFile *f);
  67 +int qemu_file_has_error(QEMUFile *f);
67 68
68 /* Try to send any outstanding data. This function is useful when output is 69 /* Try to send any outstanding data. This function is useful when output is
69 * halted due to rate limiting or EAGAIN errors occur as it can be used to 70 * halted due to rate limiting or EAGAIN errors occur as it can be used to
@@ -6197,12 +6197,15 @@ struct QEMUFile { @@ -6197,12 +6197,15 @@ struct QEMUFile {
6197 QEMUFileCloseFunc *close; 6197 QEMUFileCloseFunc *close;
6198 QEMUFileRateLimit *rate_limit; 6198 QEMUFileRateLimit *rate_limit;
6199 void *opaque; 6199 void *opaque;
  6200 + int is_write;
6200 6201
6201 int64_t buf_offset; /* start of buffer when writing, end of buffer 6202 int64_t buf_offset; /* start of buffer when writing, end of buffer
6202 when reading */ 6203 when reading */
6203 int buf_index; 6204 int buf_index;
6204 int buf_size; /* 0 when writing */ 6205 int buf_size; /* 0 when writing */
6205 uint8_t buf[IO_BUF_SIZE]; 6206 uint8_t buf[IO_BUF_SIZE];
  6207 +
  6208 + int has_error;
6206 }; 6209 };
6207 6210
6208 typedef struct QEMUFileFD 6211 typedef struct QEMUFileFD
@@ -6211,34 +6214,6 @@ typedef struct QEMUFileFD @@ -6211,34 +6214,6 @@ typedef struct QEMUFileFD
6211 QEMUFile *file; 6214 QEMUFile *file;
6212 } QEMUFileFD; 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 static int fd_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) 6217 static int fd_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
6243 { 6218 {
6244 QEMUFileFD *s = opaque; 6219 QEMUFileFD *s = opaque;
@@ -6269,7 +6244,7 @@ QEMUFile *qemu_fopen_fd(int fd) @@ -6269,7 +6244,7 @@ QEMUFile *qemu_fopen_fd(int fd)
6269 return NULL; 6244 return NULL;
6270 6245
6271 s->fd = fd; 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 return s->file; 6248 return s->file;
6274 } 6249 }
6275 6250
@@ -6278,12 +6253,13 @@ typedef struct QEMUFileStdio @@ -6278,12 +6253,13 @@ typedef struct QEMUFileStdio
6278 FILE *outfile; 6253 FILE *outfile;
6279 } QEMUFileStdio; 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 int64_t pos, int size) 6257 int64_t pos, int size)
6283 { 6258 {
6284 QEMUFileStdio *s = opaque; 6259 QEMUFileStdio *s = opaque;
6285 fseek(s->outfile, pos, SEEK_SET); 6260 fseek(s->outfile, pos, SEEK_SET);
6286 fwrite(buf, 1, size, s->outfile); 6261 fwrite(buf, 1, size, s->outfile);
  6262 + return size;
6287 } 6263 }
6288 6264
6289 static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) 6265 static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
@@ -6331,11 +6307,12 @@ typedef struct QEMUFileBdrv @@ -6331,11 +6307,12 @@ typedef struct QEMUFileBdrv
6331 int64_t base_offset; 6307 int64_t base_offset;
6332 } QEMUFileBdrv; 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 QEMUFileBdrv *s = opaque; 6313 QEMUFileBdrv *s = opaque;
6338 bdrv_pwrite(s->bs, s->base_offset + pos, buf, size); 6314 bdrv_pwrite(s->bs, s->base_offset + pos, buf, size);
  6315 + return size;
6339 } 6316 }
6340 6317
6341 static int bdrv_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) 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,18 +6361,29 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
6384 f->get_buffer = get_buffer; 6361 f->get_buffer = get_buffer;
6385 f->close = close; 6362 f->close = close;
6386 f->rate_limit = rate_limit; 6363 f->rate_limit = rate_limit;
  6364 + f->is_write = 0;
6387 6365
6388 return f; 6366 return f;
6389 } 6367 }
6390 6368
  6369 +int qemu_file_has_error(QEMUFile *f)
  6370 +{
  6371 + return f->has_error;
  6372 +}
  6373 +
6391 void qemu_fflush(QEMUFile *f) 6374 void qemu_fflush(QEMUFile *f)
6392 { 6375 {
6393 if (!f->put_buffer) 6376 if (!f->put_buffer)
6394 return; 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 f->buf_index = 0; 6387 f->buf_index = 0;
6400 } 6388 }
6401 } 6389 }
@@ -6407,13 +6395,16 @@ static void qemu_fill_buffer(QEMUFile *f) @@ -6407,13 +6395,16 @@ static void qemu_fill_buffer(QEMUFile *f)
6407 if (!f->get_buffer) 6395 if (!f->get_buffer)
6408 return; 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 int qemu_fclose(QEMUFile *f) 6410 int qemu_fclose(QEMUFile *f)
@@ -6434,11 +6425,19 @@ void qemu_file_put_notify(QEMUFile *f) @@ -6434,11 +6425,19 @@ void qemu_file_put_notify(QEMUFile *f)
6434 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) 6425 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
6435 { 6426 {
6436 int l; 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 l = IO_BUF_SIZE - f->buf_index; 6436 l = IO_BUF_SIZE - f->buf_index;
6439 if (l > size) 6437 if (l > size)
6440 l = size; 6438 l = size;
6441 memcpy(f->buf + f->buf_index, buf, l); 6439 memcpy(f->buf + f->buf_index, buf, l);
  6440 + f->is_write = 1;
6442 f->buf_index += l; 6441 f->buf_index += l;
6443 buf += l; 6442 buf += l;
6444 size -= l; 6443 size -= l;
@@ -6449,7 +6448,14 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) @@ -6449,7 +6448,14 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
6449 6448
6450 void qemu_put_byte(QEMUFile *f, int v) 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 f->buf[f->buf_index++] = v; 6457 f->buf[f->buf_index++] = v;
  6458 + f->is_write = 1;
6453 if (f->buf_index >= IO_BUF_SIZE) 6459 if (f->buf_index >= IO_BUF_SIZE)
6454 qemu_fflush(f); 6460 qemu_fflush(f);
6455 } 6461 }
@@ -6458,6 +6464,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) @@ -6458,6 +6464,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
6458 { 6464 {
6459 int size, l; 6465 int size, l;
6460 6466
  6467 + if (f->is_write)
  6468 + abort();
  6469 +
6461 size = size1; 6470 size = size1;
6462 while (size > 0) { 6471 while (size > 0) {
6463 l = f->buf_size - f->buf_index; 6472 l = f->buf_size - f->buf_index;
@@ -6479,6 +6488,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) @@ -6479,6 +6488,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
6479 6488
6480 int qemu_get_byte(QEMUFile *f) 6489 int qemu_get_byte(QEMUFile *f)
6481 { 6490 {
  6491 + if (f->is_write)
  6492 + abort();
  6493 +
6482 if (f->buf_index >= f->buf_size) { 6494 if (f->buf_index >= f->buf_size) {
6483 qemu_fill_buffer(f); 6495 qemu_fill_buffer(f);
6484 if (f->buf_index >= f->buf_size) 6496 if (f->buf_index >= f->buf_size)
@@ -6671,6 +6683,9 @@ int qemu_savevm_state_begin(QEMUFile *f) @@ -6671,6 +6683,9 @@ int qemu_savevm_state_begin(QEMUFile *f)
6671 se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque); 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 return 0; 6689 return 0;
6675 } 6690 }
6676 6691
@@ -6693,6 +6708,9 @@ int qemu_savevm_state_iterate(QEMUFile *f) @@ -6693,6 +6708,9 @@ int qemu_savevm_state_iterate(QEMUFile *f)
6693 if (ret) 6708 if (ret)
6694 return 1; 6709 return 1;
6695 6710
  6711 + if (qemu_file_has_error(f))
  6712 + return -EIO;
  6713 +
6696 return 0; 6714 return 0;
6697 } 6715 }
6698 6716
@@ -6734,6 +6752,9 @@ int qemu_savevm_state_complete(QEMUFile *f) @@ -6734,6 +6752,9 @@ int qemu_savevm_state_complete(QEMUFile *f)
6734 6752
6735 qemu_put_byte(f, QEMU_VM_EOF); 6753 qemu_put_byte(f, QEMU_VM_EOF);
6736 6754
  6755 + if (qemu_file_has_error(f))
  6756 + return -EIO;
  6757 +
6737 return 0; 6758 return 0;
6738 } 6759 }
6739 6760
@@ -6758,8 +6779,12 @@ int qemu_savevm_state(QEMUFile *f) @@ -6758,8 +6779,12 @@ int qemu_savevm_state(QEMUFile *f)
6758 ret = qemu_savevm_state_complete(f); 6779 ret = qemu_savevm_state_complete(f);
6759 6780
6760 out: 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 vm_start(); 6786 vm_start();
  6787 +
6763 return ret; 6788 return ret;
6764 } 6789 }
6765 6790
@@ -6815,6 +6840,10 @@ static int qemu_loadvm_state_v2(QEMUFile *f) @@ -6815,6 +6840,10 @@ static int qemu_loadvm_state_v2(QEMUFile *f)
6815 /* always seek to exact end of record */ 6840 /* always seek to exact end of record */
6816 qemu_fseek(f, cur_pos + record_len, SEEK_SET); 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 return 0; 6847 return 0;
6819 } 6848 }
6820 6849
@@ -6913,6 +6942,9 @@ out: @@ -6913,6 +6942,9 @@ out:
6913 qemu_free(le); 6942 qemu_free(le);
6914 } 6943 }
6915 6944
  6945 + if (qemu_file_has_error(f))
  6946 + ret = -EIO;
  6947 +
6916 return ret; 6948 return ret;
6917 } 6949 }
6918 6950
@@ -7224,6 +7256,10 @@ static int ram_get_page(QEMUFile *f, uint8_t *buf, int len) @@ -7224,6 +7256,10 @@ static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
7224 default: 7256 default:
7225 return -EINVAL; 7257 return -EINVAL;
7226 } 7258 }
  7259 +
  7260 + if (qemu_file_has_error(f))
  7261 + return -EIO;
  7262 +
7227 return 0; 7263 return 0;
7228 } 7264 }
7229 7265