block: fix snapshot on QED
QED's opaque data includes a pointer back to the BlockDriverState. This breaks when bdrv_append shuffles data between bs_new and bs_top. To avoid this, add a "rebind" function that tells the driver about the new relationship between the BlockDriverState and its opaque. The patch also adds rebind to VVFAT for completeness, even though it is not used with live snapshots. Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
93e9eb6808
commit
e023b2e244
10
block.c
10
block.c
@ -949,6 +949,13 @@ void bdrv_make_anon(BlockDriverState *bs)
|
||||
bs->device_name[0] = '\0';
|
||||
}
|
||||
|
||||
static void bdrv_rebind(BlockDriverState *bs)
|
||||
{
|
||||
if (bs->drv && bs->drv->bdrv_rebind) {
|
||||
bs->drv->bdrv_rebind(bs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add new bs contents at the top of an image chain while the chain is
|
||||
* live, while keeping required fields on the top layer.
|
||||
@ -1037,6 +1044,9 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
|
||||
bs_new->slice_time = 0;
|
||||
bs_new->slice_start = 0;
|
||||
bs_new->slice_end = 0;
|
||||
|
||||
bdrv_rebind(bs_new);
|
||||
bdrv_rebind(bs_top);
|
||||
}
|
||||
|
||||
void bdrv_delete(BlockDriverState *bs)
|
||||
|
@ -367,6 +367,12 @@ static void qed_cancel_need_check_timer(BDRVQEDState *s)
|
||||
qemu_del_timer(s->need_check_timer);
|
||||
}
|
||||
|
||||
static void bdrv_qed_rebind(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
s->bs = bs;
|
||||
}
|
||||
|
||||
static int bdrv_qed_open(BlockDriverState *bs, int flags)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
@ -1550,6 +1556,7 @@ static BlockDriver bdrv_qed = {
|
||||
.create_options = qed_create_options,
|
||||
|
||||
.bdrv_probe = bdrv_qed_probe,
|
||||
.bdrv_rebind = bdrv_qed_rebind,
|
||||
.bdrv_open = bdrv_qed_open,
|
||||
.bdrv_close = bdrv_qed_close,
|
||||
.bdrv_create = bdrv_qed_create,
|
||||
|
@ -982,6 +982,12 @@ static BDRVVVFATState *vvv = NULL;
|
||||
static int enable_write_target(BDRVVVFATState *s);
|
||||
static int is_consistent(BDRVVVFATState *s);
|
||||
|
||||
static void vvfat_rebind(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVVFATState *s = bs->opaque;
|
||||
s->bs = bs;
|
||||
}
|
||||
|
||||
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
|
||||
{
|
||||
BDRVVVFATState *s = bs->opaque;
|
||||
@ -2855,6 +2861,7 @@ static BlockDriver bdrv_vvfat = {
|
||||
.format_name = "vvfat",
|
||||
.instance_size = sizeof(BDRVVVFATState),
|
||||
.bdrv_file_open = vvfat_open,
|
||||
.bdrv_rebind = vvfat_rebind,
|
||||
.bdrv_read = vvfat_co_read,
|
||||
.bdrv_write = vvfat_co_write,
|
||||
.bdrv_close = vvfat_close,
|
||||
|
@ -140,6 +140,7 @@ struct BlockDriver {
|
||||
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
void (*bdrv_close)(BlockDriverState *bs);
|
||||
void (*bdrv_rebind)(BlockDriverState *bs);
|
||||
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
|
||||
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
|
||||
int (*bdrv_make_empty)(BlockDriverState *bs);
|
||||
|
Loading…
Reference in New Issue
Block a user