From patchwork Wed Feb 13 13:21:53 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 220169 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 698512C0293 for ; Thu, 14 Feb 2013 02:36:09 +1100 (EST) Received: from localhost ([::1]:34223 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U5cIx-0007Uf-ML for incoming@patchwork.ozlabs.org; Wed, 13 Feb 2013 08:23:19 -0500 Received: from eggs.gnu.org ([208.118.235.92]:51530) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U5cIE-0005m3-Hh for qemu-devel@nongnu.org; Wed, 13 Feb 2013 08:22:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U5cI8-0002pA-6x for qemu-devel@nongnu.org; Wed, 13 Feb 2013 08:22:34 -0500 Received: from mx1.redhat.com ([209.132.183.28]:10529) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U5cI7-0002p0-Va for qemu-devel@nongnu.org; Wed, 13 Feb 2013 08:22:28 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r1DDMRYI006839 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 13 Feb 2013 08:22:27 -0500 Received: from dhcp-5-188.str.redhat.com (dhcp-192-240.str.redhat.com [10.33.192.240]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r1DDMGRa011418; Wed, 13 Feb 2013 08:22:25 -0500 From: Kevin Wolf To: qemu-devel@nongnu.org Date: Wed, 13 Feb 2013 14:21:53 +0100 Message-Id: <1360761733-25347-4-git-send-email-kwolf@redhat.com> In-Reply-To: <1360761733-25347-1-git-send-email-kwolf@redhat.com> References: <1360761733-25347-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, pbonzini@redhat.com, lersek@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [RFC PATCH v2 03/23] qcow2: Change handle_dependency to byte granularity X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 40 ++++++++++++++++++++++++++++------------ block/qcow2.h | 11 +++++++++++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 0e804ba..a3b2447 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -756,31 +756,41 @@ out: * Check if there already is an AIO write request in flight which allocates * the same cluster. In this case we need to wait until the previous * request has completed and updated the L2 table accordingly. + * + * Returns: + * 0 if there was no dependency. *cur_bytes indicates the number of + * bytes from guest_offset that can be read before the next + * dependency must be processed (or the request is complete) + * + * -EAGAIN if we had to wait for another request, previously gathered + * information on cluster allocation may be invalid now. The caller + * must start over anyway, so consider *cur_bytes undefined. */ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, - unsigned int *nb_clusters) + uint64_t *cur_bytes) { BDRVQcowState *s = bs->opaque; QCowL2Meta *old_alloc; + uint64_t bytes = *cur_bytes; QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) { - uint64_t start = guest_offset >> s->cluster_bits; - uint64_t end = start + *nb_clusters; - uint64_t old_start = old_alloc->offset >> s->cluster_bits; - uint64_t old_end = old_start + old_alloc->nb_clusters; + uint64_t start = guest_offset; + uint64_t end = start + bytes; + uint64_t old_start = l2meta_cow_start(old_alloc); + uint64_t old_end = l2meta_cow_end(old_alloc); if (end <= old_start || start >= old_end) { /* No intersection */ } else { if (start < old_start) { /* Stop at the start of a running allocation */ - *nb_clusters = old_start - start; + bytes = old_start - start; } else { - *nb_clusters = 0; + bytes = 0; } - if (*nb_clusters == 0) { + if (bytes == 0) { /* Wait for the dependency to complete. We need to recheck * the free/allocated clusters when we continue. */ qemu_co_mutex_unlock(&s->lock); @@ -791,9 +801,9 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, } } - if (!*nb_clusters) { - abort(); - } + /* Make sure that existing clusters and new allocations are only used up to + * the next dependency if we shortened the request above */ + *cur_bytes = bytes; return 0; } @@ -872,6 +882,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, uint64_t *l2_table; unsigned int nb_clusters, keep_clusters; uint64_t cluster_offset; + uint64_t cur_bytes; trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, n_start, n_end); @@ -884,6 +895,7 @@ again: l2_index = offset_to_l2_index(s, offset); nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS), s->l2_size - l2_index); + n_end = MIN(n_end, nb_clusters * s->cluster_sectors); /* * Now start gathering as many contiguous clusters as possible: @@ -908,7 +920,8 @@ again: * 3. If the request still hasn't completed, allocate new clusters, * considering any cluster_offset of steps 1c or 2. */ - ret = handle_dependencies(bs, offset, &nb_clusters); + cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE; + ret = handle_dependencies(bs, offset, &cur_bytes); if (ret == -EAGAIN) { goto again; } else if (ret < 0) { @@ -919,6 +932,9 @@ again: * correctly during the next loop iteration. */ } + nb_clusters = size_to_clusters(s, offset + cur_bytes) + - (offset >> s->cluster_bits); + /* Find L2 entry for the first involved cluster */ ret = get_cluster_table(bs, offset, &l2_table, &l2_index); if (ret < 0) { diff --git a/block/qcow2.h b/block/qcow2.h index 1322012..72e6d12 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -303,6 +303,17 @@ static inline bool qcow2_need_accurate_refcounts(BDRVQcowState *s) return !(s->incompatible_features & QCOW2_INCOMPAT_DIRTY); } +static inline uint64_t l2meta_cow_start(QCowL2Meta *m) +{ + return m->offset + m->cow_start.offset; +} + +static inline uint64_t l2meta_cow_end(QCowL2Meta *m) +{ + return m->offset + m->cow_end.offset + + (m->cow_end.nb_sectors << BDRV_SECTOR_BITS); +} + // FIXME Need qcow2_ prefix to global functions /* qcow2.c functions */