From 22bc0b986d392e96634ce0c74dfad777736ddbab Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 14 Feb 2012 11:14:56 +0100 Subject: [PATCH 91/99] block: add a CoMutex to synchronous read drivers RH-Author: Kevin Wolf Message-id: <1329218101-24213-92-git-send-email-kwolf@redhat.com> Patchwork-id: 37289 O-Subject: [RHEL-6.3 qemu-kvm PATCH v2 91/96] block: add a CoMutex to synchronous read drivers Bugzilla: 783950 RH-Acked-by: Paolo Bonzini RH-Acked-by: Marcelo Tosatti RH-Acked-by: Laszlo Ersek From: Paolo Bonzini Bugzilla: 783950 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 Signed-off-by: Kevin Wolf (cherry picked from commit 848c66e8f5b631961580f7f010a5831430dc84c2) Conflicts: block/nbd.c block/vmdk.c Signed-off-by: Kevin Wolf --- block/bochs.c | 2 ++ block/cloop.c | 2 ++ block/cow.c | 2 ++ block/dmg.c | 2 ++ block/nbd.c | 3 +++ block/parallels.c | 2 ++ block/vmdk.c | 3 +++ block/vpc.c | 2 ++ block/vvfat.c | 2 ++ 9 files changed, 20 insertions(+), 0 deletions(-) Signed-off-by: Michal Novotny --- block/bochs.c | 2 ++ block/cloop.c | 2 ++ block/cow.c | 2 ++ block/dmg.c | 2 ++ block/nbd.c | 3 +++ block/parallels.c | 2 ++ block/vmdk.c | 3 +++ block/vpc.c | 2 ++ block/vvfat.c | 2 ++ 9 files changed, 20 insertions(+), 0 deletions(-) diff --git a/block/bochs.c b/block/bochs.c index 3c2f8d1..b0f8072 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -80,6 +80,7 @@ struct bochs_header { }; typedef struct BDRVBochsState { + CoMutex lock; uint32_t *catalog_bitmap; 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); + qemu_co_mutex_init(&s->lock); return 0; fail: return -1; diff --git a/block/cloop.c b/block/cloop.c index 8cff9f2..a91f372 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -27,6 +27,7 @@ #include typedef struct BDRVCloopState { + CoMutex lock; uint32_t block_size; uint32_t n_blocks; uint64_t* offsets; @@ -93,6 +94,7 @@ static int cloop_open(BlockDriverState *bs, int flags) s->sectors_per_block = s->block_size/512; bs->total_sectors = s->n_blocks*s->sectors_per_block; + qemu_co_mutex_init(&s->lock); return 0; cloop_close: diff --git a/block/cow.c b/block/cow.c index 799569c..23833a2 100644 --- a/block/cow.c +++ b/block/cow.c @@ -42,6 +42,7 @@ struct cow_header_v2 { }; typedef struct BDRVCowState { + CoMutex lock; int64_t cow_sectors_offset; } BDRVCowState; @@ -84,6 +85,7 @@ static int cow_open(BlockDriverState *bs, int flags) bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header); s->cow_sectors_offset = (bitmap_size + 511) & ~511; + qemu_co_mutex_init(&s->lock); return 0; fail: return -1; diff --git a/block/dmg.c b/block/dmg.c index 64c3cce..111aeae 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -28,6 +28,7 @@ #include typedef struct BDRVDMGState { + CoMutex lock; /* each chunk contains a certain number of sectors, * offsets[i] is the offset in the .dmg file, * 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; + qemu_co_mutex_init(&s->lock); return 0; fail: return -1; diff --git a/block/nbd.c b/block/nbd.c index b5cb06c..4afb6d0 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -34,6 +34,7 @@ #include typedef struct BDRVNBDState { + CoMutex lock; int sock; off_t size; size_t blocksize; @@ -93,6 +94,8 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags) s->size = size; s->blocksize = blocksize; + qemu_co_mutex_init(&s->lock); + return 0; } diff --git a/block/parallels.c b/block/parallels.c index 37d151d..ad20687 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -46,6 +46,7 @@ struct parallels_header { } __attribute__((packed)); typedef struct BDRVParallelsState { + CoMutex lock; uint32_t *catalog_bitmap; int catalog_size; @@ -95,6 +96,7 @@ static int parallels_open(BlockDriverState *bs, int flags) for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); + qemu_co_mutex_init(&s->lock); return 0; fail: if (s->catalog_bitmap) diff --git a/block/vmdk.c b/block/vmdk.c index e2cfcad..4a48f9e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -75,6 +75,8 @@ typedef struct BDRVVmdkState { uint32_t l2_cache_counts[L2_CACHE_SIZE]; unsigned int cluster_sectors; + + CoMutex lock; uint32_t parent_cid; } BDRVVmdkState; @@ -425,6 +427,7 @@ static int vmdk_open(BlockDriverState *bs, int flags) } s->l2_cache = g_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); + qemu_co_mutex_init(&s->lock); return 0; fail: g_free(s->l1_backup_table); diff --git a/block/vpc.c b/block/vpc.c index d9f5e6e..b7a2e33 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -110,6 +110,7 @@ struct vhd_dyndisk_header { }; typedef struct BDRVVPCState { + CoMutex lock; uint8_t footer_buf[HEADER_SIZE]; uint64_t free_data_block_offset; int max_table_entries; @@ -220,6 +221,7 @@ static int vpc_open(BlockDriverState *bs, int flags) s->last_pagetable = -1; #endif + qemu_co_mutex_init(&s->lock); return 0; fail: return -1; diff --git a/block/vvfat.c b/block/vvfat.c index 1d88070..a2bec26 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -318,6 +318,7 @@ static void print_mapping(const struct mapping_t* mapping); /* here begins the real VVFAT driver */ typedef struct BDRVVVFATState { + CoMutex lock; BlockDriverState* bs; /* pointer to parent */ unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */ unsigned char first_sectors[0x40*0x200]; @@ -1079,6 +1080,7 @@ DLOG(if (stderr == NULL) { bs->heads = bs->cyls = bs->secs = 0; // assert(is_consistent(s)); + qemu_co_mutex_init(&s->lock); return 0; } -- 1.7.7.5