From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, jsnow@redhat.com, famz@redhat.com,
qemu-block@nongnu.org, Stefan Hajnoczi <stefanha@redhat.com>,
Max Reitz <mreitz@redhat.com>
Subject: [Qemu-devel] [PATCH v5 07/23] block: Convert bdrv_get_block_status() to bytes
Date: Tue, 3 Oct 2017 21:00:32 -0500 [thread overview]
Message-ID: <20171004020048.26379-8-eblake@redhat.com> (raw)
In-Reply-To: <20171004020048.26379-1-eblake@redhat.com>
We are gradually moving away from sector-based interfaces, towards
byte-based. In the common case, allocation is unlikely to ever use
values that are not naturally sector-aligned, but it is possible
that byte-based values will let us be more precise about allocation
at the end of an unaligned file that can do byte-based access.
Changing the name of the function from bdrv_get_block_status() to
bdrv_block_status() ensures that the compiler enforces that all
callers are updated. For now, the io.c layer still assert()s that
all callers are sector-aligned, but that can be relaxed when a later
patch implements byte-based block status in the drivers.
Note that we have an inherent limitation in the BDRV_BLOCK_* return
values: BDRV_BLOCK_OFFSET_VALID can only return the start of a
sector, even if we later relax the interface to query for the status
starting at an intermediate byte; document the obvious interpretation
that valid offsets are always sector-relative.
Therefore, for the most part this patch is just the addition of scaling
at the callers followed by inverse scaling at bdrv_block_status(). But
some code, particularly bdrv_is_allocated(), gets a lot simpler because
it no longer has to mess with sectors.
For ease of review, bdrv_get_block_status_above() will be tackled
separately.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
v5: drop pointless 'if (pnum)' [John], add comment
v4: no change
v3: clamp bytes to 32-bits, rather than asserting
v2: rebase to earlier changes
---
include/block/block.h | 12 +++++++-----
block/io.c | 35 +++++++++++++++++++++++------------
block/qcow2-cluster.c | 2 +-
qemu-img.c | 20 +++++++++++---------
4 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/include/block/block.h b/include/block/block.h
index be49c4ae9d..4ecd2c4a65 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -138,8 +138,10 @@ typedef struct HDGeometry {
*
* If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK)
* represent the offset in the returned BDS that is allocated for the
- * corresponding raw data; however, whether that offset actually contains
- * data also depends on BDRV_BLOCK_DATA and BDRV_BLOCK_ZERO, as follows:
+ * corresponding raw data. Individual bytes are at the same sector-relative
+ * locations (and thus, this bit cannot be set for mappings which are
+ * not equivalent modulo 512). However, whether that offset actually
+ * contains data also depends on BDRV_BLOCK_DATA, as follows:
*
* DATA ZERO OFFSET_VALID
* t t t sectors read as zero, returned file is zero at offset
@@ -422,9 +424,9 @@ int bdrv_has_zero_init_1(BlockDriverState *bs);
int bdrv_has_zero_init(BlockDriverState *bs);
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
-int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors, int *pnum,
- BlockDriverState **file);
+int64_t bdrv_block_status(BlockDriverState *bs, int64_t offset,
+ int64_t bytes, int64_t *pnum,
+ BlockDriverState **file);
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
BlockDriverState *base,
int64_t sector_num,
diff --git a/block/io.c b/block/io.c
index afba2da1c4..ab1853dc2d 100644
--- a/block/io.c
+++ b/block/io.c
@@ -698,7 +698,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
{
int64_t target_size, ret, bytes, offset = 0;
BlockDriverState *bs = child->bs;
- int n; /* sectors */
target_size = bdrv_getlength(bs);
if (target_size < 0) {
@@ -710,24 +709,23 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
if (bytes <= 0) {
return 0;
}
- ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
- bytes >> BDRV_SECTOR_BITS, &n, NULL);
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL);
if (ret < 0) {
error_report("error getting block status at offset %" PRId64 ": %s",
offset, strerror(-ret));
return ret;
}
if (ret & BDRV_BLOCK_ZERO) {
- offset += n * BDRV_SECTOR_BITS;
+ offset += bytes;
continue;
}
- ret = bdrv_pwrite_zeroes(child, offset, n * BDRV_SECTOR_SIZE, flags);
+ ret = bdrv_pwrite_zeroes(child, offset, bytes, flags);
if (ret < 0) {
error_report("error writing zeroes at offset %" PRId64 ": %s",
offset, strerror(-ret));
return ret;
}
- offset += n * BDRV_SECTOR_SIZE;
+ offset += bytes;
}
}
@@ -2021,13 +2019,26 @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs,
nb_sectors, pnum, file);
}
-int64_t bdrv_get_block_status(BlockDriverState *bs,
- int64_t sector_num,
- int nb_sectors, int *pnum,
- BlockDriverState **file)
+int64_t bdrv_block_status(BlockDriverState *bs,
+ int64_t offset, int64_t bytes, int64_t *pnum,
+ BlockDriverState **file)
{
- return bdrv_get_block_status_above(bs, backing_bs(bs),
- sector_num, nb_sectors, pnum, file);
+ int64_t ret;
+ int n;
+
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+ assert(pnum);
+ /*
+ * The contract allows us to return pnum smaller than bytes, even
+ * if the next query would see the same status; we truncate the
+ * request to avoid overflowing the driver's 32-bit interface.
+ */
+ bytes = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
+ ret = bdrv_get_block_status_above(bs, backing_bs(bs),
+ offset >> BDRV_SECTOR_BITS,
+ bytes >> BDRV_SECTOR_BITS, &n, file);
+ *pnum = n * BDRV_SECTOR_SIZE;
+ return ret;
}
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d2518d1893..395763b612 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1634,7 +1634,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
* cluster is already marked as zero, or if it's unallocated and we
* don't have a backing file.
*
- * TODO We might want to use bdrv_get_block_status(bs) here, but we're
+ * TODO We might want to use bdrv_block_status(bs) here, but we're
* holding s->lock, so that doesn't work today.
*
* If full_discard is true, the sector should not read back as zeroes,
diff --git a/qemu-img.c b/qemu-img.c
index af3effdec5..d226dcc166 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1599,9 +1599,14 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
if (s->sector_next_status <= sector_num) {
if (s->target_has_backing) {
- ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
- sector_num - src_cur_offset,
- n, &n, NULL);
+ int64_t count = n * BDRV_SECTOR_SIZE;
+
+ ret = bdrv_block_status(blk_bs(s->src[src_cur]),
+ (sector_num - src_cur_offset) *
+ BDRV_SECTOR_SIZE,
+ count, &count, NULL);
+ assert(ret < 0 || QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
+ n = count >> BDRV_SECTOR_BITS;
} else {
ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
sector_num - src_cur_offset,
@@ -2678,9 +2683,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
int depth;
BlockDriverState *file;
bool has_offset;
- int nb_sectors = bytes >> BDRV_SECTOR_BITS;
- assert(bytes < INT_MAX);
/* As an optimization, we could cache the current range of unallocated
* clusters in each file of the chain, and avoid querying the same
* range repeatedly.
@@ -2688,12 +2691,11 @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
depth = 0;
for (;;) {
- ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS, nb_sectors,
- &nb_sectors, &file);
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, &file);
if (ret < 0) {
return ret;
}
- assert(nb_sectors);
+ assert(bytes);
if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {
break;
}
@@ -2710,7 +2712,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
*e = (MapEntry) {
.start = offset,
- .length = nb_sectors * BDRV_SECTOR_SIZE,
+ .length = bytes,
.data = !!(ret & BDRV_BLOCK_DATA),
.zero = !!(ret & BDRV_BLOCK_ZERO),
.offset = ret & BDRV_BLOCK_OFFSET_MASK,
--
2.13.6
next prev parent reply other threads:[~2017-10-04 2:01 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-04 2:00 [Qemu-devel] [PATCH v5 00/23] make bdrv_get_block_status byte-based Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 01/23] block: Allow NULL file for bdrv_get_block_status() Eric Blake
2017-10-10 13:59 ` Kevin Wolf
2017-10-10 14:43 ` Eric Blake
2017-10-10 19:00 ` Eric Blake
2017-10-10 19:24 ` John Snow
2017-10-11 8:42 ` Kevin Wolf
2017-10-11 17:42 ` John Snow
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 02/23] block: Add flag to avoid wasted work in bdrv_is_allocated() Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 03/23] block: Make bdrv_round_to_clusters() signature more useful Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 04/23] qcow2: Switch is_zero_sectors() to byte-based Eric Blake
2017-10-10 14:15 ` Kevin Wolf
2017-10-10 14:47 ` Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 05/23] block: Switch bdrv_make_zero() " Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 06/23] qemu-img: Switch get_block_status() " Eric Blake
2017-10-04 2:00 ` Eric Blake [this message]
2017-10-10 14:46 ` [Qemu-devel] [PATCH v5 07/23] block: Convert bdrv_get_block_status() to bytes Kevin Wolf
2017-10-10 15:38 ` Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 08/23] block: Switch bdrv_co_get_block_status() to byte-based Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 09/23] block: Switch BdrvCoGetBlockStatusData " Eric Blake
2017-10-09 20:07 ` [Qemu-devel] [Qemu-block] " Jeff Cody
2017-10-09 21:30 ` Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 10/23] block: Switch bdrv_common_block_status_above() " Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 11/23] block: Switch bdrv_co_get_block_status_above() " Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 12/23] block: Convert bdrv_get_block_status_above() to bytes Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 13/23] qemu-img: Simplify logic in img_compare() Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 14/23] qemu-img: Speed up compare on pre-allocated larger file Eric Blake
2017-10-11 18:33 ` Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 15/23] qemu-img: Add find_nonzero() Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 16/23] qemu-img: Drop redundant error message in compare Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 17/23] qemu-img: Change check_empty_sectors() to byte-based Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 18/23] qemu-img: Change compare_sectors() to be byte-based Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 19/23] qemu-img: Change img_rebase() " Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 20/23] qemu-img: Change img_compare() " Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 21/23] block: Align block status requests Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 22/23] block: Relax bdrv_aligned_preadv() assertion Eric Blake
2017-10-04 2:00 ` [Qemu-devel] [PATCH v5 23/23] qemu-io: Relax 'alloc' now that block-status doesn't assert Eric Blake
2017-10-10 12:58 ` [Qemu-devel] [PATCH v5 00/23] make bdrv_get_block_status byte-based Kevin Wolf
2017-10-10 14:48 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171004020048.26379-8-eblake@redhat.com \
--to=eblake@redhat.com \
--cc=famz@redhat.com \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.