block: add a CoMutex to synchronous read drivers
The big conversion of bdrv_read/write to coroutines caused the two homonymous callbacks in BlockDriver to become reentrant. It goes like this: 1) bdrv_read is now called in a coroutine, and calls bdrv_read or bdrv_pread. 2) the nested bdrv_read goes through the fast path in bdrv_rw_co_entry; 3) in the common case when the protocol is file, bdrv_co_do_readv calls bdrv_co_readv_em (and from here goes to bdrv_co_io_em), which yields until the AIO operation is complete; 4) if bdrv_read had been called from a bottom half, the main loop is free to iterate again: a device model or another bottom half can then come and call bdrv_read again. This applies to all four of read/write/flush/discard. It would also apply to is_allocated, but it is not used from within coroutines: besides qemu-img.c and qemu-io.c, which operate synchronously, the only user is the monitor. Copy-on-read will introduce a use in the block layer, and will require converting it. The solution is "simply" to convert all drivers to coroutines! We just need to add a CoMutex that is taken around affected operations. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
bae0a0cc38
commit
848c66e8f5
@ -80,6 +80,7 @@ struct bochs_header {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct BDRVBochsState {
|
typedef struct BDRVBochsState {
|
||||||
|
CoMutex lock;
|
||||||
uint32_t *catalog_bitmap;
|
uint32_t *catalog_bitmap;
|
||||||
int catalog_size;
|
int catalog_size;
|
||||||
|
|
||||||
@ -150,6 +151,7 @@ static int bochs_open(BlockDriverState *bs, int flags)
|
|||||||
|
|
||||||
s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
|
s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
|
||||||
|
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
typedef struct BDRVCloopState {
|
typedef struct BDRVCloopState {
|
||||||
|
CoMutex lock;
|
||||||
uint32_t block_size;
|
uint32_t block_size;
|
||||||
uint32_t n_blocks;
|
uint32_t n_blocks;
|
||||||
uint64_t* offsets;
|
uint64_t* offsets;
|
||||||
@ -93,6 +94,7 @@ static int cloop_open(BlockDriverState *bs, int flags)
|
|||||||
|
|
||||||
s->sectors_per_block = s->block_size/512;
|
s->sectors_per_block = s->block_size/512;
|
||||||
bs->total_sectors = s->n_blocks*s->sectors_per_block;
|
bs->total_sectors = s->n_blocks*s->sectors_per_block;
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cloop_close:
|
cloop_close:
|
||||||
|
@ -42,6 +42,7 @@ struct cow_header_v2 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct BDRVCowState {
|
typedef struct BDRVCowState {
|
||||||
|
CoMutex lock;
|
||||||
int64_t cow_sectors_offset;
|
int64_t cow_sectors_offset;
|
||||||
} BDRVCowState;
|
} BDRVCowState;
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ static int cow_open(BlockDriverState *bs, int flags)
|
|||||||
|
|
||||||
bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
|
bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
|
||||||
s->cow_sectors_offset = (bitmap_size + 511) & ~511;
|
s->cow_sectors_offset = (bitmap_size + 511) & ~511;
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
typedef struct BDRVDMGState {
|
typedef struct BDRVDMGState {
|
||||||
|
CoMutex lock;
|
||||||
/* each chunk contains a certain number of sectors,
|
/* each chunk contains a certain number of sectors,
|
||||||
* offsets[i] is the offset in the .dmg file,
|
* offsets[i] is the offset in the .dmg file,
|
||||||
* lengths[i] is the length of the compressed chunk,
|
* lengths[i] is the length of the compressed chunk,
|
||||||
@ -177,6 +178,7 @@ static int dmg_open(BlockDriverState *bs, int flags)
|
|||||||
|
|
||||||
s->current_chunk = s->n_chunks;
|
s->current_chunk = s->n_chunks;
|
||||||
|
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct BDRVNBDState {
|
typedef struct BDRVNBDState {
|
||||||
|
CoMutex lock;
|
||||||
int sock;
|
int sock;
|
||||||
uint32_t nbdflags;
|
uint32_t nbdflags;
|
||||||
off_t size;
|
off_t size;
|
||||||
@ -175,6 +176,7 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
|
|||||||
*/
|
*/
|
||||||
result = nbd_establish_connection(bs);
|
result = nbd_establish_connection(bs);
|
||||||
|
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ struct parallels_header {
|
|||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
|
||||||
typedef struct BDRVParallelsState {
|
typedef struct BDRVParallelsState {
|
||||||
|
CoMutex lock;
|
||||||
|
|
||||||
uint32_t *catalog_bitmap;
|
uint32_t *catalog_bitmap;
|
||||||
int catalog_size;
|
int catalog_size;
|
||||||
@ -95,6 +96,7 @@ static int parallels_open(BlockDriverState *bs, int flags)
|
|||||||
for (i = 0; i < s->catalog_size; i++)
|
for (i = 0; i < s->catalog_size; i++)
|
||||||
le32_to_cpus(&s->catalog_bitmap[i]);
|
le32_to_cpus(&s->catalog_bitmap[i]);
|
||||||
|
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
if (s->catalog_bitmap)
|
if (s->catalog_bitmap)
|
||||||
|
@ -90,6 +90,7 @@ typedef struct VmdkExtent {
|
|||||||
} VmdkExtent;
|
} VmdkExtent;
|
||||||
|
|
||||||
typedef struct BDRVVmdkState {
|
typedef struct BDRVVmdkState {
|
||||||
|
CoMutex lock;
|
||||||
int desc_offset;
|
int desc_offset;
|
||||||
bool cid_updated;
|
bool cid_updated;
|
||||||
uint32_t parent_cid;
|
uint32_t parent_cid;
|
||||||
@ -646,6 +647,7 @@ static int vmdk_open(BlockDriverState *bs, int flags)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
s->parent_cid = vmdk_read_cid(bs, 1);
|
s->parent_cid = vmdk_read_cid(bs, 1);
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -110,6 +110,7 @@ struct vhd_dyndisk_header {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct BDRVVPCState {
|
typedef struct BDRVVPCState {
|
||||||
|
CoMutex lock;
|
||||||
uint8_t footer_buf[HEADER_SIZE];
|
uint8_t footer_buf[HEADER_SIZE];
|
||||||
uint64_t free_data_block_offset;
|
uint64_t free_data_block_offset;
|
||||||
int max_table_entries;
|
int max_table_entries;
|
||||||
@ -226,6 +227,7 @@ static int vpc_open(BlockDriverState *bs, int flags)
|
|||||||
s->last_pagetable = -1;
|
s->last_pagetable = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
return err;
|
return err;
|
||||||
|
@ -317,6 +317,7 @@ static void print_mapping(const struct mapping_t* mapping);
|
|||||||
/* here begins the real VVFAT driver */
|
/* here begins the real VVFAT driver */
|
||||||
|
|
||||||
typedef struct BDRVVVFATState {
|
typedef struct BDRVVVFATState {
|
||||||
|
CoMutex lock;
|
||||||
BlockDriverState* bs; /* pointer to parent */
|
BlockDriverState* bs; /* pointer to parent */
|
||||||
unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
|
unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
|
||||||
unsigned char first_sectors[0x40*0x200];
|
unsigned char first_sectors[0x40*0x200];
|
||||||
@ -1065,6 +1066,7 @@ DLOG(if (stderr == NULL) {
|
|||||||
bs->heads = bs->cyls = bs->secs = 0;
|
bs->heads = bs->cyls = bs->secs = 0;
|
||||||
|
|
||||||
// assert(is_consistent(s));
|
// assert(is_consistent(s));
|
||||||
|
qemu_co_mutex_init(&s->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user