From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498585179216755.6222851624356; Tue, 27 Jun 2017 10:39:39 -0700 (PDT) Received: from localhost ([::1]:57377 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuSe-0006UR-MD for importer@patchew.org; Tue, 27 Jun 2017 13:39:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52530) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtm1-00077i-73 for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsKf-00029i-55 for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56306) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsKe-00022n-1j; Tue, 27 Jun 2017 11:23:12 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0C39975729; Tue, 27 Jun 2017 15:23:11 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 30B958ED23; Tue, 27 Jun 2017 15:23:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0C39975729 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 0C39975729 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:39 +0200 Message-Id: <20170627152248.10446-2-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 27 Jun 2017 15:23:11 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 01/10] qcow2: call CoQueue APIs under CoMutex X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/qcow2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 2f94f0326e..70d3f4a18e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1741,8 +1741,6 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverS= tate *bs, uint64_t offset, ret =3D 0; =20 fail: - qemu_co_mutex_unlock(&s->lock); - while (l2meta !=3D NULL) { QCowL2Meta *next; =20 @@ -1756,6 +1754,8 @@ fail: l2meta =3D next; } =20 + qemu_co_mutex_unlock(&s->lock); + qemu_iovec_destroy(&hd_qiov); qemu_vfree(cluster_data); trace_qcow2_writev_done_req(qemu_coroutine_self(), ret); --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149858501936993.82590229050209; Tue, 27 Jun 2017 10:36:59 -0700 (PDT) Received: from localhost ([::1]:57360 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuQ3-0003ob-U1 for importer@patchew.org; Tue, 27 Jun 2017 13:36:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53576) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtm1-00084h-28 for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsKs-00031L-WC for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58460) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsKp-0002kk-OV; Tue, 27 Jun 2017 11:23:23 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C2404558B1; Tue, 27 Jun 2017 15:23:22 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6023C8D771; Tue, 27 Jun 2017 15:23:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C2404558B1 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com C2404558B1 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:40 +0200 Message-Id: <20170627152248.10446-3-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 27 Jun 2017 15:23:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 02/10] coroutine-lock: add qemu_co_rwlock_downgrade and qemu_co_rwlock_upgrade X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These functions are more efficient in the presence of contention. qemu_co_rwlock_downgrade also guarantees not to block, which may be useful in some algorithms too. Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- include/qemu/coroutine.h | 18 ++++++++++++++++++ util/qemu-coroutine-lock.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index a4509bd977..9aff9a735e 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -229,6 +229,24 @@ void qemu_co_rwlock_init(CoRwlock *lock); void qemu_co_rwlock_rdlock(CoRwlock *lock); =20 /** + * Write Locks the CoRwlock from a reader. This is a bit more efficient t= han + * @qemu_co_rwlock_unlock followed by a separate @qemu_co_rwlock_wrlock. + * However, if the lock cannot be upgraded immediately, control is transfe= rred + * to the caller of the current coroutine. Also, @qemu_co_rwlock_upgrade + * only overrides CoRwlock fairness if there are no concurrent readers, so + * another writer might run while @qemu_co_rwlock_upgrade blocks. + */ +void qemu_co_rwlock_upgrade(CoRwlock *lock); + +/** + * Downgrades a write-side critical section to a reader. Downgrading with + * @qemu_co_rwlock_downgrade never blocks, unlike @qemu_co_rwlock_unlock + * followed by @qemu_co_rwlock_rdlock. This makes it more efficient, but + * may also sometimes be necessary for correctness. + */ +void qemu_co_rwlock_downgrade(CoRwlock *lock); + +/** * Write Locks the mutex. If the lock cannot be taken immediately because * of a parallel reader, control is transferred to the caller of the curre= nt * coroutine. diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c index b44b5d55eb..846ff9167f 100644 --- a/util/qemu-coroutine-lock.c +++ b/util/qemu-coroutine-lock.c @@ -402,6 +402,21 @@ void qemu_co_rwlock_unlock(CoRwlock *lock) qemu_co_mutex_unlock(&lock->mutex); } =20 +void qemu_co_rwlock_downgrade(CoRwlock *lock) +{ + Coroutine *self =3D qemu_coroutine_self(); + + /* lock->mutex critical section started in qemu_co_rwlock_wrlock or + * qemu_co_rwlock_upgrade. + */ + assert(lock->reader =3D=3D 0); + lock->reader++; + qemu_co_mutex_unlock(&lock->mutex); + + /* The rest of the read-side critical section is run without the mutex= . */ + self->locks_held++; +} + void qemu_co_rwlock_wrlock(CoRwlock *lock) { qemu_co_mutex_lock(&lock->mutex); @@ -416,3 +431,23 @@ void qemu_co_rwlock_wrlock(CoRwlock *lock) * There is no need to update self->locks_held. */ } + +void qemu_co_rwlock_upgrade(CoRwlock *lock) +{ + Coroutine *self =3D qemu_coroutine_self(); + + qemu_co_mutex_lock(&lock->mutex); + assert(lock->reader > 0); + lock->reader--; + lock->pending_writer++; + while (lock->reader) { + qemu_co_queue_wait(&lock->queue, &lock->mutex); + } + lock->pending_writer--; + + /* The rest of the write-side critical section is run with + * the mutex taken, similar to qemu_co_rwlock_wrlock. Do + * not account for the lock twice in self->locks_held. + */ + self->locks_held--; +} --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498584848534790.1164668018577; Tue, 27 Jun 2017 10:34:08 -0700 (PDT) Received: from localhost ([::1]:57341 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuNI-00012A-Ey for importer@patchew.org; Tue, 27 Jun 2017 13:34:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52326) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtm0-0006m9-5K for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsKt-00031e-0f for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44485) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsKr-0002rD-C6; Tue, 27 Jun 2017 11:23:25 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 79044C013C32; Tue, 27 Jun 2017 15:23:24 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 217DE8A785; Tue, 27 Jun 2017 15:23:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 79044C013C32 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 79044C013C32 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:41 +0200 Message-Id: <20170627152248.10446-4-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 27 Jun 2017 15:23:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 03/10] vdi: make it thread-safe X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The VirtualBox driver is using a mutex to order all allocating writes, but it is not protecting accesses to the bitmap because they implicitly happen under the AioContext mutex. Change this to use a CoRwlock explicitly. Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/vdi.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 79af47763b..080e1562e3 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -172,7 +172,7 @@ typedef struct { /* VDI header (converted to host endianness). */ VdiHeader header; =20 - CoMutex write_lock; + CoRwlock bmap_lock; =20 Error *migration_blocker; } BDRVVdiState; @@ -485,7 +485,7 @@ static int vdi_open(BlockDriverState *bs, QDict *option= s, int flags, goto fail_free_bmap; } =20 - qemu_co_mutex_init(&s->write_lock); + qemu_co_rwlock_init(&s->bmap_lock); =20 return 0; =20 @@ -557,7 +557,9 @@ vdi_co_preadv(BlockDriverState *bs, uint64_t offset, ui= nt64_t bytes, n_bytes, offset); =20 /* prepare next AIO request */ + qemu_co_rwlock_rdlock(&s->bmap_lock); bmap_entry =3D le32_to_cpu(s->bmap[block_index]); + qemu_co_rwlock_unlock(&s->bmap_lock); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Block not allocated, return zeros, no need to wait. */ qemu_iovec_memset(qiov, bytes_done, 0, n_bytes); @@ -595,6 +597,7 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset, u= int64_t bytes, uint32_t block_index; uint32_t offset_in_block; uint32_t n_bytes; + uint64_t data_offset; uint32_t bmap_first =3D VDI_UNALLOCATED; uint32_t bmap_last =3D VDI_UNALLOCATED; uint8_t *block =3D NULL; @@ -614,10 +617,19 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset,= uint64_t bytes, n_bytes, offset); =20 /* prepare next AIO request */ + qemu_co_rwlock_rdlock(&s->bmap_lock); bmap_entry =3D le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Allocate new block and write to it. */ uint64_t data_offset; + qemu_co_rwlock_upgrade(&s->bmap_lock); + bmap_entry =3D le32_to_cpu(s->bmap[block_index]); + if (VDI_IS_ALLOCATED(bmap_entry)) { + /* A concurrent allocation did the work for us. */ + qemu_co_rwlock_downgrade(&s->bmap_lock); + goto nonallocating_write; + } + bmap_entry =3D s->header.blocks_allocated; s->bmap[block_index] =3D cpu_to_le32(bmap_entry); s->header.blocks_allocated++; @@ -635,30 +647,18 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset,= uint64_t bytes, memset(block + offset_in_block + n_bytes, 0, s->block_size - n_bytes - offset_in_block); =20 - /* Note that this coroutine does not yield anywhere from readi= ng the - * bmap entry until here, so in regards to all the coroutines = trying - * to write to this cluster, the one doing the allocation will - * always be the first to try to acquire the lock. - * Therefore, it is also the first that will actually be able = to - * acquire the lock and thus the padded cluster is written bef= ore - * the other coroutines can write to the affected area. */ - qemu_co_mutex_lock(&s->write_lock); + /* Write the new block under CoRwLock write-side protection, + * so this full-cluster write does not overlap a partial write + * of the same cluster, issued from the "else" branch. + */ ret =3D bdrv_pwrite(bs->file, data_offset, block, s->block_siz= e); - qemu_co_mutex_unlock(&s->write_lock); + qemu_co_rwlock_unlock(&s->bmap_lock); } else { - uint64_t data_offset =3D s->header.offset_data + - (uint64_t)bmap_entry * s->block_size + - offset_in_block; - qemu_co_mutex_lock(&s->write_lock); - /* This lock is only used to make sure the following write ope= ration - * is executed after the write issued by the coroutine allocat= ing - * this cluster, therefore we do not need to keep it locked. - * As stated above, the allocating coroutine will always try t= o lock - * the mutex before all the other concurrent accesses to that - * cluster, therefore at this point we can be absolutely certa= in - * that that write operation has returned (there may be other = writes - * in flight, but they do not concern this very operation). */ - qemu_co_mutex_unlock(&s->write_lock); +nonallocating_write: + data_offset =3D s->header.offset_data + + (uint64_t)bmap_entry * s->block_size + + offset_in_block; + qemu_co_rwlock_unlock(&s->bmap_lock); =20 qemu_iovec_reset(&local_qiov); qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498584655358526.71897693815; Tue, 27 Jun 2017 10:30:55 -0700 (PDT) Received: from localhost ([::1]:57327 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuKE-0007Ii-3V for importer@patchew.org; Tue, 27 Jun 2017 13:30:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52896) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtm0-0007PJ-1t for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsKw-0003Gk-6c for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49826) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsKv-000374-0D; Tue, 27 Jun 2017 11:23:29 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0E0D37A16E; Tue, 27 Jun 2017 15:23:28 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id D13A18A79C; Tue, 27 Jun 2017 15:23:24 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0E0D37A16E Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 0E0D37A16E From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:42 +0200 Message-Id: <20170627152248.10446-5-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 27 Jun 2017 15:23:28 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 04/10] vpc: make it thread-safe X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/vpc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index 4240ba9d1c..0ff686540a 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -496,12 +496,6 @@ static inline int64_t get_image_offset(BlockDriverStat= e *bs, uint64_t offset, return block_offset; } =20 -static inline int64_t get_sector_offset(BlockDriverState *bs, - int64_t sector_num, bool write) -{ - return get_image_offset(bs, sector_num * BDRV_SECTOR_SIZE, write); -} - /* * Writes the footer to the end of the image file. This is needed when the * file grows as it overwrites the old footer @@ -696,6 +690,7 @@ static int64_t coroutine_fn vpc_co_get_block_status(Blo= ckDriverState *bs, VHDFooter *footer =3D (VHDFooter*) s->footer_buf; int64_t start, offset; bool allocated; + int64_t ret; int n; =20 if (be32_to_cpu(footer->type) =3D=3D VHD_FIXED) { @@ -705,10 +700,13 @@ static int64_t coroutine_fn vpc_co_get_block_status(B= lockDriverState *bs, (sector_num << BDRV_SECTOR_BITS); } =20 - offset =3D get_sector_offset(bs, sector_num, 0); + qemu_co_mutex_lock(&s->lock); + + offset =3D get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false); start =3D offset; allocated =3D (offset !=3D -1); *pnum =3D 0; + ret =3D 0; =20 do { /* All sectors in a block are contiguous (without using the bitmap= ) */ @@ -723,15 +721,17 @@ static int64_t coroutine_fn vpc_co_get_block_status(B= lockDriverState *bs, * sectors since there is always a bitmap in between. */ if (allocated) { *file =3D bs->file->bs; - return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + ret =3D BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + break; } if (nb_sectors =3D=3D 0) { break; } - offset =3D get_sector_offset(bs, sector_num, 0); + offset =3D get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, fa= lse); } while (offset =3D=3D -1); =20 - return 0; + qemu_co_mutex_unlock(&s->lock); + return ret; } =20 /* --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498585843705775.4853398012713; Tue, 27 Jun 2017 10:50:43 -0700 (PDT) Received: from localhost ([::1]:57479 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPudN-0007BQ-3u for importer@patchew.org; Tue, 27 Jun 2017 13:50:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52451) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtlz-000719-DE for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsL3-0003mJ-0c for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60136) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsL0-0003VS-1v; Tue, 27 Jun 2017 11:23:34 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 154D47F419; Tue, 27 Jun 2017 15:23:33 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 628FB77DFD; Tue, 27 Jun 2017 15:23:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 154D47F419 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 154D47F419 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:43 +0200 Message-Id: <20170627152248.10446-6-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 27 Jun 2017 15:23:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 05/10] vvfat: make it thread-safe X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/vvfat.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/block/vvfat.c b/block/vvfat.c index 8ab647c0c6..d2679c2ff5 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2982,8 +2982,14 @@ static int coroutine_fn write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) { + int ret; + BDRVVVFATState* s =3D *((BDRVVVFATState**) bs->opaque); - return try_commit(s); + qemu_co_mutex_lock(&s->lock); + ret =3D try_commit(s); + qemu_co_mutex_unlock(&s->lock); + + return ret; } =20 static void write_target_close(BlockDriverState *bs) { --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149858556039038.70197346636223; Tue, 27 Jun 2017 10:46:00 -0700 (PDT) Received: from localhost ([::1]:57437 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuYm-0003Ys-Vw for importer@patchew.org; Tue, 27 Jun 2017 13:45:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52421) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtly-0006uy-EO for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsL8-0004Ag-Jz for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51428) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsL7-0003zm-6L; Tue, 27 Jun 2017 11:23:41 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3A1D443A25; Tue, 27 Jun 2017 15:23:40 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 696C677DFD; Tue, 27 Jun 2017 15:23:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3A1D443A25 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 3A1D443A25 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:44 +0200 Message-Id: <20170627152248.10446-7-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 27 Jun 2017 15:23:40 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 06/10] qed: move tail of qed_aio_write_main to qed_aio_write_{cow, alloc} X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This part is never called for in-place writes, move it away to avoid the "backwards" coding style typical of callback-based code. Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/qed.c | 69 +++++++++++++++++++++++++++------------------------------= ---- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/block/qed.c b/block/qed.c index 385381a78a..3ffdc1716d 100644 --- a/block/qed.c +++ b/block/qed.c @@ -982,40 +982,11 @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *= acb) BDRVQEDState *s =3D acb_to_s(acb); uint64_t offset =3D acb->cur_cluster + qed_offset_into_cluster(s, acb->cur_pos); - int ret; =20 trace_qed_aio_write_main(s, acb, 0, offset, acb->cur_qiov.size); =20 BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO); - ret =3D bdrv_co_pwritev(s->bs->file, offset, acb->cur_qiov.size, - &acb->cur_qiov, 0); - if (ret < 0) { - return ret; - } - - if (acb->find_cluster_ret !=3D QED_CLUSTER_FOUND) { - if (s->bs->backing) { - /* - * Flush new data clusters before updating the L2 table - * - * This flush is necessary when a backing file is in use. A c= rash - * during an allocating write could result in empty clusters i= n the - * image. If the write only touched a subregion of the cluste= r, - * then backing image sectors have been lost in the untouched - * region. The solution is to flush after writing a new data - * cluster and before updating the L2 table. - */ - ret =3D bdrv_co_flush(s->bs->file->bs); - if (ret < 0) { - return ret; - } - } - ret =3D qed_aio_write_l2_update(acb, acb->cur_cluster); - if (ret < 0) { - return ret; - } - } - return 0; + return bdrv_co_pwritev(s->bs->file, offset, &acb->cur_qiov); } =20 /** @@ -1050,7 +1021,29 @@ static int coroutine_fn qed_aio_write_cow(QEDAIOCB *= acb) return ret; } =20 - return qed_aio_write_main(acb); + ret =3D qed_aio_write_main(acb); + if (ret < 0) { + return ret; + } + + if (s->bs->backing) { + /* + * Flush new data clusters before updating the L2 table + * + * This flush is necessary when a backing file is in use. A crash + * during an allocating write could result in empty clusters in the + * image. If the write only touched a subregion of the cluster, + * then backing image sectors have been lost in the untouched + * region. The solution is to flush after writing a new data + * cluster and before updating the L2 table. + */ + ret =3D bdrv_co_flush(s->bs->file->bs); + if (ret < 0) { + return ret; + } + } + + return 0; } =20 /** @@ -1103,6 +1096,7 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOCB = *acb, size_t len) if (acb->find_cluster_ret =3D=3D QED_CLUSTER_ZERO) { return 0; } + acb->cur_cluster =3D 1; } else { acb->cur_cluster =3D qed_alloc_clusters(s, acb->cur_nclusters); } @@ -1115,15 +1109,14 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOC= B *acb, size_t len) } } =20 - if (acb->flags & QED_AIOCB_ZERO) { - ret =3D qed_aio_write_l2_update(acb, 1); - } else { + if (!(acb->flags & QED_AIOCB_ZERO)) { ret =3D qed_aio_write_cow(acb); + if (ret < 0) { + return ret; + } } - if (ret < 0) { - return ret; - } - return 0; + + return qed_aio_write_l2_update(acb, acb->cur_cluster); } =20 /** --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149858448920957.024709592549584; Tue, 27 Jun 2017 10:28:09 -0700 (PDT) Received: from localhost ([::1]:57304 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuHX-0004YN-Nl for importer@patchew.org; Tue, 27 Jun 2017 13:28:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53208) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtlx-0007u9-TX for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsLE-0004gN-St for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34828) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsLD-0004Ts-7c; Tue, 27 Jun 2017 11:23:47 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1C39B796E9; Tue, 27 Jun 2017 15:23:46 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6B6E290C33; Tue, 27 Jun 2017 15:23:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 1C39B796E9 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 1C39B796E9 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:45 +0200 Message-Id: <20170627152248.10446-8-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 27 Jun 2017 15:23:46 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 07/10] block: invoke .bdrv_drain callback in coroutine context and from AioContext X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This will let the callback take a CoMutex in the next patch. Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/io.c | 42 +++++++++++++++++++++++++++++++++--------- block/qed.c | 6 +++--- include/block/block_int.h | 2 +- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/block/io.c b/block/io.c index 9bba730a7e..68f19bbe69 100644 --- a/block/io.c +++ b/block/io.c @@ -149,6 +149,37 @@ bool bdrv_requests_pending(BlockDriverState *bs) return false; } =20 +typedef struct { + Coroutine *co; + BlockDriverState *bs; + bool done; +} BdrvCoDrainData; + +static void coroutine_fn bdrv_drain_invoke_entry(void *opaque) +{ + BdrvCoDrainData *data =3D opaque; + BlockDriverState *bs =3D data->bs; + + bs->drv->bdrv_co_drain(bs); + + /* Set data->done before reading bs->wakeup. */ + atomic_mb_set(&data->done, true); + bdrv_wakeup(bs); +} + +static void bdrv_drain_invoke(BlockDriverState *bs) +{ + BdrvCoDrainData data =3D { .bs =3D bs, .done =3D false }; + + if (!bs->drv || !bs->drv->bdrv_co_drain) { + return; + } + + data.co =3D qemu_coroutine_create(bdrv_drain_invoke_entry, &data); + bdrv_coroutine_enter(bs, data.co); + BDRV_POLL_WHILE(bs, !data.done); +} + static bool bdrv_drain_recurse(BlockDriverState *bs) { BdrvChild *child, *tmp; @@ -156,9 +187,8 @@ static bool bdrv_drain_recurse(BlockDriverState *bs) =20 waited =3D BDRV_POLL_WHILE(bs, atomic_read(&bs->in_flight) > 0); =20 - if (bs->drv && bs->drv->bdrv_drain) { - bs->drv->bdrv_drain(bs); - } + /* Ensure any pending metadata writes are submitted to bs->file. */ + bdrv_drain_invoke(bs); =20 QLIST_FOREACH_SAFE(child, &bs->children, next, tmp) { BlockDriverState *bs =3D child->bs; @@ -184,12 +214,6 @@ static bool bdrv_drain_recurse(BlockDriverState *bs) return waited; } =20 -typedef struct { - Coroutine *co; - BlockDriverState *bs; - bool done; -} BdrvCoDrainData; - static void bdrv_co_drain_bh_cb(void *opaque) { BdrvCoDrainData *data =3D opaque; diff --git a/block/qed.c b/block/qed.c index 3ffdc1716d..454b7f0f2b 100644 --- a/block/qed.c +++ b/block/qed.c @@ -350,7 +350,7 @@ static void bdrv_qed_attach_aio_context(BlockDriverStat= e *bs, } } =20 -static void bdrv_qed_drain(BlockDriverState *bs) +static void coroutine_fn bdrv_qed_co_drain(BlockDriverState *bs) { BDRVQEDState *s =3D bs->opaque; =20 @@ -359,7 +359,7 @@ static void bdrv_qed_drain(BlockDriverState *bs) */ if (s->need_check_timer && timer_pending(s->need_check_timer)) { qed_cancel_need_check_timer(s); - qed_need_check_timer_cb(s); + qed_need_check_timer_entry(s); } } =20 @@ -1540,7 +1540,7 @@ static BlockDriver bdrv_qed =3D { .bdrv_check =3D bdrv_qed_check, .bdrv_detach_aio_context =3D bdrv_qed_detach_aio_context, .bdrv_attach_aio_context =3D bdrv_qed_attach_aio_context, - .bdrv_drain =3D bdrv_qed_drain, + .bdrv_co_drain =3D bdrv_qed_co_drain, }; =20 static void bdrv_qed_init(void) diff --git a/include/block/block_int.h b/include/block/block_int.h index 15fa602150..6d3fbbfc1e 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -321,7 +321,7 @@ struct BlockDriver { * Drain and stop any internal sources of requests in the driver, and * remain so until next I/O callback (e.g. bdrv_co_writev) is called. */ - void (*bdrv_drain)(BlockDriverState *bs); + void coroutine_fn (*bdrv_co_drain)(BlockDriverState *bs); =20 void (*bdrv_add_child)(BlockDriverState *parent, BlockDriverState *chi= ld, Error **errp); --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498585723311514.1610053784694; Tue, 27 Jun 2017 10:48:43 -0700 (PDT) Received: from localhost ([::1]:57458 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPubQ-0005KQ-PF for importer@patchew.org; Tue, 27 Jun 2017 13:48:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52799) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtlx-0007MS-HX for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsLI-0004ur-Oe for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60626) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsLF-0004hg-Pg; Tue, 27 Jun 2017 11:23:50 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D078FD7D7D; Tue, 27 Jun 2017 15:23:48 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 71E958D776; Tue, 27 Jun 2017 15:23:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D078FD7D7D Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com D078FD7D7D From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:46 +0200 Message-Id: <20170627152248.10446-9-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 27 Jun 2017 15:23:49 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 08/10] qed: protect table cache with CoMutex X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This makes the driver thread-safe. The CoMutex is dropped temporarily while accessing the data clusters or the backing file. Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/qed-cluster.c | 4 +- block/qed-l2-cache.c | 6 +++ block/qed-table.c | 24 +++++++--- block/qed.c | 130 ++++++++++++++++++++++++++++++++++-------------= ---- block/qed.h | 11 +++-- 5 files changed, 121 insertions(+), 54 deletions(-) diff --git a/block/qed-cluster.c b/block/qed-cluster.c index d8d6e66a0f..672e2e654b 100644 --- a/block/qed-cluster.c +++ b/block/qed-cluster.c @@ -85,6 +85,8 @@ static unsigned int qed_count_contiguous_clusters(BDRVQED= State *s, * * On failure QED_CLUSTER_L2 or QED_CLUSTER_L1 is returned for missing L2 = or L1 * table offset, respectively. len is number of contiguous unallocated byt= es. + * + * Called with table_lock held. */ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos, size_t *len, @@ -112,7 +114,6 @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDR= equest *request, } =20 ret =3D qed_read_l2_table(s, request, l2_offset); - qed_acquire(s); if (ret) { goto out; } @@ -137,6 +138,5 @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDR= equest *request, =20 out: *img_offset =3D offset; - qed_release(s); return ret; } diff --git a/block/qed-l2-cache.c b/block/qed-l2-cache.c index 5cba794650..b548362398 100644 --- a/block/qed-l2-cache.c +++ b/block/qed-l2-cache.c @@ -101,6 +101,8 @@ CachedL2Table *qed_alloc_l2_cache_entry(L2TableCache *l= 2_cache) /** * Decrease an entry's reference count and free if necessary when the refe= rence * count drops to zero. + * + * Called with table_lock held. */ void qed_unref_l2_cache_entry(CachedL2Table *entry) { @@ -122,6 +124,8 @@ void qed_unref_l2_cache_entry(CachedL2Table *entry) * * For a cached entry, this function increases the reference count and ret= urns * the entry. + * + * Called with table_lock held. */ CachedL2Table *qed_find_l2_cache_entry(L2TableCache *l2_cache, uint64_t of= fset) { @@ -150,6 +154,8 @@ CachedL2Table *qed_find_l2_cache_entry(L2TableCache *l2= _cache, uint64_t offset) * N.B. This function steals a reference to the l2_table from the caller s= o the * caller must obtain a new reference by issuing a call to * qed_find_l2_cache_entry(). + * + * Called with table_lock held. */ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_t= able) { diff --git a/block/qed-table.c b/block/qed-table.c index ebee2c50f0..eead8b0fc7 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -18,6 +18,7 @@ #include "qed.h" #include "qemu/bswap.h" =20 +/* Called either from qed_check or with table_lock held. */ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *tabl= e) { QEMUIOVector qiov; @@ -32,18 +33,22 @@ static int qed_read_table(BDRVQEDState *s, uint64_t off= set, QEDTable *table) =20 trace_qed_read_table(s, offset, table); =20 + if (qemu_in_coroutine()) { + qemu_co_mutex_unlock(&s->table_lock); + } ret =3D bdrv_preadv(s->bs->file, offset, &qiov); + if (qemu_in_coroutine()) { + qemu_co_mutex_lock(&s->table_lock); + } if (ret < 0) { goto out; } =20 /* Byteswap offsets */ - qed_acquire(s); noffsets =3D qiov.size / sizeof(uint64_t); for (i =3D 0; i < noffsets; i++) { table->offsets[i] =3D le64_to_cpu(table->offsets[i]); } - qed_release(s); =20 ret =3D 0; out: @@ -61,6 +66,8 @@ out: * @index: Index of first element * @n: Number of elements * @flush: Whether or not to sync to disk + * + * Called either from qed_check or with table_lock held. */ static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *tab= le, unsigned int index, unsigned int n, bool flush) @@ -97,16 +104,20 @@ static int qed_write_table(BDRVQEDState *s, uint64_t o= ffset, QEDTable *table, /* Adjust for offset into table */ offset +=3D start * sizeof(uint64_t); =20 + if (qemu_in_coroutine()) { + qemu_co_mutex_unlock(&s->table_lock); + } ret =3D bdrv_pwritev(s->bs->file, offset, &qiov); + if (qemu_in_coroutine()) { + qemu_co_mutex_lock(&s->table_lock); + } trace_qed_write_table_cb(s, table, flush, ret); if (ret < 0) { goto out; } =20 if (flush) { - qed_acquire(s); ret =3D bdrv_flush(s->bs); - qed_release(s); if (ret < 0) { goto out; } @@ -123,6 +134,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s) return qed_read_table(s, s->header.l1_table_offset, s->l1_table); } =20 +/* Called either from qed_check or with table_lock held. */ int qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n) { BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE); @@ -136,6 +148,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned i= nt index, return qed_write_l1_table(s, index, n); } =20 +/* Called either from qed_check or with table_lock held. */ int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offse= t) { int ret; @@ -154,7 +167,6 @@ int qed_read_l2_table(BDRVQEDState *s, QEDRequest *requ= est, uint64_t offset) BLKDBG_EVENT(s->bs->file, BLKDBG_L2_LOAD); ret =3D qed_read_table(s, offset, request->l2_table->table); =20 - qed_acquire(s); if (ret) { /* can't trust loaded L2 table anymore */ qed_unref_l2_cache_entry(request->l2_table); @@ -170,7 +182,6 @@ int qed_read_l2_table(BDRVQEDState *s, QEDRequest *requ= est, uint64_t offset) request->l2_table =3D qed_find_l2_cache_entry(&s->l2_cache, offset= ); assert(request->l2_table !=3D NULL); } - qed_release(s); =20 return ret; } @@ -180,6 +191,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest = *request, uint64_t offset return qed_read_l2_table(s, request, offset); } =20 +/* Called either from qed_check or with table_lock held. */ int qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index, unsigned int n, bool flush) { diff --git a/block/qed.c b/block/qed.c index 454b7f0f2b..9337a9082b 100644 --- a/block/qed.c +++ b/block/qed.c @@ -93,6 +93,8 @@ int qed_write_header_sync(BDRVQEDState *s) * * This function only updates known header fields in-place and does not af= fect * extra data after the QED header. + * + * No new allocating reqs can start while this function runs. */ static int coroutine_fn qed_write_header(BDRVQEDState *s) { @@ -109,6 +111,8 @@ static int coroutine_fn qed_write_header(BDRVQEDState *= s) QEMUIOVector qiov; int ret; =20 + assert(s->allocating_acb || s->allocating_write_reqs_plugged); + buf =3D qemu_blockalign(s->bs, len); iov =3D (struct iovec) { .iov_base =3D buf, @@ -219,6 +223,8 @@ static int qed_read_string(BdrvChild *file, uint64_t of= fset, size_t n, * This function only produces the offset where the new clusters should be * written. It updates BDRVQEDState but does not make any changes to the = image * file. + * + * Called with table_lock held. */ static uint64_t qed_alloc_clusters(BDRVQEDState *s, unsigned int n) { @@ -236,6 +242,8 @@ QEDTable *qed_alloc_table(BDRVQEDState *s) =20 /** * Allocate a new zeroed L2 table + * + * Called with table_lock held. */ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s) { @@ -249,19 +257,32 @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *= s) return l2_table; } =20 -static void qed_plug_allocating_write_reqs(BDRVQEDState *s) +static bool qed_plug_allocating_write_reqs(BDRVQEDState *s) { + qemu_co_mutex_lock(&s->table_lock); + + /* No reentrancy is allowed. */ assert(!s->allocating_write_reqs_plugged); + if (s->allocating_acb !=3D NULL) { + /* Another allocating write came concurrently. This cannot happen + * from bdrv_qed_co_drain, but it can happen when the timer runs. + */ + qemu_co_mutex_unlock(&s->table_lock); + return false; + } =20 s->allocating_write_reqs_plugged =3D true; + qemu_co_mutex_unlock(&s->table_lock); + return true; } =20 static void qed_unplug_allocating_write_reqs(BDRVQEDState *s) { + qemu_co_mutex_lock(&s->table_lock); assert(s->allocating_write_reqs_plugged); - s->allocating_write_reqs_plugged =3D false; - qemu_co_enter_next(&s->allocating_write_reqs); + qemu_co_queue_next(&s->allocating_write_reqs); + qemu_co_mutex_unlock(&s->table_lock); } =20 static void coroutine_fn qed_need_check_timer_entry(void *opaque) @@ -269,17 +290,14 @@ static void coroutine_fn qed_need_check_timer_entry(v= oid *opaque) BDRVQEDState *s =3D opaque; int ret; =20 - /* The timer should only fire when allocating writes have drained */ - assert(!s->allocating_acb); - trace_qed_need_check_timer_cb(s); =20 - qed_acquire(s); - qed_plug_allocating_write_reqs(s); + if (!qed_plug_allocating_write_reqs(s)) { + return; + } =20 /* Ensure writes are on disk before clearing flag */ ret =3D bdrv_co_flush(s->bs->file->bs); - qed_release(s); if (ret < 0) { qed_unplug_allocating_write_reqs(s); return; @@ -301,16 +319,6 @@ static void qed_need_check_timer_cb(void *opaque) qemu_coroutine_enter(co); } =20 -void qed_acquire(BDRVQEDState *s) -{ - aio_context_acquire(bdrv_get_aio_context(s->bs)); -} - -void qed_release(BDRVQEDState *s) -{ - aio_context_release(bdrv_get_aio_context(s->bs)); -} - static void qed_start_need_check_timer(BDRVQEDState *s) { trace_qed_start_need_check_timer(s); @@ -372,6 +380,7 @@ static int bdrv_qed_do_open(BlockDriverState *bs, QDict= *options, int flags, int ret; =20 s->bs =3D bs; + qemu_co_mutex_init(&s->table_lock); qemu_co_queue_init(&s->allocating_write_reqs); =20 ret =3D bdrv_pread(bs->file, 0, &le_header, sizeof(le_header)); @@ -681,6 +690,7 @@ typedef struct { BlockDriverState **file; } QEDIsAllocatedCB; =20 +/* Called with table_lock held. */ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, si= ze_t len) { QEDIsAllocatedCB *cb =3D opaque; @@ -728,6 +738,7 @@ static int64_t coroutine_fn bdrv_qed_co_get_block_statu= s(BlockDriverState *bs, uint64_t offset; int ret; =20 + qemu_co_mutex_lock(&s->table_lock); ret =3D qed_find_cluster(s, &request, cb.pos, &len, &offset); qed_is_allocated_cb(&cb, ret, offset, len); =20 @@ -735,6 +746,7 @@ static int64_t coroutine_fn bdrv_qed_co_get_block_statu= s(BlockDriverState *bs, assert(cb.status !=3D BDRV_BLOCK_OFFSET_MASK); =20 qed_unref_l2_cache_entry(request.l2_table); + qemu_co_mutex_unlock(&s->table_lock); =20 return cb.status; } @@ -865,6 +877,8 @@ out: * * The cluster offset may be an allocated byte offset in the image file, t= he * zero cluster marker, or the unallocated cluster marker. + * + * Called with table_lock held. */ static void coroutine_fn qed_update_l2_table(BDRVQEDState *s, QEDTable *ta= ble, int index, unsigned int n, @@ -880,6 +894,7 @@ static void coroutine_fn qed_update_l2_table(BDRVQEDSta= te *s, QEDTable *table, } } =20 +/* Called with table_lock held. */ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb) { BDRVQEDState *s =3D acb_to_s(acb); @@ -903,7 +918,7 @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb) if (acb =3D=3D s->allocating_acb) { s->allocating_acb =3D NULL; if (!qemu_co_queue_empty(&s->allocating_write_reqs)) { - qemu_co_enter_next(&s->allocating_write_reqs); + qemu_co_queue_next(&s->allocating_write_reqs); } else if (s->header.features & QED_F_NEED_CHECK) { qed_start_need_check_timer(s); } @@ -912,6 +927,8 @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb) =20 /** * Update L1 table with new L2 table offset and write it out + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb) { @@ -940,6 +957,8 @@ static int coroutine_fn qed_aio_write_l1_update(QEDAIOC= B *acb) =20 /** * Update L2 table with new cluster offsets and write them out + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t of= fset) { @@ -976,6 +995,8 @@ static int coroutine_fn qed_aio_write_l2_update(QEDAIOC= B *acb, uint64_t offset) =20 /** * Write data to the image file + * + * Called with table_lock *not* held. */ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb) { @@ -991,6 +1012,8 @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *a= cb) =20 /** * Populate untouched regions of new data cluster + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb) { @@ -998,6 +1021,8 @@ static int coroutine_fn qed_aio_write_cow(QEDAIOCB *ac= b) uint64_t start, len, offset; int ret; =20 + qemu_co_mutex_unlock(&s->table_lock); + /* Populate front untouched region of new data cluster */ start =3D qed_start_of_cluster(s, acb->cur_pos); len =3D qed_offset_into_cluster(s, acb->cur_pos); @@ -1005,7 +1030,7 @@ static int coroutine_fn qed_aio_write_cow(QEDAIOCB *a= cb) trace_qed_aio_write_prefill(s, acb, start, len, acb->cur_cluster); ret =3D qed_copy_from_backing_file(s, start, len, acb->cur_cluster); if (ret < 0) { - return ret; + goto out; } =20 /* Populate back untouched region of new data cluster */ @@ -1018,12 +1043,12 @@ static int coroutine_fn qed_aio_write_cow(QEDAIOCB = *acb) trace_qed_aio_write_postfill(s, acb, start, len, offset); ret =3D qed_copy_from_backing_file(s, start, len, offset); if (ret < 0) { - return ret; + goto out; } =20 ret =3D qed_aio_write_main(acb); if (ret < 0) { - return ret; + goto out; } =20 if (s->bs->backing) { @@ -1038,12 +1063,11 @@ static int coroutine_fn qed_aio_write_cow(QEDAIOCB = *acb) * cluster and before updating the L2 table. */ ret =3D bdrv_co_flush(s->bs->file->bs); - if (ret < 0) { - return ret; - } } =20 - return 0; +out: + qemu_co_mutex_lock(&s->table_lock); + return ret; } =20 /** @@ -1066,6 +1090,8 @@ static bool qed_should_set_need_check(BDRVQEDState *s) * @len: Length in bytes * * This path is taken when writing to previously unallocated clusters. + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len) { @@ -1080,7 +1106,7 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOCB = *acb, size_t len) /* Freeze this request if another allocating write is in progress */ if (s->allocating_acb !=3D acb || s->allocating_write_reqs_plugged) { if (s->allocating_acb !=3D NULL) { - qemu_co_queue_wait(&s->allocating_write_reqs, NULL); + qemu_co_queue_wait(&s->allocating_write_reqs, &s->table_lock); assert(s->allocating_acb =3D=3D NULL); } s->allocating_acb =3D acb; @@ -1127,10 +1153,17 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOC= B *acb, size_t len) * @len: Length in bytes * * This path is taken when writing to already allocated clusters. + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offs= et, size_t len) { + BDRVQEDState *s =3D acb_to_s(acb); + int r; + + qemu_co_mutex_unlock(&s->table_lock); + /* Allocate buffer for zero writes */ if (acb->flags & QED_AIOCB_ZERO) { struct iovec *iov =3D acb->qiov->iov; @@ -1138,7 +1171,8 @@ static int coroutine_fn qed_aio_write_inplace(QEDAIOC= B *acb, uint64_t offset, if (!iov->iov_base) { iov->iov_base =3D qemu_try_blockalign(acb->bs, iov->iov_len); if (iov->iov_base =3D=3D NULL) { - return -ENOMEM; + r =3D -ENOMEM; + goto out; } memset(iov->iov_base, 0, iov->iov_len); } @@ -1148,8 +1182,11 @@ static int coroutine_fn qed_aio_write_inplace(QEDAIO= CB *acb, uint64_t offset, acb->cur_cluster =3D offset; qemu_iovec_concat(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len); =20 - /* Do the actual write */ - return qed_aio_write_main(acb); + /* Do the actual write. */ + r =3D qed_aio_write_main(acb); +out: + qemu_co_mutex_lock(&s->table_lock); + return r; } =20 /** @@ -1159,6 +1196,8 @@ static int coroutine_fn qed_aio_write_inplace(QEDAIOC= B *acb, uint64_t offset, * @ret: QED_CLUSTER_FOUND, QED_CLUSTER_L2 or QED_CLUSTER_L1 * @offset: Cluster offset in bytes * @len: Length in bytes + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len) @@ -1190,6 +1229,8 @@ static int coroutine_fn qed_aio_write_data(void *opaq= ue, int ret, * @ret: QED_CLUSTER_FOUND, QED_CLUSTER_L2 or QED_CLUSTER_L1 * @offset: Cluster offset in bytes * @len: Length in bytes + * + * Called with table_lock held. */ static int coroutine_fn qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len) @@ -1197,6 +1238,9 @@ static int coroutine_fn qed_aio_read_data(void *opaqu= e, int ret, QEDAIOCB *acb =3D opaque; BDRVQEDState *s =3D acb_to_s(acb); BlockDriverState *bs =3D acb->bs; + int r; + + qemu_co_mutex_unlock(&s->table_lock); =20 /* Adjust offset into cluster */ offset +=3D qed_offset_into_cluster(s, acb->cur_pos); @@ -1205,22 +1249,22 @@ static int coroutine_fn qed_aio_read_data(void *opa= que, int ret, =20 qemu_iovec_concat(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len); =20 - /* Handle zero cluster and backing file reads */ + /* Handle zero cluster and backing file reads, otherwise read + * data cluster directly. + */ if (ret =3D=3D QED_CLUSTER_ZERO) { qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size); - return 0; + r =3D 0; } else if (ret !=3D QED_CLUSTER_FOUND) { - return qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov, - &acb->backing_qiov); + r =3D qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov, + &acb->backing_qiov); + } else { + BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); + r =3D bdrv_co_preadv(bs->file, offset, &acb->cur_qiov); } =20 - BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - ret =3D bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size, - &acb->cur_qiov, 0); - if (ret < 0) { - return ret; - } - return 0; + qemu_co_mutex_lock(&s->table_lock); + return r; } =20 /** @@ -1233,6 +1277,7 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb) size_t len; int ret; =20 + qemu_co_mutex_lock(&s->table_lock); while (1) { trace_qed_aio_next_io(s, acb, 0, acb->cur_pos + acb->cur_qiov.size= ); =20 @@ -1272,6 +1317,7 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb) =20 trace_qed_aio_complete(s, acb, ret); qed_aio_complete(acb); + qemu_co_mutex_unlock(&s->table_lock); return ret; } =20 diff --git a/block/qed.h b/block/qed.h index dd3a2d5519..f35341f134 100644 --- a/block/qed.h +++ b/block/qed.h @@ -151,15 +151,21 @@ typedef struct QEDAIOCB { =20 typedef struct { BlockDriverState *bs; /* device */ - uint64_t file_size; /* length of image file, in bytes */ =20 + /* Written only by an allocating write or the timer handler (the latter + * while allocating reqs are plugged). + */ QEDHeader header; /* always cpu-endian */ + + /* Protected by table_lock. */ + CoMutex table_lock; QEDTable *l1_table; L2TableCache l2_cache; /* l2 table cache */ uint32_t table_nelems; uint32_t l1_shift; uint32_t l2_shift; uint32_t l2_mask; + uint64_t file_size; /* length of image file, in bytes */ =20 /* Allocating write request queue */ QEDAIOCB *allocating_acb; @@ -177,9 +183,6 @@ enum { QED_CLUSTER_L1, /* cluster missing in L1 */ }; =20 -void qed_acquire(BDRVQEDState *s); -void qed_release(BDRVQEDState *s); - /** * Header functions */ --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498584128921874.9220001920954; Tue, 27 Jun 2017 10:22:08 -0700 (PDT) Received: from localhost ([::1]:57267 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuBg-0007kQ-9i for importer@patchew.org; Tue, 27 Jun 2017 13:22:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54476) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtlx-0000HQ-B3 for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsLM-00056v-A7 for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:23:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55534) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsLK-0004zl-Q0; Tue, 27 Jun 2017 11:23:54 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CA9A28008D; Tue, 27 Jun 2017 15:23:53 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2F281902A8; Tue, 27 Jun 2017 15:23:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com CA9A28008D Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com CA9A28008D From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:47 +0200 Message-Id: <20170627152248.10446-10-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 27 Jun 2017 15:23:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 09/10] sheepdog: add queue_lock X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/sheepdog.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 08d7b11e9d..a6013f0f17 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -390,6 +390,7 @@ struct BDRVSheepdogState { QLIST_HEAD(inflight_aio_head, AIOReq) inflight_aio_head; QLIST_HEAD(failed_aio_head, AIOReq) failed_aio_head; =20 + CoMutex queue_lock; CoQueue overlapping_queue; QLIST_HEAD(inflight_aiocb_head, SheepdogAIOCB) inflight_aiocb_head; }; @@ -488,7 +489,7 @@ static void wait_for_overlapping_aiocb(BDRVSheepdogStat= e *s, SheepdogAIOCB *acb) retry: QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) { if (AIOCBOverlapping(acb, cb)) { - qemu_co_queue_wait(&s->overlapping_queue, NULL); + qemu_co_queue_wait(&s->overlapping_queue, &s->queue_lock); goto retry; } } @@ -525,8 +526,10 @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheep= dogState *s, return; } =20 + qemu_co_mutex_lock(&s->queue_lock); wait_for_overlapping_aiocb(s, acb); QLIST_INSERT_HEAD(&s->inflight_aiocb_head, acb, aiocb_siblings); + qemu_co_mutex_unlock(&s->queue_lock); } =20 static SocketAddress *sd_socket_address(const char *path, @@ -785,6 +788,7 @@ static coroutine_fn void reconnect_to_sdog(void *opaque) * have to move all the inflight requests to the failed queue before * resend_aioreq() is called. */ + qemu_co_mutex_lock(&s->queue_lock); QLIST_FOREACH_SAFE(aio_req, &s->inflight_aio_head, aio_siblings, next)= { QLIST_REMOVE(aio_req, aio_siblings); QLIST_INSERT_HEAD(&s->failed_aio_head, aio_req, aio_siblings); @@ -794,8 +798,11 @@ static coroutine_fn void reconnect_to_sdog(void *opaqu= e) while (!QLIST_EMPTY(&s->failed_aio_head)) { aio_req =3D QLIST_FIRST(&s->failed_aio_head); QLIST_REMOVE(aio_req, aio_siblings); + qemu_co_mutex_unlock(&s->queue_lock); resend_aioreq(s, aio_req); + qemu_co_mutex_lock(&s->queue_lock); } + qemu_co_mutex_unlock(&s->queue_lock); } =20 /* @@ -887,7 +894,10 @@ static void coroutine_fn aio_read_response(void *opaqu= e) */ s->co_recv =3D NULL; =20 + qemu_co_mutex_lock(&s->queue_lock); QLIST_REMOVE(aio_req, aio_siblings); + qemu_co_mutex_unlock(&s->queue_lock); + switch (rsp.result) { case SD_RES_SUCCESS: break; @@ -1307,7 +1317,9 @@ static void coroutine_fn add_aio_request(BDRVSheepdog= State *s, AIOReq *aio_req, uint64_t old_oid =3D aio_req->base_oid; bool create =3D aio_req->create; =20 + qemu_co_mutex_lock(&s->queue_lock); QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings); + qemu_co_mutex_unlock(&s->queue_lock); =20 if (!nr_copies) { error_report("bug"); @@ -1678,6 +1690,7 @@ static int sd_open(BlockDriverState *bs, QDict *optio= ns, int flags, bs->total_sectors =3D s->inode.vdi_size / BDRV_SECTOR_SIZE; pstrcpy(s->name, sizeof(s->name), vdi); qemu_co_mutex_init(&s->lock); + qemu_co_mutex_init(&s->queue_lock); qemu_co_queue_init(&s->overlapping_queue); qemu_opts_del(opts); g_free(buf); @@ -2431,12 +2444,16 @@ static void coroutine_fn sd_co_rw_vector(SheepdogAI= OCB *acb) =20 static void sd_aio_complete(SheepdogAIOCB *acb) { + BDRVSheepdogState *s; if (acb->aiocb_type =3D=3D AIOCB_FLUSH_CACHE) { return; } =20 + s =3D acb->s; + qemu_co_mutex_lock(&s->queue_lock); QLIST_REMOVE(acb, aiocb_siblings); - qemu_co_queue_restart_all(&acb->s->overlapping_queue); + qemu_co_queue_restart_all(&s->overlapping_queue); + qemu_co_mutex_unlock(&s->queue_lock); } =20 static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_= num, --=20 2.13.0 From nobody Sun May 5 17:38:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1498584659621974.0159212360895; Tue, 27 Jun 2017 10:30:59 -0700 (PDT) Received: from localhost ([::1]:57328 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPuKI-0007MQ-50 for importer@patchew.org; Tue, 27 Jun 2017 13:30:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53013) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPtlx-0007bW-4c for qemu-devel@nongnu.org; Tue, 27 Jun 2017 12:55:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPsLP-0005JQ-SL for qemu-devel@nongnu.org; Tue, 27 Jun 2017 11:24:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52132) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dPsLO-0005DF-ND; Tue, 27 Jun 2017 11:23:58 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C47987C84C; Tue, 27 Jun 2017 15:23:57 +0000 (UTC) Received: from donizetti.redhat.com (unknown [10.36.117.255]) by smtp.corp.redhat.com (Postfix) with ESMTP id 845278D771; Tue, 27 Jun 2017 15:23:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C47987C84C Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com C47987C84C From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 27 Jun 2017 17:22:48 +0200 Message-Id: <20170627152248.10446-11-pbonzini@redhat.com> In-Reply-To: <20170627152248.10446-1-pbonzini@redhat.com> References: <20170627152248.10446-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 27 Jun 2017 15:23:57 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 10/10] ssh: support I/O from any AioContext X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The coroutine may run in a different AioContext, causing the fd handler to busy wait. Fix this by resetting the handler in restart_coroutine, before the coroutine is restarted. Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- block/ssh.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/block/ssh.c b/block/ssh.c index 52964416da..e6a5b08de3 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -888,13 +888,22 @@ static int ssh_has_zero_init(BlockDriverState *bs) return has_zero_init; } =20 +typedef struct BDRVSSHRestart { + BlockDriverState *bs; + Coroutine *co; +} BDRVSSHRestart; + static void restart_coroutine(void *opaque) { - Coroutine *co =3D opaque; + BDRVSSHRestart *restart =3D opaque; + BlockDriverState *bs =3D restart->bs; + BDRVSSHState *s =3D bs->opaque; + AioContext *ctx =3D bdrv_get_aio_context(bs); =20 - DPRINTF("co=3D%p", co); + DPRINTF("co=3D%p", restart->co); + aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL); =20 - aio_co_wake(co); + aio_co_wake(restart->co); } =20 /* A non-blocking call returned EAGAIN, so yield, ensuring the @@ -905,7 +914,10 @@ static coroutine_fn void co_yield(BDRVSSHState *s, Blo= ckDriverState *bs) { int r; IOHandler *rd_handler =3D NULL, *wr_handler =3D NULL; - Coroutine *co =3D qemu_coroutine_self(); + BDRVSSHRestart restart =3D { + .bs =3D bs, + .co =3D qemu_coroutine_self() + }; =20 r =3D libssh2_session_block_directions(s->session); =20 @@ -920,11 +932,9 @@ static coroutine_fn void co_yield(BDRVSSHState *s, Blo= ckDriverState *bs) rd_handler, wr_handler); =20 aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, - false, rd_handler, wr_handler, NULL, co); + false, rd_handler, wr_handler, NULL, &restart); qemu_coroutine_yield(); DPRINTF("s->sock=3D%d - back", s->sock); - aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, false, - NULL, NULL, NULL, NULL); } =20 /* SFTP has a function `libssh2_sftp_seek64' which seeks to a position --=20 2.13.0