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:
Peter Maydell 2014-10-24 11:33:46 +01:00
commit 8b135a288a
35 changed files with 1170 additions and 328 deletions

View File

@ -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

31
block.c
View File

@ -3954,13 +3954,24 @@ 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.
*/
ret |= (ret2 & BDRV_BLOCK_ZERO);
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);
}
}
}
@ -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.
*/

View File

@ -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

View File

@ -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)),
};

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -687,16 +687,23 @@ static int img_check(int argc, char **argv)
check->corruptions_fixed = corruptions_fixed;
}
switch (output_format) {
case OFORMAT_HUMAN:
dump_human_image_check(check, quiet);
break;
case OFORMAT_JSON:
dump_json_image_check(check, quiet);
break;
if (!ret) {
switch (output_format) {
case OFORMAT_HUMAN:
dump_human_image_check(check, quiet);
break;
case OFORMAT_JSON:
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;
}

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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))

View File

@ -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

View File

@ -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
View 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

View 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

View File

@ -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
View 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

View 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
View 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
View 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

View File

@ -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