Commit 178e08a58f40dd5aef2ce774fe0850f5d0e56918

Authored by aliguori
1 parent 8185d2c9

Fix savevm after BDRV_FILE size enforcement

We now enforce that you cannot write beyond the end of a non-growable file.
qcow2 files are not growable but we rely on them being growable to do
savevm/loadvm.  Temporarily allow them to be growable by introducing a new
API specifically for savevm read/write operations.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6994 c046a42c-6fe2-441c-8c8c-71466251a162
block-qcow2.c
... ... @@ -2721,6 +2721,31 @@ static void dump_refcounts(BlockDriverState *bs)
2721 2721 #endif
2722 2722 #endif
2723 2723  
  2724 +static int qcow_put_buffer(BlockDriverState *bs, const uint8_t *buf,
  2725 + int64_t pos, int size)
  2726 +{
  2727 + int growable = bs->growable;
  2728 +
  2729 + bs->growable = 1;
  2730 + bdrv_pwrite(bs, pos, buf, size);
  2731 + bs->growable = growable;
  2732 +
  2733 + return size;
  2734 +}
  2735 +
  2736 +static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf,
  2737 + int64_t pos, int size)
  2738 +{
  2739 + int growable = bs->growable;
  2740 + int ret;
  2741 +
  2742 + bs->growable = 1;
  2743 + ret = bdrv_pread(bs, pos, buf, size);
  2744 + bs->growable = growable;
  2745 +
  2746 + return ret;
  2747 +}
  2748 +
2724 2749 BlockDriver bdrv_qcow2 = {
2725 2750 .format_name = "qcow2",
2726 2751 .instance_size = sizeof(BDRVQcowState),
... ... @@ -2745,5 +2770,8 @@ BlockDriver bdrv_qcow2 = {
2745 2770 .bdrv_snapshot_list = qcow_snapshot_list,
2746 2771 .bdrv_get_info = qcow_get_info,
2747 2772  
  2773 + .bdrv_put_buffer = qcow_put_buffer,
  2774 + .bdrv_get_buffer = qcow_get_buffer,
  2775 +
2748 2776 .bdrv_create2 = qcow_create2,
2749 2777 };
... ...
... ... @@ -1146,6 +1146,26 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1146 1146 return drv->bdrv_get_info(bs, bdi);
1147 1147 }
1148 1148  
  1149 +int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
  1150 +{
  1151 + BlockDriver *drv = bs->drv;
  1152 + if (!drv)
  1153 + return -ENOMEDIUM;
  1154 + if (!drv->bdrv_put_buffer)
  1155 + return -ENOTSUP;
  1156 + return drv->bdrv_put_buffer(bs, buf, pos, size);
  1157 +}
  1158 +
  1159 +int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
  1160 +{
  1161 + BlockDriver *drv = bs->drv;
  1162 + if (!drv)
  1163 + return -ENOMEDIUM;
  1164 + if (!drv->bdrv_get_buffer)
  1165 + return -ENOTSUP;
  1166 + return drv->bdrv_get_buffer(bs, buf, pos, size);
  1167 +}
  1168 +
1149 1169 /**************************************************************/
1150 1170 /* handling of snapshots */
1151 1171  
... ...
... ... @@ -178,4 +178,9 @@ void path_combine(char *dest, int dest_size,
178 178 const char *base_path,
179 179 const char *filename);
180 180  
  181 +int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf,
  182 + int64_t pos, int size);
  183 +
  184 +int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size);
  185 +
181 186 #endif
... ...
block_int.h
... ... @@ -78,6 +78,11 @@ struct BlockDriver {
78 78 QEMUSnapshotInfo **psn_info);
79 79 int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
80 80  
  81 + int (*bdrv_put_buffer)(BlockDriverState *bs, const uint8_t *buf,
  82 + int64_t pos, int size);
  83 + int (*bdrv_get_buffer)(BlockDriverState *bs, uint8_t *buf,
  84 + int64_t pos, int size);
  85 +
81 86 /* removable device specific */
82 87 int (*bdrv_is_inserted)(BlockDriverState *bs);
83 88 int (*bdrv_media_changed)(BlockDriverState *bs);
... ...
savevm.c
... ... @@ -310,18 +310,18 @@ typedef struct QEMUFileBdrv
310 310 int64_t base_offset;
311 311 } QEMUFileBdrv;
312 312  
313   -static int bdrv_put_buffer(void *opaque, const uint8_t *buf,
  313 +static int block_put_buffer(void *opaque, const uint8_t *buf,
314 314 int64_t pos, int size)
315 315 {
316 316 QEMUFileBdrv *s = opaque;
317   - bdrv_pwrite(s->bs, s->base_offset + pos, buf, size);
  317 + bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size);
318 318 return size;
319 319 }
320 320  
321   -static int bdrv_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
  321 +static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
322 322 {
323 323 QEMUFileBdrv *s = opaque;
324   - return bdrv_pread(s->bs, s->base_offset + pos, buf, size);
  324 + return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size);
325 325 }
326 326  
327 327 static int bdrv_fclose(void *opaque)
... ... @@ -341,9 +341,9 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_wr
341 341 s->base_offset = offset;
342 342  
343 343 if (is_writable)
344   - return qemu_fopen_ops(s, bdrv_put_buffer, NULL, bdrv_fclose, NULL);
  344 + return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL);
345 345  
346   - return qemu_fopen_ops(s, NULL, bdrv_get_buffer, bdrv_fclose, NULL);
  346 + return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL);
347 347 }
348 348  
349 349 QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
... ...