Block patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJUSUE1AAoJEH8JsnLIjy/Wh/8P/0D5en9rZvqeFJH/OZkgmuFV oANSxEMyV90wzFbWbTm6W+Kshpq2p9XH+0lM2XCyGWH7KJSe23SRmGSgZRPx9pr/ ZwCNi03w4skfEKf0SD6AfRIzg2bGqwY0FxULSkhb0zWfJR62K6vwKIF/1HgH6+MG 7B6iDxpalbq3pDz/cpWWRLQUG0rUXqaQav7HZC28bVGIBjj1YQvR3yn0Agwy9Hf6 OpPmOrQv1aZdLq+bNMf5UsScBYZ1rgJ8gBi/7EeAJvJc/zdl88C33tHjfKzF4HU6 +TNtfxpgB5RQBZlsLzWjg8TqEaE/75S8t8ex5XD4OO81raPOnawN3mUAEsPYaLZt 0kENTUYc9tNROiXTARIaQ4QrPOjqbKPg1w3muItC1Z0/Luqwn0L/ecnyKrxH33im /XsQVcSPvmHYtrPP5WwtwZKf4uowgl5UoeniwlfU3L6xyz/luQhWqOQMcS1bXTpM Cuc0CT6i0fg5fm6+oaw0iAVW4TmLg2xzUS7xIkcT8xJadHMSuNWvn0DcoDL2USvO yRaohr551IO40S6q/Toy8wF7wi9BkI2Eyb96jhczS69rKpPFZLYNb3YV6V2vy92j n3aLamCJRfaBByFzRht+umoWrpGrXdjIJVySPCo8XZHA2+6rIe53CCLMR/vnMBuE ciayZt+ht88bx5cmgbS9 =TMKO -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block patches # gpg: Signature made Thu 23 Oct 2014 18:56:05 BST using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: (32 commits) qemu-img: Print error if check failed block: char devices on FreeBSD are not behind a pager iotests: Add test for qcow2 L1 table update qcow2: Do not overflow when writing an L1 sector iotests: Add test for map commands qemu-io: Respect early image end for map block: Respect underlying file's EOF docs/qcow2: Limit refcount_order to [0, 6] docs/qcow2: Correct refcount_block_entries qcow2: Drop REFCOUNT_SHIFT iotests: Add test for potentially damaging repairs iotests: Fix test outputs qcow2: Clean up after refcount rebuild qcow2: Rebuild refcount structure during check qcow2: Do not perform potentially damaging repairs qcow2: Fix refcount blocks beyond image end qcow2: Reuse refcount table in calculate_refcounts() qcow2: Let inc_refcounts() resize the reftable qcow2: Let inc_refcounts() return -errno qcow2: Split fail code in L1 and L2 checks ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8b135a288a
@ -710,11 +710,15 @@ Block
|
||||
M: Kevin Wolf <kwolf@redhat.com>
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
S: Supported
|
||||
F: async.c
|
||||
F: aio-*.c
|
||||
F: block*
|
||||
F: block/
|
||||
F: hw/block/
|
||||
F: qemu-img*
|
||||
F: qemu-io*
|
||||
F: tests/image-fuzzer/
|
||||
F: tests/qemu-iotests/
|
||||
T: git git://repo.or.cz/qemu/kevin.git block
|
||||
T: git git://github.com/stefanha/qemu.git block
|
||||
|
||||
|
29
block.c
29
block.c
@ -3954,15 +3954,26 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
|
||||
if (bs->file &&
|
||||
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
|
||||
(ret & BDRV_BLOCK_OFFSET_VALID)) {
|
||||
int file_pnum;
|
||||
|
||||
ret2 = bdrv_co_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS,
|
||||
*pnum, pnum);
|
||||
*pnum, &file_pnum);
|
||||
if (ret2 >= 0) {
|
||||
/* Ignore errors. This is just providing extra information, it
|
||||
* is useful but not necessary.
|
||||
*/
|
||||
if (!file_pnum) {
|
||||
/* !file_pnum indicates an offset at or beyond the EOF; it is
|
||||
* perfectly valid for the format block driver to point to such
|
||||
* offsets, so catch it and mark everything as zero */
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
} else {
|
||||
/* Limit request to the range reported by the protocol driver */
|
||||
*pnum = file_pnum;
|
||||
ret |= (ret2 & BDRV_BLOCK_ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -5200,6 +5211,11 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size)
|
||||
return qemu_memalign(bdrv_opt_mem_align(bs), size);
|
||||
}
|
||||
|
||||
void *qemu_blockalign0(BlockDriverState *bs, size_t size)
|
||||
{
|
||||
return memset(qemu_blockalign(bs, size), 0, size);
|
||||
}
|
||||
|
||||
void *qemu_try_blockalign(BlockDriverState *bs, size_t size)
|
||||
{
|
||||
size_t align = bdrv_opt_mem_align(bs);
|
||||
@ -5213,6 +5229,17 @@ void *qemu_try_blockalign(BlockDriverState *bs, size_t size)
|
||||
return qemu_try_memalign(align, size);
|
||||
}
|
||||
|
||||
void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
|
||||
{
|
||||
void *mem = qemu_try_blockalign(bs, size);
|
||||
|
||||
if (mem) {
|
||||
memset(mem, 0, size);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if all memory in this vector is sector aligned.
|
||||
*/
|
||||
|
@ -164,12 +164,14 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
|
||||
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t buf[L1_ENTRIES_PER_SECTOR];
|
||||
uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 };
|
||||
int l1_start_index;
|
||||
int i, ret;
|
||||
|
||||
l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
|
||||
for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
|
||||
for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size;
|
||||
i++)
|
||||
{
|
||||
buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -698,6 +698,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
|
||||
s->l2_size = 1 << s->l2_bits;
|
||||
/* 2^(s->refcount_order - 3) is the refcount width in bytes */
|
||||
s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3);
|
||||
s->refcount_block_size = 1 << s->refcount_block_bits;
|
||||
bs->total_sectors = header.size / 512;
|
||||
s->csize_shift = (62 - (s->cluster_bits - 8));
|
||||
s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
|
||||
@ -907,7 +910,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
|
||||
BdrvCheckResult result = {0};
|
||||
|
||||
ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS);
|
||||
ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not repair dirty image");
|
||||
goto fail;
|
||||
@ -1871,7 +1874,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
.l1_size = cpu_to_be32(0),
|
||||
.refcount_table_offset = cpu_to_be64(cluster_size),
|
||||
.refcount_table_clusters = cpu_to_be32(1),
|
||||
.refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT),
|
||||
.refcount_order = cpu_to_be32(4),
|
||||
.header_length = cpu_to_be32(sizeof(*header)),
|
||||
};
|
||||
|
||||
|
@ -59,8 +59,6 @@
|
||||
/* The cluster reads as all zeros */
|
||||
#define QCOW_OFLAG_ZERO (1ULL << 0)
|
||||
|
||||
#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */
|
||||
|
||||
#define MIN_CLUSTER_BITS 9
|
||||
#define MAX_CLUSTER_BITS 21
|
||||
|
||||
@ -223,6 +221,8 @@ typedef struct BDRVQcowState {
|
||||
int l2_size;
|
||||
int l1_size;
|
||||
int l1_vm_state_index;
|
||||
int refcount_block_bits;
|
||||
int refcount_block_size;
|
||||
int csize_shift;
|
||||
int csize_mask;
|
||||
uint64_t cluster_offset_mask;
|
||||
|
@ -150,6 +150,7 @@ typedef struct BDRVRawState {
|
||||
bool has_discard:1;
|
||||
bool has_write_zeroes:1;
|
||||
bool discard_zeroes:1;
|
||||
bool needs_alignment;
|
||||
#ifdef CONFIG_FIEMAP
|
||||
bool skip_fiemap;
|
||||
#endif
|
||||
@ -230,7 +231,7 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
|
||||
|
||||
/* For /dev/sg devices the alignment is not really used.
|
||||
With buffered I/O, we don't have any restrictions. */
|
||||
if (bs->sg || !(s->open_flags & O_DIRECT)) {
|
||||
if (bs->sg || !s->needs_alignment) {
|
||||
bs->request_alignment = 1;
|
||||
s->buf_align = 1;
|
||||
return;
|
||||
@ -446,6 +447,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
|
||||
s->has_discard = true;
|
||||
s->has_write_zeroes = true;
|
||||
if ((bs->open_flags & BDRV_O_NOCACHE) != 0) {
|
||||
s->needs_alignment = true;
|
||||
}
|
||||
|
||||
if (fstat(s->fd, &st) < 0) {
|
||||
error_setg_errno(errp, errno, "Could not stat file");
|
||||
@ -472,6 +476,17 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
if (S_ISCHR(st.st_mode)) {
|
||||
/*
|
||||
* The file is a char device (disk), which on FreeBSD isn't behind
|
||||
* a pager, so force all requests to be aligned. This is needed
|
||||
* so QEMU makes sure all IO operations on the device are aligned
|
||||
* to sector size, or else FreeBSD will reject them with EINVAL.
|
||||
*/
|
||||
s->needs_alignment = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XFS
|
||||
if (platform_test_xfs_fd(s->fd)) {
|
||||
@ -1076,11 +1091,12 @@ static BlockAIOCB *raw_aio_submit(BlockDriverState *bs,
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If O_DIRECT is used the buffer needs to be aligned on a sector
|
||||
* boundary. Check if this is the case or tell the low-level
|
||||
* driver that it needs to copy the buffer.
|
||||
* Check if the underlying device requires requests to be aligned,
|
||||
* and if the request we are trying to submit is aligned or not.
|
||||
* If this is the case tell the low-level driver that it needs
|
||||
* to copy the buffer.
|
||||
*/
|
||||
if ((bs->open_flags & BDRV_O_NOCACHE)) {
|
||||
if (s->needs_alignment) {
|
||||
if (!bdrv_qiov_is_aligned(bs, qiov)) {
|
||||
type |= QEMU_AIO_MISALIGNED;
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
|
@ -407,8 +407,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
We accept them but round the disk size to the next multiple of
|
||||
SECTOR_SIZE. */
|
||||
logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);
|
||||
header.disk_size += SECTOR_SIZE - 1;
|
||||
header.disk_size &= ~(SECTOR_SIZE - 1);
|
||||
header.disk_size = ROUND_UP(header.disk_size, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if (header.signature != VDI_SIGNATURE) {
|
||||
@ -475,7 +474,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->header = header;
|
||||
|
||||
bmap_size = header.blocks_in_image * sizeof(uint32_t);
|
||||
bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
bmap_size = DIV_ROUND_UP(bmap_size, SECTOR_SIZE);
|
||||
s->bmap = qemu_try_blockalign(bs->file, bmap_size * SECTOR_SIZE);
|
||||
if (s->bmap == NULL) {
|
||||
ret = -ENOMEM;
|
||||
@ -736,10 +735,10 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
|
||||
/* We need enough blocks to store the given disk size,
|
||||
so always round up. */
|
||||
blocks = (bytes + block_size - 1) / block_size;
|
||||
blocks = DIV_ROUND_UP(bytes, block_size);
|
||||
|
||||
bmap_size = blocks * sizeof(uint32_t);
|
||||
bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1));
|
||||
bmap_size = ROUND_UP(bmap_size, SECTOR_SIZE);
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
pstrcpy(header.text, sizeof(header.text), VDI_TEXT);
|
||||
|
@ -110,6 +110,7 @@ in the description of a field.
|
||||
in bits: refcount_bits = 1 << refcount_order). For version 2
|
||||
images, the order is always assumed to be 4
|
||||
(i.e. refcount_bits = 16).
|
||||
This value may not exceed 6 (i.e. refcount_bits = 64).
|
||||
|
||||
100 - 103: header_length
|
||||
Length of the header structure in bytes. For version 2
|
||||
@ -183,7 +184,7 @@ blocks and are exactly one cluster in size.
|
||||
Given a offset into the image file, the refcount of its cluster can be obtained
|
||||
as follows:
|
||||
|
||||
refcount_block_entries = (cluster_size / sizeof(uint16_t))
|
||||
refcount_block_entries = (cluster_size * 8 / refcount_bits)
|
||||
|
||||
refcount_block_index = (offset / cluster_size) % refcount_block_entries
|
||||
refcount_table_index = (offset / cluster_size) / refcount_block_entries
|
||||
|
@ -412,7 +412,9 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
size_t bdrv_opt_mem_align(BlockDriverState *bs);
|
||||
void bdrv_set_guest_block_size(BlockDriverState *bs, int align);
|
||||
void *qemu_blockalign(BlockDriverState *bs, size_t size);
|
||||
void *qemu_blockalign0(BlockDriverState *bs, size_t size);
|
||||
void *qemu_try_blockalign(BlockDriverState *bs, size_t size);
|
||||
void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
|
||||
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
|
||||
|
||||
struct HBitmapIter;
|
||||
|
@ -687,6 +687,7 @@ static int img_check(int argc, char **argv)
|
||||
check->corruptions_fixed = corruptions_fixed;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
switch (output_format) {
|
||||
case OFORMAT_HUMAN:
|
||||
dump_human_image_check(check, quiet);
|
||||
@ -695,8 +696,14 @@ static int img_check(int argc, char **argv)
|
||||
dump_json_image_check(check, quiet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret || check->check_errors) {
|
||||
if (ret) {
|
||||
error_report("Check failed: %s", strerror(-ret));
|
||||
} else {
|
||||
error_report("Check failed");
|
||||
}
|
||||
ret = 1;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1900,7 +1900,7 @@ static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
num_checked = MIN(nb_sectors, INT_MAX);
|
||||
ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
|
||||
if (ret == firstret) {
|
||||
if (ret == firstret && num) {
|
||||
*pnum += num;
|
||||
} else {
|
||||
break;
|
||||
@ -1927,6 +1927,9 @@ static int map_f(BlockDriverState *bs, int argc, char **argv)
|
||||
if (ret < 0) {
|
||||
error_report("Failed to get allocation status: %s", strerror(-ret));
|
||||
return 0;
|
||||
} else if (!num) {
|
||||
error_report("Unexpected end of image");
|
||||
return 0;
|
||||
}
|
||||
|
||||
retstr = ret ? " allocated" : "not allocated";
|
||||
|
@ -25,7 +25,10 @@ read 512/512 bytes at offset 0
|
||||
incompatible_features 0x1
|
||||
|
||||
== Repairing the image file must succeed ==
|
||||
Repairing cluster 5 refcount=0 reference=1
|
||||
ERROR cluster 5 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
@ -45,7 +48,10 @@ wrote 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./039: Aborted ( ulimit -c 0; exec "$@" )
|
||||
incompatible_features 0x1
|
||||
Repairing cluster 5 refcount=0 reference=1
|
||||
ERROR cluster 5 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
wrote 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
incompatible_features 0x0
|
||||
|
@ -36,11 +36,15 @@ incompatible_features 0x0
|
||||
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed
|
||||
write failed: Input/output error
|
||||
incompatible_features 0x2
|
||||
Repairing refcount block 0 refcount=2
|
||||
ERROR refcount block 0 refcount=2
|
||||
ERROR cluster 2 refcount=1 reference=2
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=2 reference=1
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
2 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
@ -68,6 +72,8 @@ incompatible_features 0x0
|
||||
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed
|
||||
write failed: Input/output error
|
||||
incompatible_features 0x2
|
||||
ERROR cluster 4 refcount=1 reference=2
|
||||
Leaked cluster 9 refcount=1 reference=0
|
||||
Repairing cluster 4 refcount=1 reference=2
|
||||
Repairing cluster 9 refcount=1 reference=0
|
||||
Repairing OFLAG_COPIED data cluster: l2_entry=8000000000040000 refcount=2
|
||||
|
@ -76,8 +76,11 @@ autoclear_features 0x0
|
||||
refcount_order 4
|
||||
header_length 104
|
||||
|
||||
Repairing cluster 5 refcount=0 reference=1
|
||||
Repairing cluster 6 refcount=0 reference=1
|
||||
ERROR cluster 5 refcount=0 reference=1
|
||||
ERROR cluster 6 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
magic 0x514649fb
|
||||
version 2
|
||||
backing_file_offset 0x0
|
||||
@ -87,7 +90,7 @@ size 67108864
|
||||
crypt_method 0
|
||||
l1_size 1
|
||||
l1_table_offset 0x30000
|
||||
refcount_table_offset 0x10000
|
||||
refcount_table_offset 0x80000
|
||||
refcount_table_clusters 1
|
||||
nb_snapshots 0
|
||||
snapshot_offset 0x0
|
||||
@ -230,8 +233,11 @@ autoclear_features 0x0
|
||||
refcount_order 4
|
||||
header_length 104
|
||||
|
||||
Repairing cluster 5 refcount=0 reference=1
|
||||
Repairing cluster 6 refcount=0 reference=1
|
||||
ERROR cluster 5 refcount=0 reference=1
|
||||
ERROR cluster 6 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
magic 0x514649fb
|
||||
version 3
|
||||
backing_file_offset 0x0
|
||||
@ -241,7 +247,7 @@ size 67108864
|
||||
crypt_method 0
|
||||
l1_size 1
|
||||
l1_table_offset 0x30000
|
||||
refcount_table_offset 0x10000
|
||||
refcount_table_offset 0x80000
|
||||
refcount_table_clusters 1
|
||||
nb_snapshots 0
|
||||
snapshot_offset 0x0
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt cloop
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
block_size_offset=128
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt parallels
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
tracks_offset=$((0x1c))
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt bochs
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
catalog_size_offset=$((0x48))
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_proto file nfs
|
||||
_supported_os Linux
|
||||
|
||||
function test_qemu_img()
|
||||
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
header_size=104
|
||||
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt raw
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
function do_run_qemu()
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_proto file nfs
|
||||
_supported_os Linux
|
||||
|
||||
function run_qemu_img()
|
||||
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# This tests vdi-specific header fields
|
||||
_supported_fmt vdi
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
size=64M
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_proto file nfs
|
||||
_supported_os Linux
|
||||
|
||||
function run_qemu_img()
|
||||
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt vpc
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
offset_block_size=$((512 + 32))
|
||||
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_proto file nfs
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=128K
|
||||
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow
|
||||
_supported_proto generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
offset_backing_file_offset=8
|
||||
|
64
tests/qemu-iotests/102
Executable file
64
tests/qemu-iotests/102
Executable file
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test case for qemu-io -c map and qemu-img map
|
||||
#
|
||||
# Copyright (C) 2014 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
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=64K
|
||||
|
||||
echo
|
||||
echo '=== Testing map command on truncated image ==='
|
||||
echo
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
# Create cluster
|
||||
$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
# Remove data cluster from image (first cluster: image header, second: reftable,
|
||||
# third: refblock, fourth: L1 table, fifth: L2 table)
|
||||
truncate -s $((5 * 64 * 1024)) "$TEST_IMG"
|
||||
|
||||
$QEMU_IO -c map "$TEST_IMG"
|
||||
$QEMU_IMG map "$TEST_IMG"
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
status=0
|
10
tests/qemu-iotests/102.out
Normal file
10
tests/qemu-iotests/102.out
Normal file
@ -0,0 +1,10 @@
|
||||
QA output created by 102
|
||||
|
||||
=== Testing map command on truncated image ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
[ 0] 128/ 128 sectors allocated at offset 0 bytes (1)
|
||||
Offset Length Mapped to File
|
||||
*** done
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_proto file nfs
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=64K
|
||||
|
61
tests/qemu-iotests/107
Executable file
61
tests/qemu-iotests/107
Executable file
@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Tests updates of the qcow2 L1 table
|
||||
#
|
||||
# Copyright (C) 2014 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"
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
|
||||
IMG_SIZE=64K
|
||||
|
||||
echo
|
||||
echo '=== Updates should not write random data ==='
|
||||
echo
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'read -p -P 0 196616 65528' \
|
||||
| _filter_qemu_io
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
||||
|
10
tests/qemu-iotests/107.out
Normal file
10
tests/qemu-iotests/107.out
Normal file
@ -0,0 +1,10 @@
|
||||
QA output created by 107
|
||||
|
||||
=== Updates should not write random data ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65528/65528 bytes at offset 196616
|
||||
63.992 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
*** done
|
141
tests/qemu-iotests/108
Executable file
141
tests/qemu-iotests/108
Executable file
@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test case for repairing qcow2 images which cannot be repaired using
|
||||
# the on-disk refcount structures
|
||||
#
|
||||
# Copyright (C) 2014 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"
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
# This tests qocw2-specific low-level functionality
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
echo
|
||||
echo '=== Repairing an image without any refcount table ==='
|
||||
echo
|
||||
|
||||
_make_test_img 64M
|
||||
# just write some data
|
||||
$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# refcount_table_offset
|
||||
poke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
# refcount_table_clusters
|
||||
poke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00"
|
||||
|
||||
_check_test_img -r all
|
||||
|
||||
$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo '=== Repairing unreferenced data cluster in new refblock area ==='
|
||||
echo
|
||||
|
||||
IMGOPTS='cluster_size=512' _make_test_img 64M
|
||||
# Allocate the first 128 kB in the image (first refblock)
|
||||
$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io
|
||||
# should be 131072 == 0x20000
|
||||
stat -c '%s' "$TEST_IMG"
|
||||
|
||||
# Enter a cluster at 128 kB (0x20000)
|
||||
# XXX: This should be the first free entry in the last L2 table, but we cannot
|
||||
# be certain
|
||||
poke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00"
|
||||
|
||||
# Fill the cluster
|
||||
truncate -s $((0x20200)) "$TEST_IMG"
|
||||
$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \
|
||||
| _filter_qemu_io
|
||||
|
||||
# The data should now appear at this guest offset
|
||||
$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# This cluster is unallocated; fix it
|
||||
_check_test_img -r all
|
||||
|
||||
# This repair operation must have allocated a new refblock; and that refblock
|
||||
# should not overlap with the unallocated data cluster. If it does, the data
|
||||
# will be damaged, so check it.
|
||||
$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo '=== Repairing refblock beyond the image end ==='
|
||||
echo
|
||||
|
||||
echo
|
||||
echo '--- Otherwise clean ---'
|
||||
echo
|
||||
|
||||
_make_test_img 64M
|
||||
# Normally, qemu doesn't create empty refblocks, so we just have to do it by
|
||||
# hand
|
||||
# XXX: This should be the entry for the second refblock
|
||||
poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00"
|
||||
# Mark that refblock as used
|
||||
# XXX: This should be the 17th entry (cluster 16) of the first
|
||||
# refblock
|
||||
poke_file "$TEST_IMG" $((0x20020)) "\x00\x01"
|
||||
_check_test_img -r all
|
||||
|
||||
echo
|
||||
echo '--- Refblock is unallocated ---'
|
||||
echo
|
||||
|
||||
_make_test_img 64M
|
||||
poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00"
|
||||
_check_test_img -r all
|
||||
|
||||
echo
|
||||
echo '--- Signed overflow after the refblock ---'
|
||||
echo
|
||||
|
||||
_make_test_img 64M
|
||||
poke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00"
|
||||
_check_test_img -r all
|
||||
|
||||
echo
|
||||
echo '--- Unsigned overflow after the refblock ---'
|
||||
echo
|
||||
|
||||
_make_test_img 64M
|
||||
poke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00"
|
||||
_check_test_img -r all
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
status=0
|
110
tests/qemu-iotests/108.out
Normal file
110
tests/qemu-iotests/108.out
Normal file
@ -0,0 +1,110 @@
|
||||
QA output created by 108
|
||||
|
||||
=== Repairing an image without any refcount table ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
ERROR cluster 0 refcount=0 reference=1
|
||||
ERROR cluster 3 refcount=0 reference=1
|
||||
ERROR cluster 4 refcount=0 reference=1
|
||||
ERROR cluster 5 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
4 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Repairing unreferenced data cluster in new refblock area ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
wrote 111104/111104 bytes at offset 0
|
||||
108.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
131072
|
||||
wrote 512/512 bytes at offset 131072
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 111104
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
ERROR cluster 256 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
read 512/512 bytes at offset 111104
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Repairing refblock beyond the image end ===
|
||||
|
||||
|
||||
--- Otherwise clean ---
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Repairing refcount block 1 is outside image
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
|
||||
--- Refblock is unallocated ---
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Repairing refcount block 1 is outside image
|
||||
ERROR cluster 16 refcount=0 reference=1
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
Repairing cluster 16 refcount=1 reference=0
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
2 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
|
||||
--- Signed overflow after the refblock ---
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Repairing refcount block 1 is outside image
|
||||
ERROR could not resize image: Invalid argument
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
|
||||
--- Unsigned overflow after the refblock ---
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Repairing refcount block 1 is outside image
|
||||
ERROR could not resize image: Invalid argument
|
||||
Rebuilding refcount structure
|
||||
Repairing cluster 1 refcount=1 reference=0
|
||||
Repairing cluster 2 refcount=1 reference=0
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
*** done
|
@ -103,6 +103,9 @@
|
||||
099 rw auto quick
|
||||
100 rw auto quick
|
||||
101 rw auto quick
|
||||
102 rw auto quick
|
||||
103 rw auto quick
|
||||
104 rw auto
|
||||
105 rw auto quick
|
||||
107 rw auto quick
|
||||
108 rw auto quick
|
||||
|
Loading…
Reference in New Issue
Block a user