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, | ... | ... |