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,6 +2721,31 @@ static void dump_refcounts(BlockDriverState *bs) | ||
| 2721 | #endif | 2721 | #endif |
| 2722 | #endif | 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 | BlockDriver bdrv_qcow2 = { | 2749 | BlockDriver bdrv_qcow2 = { |
| 2725 | .format_name = "qcow2", | 2750 | .format_name = "qcow2", |
| 2726 | .instance_size = sizeof(BDRVQcowState), | 2751 | .instance_size = sizeof(BDRVQcowState), |
| @@ -2745,5 +2770,8 @@ BlockDriver bdrv_qcow2 = { | @@ -2745,5 +2770,8 @@ BlockDriver bdrv_qcow2 = { | ||
| 2745 | .bdrv_snapshot_list = qcow_snapshot_list, | 2770 | .bdrv_snapshot_list = qcow_snapshot_list, |
| 2746 | .bdrv_get_info = qcow_get_info, | 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 | .bdrv_create2 = qcow_create2, | 2776 | .bdrv_create2 = qcow_create2, |
| 2749 | }; | 2777 | }; |
block.c
| @@ -1146,6 +1146,26 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | @@ -1146,6 +1146,26 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
| 1146 | return drv->bdrv_get_info(bs, bdi); | 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 | /* handling of snapshots */ | 1170 | /* handling of snapshots */ |
| 1151 | 1171 |
block.h
| @@ -178,4 +178,9 @@ void path_combine(char *dest, int dest_size, | @@ -178,4 +178,9 @@ void path_combine(char *dest, int dest_size, | ||
| 178 | const char *base_path, | 178 | const char *base_path, |
| 179 | const char *filename); | 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 | #endif | 186 | #endif |
block_int.h
| @@ -78,6 +78,11 @@ struct BlockDriver { | @@ -78,6 +78,11 @@ struct BlockDriver { | ||
| 78 | QEMUSnapshotInfo **psn_info); | 78 | QEMUSnapshotInfo **psn_info); |
| 79 | int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); | 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 | /* removable device specific */ | 86 | /* removable device specific */ |
| 82 | int (*bdrv_is_inserted)(BlockDriverState *bs); | 87 | int (*bdrv_is_inserted)(BlockDriverState *bs); |
| 83 | int (*bdrv_media_changed)(BlockDriverState *bs); | 88 | int (*bdrv_media_changed)(BlockDriverState *bs); |
savevm.c
| @@ -310,18 +310,18 @@ typedef struct QEMUFileBdrv | @@ -310,18 +310,18 @@ typedef struct QEMUFileBdrv | ||
| 310 | int64_t base_offset; | 310 | int64_t base_offset; |
| 311 | } QEMUFileBdrv; | 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 | int64_t pos, int size) | 314 | int64_t pos, int size) |
| 315 | { | 315 | { |
| 316 | QEMUFileBdrv *s = opaque; | 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 | return size; | 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 | QEMUFileBdrv *s = opaque; | 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 | static int bdrv_fclose(void *opaque) | 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,9 +341,9 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_wr | ||
| 341 | s->base_offset = offset; | 341 | s->base_offset = offset; |
| 342 | 342 | ||
| 343 | if (is_writable) | 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 | QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, | 349 | QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, |