From patchwork Fri Jul 7 17:07:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 9830853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D361F60352 for ; Fri, 7 Jul 2017 17:38:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9F2228683 for ; Fri, 7 Jul 2017 17:38:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AE486286E6; Fri, 7 Jul 2017 17:38:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 08A3928683 for ; Fri, 7 Jul 2017 17:38:10 +0000 (UTC) Received: from localhost ([::1]:57847 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dTXCj-0004UD-95 for patchwork-qemu-devel@patchwork.kernel.org; Fri, 07 Jul 2017 13:38:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41987) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dTWlR-0005IJ-H9 for qemu-devel@nongnu.org; Fri, 07 Jul 2017 13:09:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dTWlM-00088V-Kw for qemu-devel@nongnu.org; Fri, 07 Jul 2017 13:09:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49860) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dTWlI-000830-Ui; Fri, 07 Jul 2017 13:09:49 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F0F978B11B; Fri, 7 Jul 2017 17:09:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F0F978B11B 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=kwolf@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F0F978B11B Received: from noname.redhat.com (ovpn-117-34.ams2.redhat.com [10.36.117.34]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0DAF961F52; Fri, 7 Jul 2017 17:09:46 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 7 Jul 2017 19:07:47 +0200 Message-Id: <1499447335-6125-33-git-send-email-kwolf@redhat.com> In-Reply-To: <1499447335-6125-1-git-send-email-kwolf@redhat.com> References: <1499447335-6125-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 07 Jul 2017 17:09:48 +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] [PULL 032/100] mirror: Switch mirror_iteration() to byte-based 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-devel@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Blake We are gradually converting to byte-based interfaces, as they are easier to reason about than sector-based. Change the internal loop iteration of mirroring to track by bytes instead of sectors (although we are still guaranteed that we iterate by steps that are both sector-aligned and multiples of the granularity). Drop the now-unused mirror_clip_sectors(). Signed-off-by: Eric Blake Reviewed-by: John Snow Reviewed-by: Jeff Cody Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/mirror.c | 105 +++++++++++++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 59 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 262fddf..b33f4bb 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -184,15 +184,6 @@ static inline int64_t mirror_clip_bytes(MirrorBlockJob *s, return MIN(bytes, s->bdev_length - offset); } -/* Clip nb_sectors relative to sector_num to not exceed end-of-file */ -static inline int mirror_clip_sectors(MirrorBlockJob *s, - int64_t sector_num, - int nb_sectors) -{ - return MIN(nb_sectors, - s->bdev_length / BDRV_SECTOR_SIZE - sector_num); -} - /* Round offset and/or bytes to target cluster if COW is needed, and * return the offset of the adjusted tail against original. */ static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset, @@ -336,30 +327,28 @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s, static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) { BlockDriverState *source = s->source; - int64_t sector_num, first_chunk; + int64_t offset, first_chunk; uint64_t delay_ns = 0; /* At least the first dirty chunk is mirrored in one iteration. */ int nb_chunks = 1; - int64_t end = s->bdev_length / BDRV_SECTOR_SIZE; int sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)); int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES); bdrv_dirty_bitmap_lock(s->dirty_bitmap); - sector_num = bdrv_dirty_iter_next(s->dbi); - if (sector_num < 0) { + offset = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE; + if (offset < 0) { bdrv_set_dirty_iter(s->dbi, 0); - sector_num = bdrv_dirty_iter_next(s->dbi); + offset = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE; trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap) * BDRV_SECTOR_SIZE); - assert(sector_num >= 0); + assert(offset >= 0); } bdrv_dirty_bitmap_unlock(s->dirty_bitmap); - first_chunk = sector_num / sectors_per_chunk; + first_chunk = offset / s->granularity; while (test_bit(first_chunk, s->in_flight_bitmap)) { - trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE, - s->in_flight); + trace_mirror_yield_in_flight(s, offset, s->in_flight); mirror_wait_for_io(s); } @@ -368,25 +357,26 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) /* Find the number of consective dirty chunks following the first dirty * one, and wait for in flight requests in them. */ bdrv_dirty_bitmap_lock(s->dirty_bitmap); - while (nb_chunks * sectors_per_chunk < (s->buf_size >> BDRV_SECTOR_BITS)) { + while (nb_chunks * s->granularity < s->buf_size) { int64_t next_dirty; - int64_t next_sector = sector_num + nb_chunks * sectors_per_chunk; - int64_t next_chunk = next_sector / sectors_per_chunk; - if (next_sector >= end || - !bdrv_get_dirty_locked(source, s->dirty_bitmap, next_sector)) { + int64_t next_offset = offset + nb_chunks * s->granularity; + int64_t next_chunk = next_offset / s->granularity; + if (next_offset >= s->bdev_length || + !bdrv_get_dirty_locked(source, s->dirty_bitmap, + next_offset >> BDRV_SECTOR_BITS)) { break; } if (test_bit(next_chunk, s->in_flight_bitmap)) { break; } - next_dirty = bdrv_dirty_iter_next(s->dbi); - if (next_dirty > next_sector || next_dirty < 0) { + next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE; + if (next_dirty > next_offset || next_dirty < 0) { /* The bitmap iterator's cache is stale, refresh it */ - bdrv_set_dirty_iter(s->dbi, next_sector); - next_dirty = bdrv_dirty_iter_next(s->dbi); + bdrv_set_dirty_iter(s->dbi, next_offset >> BDRV_SECTOR_BITS); + next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE; } - assert(next_dirty == next_sector); + assert(next_dirty == next_offset); nb_chunks++; } @@ -394,14 +384,15 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) * calling bdrv_get_block_status_above could yield - if some blocks are * marked dirty in this window, we need to know. */ - bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, sector_num, - nb_chunks * sectors_per_chunk); + bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, offset >> BDRV_SECTOR_BITS, + nb_chunks * sectors_per_chunk); bdrv_dirty_bitmap_unlock(s->dirty_bitmap); - bitmap_set(s->in_flight_bitmap, sector_num / sectors_per_chunk, nb_chunks); - while (nb_chunks > 0 && sector_num < end) { + bitmap_set(s->in_flight_bitmap, offset / s->granularity, nb_chunks); + while (nb_chunks > 0 && offset < s->bdev_length) { int64_t ret; int io_sectors; + unsigned int io_bytes; int64_t io_bytes_acct; BlockDriverState *file; enum MirrorMethod { @@ -410,28 +401,28 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) MIRROR_METHOD_DISCARD } mirror_method = MIRROR_METHOD_COPY; - assert(!(sector_num % sectors_per_chunk)); - ret = bdrv_get_block_status_above(source, NULL, sector_num, + assert(!(offset % s->granularity)); + ret = bdrv_get_block_status_above(source, NULL, + offset >> BDRV_SECTOR_BITS, nb_chunks * sectors_per_chunk, &io_sectors, &file); + io_bytes = io_sectors * BDRV_SECTOR_SIZE; if (ret < 0) { - io_sectors = MIN(nb_chunks * sectors_per_chunk, - max_io_bytes >> BDRV_SECTOR_BITS); + io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes); } else if (ret & BDRV_BLOCK_DATA) { - io_sectors = MIN(io_sectors, max_io_bytes >> BDRV_SECTOR_BITS); + io_bytes = MIN(io_bytes, max_io_bytes); } - io_sectors -= io_sectors % sectors_per_chunk; - if (io_sectors < sectors_per_chunk) { - io_sectors = sectors_per_chunk; + io_bytes -= io_bytes % s->granularity; + if (io_bytes < s->granularity) { + io_bytes = s->granularity; } else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) { - int64_t target_sector_num; - int target_nb_sectors; - bdrv_round_sectors_to_clusters(blk_bs(s->target), sector_num, - io_sectors, &target_sector_num, - &target_nb_sectors); - if (target_sector_num == sector_num && - target_nb_sectors == io_sectors) { + int64_t target_offset; + unsigned int target_bytes; + bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes, + &target_offset, &target_bytes); + if (target_offset == offset && + target_bytes == io_bytes) { mirror_method = ret & BDRV_BLOCK_ZERO ? MIRROR_METHOD_ZERO : MIRROR_METHOD_DISCARD; @@ -439,8 +430,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) } while (s->in_flight >= MAX_IN_FLIGHT) { - trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE, - s->in_flight); + trace_mirror_yield_in_flight(s, offset, s->in_flight); mirror_wait_for_io(s); } @@ -448,30 +438,27 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) return 0; } - io_sectors = mirror_clip_sectors(s, sector_num, io_sectors); + io_bytes = mirror_clip_bytes(s, offset, io_bytes); switch (mirror_method) { case MIRROR_METHOD_COPY: - io_bytes_acct = mirror_do_read(s, sector_num * BDRV_SECTOR_SIZE, - io_sectors * BDRV_SECTOR_SIZE); - io_sectors = io_bytes_acct / BDRV_SECTOR_SIZE; + io_bytes = io_bytes_acct = mirror_do_read(s, offset, io_bytes); break; case MIRROR_METHOD_ZERO: case MIRROR_METHOD_DISCARD: - mirror_do_zero_or_discard(s, sector_num * BDRV_SECTOR_SIZE, - io_sectors * BDRV_SECTOR_SIZE, + mirror_do_zero_or_discard(s, offset, io_bytes, mirror_method == MIRROR_METHOD_DISCARD); if (write_zeroes_ok) { io_bytes_acct = 0; } else { - io_bytes_acct = io_sectors * BDRV_SECTOR_SIZE; + io_bytes_acct = io_bytes; } break; default: abort(); } - assert(io_sectors); - sector_num += io_sectors; - nb_chunks -= DIV_ROUND_UP(io_sectors, sectors_per_chunk); + assert(io_bytes); + offset += io_bytes; + nb_chunks -= DIV_ROUND_UP(io_bytes, s->granularity); if (s->common.speed) { delay_ns = ratelimit_calculate_delay(&s->limit, io_bytes_acct); }