Commit 178e08a58f40dd5aef2ce774fe0850f5d0e56918
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
Showing
5 changed files
with
64 additions
and
6 deletions
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 | }; | ... | ... |
block.c
... | ... | @@ -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 | ... | ... |
block.h
... | ... | @@ -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, | ... | ... |