mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches # gpg: Signature made Thu 26 Oct 2017 14:02:54 BST # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (35 commits) iotests: Add cluster_size=64k to 125 qcow2: Always execute preallocate() in a coroutine qcow2: Fix unaligned preallocated truncation qcow2: Emit errp when truncating the image tail iotests: Filter actual image size in 184 and 191 iotests: Pull _filter_actual_image_size from 67/87 iotests: Add test for dataplane mirroring qcow2: Use BDRV_SECTOR_BITS instead of its literal value qemu-img.1: Image invalidation on qemu-img commit qemu-io: Relax 'alloc' now that block-status doesn't assert qcow2: Reduce is_zero() rounding block: Reduce bdrv_aligned_preadv() rounding block: Align block status requests qemu-img: Change img_compare() to be byte-based qemu-img: Change img_rebase() to be byte-based qemu-img: Change compare_sectors() to be byte-based qemu-img: Change check_empty_sectors() to byte-based qemu-img: Drop redundant error message in compare qemu-img: Add find_nonzero() qemu-img: Speed up compare on pre-allocated larger file ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -2245,7 +2245,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
|
||||
if (!reference &&
|
||||
bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
|
||||
qdict_put_str(options, "driver", bs->backing_format);
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -627,6 +627,17 @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
|
||||
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn blkdebug_co_get_block_status(
|
||||
BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
assert(QEMU_IS_ALIGNED(sector_num | nb_sectors,
|
||||
DIV_ROUND_UP(bs->bl.request_alignment,
|
||||
BDRV_SECTOR_SIZE)));
|
||||
return bdrv_co_get_block_status_from_file(bs, sector_num, nb_sectors,
|
||||
pnum, file);
|
||||
}
|
||||
|
||||
static void blkdebug_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
@@ -896,7 +907,7 @@ static BlockDriver bdrv_blkdebug = {
|
||||
.bdrv_co_flush_to_disk = blkdebug_co_flush,
|
||||
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
|
||||
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
|
||||
.bdrv_co_get_block_status = bdrv_co_get_block_status_from_file,
|
||||
.bdrv_co_get_block_status = blkdebug_co_get_block_status,
|
||||
|
||||
.bdrv_debug_event = blkdebug_debug_event,
|
||||
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
|
||||
|
||||
+198
-134
File diff suppressed because it is too large
Load Diff
+9
-17
@@ -190,10 +190,9 @@ static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
|
||||
bool need_cow;
|
||||
int ret = 0;
|
||||
int64_t align_offset = *offset;
|
||||
unsigned int align_bytes = *bytes;
|
||||
int64_t align_bytes = *bytes;
|
||||
int max_bytes = s->granularity * s->max_iov;
|
||||
|
||||
assert(*bytes < INT_MAX);
|
||||
need_cow = !test_bit(*offset / s->granularity, s->cow_bitmap);
|
||||
need_cow |= !test_bit((*offset + *bytes - 1) / s->granularity,
|
||||
s->cow_bitmap);
|
||||
@@ -329,7 +328,6 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
uint64_t delay_ns = 0;
|
||||
/* At least the first dirty chunk is mirrored in one iteration. */
|
||||
int nb_chunks = 1;
|
||||
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);
|
||||
|
||||
@@ -377,7 +375,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
}
|
||||
|
||||
/* Clear dirty bits before querying the block status, because
|
||||
* calling bdrv_get_block_status_above could yield - if some blocks are
|
||||
* calling bdrv_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, offset,
|
||||
@@ -386,11 +384,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
|
||||
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;
|
||||
int ret;
|
||||
int64_t io_bytes;
|
||||
int64_t io_bytes_acct;
|
||||
BlockDriverState *file;
|
||||
enum MirrorMethod {
|
||||
MIRROR_METHOD_COPY,
|
||||
MIRROR_METHOD_ZERO,
|
||||
@@ -398,11 +394,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
} mirror_method = MIRROR_METHOD_COPY;
|
||||
|
||||
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;
|
||||
ret = bdrv_block_status_above(source, NULL, offset,
|
||||
nb_chunks * s->granularity,
|
||||
&io_bytes, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
|
||||
} else if (ret & BDRV_BLOCK_DATA) {
|
||||
@@ -414,7 +408,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
io_bytes = s->granularity;
|
||||
} else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) {
|
||||
int64_t target_offset;
|
||||
unsigned int target_bytes;
|
||||
int64_t target_bytes;
|
||||
bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
|
||||
&target_offset, &target_bytes);
|
||||
if (target_offset == offset &&
|
||||
@@ -1133,9 +1127,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||
granularity = bdrv_get_default_bitmap_granularity(target);
|
||||
}
|
||||
|
||||
assert ((granularity & (granularity - 1)) == 0);
|
||||
/* Granularity must be large enough for sector-based dirty bitmap */
|
||||
assert(granularity >= BDRV_SECTOR_SIZE);
|
||||
assert(is_power_of_2(granularity));
|
||||
|
||||
if (buf_size < 0) {
|
||||
error_setg(errp, "Invalid parameter 'buf-size'");
|
||||
|
||||
@@ -1632,7 +1632,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,
|
||||
|
||||
+65
-47
@@ -1139,7 +1139,7 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
s->cluster_bits = header.cluster_bits;
|
||||
s->cluster_size = 1 << s->cluster_bits;
|
||||
s->cluster_sectors = 1 << (s->cluster_bits - 9);
|
||||
s->cluster_sectors = 1 << (s->cluster_bits - BDRV_SECTOR_BITS);
|
||||
|
||||
/* Initialise version 3 header fields */
|
||||
if (header.version == 2) {
|
||||
@@ -1636,7 +1636,7 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
|
||||
|
||||
bytes = MIN(INT_MAX, nb_sectors * BDRV_SECTOR_SIZE);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = qcow2_get_cluster_offset(bs, sector_num << 9, &bytes,
|
||||
ret = qcow2_get_cluster_offset(bs, sector_num << BDRV_SECTOR_BITS, &bytes,
|
||||
&cluster_offset);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
if (ret < 0) {
|
||||
@@ -2460,6 +2460,14 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
|
||||
}
|
||||
|
||||
|
||||
typedef struct PreallocCo {
|
||||
BlockDriverState *bs;
|
||||
uint64_t offset;
|
||||
uint64_t new_length;
|
||||
|
||||
int ret;
|
||||
} PreallocCo;
|
||||
|
||||
/**
|
||||
* Preallocates metadata structures for data clusters between @offset (in the
|
||||
* guest disk) and @new_length (which is thus generally the new guest disk
|
||||
@@ -2467,9 +2475,12 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
|
||||
*
|
||||
* Returns: 0 on success, -errno on failure.
|
||||
*/
|
||||
static int preallocate(BlockDriverState *bs,
|
||||
uint64_t offset, uint64_t new_length)
|
||||
static void coroutine_fn preallocate_co(void *opaque)
|
||||
{
|
||||
PreallocCo *params = opaque;
|
||||
BlockDriverState *bs = params->bs;
|
||||
uint64_t offset = params->offset;
|
||||
uint64_t new_length = params->new_length;
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t bytes;
|
||||
uint64_t host_offset = 0;
|
||||
@@ -2477,9 +2488,7 @@ static int preallocate(BlockDriverState *bs,
|
||||
int ret;
|
||||
QCowL2Meta *meta;
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
}
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
assert(offset <= new_length);
|
||||
bytes = new_length - offset;
|
||||
@@ -2533,10 +2542,28 @@ static int preallocate(BlockDriverState *bs,
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
params->ret = ret;
|
||||
}
|
||||
|
||||
static int preallocate(BlockDriverState *bs,
|
||||
uint64_t offset, uint64_t new_length)
|
||||
{
|
||||
PreallocCo params = {
|
||||
.bs = bs,
|
||||
.offset = offset,
|
||||
.new_length = new_length,
|
||||
.ret = -EINPROGRESS,
|
||||
};
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
preallocate_co(¶ms);
|
||||
} else {
|
||||
Coroutine *co = qemu_coroutine_create(preallocate_co, ¶ms);
|
||||
bdrv_coroutine_enter(bs, co);
|
||||
BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS);
|
||||
}
|
||||
return ret;
|
||||
return params.ret;
|
||||
}
|
||||
|
||||
/* qcow2_refcount_metadata_size:
|
||||
@@ -2972,23 +2999,21 @@ finish:
|
||||
}
|
||||
|
||||
|
||||
static bool is_zero_sectors(BlockDriverState *bs, int64_t start,
|
||||
uint32_t count)
|
||||
static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
|
||||
{
|
||||
int nr;
|
||||
BlockDriverState *file;
|
||||
int64_t res;
|
||||
int64_t nr;
|
||||
int res;
|
||||
|
||||
if (start + count > bs->total_sectors) {
|
||||
count = bs->total_sectors - start;
|
||||
/* Clamp to image length, before checking status of underlying sectors */
|
||||
if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) {
|
||||
bytes = bs->total_sectors * BDRV_SECTOR_SIZE - offset;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
if (!bytes) {
|
||||
return true;
|
||||
}
|
||||
res = bdrv_get_block_status_above(bs, NULL, start, count,
|
||||
&nr, &file);
|
||||
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == count;
|
||||
res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL);
|
||||
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == bytes;
|
||||
}
|
||||
|
||||
static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
@@ -3006,24 +3031,21 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
if (head || tail) {
|
||||
int64_t cl_start = (offset - head) >> BDRV_SECTOR_BITS;
|
||||
uint64_t off;
|
||||
unsigned int nr;
|
||||
|
||||
assert(head + bytes <= s->cluster_size);
|
||||
|
||||
/* check whether remainder of cluster already reads as zero */
|
||||
if (!(is_zero_sectors(bs, cl_start,
|
||||
DIV_ROUND_UP(head, BDRV_SECTOR_SIZE)) &&
|
||||
is_zero_sectors(bs, (offset + bytes) >> BDRV_SECTOR_BITS,
|
||||
DIV_ROUND_UP(-tail & (s->cluster_size - 1),
|
||||
BDRV_SECTOR_SIZE)))) {
|
||||
if (!(is_zero(bs, offset - head, head) &&
|
||||
is_zero(bs, offset + bytes,
|
||||
tail ? s->cluster_size - tail : 0))) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
/* We can have new write after previous check */
|
||||
offset = cl_start << BDRV_SECTOR_BITS;
|
||||
offset = QEMU_ALIGN_DOWN(offset, s->cluster_size);
|
||||
bytes = s->cluster_size;
|
||||
nr = s->cluster_size;
|
||||
ret = qcow2_get_cluster_offset(bs, offset, &nr, &off);
|
||||
@@ -3150,12 +3172,13 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
|
||||
return last_cluster;
|
||||
}
|
||||
if ((last_cluster + 1) * s->cluster_size < old_file_size) {
|
||||
ret = bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
|
||||
PREALLOC_MODE_OFF, NULL);
|
||||
if (ret < 0) {
|
||||
warn_report("Failed to truncate the tail of the image: %s",
|
||||
strerror(-ret));
|
||||
ret = 0;
|
||||
Error *local_err = NULL;
|
||||
|
||||
bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
|
||||
PREALLOC_MODE_OFF, &local_err);
|
||||
if (local_err) {
|
||||
warn_reportf_err(local_err,
|
||||
"Failed to truncate the tail of the image: ");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -3192,6 +3215,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
|
||||
"Failed to inquire current file length");
|
||||
return old_file_size;
|
||||
}
|
||||
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
|
||||
|
||||
nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
|
||||
s->cluster_size);
|
||||
@@ -3697,19 +3721,14 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
|
||||
required = virtual_size;
|
||||
} else {
|
||||
int64_t offset;
|
||||
int pnum = 0;
|
||||
int64_t pnum = 0;
|
||||
|
||||
for (offset = 0; offset < ssize;
|
||||
offset += pnum * BDRV_SECTOR_SIZE) {
|
||||
int nb_sectors = MIN(ssize - offset,
|
||||
BDRV_REQUEST_MAX_BYTES) / BDRV_SECTOR_SIZE;
|
||||
BlockDriverState *file;
|
||||
int64_t ret;
|
||||
for (offset = 0; offset < ssize; offset += pnum) {
|
||||
int ret;
|
||||
|
||||
ret = bdrv_get_block_status_above(in_bs, NULL,
|
||||
offset >> BDRV_SECTOR_BITS,
|
||||
nb_sectors,
|
||||
&pnum, &file);
|
||||
ret = bdrv_block_status_above(in_bs, NULL, offset,
|
||||
ssize - offset, &pnum, NULL,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(&local_err, -ret,
|
||||
"Unable to get block status");
|
||||
@@ -3721,11 +3740,10 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
|
||||
} else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ==
|
||||
(BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) {
|
||||
/* Extend pnum to end of cluster for next iteration */
|
||||
pnum = (ROUND_UP(offset + pnum * BDRV_SECTOR_SIZE,
|
||||
cluster_size) - offset) >> BDRV_SECTOR_BITS;
|
||||
pnum = ROUND_UP(offset + pnum, cluster_size) - offset;
|
||||
|
||||
/* Count clusters we've seen */
|
||||
required += offset % cluster_size + pnum * BDRV_SECTOR_SIZE;
|
||||
required += offset % cluster_size + pnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ blk_co_pwritev(void *blk, void *bs, int64_t offset, unsigned int bytes, int flag
|
||||
bdrv_co_preadv(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
|
||||
bdrv_co_pwritev(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
|
||||
bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int count, int flags) "bs %p offset %"PRId64" count %d flags 0x%x"
|
||||
bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, unsigned int cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %u"
|
||||
bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, int64_t cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %"PRId64
|
||||
|
||||
# block/stream.c
|
||||
stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
|
||||
|
||||
+14
-15
@@ -121,7 +121,7 @@ typedef struct HDGeometry {
|
||||
#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
|
||||
|
||||
/*
|
||||
* Allocation status flags for bdrv_get_block_status() and friends.
|
||||
* Allocation status flags for bdrv_block_status() and friends.
|
||||
*
|
||||
* Public flags:
|
||||
* BDRV_BLOCK_DATA: allocation for data at offset is tied to this layer
|
||||
@@ -136,10 +136,11 @@ typedef struct HDGeometry {
|
||||
* that the block layer recompute the answer from the returned
|
||||
* BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
|
||||
*
|
||||
* 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:
|
||||
* If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK) of
|
||||
* the return value (old interface) or the entire map parameter (new
|
||||
* interface) 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, as follows:
|
||||
*
|
||||
* DATA ZERO OFFSET_VALID
|
||||
* t t t sectors read as zero, returned file is zero at offset
|
||||
@@ -421,14 +422,12 @@ 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_get_block_status_above(BlockDriverState *bs,
|
||||
BlockDriverState *base,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum,
|
||||
BlockDriverState **file);
|
||||
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum, int64_t *map,
|
||||
BlockDriverState **file);
|
||||
int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
|
||||
int64_t offset, int64_t bytes, int64_t *pnum,
|
||||
int64_t *map, BlockDriverState **file);
|
||||
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
int64_t *pnum);
|
||||
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
|
||||
@@ -474,9 +473,9 @@ int bdrv_get_flags(BlockDriverState *bs);
|
||||
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
|
||||
void bdrv_round_to_clusters(BlockDriverState *bs,
|
||||
int64_t offset, unsigned int bytes,
|
||||
int64_t offset, int64_t bytes,
|
||||
int64_t *cluster_offset,
|
||||
unsigned int *cluster_bytes);
|
||||
int64_t *cluster_bytes);
|
||||
|
||||
const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
|
||||
void bdrv_get_backing_filename(BlockDriverState *bs,
|
||||
|
||||
@@ -202,10 +202,13 @@ struct BlockDriver {
|
||||
int64_t offset, int bytes);
|
||||
|
||||
/*
|
||||
* Building block for bdrv_block_status[_above]. The driver should
|
||||
* answer only according to the current layer, and should not
|
||||
* set BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
|
||||
* for the meaning of _DATA, _ZERO, and _OFFSET_VALID.
|
||||
* Building block for bdrv_block_status[_above] and
|
||||
* bdrv_is_allocated[_above]. The driver should answer only
|
||||
* according to the current layer, and should not set
|
||||
* BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
|
||||
* for the meaning of _DATA, _ZERO, and _OFFSET_VALID. The block
|
||||
* layer guarantees input aligned to request_alignment, as well as
|
||||
* non-NULL pnum and file.
|
||||
*/
|
||||
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, int *pnum,
|
||||
|
||||
+176
-213
File diff suppressed because it is too large
Load Diff
+4
-5
@@ -274,11 +274,10 @@ If the backing chain of the given image file @var{filename} has more than one
|
||||
layer, the backing file into which the changes will be committed may be
|
||||
specified as @var{base} (which has to be part of @var{filename}'s backing
|
||||
chain). If @var{base} is not specified, the immediate backing file of the top
|
||||
image (which is @var{filename}) will be used. For reasons of consistency,
|
||||
explicitly specifying @var{base} will always imply @code{-d} (since emptying an
|
||||
image after committing to an indirect backing file would lead to different data
|
||||
being read from the image due to content in the intermediate backing chain
|
||||
overruling the commit target).
|
||||
image (which is @var{filename}) will be used. Note that after a commit operation
|
||||
all images between @var{base} and the top image will be invalid and may return
|
||||
garbage data when read. For this reason, @code{-b} implies @code{-d} (so that
|
||||
the top image stays valid).
|
||||
|
||||
@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2}
|
||||
|
||||
|
||||
@@ -1769,10 +1769,6 @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
|
||||
if (offset < 0) {
|
||||
print_cvtnum_err(offset, argv[1]);
|
||||
return 0;
|
||||
} else if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
|
||||
printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
|
||||
offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
@@ -1780,19 +1776,10 @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
|
||||
if (count < 0) {
|
||||
print_cvtnum_err(count, argv[2]);
|
||||
return 0;
|
||||
} else if (count > INT_MAX * BDRV_SECTOR_SIZE) {
|
||||
printf("length argument cannot exceed %llu, given %s\n",
|
||||
INT_MAX * BDRV_SECTOR_SIZE, argv[2]);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
count = BDRV_SECTOR_SIZE;
|
||||
}
|
||||
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
|
||||
printf("%" PRId64 " is not a sector-aligned value for 'count'\n",
|
||||
count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
remaining = count;
|
||||
sum_alloc = 0;
|
||||
|
||||
@@ -56,7 +56,7 @@ _filter_qmp_events()
|
||||
function run_qemu()
|
||||
{
|
||||
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \
|
||||
| sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' \
|
||||
| _filter_actual_image_size \
|
||||
| _filter_generated_node_ids | _filter_qmp_events
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
|
||||
wrote 512/512 bytes at offset 512
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
|
||||
qemu-img: Error while reading offset 0: Input/output error
|
||||
4
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
|
||||
Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0
|
||||
@@ -12,7 +11,6 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0
|
||||
wrote 512/512 bytes at offset 512
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
|
||||
qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
|
||||
Warning: Image size mismatch!
|
||||
4
|
||||
Cleanup
|
||||
|
||||
@@ -46,7 +46,7 @@ function run_qemu()
|
||||
{
|
||||
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
|
||||
| _filter_qemu | _filter_imgfmt \
|
||||
| sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
|
||||
| _filter_actual_image_size
|
||||
}
|
||||
|
||||
size=128M
|
||||
|
||||
@@ -69,13 +69,15 @@ fi
|
||||
# in B
|
||||
CREATION_SIZE=$((2 * 1024 * 1024 - 48 * 1024))
|
||||
|
||||
# 512 is the actual test -- but it's good to test 64k as well, just to be sure.
|
||||
for cluster_size in 512 64k; do
|
||||
# in kB
|
||||
for GROWTH_SIZE in 16 48 80; do
|
||||
for create_mode in off metadata falloc full; do
|
||||
for growth_mode in off metadata falloc full; do
|
||||
echo "--- growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
|
||||
echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
|
||||
|
||||
IMGOPTS="preallocation=$create_mode,cluster_size=512" _make_test_img ${CREATION_SIZE}
|
||||
IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE}
|
||||
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
|
||||
|
||||
host_size_0=$(get_image_size_on_host)
|
||||
@@ -123,6 +125,7 @@ for GROWTH_SIZE in 16 48 80; do
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
|
||||
+432
-48
File diff suppressed because it is too large
Load Diff
Executable
+97
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test case for mirroring with dataplane
|
||||
#
|
||||
# Copyright (C) 2017 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=mreitz@redhat.com
|
||||
|
||||
seq=$(basename $0)
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=$PWD
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_qemu
|
||||
_cleanup_test_img
|
||||
_rm_test_img "$TEST_IMG.overlay0"
|
||||
_rm_test_img "$TEST_IMG.overlay1"
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and qemu instance handling
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.qemu
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=64K
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
TEST_IMG="$TEST_IMG.overlay0" _make_test_img -b "$TEST_IMG" $IMG_SIZE
|
||||
TEST_IMG="$TEST_IMG.overlay1" _make_test_img -b "$TEST_IMG" $IMG_SIZE
|
||||
|
||||
# So that we actually have something to mirror and the job does not return
|
||||
# immediately (which may be bad because then we cannot know whether the
|
||||
# 'return' or the 'BLOCK_JOB_READY' comes first).
|
||||
$QEMU_IO -c 'write 0 42' "$TEST_IMG.overlay0" | _filter_qemu_io
|
||||
|
||||
# We cannot use virtio-blk here because that does not actually set the attached
|
||||
# BB's AioContext in qtest mode
|
||||
_launch_qemu \
|
||||
-object iothread,id=iothr \
|
||||
-blockdev node-name=source,driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG.overlay0" \
|
||||
-device virtio-scsi,id=scsi-bus,iothread=iothr \
|
||||
-device scsi-hd,bus=scsi-bus.0,drive=source
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'qmp_capabilities' }" \
|
||||
'return'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'drive-mirror',
|
||||
'arguments': {
|
||||
'job-id': 'mirror',
|
||||
'device': 'source',
|
||||
'target': '$TEST_IMG.overlay1',
|
||||
'mode': 'existing',
|
||||
'sync': 'top'
|
||||
} }" \
|
||||
'BLOCK_JOB_READY'
|
||||
|
||||
# The backing BDS should be assigned the overlay's AioContext
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'block-job-complete',
|
||||
'arguments': { 'device': 'mirror' } }" \
|
||||
'BLOCK_JOB_COMPLETED'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'quit' }" \
|
||||
'return'
|
||||
|
||||
wait=yes _cleanup_qemu
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
status=0
|
||||
@@ -0,0 +1,14 @@
|
||||
QA output created by 127
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
|
||||
Formatting 'TEST_DIR/t.IMGFMT.overlay0', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT
|
||||
Formatting 'TEST_DIR/t.IMGFMT.overlay1', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT
|
||||
wrote 42/42 bytes at offset 0
|
||||
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
*** done
|
||||
+10
-2
@@ -51,7 +51,7 @@ echo "== setting up files =="
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img $size
|
||||
$QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io
|
||||
_make_test_img -b "$TEST_IMG.base"
|
||||
$QEMU_IO -c "write -P 22 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 22 0 110M" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# Limited to 64k max-transfer
|
||||
echo
|
||||
@@ -81,6 +81,13 @@ limits=align=512,opt-write-zero=15M,max-write-zero=15M,opt-discard=15M,max-disca
|
||||
$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
|
||||
-c "discard 80000001 30M" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== block status smaller than alignment =="
|
||||
limits=align=4k
|
||||
$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
|
||||
-c "alloc 1 1" -c "alloc 0x6dffff0 1000" -c "alloc 127m 5P" \
|
||||
-c map | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== verify image content =="
|
||||
|
||||
@@ -103,7 +110,8 @@ function verify_io()
|
||||
echo read -P 0 32M 32M
|
||||
echo read -P 22 64M 13M
|
||||
echo read -P $discarded 77M 29M
|
||||
echo read -P 22 106M 22M
|
||||
echo read -P 22 106M 4M
|
||||
echo read -P 11 110M 18M
|
||||
}
|
||||
|
||||
verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user