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