1
The following changes since commit 76d20ea0f1b26ebd5da2f5fb2fdf3250cde887bb:
1
The following changes since commit b2f7a038bb4c4fc5ce6b8486e8513dfd97665e2a:
2
2
3
Merge remote-tracking branch 'armbru/tags/pull-qapi-2017-05-04-v3' into staging (2017-05-09 15:49:14 -0400)
3
Merge remote-tracking branch 'remotes/rth/tags/pull-softfloat-20181104' into staging (2018-11-05 10:32:49 +0000)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
7
6
8
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
9
8
10
for you to fetch changes up to d541e201bd3ad888f02abeddf0e14f7b0c126529:
9
for you to fetch changes up to 1240ac558d348f6c7a5752b1a57c1da58e4efe3e:
11
10
12
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-05-11' into queue-block (2017-05-11 14:34:56 +0200)
11
include: Add a comment to explain the origin of sizes' lookup table (2018-11-05 15:29:59 +0100)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
15
15
16
Block layer patches
16
- auto-read-only option to fix commit job when used with -blockdev
17
- Fix help text related qemu-iotests failure (by improving the help text
18
and updating the reference output)
19
- quorum: Add missing checks when adding/removing child nodes
20
- Don't take address of fields in packed structs
21
- vvfat: Fix crash when reporting error about too many files in directory
17
22
18
----------------------------------------------------------------
23
----------------------------------------------------------------
19
Anton Nefedov (1):
24
Alberto Garcia (7):
20
qemu-img: wait for convert coroutines to complete
25
block: replace "discard" literal with BDRV_OPT_DISCARD macro
26
qcow2: Get the request alignment for encrypted images from QCryptoBlock
27
quorum: Remove quorum_err()
28
quorum: Return an error if the blkverify mode has invalid settings
29
iotest: Test the blkverify mode of the Quorum driver
30
quorum: Forbid adding children in blkverify mode
31
iotest: Test x-blockdev-change on a Quorum
21
32
22
Christoph Hellwig (1):
33
Cleber Rosa (1):
23
nvme: Implement Write Zeroes
34
iotests: make 083 specific to raw
24
35
25
Eric Blake (21):
36
Daniel P. Berrangé (1):
26
qemu-io: Improve alignment checks
37
crypto: initialize sector size even when opening with no IO flag
27
qemu-io: Switch 'alloc' command to byte-based length
28
qemu-io: Switch 'map' output to byte-based reporting
29
blkdebug: Sanity check block layer guarantees
30
blkdebug: Refactor error injection
31
blkdebug: Add pass-through write_zero and discard support
32
blkdebug: Simplify override logic
33
blkdebug: Add ability to override unmap geometries
34
tests: Add coverage for recent block geometry fixes
35
qcow2: Nicer variable names in qcow2_update_snapshot_refcount()
36
qcow2: Use consistent switch indentation
37
block: Update comments on BDRV_BLOCK_* meanings
38
qcow2: Correctly report status of preallocated zero clusters
39
qcow2: Name typedef for cluster type
40
qcow2: Make distinction between zero cluster types obvious
41
qcow2: Optimize zero_single_l2() to minimize L2 churn
42
iotests: Improve _filter_qemu_img_map
43
iotests: Add test 179 to cover write zeroes with unmap
44
qcow2: Optimize write zero of unaligned tail cluster
45
qcow2: Assert that cluster operations are aligned
46
qcow2: Discard/zero clusters by byte count
47
38
48
Fam Zheng (23):
39
Kevin Wolf (12):
49
block: Make bdrv_perm_names public
40
vpc: Don't leak opts in vpc_open()
50
block: Add, parse and store "force-share" option
41
block: Update flags in bdrv_set_read_only()
51
block: Respect "force-share" in perm propagating
42
block: Add auto-read-only option
52
qemu-img: Add --force-share option to subcommands
43
rbd: Close image in qemu_rbd_open() error path
53
qemu-img: Update documentation for -U
44
block: Require auto-read-only for existing fallbacks
54
qemu-io: Add --force-share option
45
nbd: Support auto-read-only option
55
iotests: 030: Prepare for image locking
46
file-posix: Support auto-read-only option
56
iotests: 046: Prepare for image locking
47
curl: Support auto-read-only option
57
iotests: 055: Don't attach the target image already for drive-backup
48
gluster: Support auto-read-only option
58
iotests: 085: Avoid image locking conflict
49
iscsi: Support auto-read-only option
59
iotests: 087: Don't attach test image twice
50
block: Make auto-read-only=on default for -drive
60
iotests: 091: Quit QEMU before checking image
51
qemu-iotests: Test auto-read-only with -drive and -blockdev
61
iotests: 172: Use separate images for multiple devices
62
tests: Use null-co:// instead of /dev/null as the dummy image
63
file-posix: Add 'locking' option
64
file-win32: Error out if locking=on
65
tests: Disable image lock in test-replication
66
block: Reuse bs as backing hd for drive-backup sync=none
67
osdep: Add qemu_lock_fd and qemu_unlock_fd
68
osdep: Fall back to posix lock when OFD lock is unavailable
69
file-posix: Add image locking to perm operations
70
qemu-iotests: Add test case 153 for image locking
71
tests: Add POSIX image locking test case 182
72
52
73
John Snow (1):
53
Leonid Bloch (2):
74
blockdev: use drained_begin/end for qmp_block_resize
54
vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE
55
include: Add a comment to explain the origin of sizes' lookup table
75
56
76
Kevin Wolf (7):
57
Li Qiang (1):
77
migration: Unify block node activation error handling
58
block: change some function return type to bool
78
block: New BdrvChildRole.activate() for blk_resume_after_migration()
79
block: Drop permissions when migration completes
80
block: Inactivate parents before children
81
block: Fix write/resize permissions for inactive images
82
file-posix: Remove .bdrv_inactivate/invalidate_cache
83
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-05-11' into queue-block
84
59
85
Max Reitz (5):
60
Max Reitz (5):
86
qcow2: Fix preallocation size formula
61
option: Make option help nicer to read
87
qcow2: Reuse preallocated zero clusters
62
chardev: Indent list of chardevs
88
qcow2: Discard preallocated zero clusters
63
qdev-monitor: Make device options help nicer
89
iotests: Extend test 066
64
object: Make option help nicer to read
90
MAINTAINERS: Add qemu-progress to the block layer
65
fw_cfg: Drop newline in @file description
91
66
92
MAINTAINERS | 1 +
67
Peter Maydell (5):
93
block.c | 127 +++++++++++--
68
block/qcow2: Don't take address of fields in packed structs
94
block/blkdebug.c | 264 +++++++++++++++++++++-----
69
block/qcow: Don't take address of fields in packed structs
95
block/block-backend.c | 81 +++++---
70
block/qcow2-bitmap: Don't take address of fields in packed structs
96
block/file-posix.c | 248 +++++++++++++++++++++++-
71
block/vhdx: Don't take address of fields in packed structs
97
block/file-win32.c | 5 +
72
block/vdi: Don't take address of fields in packed structs
98
block/qcow2-cluster.c | 252 ++++++++++++++----------
99
block/qcow2-refcount.c | 148 +++++++--------
100
block/qcow2-snapshot.c | 7 +-
101
block/qcow2.c | 47 +++--
102
block/qcow2.h | 26 ++-
103
blockdev.c | 20 +-
104
hw/block/nvme.c | 26 +++
105
hw/block/nvme.h | 1 +
106
include/block/block.h | 41 ++--
107
include/block/block_int.h | 14 ++
108
include/qemu/osdep.h | 3 +
109
migration/migration.c | 13 +-
110
migration/savevm.c | 9 +-
111
qapi/block-core.json | 40 +++-
112
qemu-img-cmds.hx | 36 ++--
113
qemu-img.c | 179 ++++++++++++-----
114
qemu-io-cmds.c | 61 +++---
115
qemu-io.c | 42 +++-
116
qmp.c | 18 +-
117
tests/drive_del-test.c | 2 +-
118
tests/nvme-test.c | 2 +-
119
tests/qemu-iotests/019.out | 8 +-
120
tests/qemu-iotests/030 | 18 +-
121
tests/qemu-iotests/046 | 2 +-
122
tests/qemu-iotests/055 | 32 ++--
123
tests/qemu-iotests/060.out | 6 +-
124
tests/qemu-iotests/066 | 128 ++++++++++++-
125
tests/qemu-iotests/066.out | 46 +++++
126
tests/qemu-iotests/085 | 33 ++--
127
tests/qemu-iotests/085.out | 3 +-
128
tests/qemu-iotests/087 | 6 +-
129
tests/qemu-iotests/091 | 2 +
130
tests/qemu-iotests/102.out | 4 +-
131
tests/qemu-iotests/122.out | 16 +-
132
tests/qemu-iotests/146.out | 30 +--
133
tests/qemu-iotests/153 | 233 +++++++++++++++++++++++
134
tests/qemu-iotests/153.out | 390 ++++++++++++++++++++++++++++++++++++++
135
tests/qemu-iotests/154 | 160 +++++++++++++++-
136
tests/qemu-iotests/154.out | 158 +++++++++++++--
137
tests/qemu-iotests/172 | 55 +++---
138
tests/qemu-iotests/172.out | 50 ++---
139
tests/qemu-iotests/177 | 114 +++++++++++
140
tests/qemu-iotests/177.out | 49 +++++
141
tests/qemu-iotests/179 | 130 +++++++++++++
142
tests/qemu-iotests/179.out | 156 +++++++++++++++
143
tests/qemu-iotests/182 | 68 +++++++
144
tests/qemu-iotests/182.out | 8 +
145
tests/qemu-iotests/common.filter | 4 +-
146
tests/qemu-iotests/common.pattern | 2 +-
147
tests/qemu-iotests/group | 4 +
148
tests/test-replication.c | 9 +-
149
tests/usb-hcd-uhci-test.c | 2 +-
150
tests/usb-hcd-xhci-test.c | 2 +-
151
tests/virtio-blk-test.c | 2 +-
152
tests/virtio-scsi-test.c | 5 +-
153
util/osdep.c | 48 +++++
154
62 files changed, 3086 insertions(+), 610 deletions(-)
155
create mode 100755 tests/qemu-iotests/153
156
create mode 100644 tests/qemu-iotests/153.out
157
create mode 100755 tests/qemu-iotests/177
158
create mode 100644 tests/qemu-iotests/177.out
159
create mode 100755 tests/qemu-iotests/179
160
create mode 100644 tests/qemu-iotests/179.out
161
create mode 100755 tests/qemu-iotests/182
162
create mode 100644 tests/qemu-iotests/182.out
163
73
74
Stefan Weil (1):
75
qemu-io-cmds: Fix two format strings
76
77
Thomas Huth (1):
78
block/vvfat: Fix crash when reporting error about too many files in directory
79
80
qapi/block-core.json | 7 +
81
block/vhdx.h | 12 +-
82
include/block/block.h | 5 +-
83
include/qemu/option.h | 2 +-
84
include/qemu/units.h | 18 +
85
include/sysemu/block-backend.h | 6 +-
86
block.c | 60 ++-
87
block/block-backend.c | 8 +-
88
block/bochs.c | 17 +-
89
block/cloop.c | 16 +-
90
block/curl.c | 8 +-
91
block/dmg.c | 16 +-
92
block/file-posix.c | 19 +-
93
block/gluster.c | 12 +-
94
block/iscsi.c | 8 +-
95
block/nbd-client.c | 10 +-
96
block/qcow.c | 18 +-
97
block/qcow2-bitmap.c | 24 +-
98
block/qcow2.c | 66 +--
99
block/quorum.c | 45 +-
100
block/rbd.c | 14 +-
101
block/vdi.c | 68 +--
102
block/vhdx-endian.c | 118 ++---
103
block/vhdx-log.c | 4 +-
104
block/vhdx.c | 18 +-
105
block/vpc.c | 2 +
106
block/vvfat.c | 15 +-
107
blockdev.c | 3 +-
108
chardev/char.c | 2 +-
109
crypto/block-qcow.c | 2 +
110
qdev-monitor.c | 13 +-
111
qemu-img.c | 4 +-
112
qemu-io-cmds.c | 4 +-
113
util/qemu-option.c | 32 +-
114
vl.c | 15 +-
115
tests/qemu-iotests/081 | 116 +++++
116
tests/qemu-iotests/081.out | 70 +++
117
tests/qemu-iotests/082.out | 956 ++++++++++++++++++++---------------------
118
tests/qemu-iotests/083 | 2 +-
119
tests/qemu-iotests/232 | 147 +++++++
120
tests/qemu-iotests/232.out | 59 +++
121
tests/qemu-iotests/group | 1 +
122
42 files changed, 1266 insertions(+), 776 deletions(-)
123
create mode 100755 tests/qemu-iotests/232
124
create mode 100644 tests/qemu-iotests/232.out
125
diff view generated by jsdifflib
1
From: Christoph Hellwig <hch@lst.de>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Signed-off-by: Keith Busch <keith.busch@intel.com>
3
When using the vvfat driver with a directory that contains too many files,
4
[hch: ported over from qemu-nvme.git to mainline]
4
QEMU currently crashes. This can be triggered like this for example:
5
Signed-off-by: Christoph Hellwig <hch@lst.de>
5
6
Acked-by: Keith Busch <keith.busch@intel.com>
6
mkdir /tmp/vvfattest
7
cd /tmp/vvfattest
8
for ((x=0;x<=513;x++)); do mkdir $x; done
9
qemu-system-x86_64 -drive \
10
file.driver=vvfat,file.dir=.,read-only=on,media=cdrom
11
12
Seems like read_directory() is changing the mapping->path variable. Make
13
sure we use the right pointer instead.
14
15
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
17
---
9
hw/block/nvme.c | 26 ++++++++++++++++++++++++++
18
block/vvfat.c | 4 ++--
10
hw/block/nvme.h | 1 +
19
1 file changed, 2 insertions(+), 2 deletions(-)
11
2 files changed, 27 insertions(+)
12
20
13
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
21
diff --git a/block/vvfat.c b/block/vvfat.c
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/block/nvme.c
23
--- a/block/vvfat.c
16
+++ b/hw/block/nvme.c
24
+++ b/block/vvfat.c
17
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_flush(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
25
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
18
return NVME_NO_COMPLETE;
26
mapping = array_get(&(s->mapping), i);
19
}
27
20
28
if (mapping->mode & MODE_DIRECTORY) {
21
+static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
29
+ char *path = mapping->path;
22
+ NvmeRequest *req)
30
mapping->begin = cluster;
23
+{
31
if(read_directory(s, i)) {
24
+ NvmeRwCmd *rw = (NvmeRwCmd *)cmd;
32
- error_setg(errp, "Could not read directory %s",
25
+ const uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas);
33
- mapping->path);
26
+ const uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds;
34
+ error_setg(errp, "Could not read directory %s", path);
27
+ uint64_t slba = le64_to_cpu(rw->slba);
35
return -1;
28
+ uint32_t nlb = le16_to_cpu(rw->nlb) + 1;
36
}
29
+ uint64_t aio_slba = slba << (data_shift - BDRV_SECTOR_BITS);
37
mapping = array_get(&(s->mapping), i);
30
+ uint32_t aio_nlb = nlb << (data_shift - BDRV_SECTOR_BITS);
31
+
32
+ if (slba + nlb > ns->id_ns.nsze) {
33
+ return NVME_LBA_RANGE | NVME_DNR;
34
+ }
35
+
36
+ req->has_sg = false;
37
+ block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0,
38
+ BLOCK_ACCT_WRITE);
39
+ req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, aio_slba, aio_nlb,
40
+ BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req);
41
+ return NVME_NO_COMPLETE;
42
+}
43
+
44
static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
45
NvmeRequest *req)
46
{
47
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
48
switch (cmd->opcode) {
49
case NVME_CMD_FLUSH:
50
return nvme_flush(n, ns, cmd, req);
51
+ case NVME_CMD_WRITE_ZEROS:
52
+ return nvme_write_zeros(n, ns, cmd, req);
53
case NVME_CMD_WRITE:
54
case NVME_CMD_READ:
55
return nvme_rw(n, ns, cmd, req);
56
@@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev)
57
id->sqes = (0x6 << 4) | 0x6;
58
id->cqes = (0x4 << 4) | 0x4;
59
id->nn = cpu_to_le32(n->num_namespaces);
60
+ id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS);
61
id->psd[0].mp = cpu_to_le16(0x9c4);
62
id->psd[0].enlat = cpu_to_le32(0x10);
63
id->psd[0].exlat = cpu_to_le32(0x4);
64
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/block/nvme.h
67
+++ b/hw/block/nvme.h
68
@@ -XXX,XX +XXX,XX @@ enum NvmeIoCommands {
69
NVME_CMD_READ = 0x02,
70
NVME_CMD_WRITE_UNCOR = 0x04,
71
NVME_CMD_COMPARE = 0x05,
72
+ NVME_CMD_WRITE_ZEROS = 0x08,
73
NVME_CMD_DSM = 0x09,
74
};
75
76
--
38
--
77
1.8.3.1
39
2.19.1
78
40
79
41
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
5
---
6
block.c | 32 ++++++++++++++++++++++++--------
6
block.c | 6 +++---
7
1 file changed, 24 insertions(+), 8 deletions(-)
7
1 file changed, 3 insertions(+), 3 deletions(-)
8
8
9
diff --git a/block.c b/block.c
9
diff --git a/block.c b/block.c
10
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
11
--- a/block.c
12
+++ b/block.c
12
+++ b/block.c
13
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
13
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
14
static void bdrv_child_abort_perm_update(BdrvChild *c);
14
.help = "try to optimize zero writes (off, on, unmap)",
15
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
15
},
16
16
{
17
+static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
17
- .name = "discard",
18
+ BdrvChild *c,
18
+ .name = BDRV_OPT_DISCARD,
19
+ const BdrvChildRole *role,
19
.type = QEMU_OPT_STRING,
20
+ uint64_t parent_perm, uint64_t parent_shared,
20
.help = "discard operation (ignore/off, unmap/on)",
21
+ uint64_t *nperm, uint64_t *nshared)
21
},
22
+{
22
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
23
+ if (bs->drv && bs->drv->bdrv_child_perm) {
23
}
24
+ bs->drv->bdrv_child_perm(bs, c, role,
25
+ parent_perm, parent_shared,
26
+ nperm, nshared);
27
+ }
28
+ if (child_bs && child_bs->force_share) {
29
+ *nshared = BLK_PERM_ALL;
30
+ }
31
+}
32
+
33
/*
34
* Check whether permissions on this node can be changed in a way that
35
* @cumulative_perms and @cumulative_shared_perms are the new cumulative
36
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms,
37
/* Check all children */
38
QLIST_FOREACH(c, &bs->children, next) {
39
uint64_t cur_perm, cur_shared;
40
- drv->bdrv_child_perm(bs, c, c->role,
41
- cumulative_perms, cumulative_shared_perms,
42
- &cur_perm, &cur_shared);
43
+ bdrv_child_perm(bs, c->bs, c, c->role,
44
+ cumulative_perms, cumulative_shared_perms,
45
+ &cur_perm, &cur_shared);
46
ret = bdrv_child_check_perm(c, cur_perm, cur_shared, ignore_children,
47
errp);
48
if (ret < 0) {
49
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
50
/* Update all children */
51
QLIST_FOREACH(c, &bs->children, next) {
52
uint64_t cur_perm, cur_shared;
53
- drv->bdrv_child_perm(bs, c, c->role,
54
- cumulative_perms, cumulative_shared_perms,
55
- &cur_perm, &cur_shared);
56
+ bdrv_child_perm(bs, c->bs, c, c->role,
57
+ cumulative_perms, cumulative_shared_perms,
58
+ &cur_perm, &cur_shared);
59
bdrv_child_set_perm(c, cur_perm, cur_shared);
60
}
24
}
61
}
25
62
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
26
- discard = qemu_opt_get(opts, "discard");
63
27
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
64
assert(parent_bs->drv);
28
if (discard != NULL) {
65
assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs));
29
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
66
- parent_bs->drv->bdrv_child_perm(parent_bs, NULL, child_role,
30
error_setg(errp, "Invalid discard option");
67
- perm, shared_perm, &perm, &shared_perm);
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
68
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_role,
32
69
+ perm, shared_perm, &perm, &shared_perm);
33
update_flags_from_options(&reopen_state->flags, opts);
70
34
71
child = bdrv_root_attach_child(child_bs, child_name, child_role,
35
- discard = qemu_opt_get_del(opts, "discard");
72
perm, shared_perm, parent_bs, errp);
36
+ discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
37
if (discard != NULL) {
38
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
39
error_setg(errp, "Invalid discard option");
73
--
40
--
74
1.8.3.1
41
2.19.1
75
42
76
43
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Stefan Weil <sw@weilnetz.de>
2
2
3
Several copy-and-pasted alignment checks exist in qemu-io, which
3
Use %zu instead of %zd for unsigned numbers.
4
could use some minor improvements:
5
4
6
- Manual comparison against 0x1ff is not as clean as using our
5
This fixes two error messages from the LSTM static code analyzer:
7
alignment macros (QEMU_IS_ALIGNED) from osdep.h.
8
6
9
- The error messages aren't quite grammatically correct.
7
This argument should be of type 'ssize_t' but is of type 'unsigned long'
10
8
11
Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Stefan Weil <sw@weilnetz.de>
12
Suggested-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Message-id: 20170429191419.30051-2-eblake@redhat.com
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
12
---
19
qemu-io-cmds.c | 20 ++++++++++----------
13
qemu-io-cmds.c | 4 ++--
20
1 file changed, 10 insertions(+), 10 deletions(-)
14
1 file changed, 2 insertions(+), 2 deletions(-)
21
15
22
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-io-cmds.c
18
--- a/qemu-io-cmds.c
25
+++ b/qemu-io-cmds.c
19
+++ b/qemu-io-cmds.c
26
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
20
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
27
}
21
memset(cmp_buf, pattern, qiov.size);
28
22
if (memcmp(buf, cmp_buf, qiov.size)) {
29
if (bflag) {
23
printf("Pattern verification failed at offset %"
30
- if (offset & 0x1ff) {
24
- PRId64 ", %zd bytes\n", offset, qiov.size);
31
- printf("offset %" PRId64 " is not sector aligned\n",
25
+ PRId64 ", %zu bytes\n", offset, qiov.size);
32
+ if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
26
ret = -EINVAL;
33
+ printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
34
offset);
35
return 0;
36
}
27
}
37
- if (count & 0x1ff) {
28
g_free(cmp_buf);
38
- printf("count %"PRId64" is not sector aligned\n",
29
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
39
+ if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
30
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
40
+ printf("%"PRId64" is not a sector-aligned value for 'count'\n",
31
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
41
count);
32
printf("Pattern verification failed at offset %"
42
return 0;
33
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
34
+ PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
43
}
35
}
44
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
36
g_free(cmp_buf);
45
}
46
47
if (bflag || cflag) {
48
- if (offset & 0x1ff) {
49
- printf("offset %" PRId64 " is not sector aligned\n",
50
+ if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
51
+ printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
52
offset);
53
return 0;
54
}
55
56
- if (count & 0x1ff) {
57
- printf("count %"PRId64" is not sector aligned\n",
58
+ if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
59
+ printf("%"PRId64" is not a sector-aligned value for 'count'\n",
60
count);
61
return 0;
62
}
63
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
64
if (offset < 0) {
65
print_cvtnum_err(offset, argv[1]);
66
return 0;
67
- } else if (offset & 0x1ff) {
68
- printf("offset %" PRId64 " is not sector aligned\n",
69
+ } else if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
70
+ printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
71
offset);
72
return 0;
73
}
37
}
74
--
38
--
75
1.8.3.1
39
2.19.1
76
40
77
41
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
Passing a byte offset, but sector count, when we ultimately
3
Taking the address of a field in a packed struct is a bad idea, because
4
want to operate on cluster granularity, is madness. Clean up
4
it might not be actually aligned enough for that pointer type (and
5
the external interfaces to take both offset and count as bytes,
5
thus cause a crash on dereference on some host architectures). Newer
6
while still keeping the assertion added previously that the
6
versions of clang warn about this. Avoid the bug by not using the
7
caller must align the values to a cluster. Then rename things
7
"modify in place" byte swapping functions.
8
to make sure backports don't get confused by changed units:
9
instead of qcow2_discard_clusters() and qcow2_zero_clusters(),
10
we now have qcow2_cluster_discard() and qcow2_cluster_zeroize().
11
8
12
The internal functions still operate on clusters at a time, and
9
There are a few places where the in-place swap function is
13
return an int for number of cleared clusters; but on an image
10
used on something other than a packed struct field; we convert
14
with 2M clusters, a single L2 table holds 256k entries that each
11
those anyway, for consistency.
15
represent a 2M cluster, totalling well over INT_MAX bytes if we
16
ever had a request for that many bytes at once. All our callers
17
currently limit themselves to 32-bit bytes (and therefore fewer
18
clusters), but by making this function 64-bit clean, we have one
19
less place to clean up if we later improve the block layer to
20
support 64-bit bytes through all operations (with the block layer
21
auto-fragmenting on behalf of more-limited drivers), rather than
22
the current state where some interfaces are artificially limited
23
to INT_MAX at a time.
24
12
25
Signed-off-by: Eric Blake <eblake@redhat.com>
13
This patch was produced with the following spatch script
26
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
(and hand-editing to fold a few resulting overlength lines):
27
Message-id: 20170507000552.20847-13-eblake@redhat.com
15
28
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
@@
17
expression E;
18
@@
19
-be16_to_cpus(&E);
20
+E = be16_to_cpu(E);
21
@@
22
expression E;
23
@@
24
-be32_to_cpus(&E);
25
+E = be32_to_cpu(E);
26
@@
27
expression E;
28
@@
29
-be64_to_cpus(&E);
30
+E = be64_to_cpu(E);
31
@@
32
expression E;
33
@@
34
-cpu_to_be16s(&E);
35
+E = cpu_to_be16(E);
36
@@
37
expression E;
38
@@
39
-cpu_to_be32s(&E);
40
+E = cpu_to_be32(E);
41
@@
42
expression E;
43
@@
44
-cpu_to_be64s(&E);
45
+E = cpu_to_be64(E);
46
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
49
Tested-by: John Snow <jsnow@redhat.com>
50
Reviewed-by: John Snow <jsnow@redhat.com>
51
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
---
52
---
30
block/qcow2-cluster.c | 42 ++++++++++++++++++++++--------------------
53
block/qcow2.c | 64 +++++++++++++++++++++++++++------------------------
31
block/qcow2-snapshot.c | 7 +++----
54
1 file changed, 34 insertions(+), 30 deletions(-)
32
block/qcow2.c | 22 +++++++++-------------
33
block/qcow2.h | 9 +++++----
34
4 files changed, 39 insertions(+), 41 deletions(-)
35
55
36
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/qcow2-cluster.c
39
+++ b/block/qcow2-cluster.c
40
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
41
return nb_clusters;
42
}
43
44
-int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
45
- int nb_sectors, enum qcow2_discard_type type, bool full_discard)
46
+int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
47
+ uint64_t bytes, enum qcow2_discard_type type,
48
+ bool full_discard)
49
{
50
BDRVQcow2State *s = bs->opaque;
51
- uint64_t end_offset;
52
+ uint64_t end_offset = offset + bytes;
53
uint64_t nb_clusters;
54
+ int64_t cleared;
55
int ret;
56
57
- end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
58
-
59
/* Caller must pass aligned values, except at image end */
60
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
61
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
62
end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
63
64
- nb_clusters = size_to_clusters(s, end_offset - offset);
65
+ nb_clusters = size_to_clusters(s, bytes);
66
67
s->cache_discards = true;
68
69
/* Each L2 table is handled by its own loop iteration */
70
while (nb_clusters > 0) {
71
- ret = discard_single_l2(bs, offset, nb_clusters, type, full_discard);
72
- if (ret < 0) {
73
+ cleared = discard_single_l2(bs, offset, nb_clusters, type,
74
+ full_discard);
75
+ if (cleared < 0) {
76
+ ret = cleared;
77
goto fail;
78
}
79
80
- nb_clusters -= ret;
81
- offset += (ret * s->cluster_size);
82
+ nb_clusters -= cleared;
83
+ offset += (cleared * s->cluster_size);
84
}
85
86
ret = 0;
87
@@ -XXX,XX +XXX,XX @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
88
return nb_clusters;
89
}
90
91
-int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors,
92
- int flags)
93
+int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
94
+ uint64_t bytes, int flags)
95
{
96
BDRVQcow2State *s = bs->opaque;
97
- uint64_t end_offset;
98
+ uint64_t end_offset = offset + bytes;
99
uint64_t nb_clusters;
100
+ int64_t cleared;
101
int ret;
102
103
- end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
104
-
105
/* Caller must pass aligned values, except at image end */
106
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
107
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
108
@@ -XXX,XX +XXX,XX @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors,
109
}
110
111
/* Each L2 table is handled by its own loop iteration */
112
- nb_clusters = size_to_clusters(s, nb_sectors << BDRV_SECTOR_BITS);
113
+ nb_clusters = size_to_clusters(s, bytes);
114
115
s->cache_discards = true;
116
117
while (nb_clusters > 0) {
118
- ret = zero_single_l2(bs, offset, nb_clusters, flags);
119
- if (ret < 0) {
120
+ cleared = zero_single_l2(bs, offset, nb_clusters, flags);
121
+ if (cleared < 0) {
122
+ ret = cleared;
123
goto fail;
124
}
125
126
- nb_clusters -= ret;
127
- offset += (ret * s->cluster_size);
128
+ nb_clusters -= cleared;
129
+ offset += (cleared * s->cluster_size);
130
}
131
132
ret = 0;
133
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/block/qcow2-snapshot.c
136
+++ b/block/qcow2-snapshot.c
137
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
138
139
/* The VM state isn't needed any more in the active L1 table; in fact, it
140
* hurts by causing expensive COW for the next snapshot. */
141
- qcow2_discard_clusters(bs, qcow2_vm_state_offset(s),
142
- align_offset(sn->vm_state_size, s->cluster_size)
143
- >> BDRV_SECTOR_BITS,
144
- QCOW2_DISCARD_NEVER, false);
145
+ qcow2_cluster_discard(bs, qcow2_vm_state_offset(s),
146
+ align_offset(sn->vm_state_size, s->cluster_size),
147
+ QCOW2_DISCARD_NEVER, false);
148
149
#ifdef DEBUG_ALLOC
150
{
151
diff --git a/block/qcow2.c b/block/qcow2.c
56
diff --git a/block/qcow2.c b/block/qcow2.c
152
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
153
--- a/block/qcow2.c
58
--- a/block/qcow2.c
154
+++ b/block/qcow2.c
59
+++ b/block/qcow2.c
155
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
60
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
156
trace_qcow2_pwrite_zeroes(qemu_coroutine_self(), offset, count);
61
"pread fail from offset %" PRIu64, offset);
157
62
return 1;
158
/* Whatever is left can use real zero clusters */
63
}
159
- ret = qcow2_zero_clusters(bs, offset, count >> BDRV_SECTOR_BITS, flags);
64
- be32_to_cpus(&ext.magic);
160
+ ret = qcow2_cluster_zeroize(bs, offset, count, flags);
65
- be32_to_cpus(&ext.len);
161
qemu_co_mutex_unlock(&s->lock);
66
+ ext.magic = be32_to_cpu(ext.magic);
162
67
+ ext.len = be32_to_cpu(ext.len);
163
return ret;
68
offset += sizeof(ext);
164
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
69
#ifdef DEBUG_EXT
70
printf("ext.magic = 0x%x\n", ext.magic);
71
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
72
"Unable to read CRYPTO header extension");
73
return ret;
74
}
75
- be64_to_cpus(&s->crypto_header.offset);
76
- be64_to_cpus(&s->crypto_header.length);
77
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
78
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
79
80
if ((s->crypto_header.offset % s->cluster_size) != 0) {
81
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
82
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
83
return -EINVAL;
84
}
85
86
- be32_to_cpus(&bitmaps_ext.nb_bitmaps);
87
- be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
88
- be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
89
+ bitmaps_ext.nb_bitmaps = be32_to_cpu(bitmaps_ext.nb_bitmaps);
90
+ bitmaps_ext.bitmap_directory_size =
91
+ be64_to_cpu(bitmaps_ext.bitmap_directory_size);
92
+ bitmaps_ext.bitmap_directory_offset =
93
+ be64_to_cpu(bitmaps_ext.bitmap_directory_offset);
94
95
if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
96
error_setg(errp,
97
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
98
error_setg_errno(errp, -ret, "Could not read qcow2 header");
99
goto fail;
165
}
100
}
166
101
- be32_to_cpus(&header.magic);
167
qemu_co_mutex_lock(&s->lock);
102
- be32_to_cpus(&header.version);
168
- ret = qcow2_discard_clusters(bs, offset, count >> BDRV_SECTOR_BITS,
103
- be64_to_cpus(&header.backing_file_offset);
169
- QCOW2_DISCARD_REQUEST, false);
104
- be32_to_cpus(&header.backing_file_size);
170
+ ret = qcow2_cluster_discard(bs, offset, count, QCOW2_DISCARD_REQUEST,
105
- be64_to_cpus(&header.size);
171
+ false);
106
- be32_to_cpus(&header.cluster_bits);
172
qemu_co_mutex_unlock(&s->lock);
107
- be32_to_cpus(&header.crypt_method);
173
return ret;
108
- be64_to_cpus(&header.l1_table_offset);
174
}
109
- be32_to_cpus(&header.l1_size);
175
@@ -XXX,XX +XXX,XX @@ fail:
110
- be64_to_cpus(&header.refcount_table_offset);
176
static int qcow2_make_empty(BlockDriverState *bs)
111
- be32_to_cpus(&header.refcount_table_clusters);
177
{
112
- be64_to_cpus(&header.snapshots_offset);
178
BDRVQcow2State *s = bs->opaque;
113
- be32_to_cpus(&header.nb_snapshots);
179
- uint64_t start_sector;
114
+ header.magic = be32_to_cpu(header.magic);
180
- int sector_step = (QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size) /
115
+ header.version = be32_to_cpu(header.version);
181
- BDRV_SECTOR_SIZE);
116
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
182
+ uint64_t offset, end_offset;
117
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
183
+ int step = QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size);
118
+ header.size = be64_to_cpu(header.size);
184
int l1_clusters, ret = 0;
119
+ header.cluster_bits = be32_to_cpu(header.cluster_bits);
185
120
+ header.crypt_method = be32_to_cpu(header.crypt_method);
186
l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t));
121
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
187
@@ -XXX,XX +XXX,XX @@ static int qcow2_make_empty(BlockDriverState *bs)
122
+ header.l1_size = be32_to_cpu(header.l1_size);
188
123
+ header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
189
/* This fallback code simply discards every active cluster; this is slow,
124
+ header.refcount_table_clusters =
190
* but works in all cases */
125
+ be32_to_cpu(header.refcount_table_clusters);
191
- for (start_sector = 0; start_sector < bs->total_sectors;
126
+ header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
192
- start_sector += sector_step)
127
+ header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
193
- {
128
194
+ end_offset = bs->total_sectors * BDRV_SECTOR_SIZE;
129
if (header.magic != QCOW_MAGIC) {
195
+ for (offset = 0; offset < end_offset; offset += step) {
130
error_setg(errp, "Image is not in qcow2 format");
196
/* As this function is generally used after committing an external
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
197
* snapshot, QCOW2_DISCARD_SNAPSHOT seems appropriate. Also, the
132
header.refcount_order = 4;
198
* default action for this kind of discard is to pass the discard,
133
header.header_length = 72;
199
* which will ideally result in an actually smaller image file, as
134
} else {
200
* is probably desired. */
135
- be64_to_cpus(&header.incompatible_features);
201
- ret = qcow2_discard_clusters(bs, start_sector * BDRV_SECTOR_SIZE,
136
- be64_to_cpus(&header.compatible_features);
202
- MIN(sector_step,
137
- be64_to_cpus(&header.autoclear_features);
203
- bs->total_sectors - start_sector),
138
- be32_to_cpus(&header.refcount_order);
204
- QCOW2_DISCARD_SNAPSHOT, true);
139
- be32_to_cpus(&header.header_length);
205
+ ret = qcow2_cluster_discard(bs, offset, MIN(step, end_offset - offset),
140
+ header.incompatible_features =
206
+ QCOW2_DISCARD_SNAPSHOT, true);
141
+ be64_to_cpu(header.incompatible_features);
142
+ header.compatible_features = be64_to_cpu(header.compatible_features);
143
+ header.autoclear_features = be64_to_cpu(header.autoclear_features);
144
+ header.refcount_order = be32_to_cpu(header.refcount_order);
145
+ header.header_length = be32_to_cpu(header.header_length);
146
147
if (header.header_length < 104) {
148
error_setg(errp, "qcow2 header too short");
149
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
150
goto fail;
151
}
152
for(i = 0;i < s->l1_size; i++) {
153
- be64_to_cpus(&s->l1_table[i]);
154
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
155
}
156
}
157
158
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
159
160
/* Full disk encryption header pointer extension */
161
if (s->crypto_header.offset != 0) {
162
- cpu_to_be64s(&s->crypto_header.offset);
163
- cpu_to_be64s(&s->crypto_header.length);
164
+ s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
165
+ s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
166
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
167
&s->crypto_header, sizeof(s->crypto_header),
168
buflen);
169
- be64_to_cpus(&s->crypto_header.offset);
170
- be64_to_cpus(&s->crypto_header.length);
171
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
172
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
207
if (ret < 0) {
173
if (ret < 0) {
208
break;
174
goto fail;
209
}
175
}
210
diff --git a/block/qcow2.h b/block/qcow2.h
211
index XXXXXXX..XXXXXXX 100644
212
--- a/block/qcow2.h
213
+++ b/block/qcow2.h
214
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
215
int compressed_size);
216
217
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
218
-int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
219
- int nb_sectors, enum qcow2_discard_type type, bool full_discard);
220
-int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors,
221
- int flags);
222
+int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
223
+ uint64_t bytes, enum qcow2_discard_type type,
224
+ bool full_discard);
225
+int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
226
+ uint64_t bytes, int flags);
227
228
int qcow2_expand_zero_clusters(BlockDriverState *bs,
229
BlockDriverAmendStatusCB *status_cb,
230
--
176
--
231
1.8.3.1
177
2.19.1
232
178
233
179
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
Opening the backing image for the second time is bad, especially here
3
Taking the address of a field in a packed struct is a bad idea, because
4
when it is also in use as the active image as the source. The
4
it might not be actually aligned enough for that pointer type (and
5
drive-backup job itself doesn't read from target->backing for COW,
5
thus cause a crash on dereference on some host architectures). Newer
6
instead it gets data from the write notifier, so it's not a big problem.
6
versions of clang warn about this. Avoid the bug by not using the
7
However, exporting the target to NBD etc. won't work, because of the
7
"modify in place" byte swapping functions.
8
likely stale metadata cache.
9
8
10
Use BDRV_O_NO_BACKING in this case and manually set up the backing
9
There are a few places where the in-place swap function is
11
BdrvChild.
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
12
13
Cc: qemu-stable@nongnu.org
13
This patch was produced with the following spatch script:
14
Signed-off-by: Fam Zheng <famz@redhat.com>
14
15
@@
16
expression E;
17
@@
18
-be16_to_cpus(&E);
19
+E = be16_to_cpu(E);
20
@@
21
expression E;
22
@@
23
-be32_to_cpus(&E);
24
+E = be32_to_cpu(E);
25
@@
26
expression E;
27
@@
28
-be64_to_cpus(&E);
29
+E = be64_to_cpu(E);
30
@@
31
expression E;
32
@@
33
-cpu_to_be16s(&E);
34
+E = cpu_to_be16(E);
35
@@
36
expression E;
37
@@
38
-cpu_to_be32s(&E);
39
+E = cpu_to_be32(E);
40
@@
41
expression E;
42
@@
43
-cpu_to_be64s(&E);
44
+E = cpu_to_be64(E);
45
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
Tested-by: John Snow <jsnow@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
51
---
17
blockdev.c | 15 ++++++++++++++-
52
block/qcow.c | 18 +++++++++---------
18
1 file changed, 14 insertions(+), 1 deletion(-)
53
1 file changed, 9 insertions(+), 9 deletions(-)
19
54
20
diff --git a/blockdev.c b/blockdev.c
55
diff --git a/block/qcow.c b/block/qcow.c
21
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
22
--- a/blockdev.c
57
--- a/block/qcow.c
23
+++ b/blockdev.c
58
+++ b/block/qcow.c
24
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
59
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
25
Error *local_err = NULL;
60
if (ret < 0) {
26
int flags;
61
goto fail;
27
int64_t size;
28
+ bool set_backing_hd = false;
29
30
if (!backup->has_speed) {
31
backup->speed = 0;
32
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
33
}
62
}
34
if (backup->sync == MIRROR_SYNC_MODE_NONE) {
63
- be32_to_cpus(&header.magic);
35
source = bs;
64
- be32_to_cpus(&header.version);
36
+ flags |= BDRV_O_NO_BACKING;
65
- be64_to_cpus(&header.backing_file_offset);
37
+ set_backing_hd = true;
66
- be32_to_cpus(&header.backing_file_size);
67
- be32_to_cpus(&header.mtime);
68
- be64_to_cpus(&header.size);
69
- be32_to_cpus(&header.crypt_method);
70
- be64_to_cpus(&header.l1_table_offset);
71
+ header.magic = be32_to_cpu(header.magic);
72
+ header.version = be32_to_cpu(header.version);
73
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
74
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
75
+ header.mtime = be32_to_cpu(header.mtime);
76
+ header.size = be64_to_cpu(header.size);
77
+ header.crypt_method = be32_to_cpu(header.crypt_method);
78
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
79
80
if (header.magic != QCOW_MAGIC) {
81
error_setg(errp, "Image not in qcow format");
82
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
38
}
83
}
39
84
40
size = bdrv_getlength(bs);
85
for(i = 0;i < s->l1_size; i++) {
41
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
86
- be64_to_cpus(&s->l1_table[i]);
87
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
42
}
88
}
43
89
44
if (backup->format) {
90
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
45
- options = qdict_new();
46
+ if (!options) {
47
+ options = qdict_new();
48
+ }
49
qdict_put_str(options, "driver", backup->format);
50
}
51
52
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
53
54
bdrv_set_aio_context(target_bs, aio_context);
55
56
+ if (set_backing_hd) {
57
+ bdrv_set_backing_hd(target_bs, source, &local_err);
58
+ if (local_err) {
59
+ bdrv_unref(target_bs);
60
+ goto out;
61
+ }
62
+ }
63
+
64
if (backup->has_bitmap) {
65
bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
66
if (!bmap) {
67
--
91
--
68
1.8.3.1
92
2.19.1
69
93
70
94
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
In the case where we test the expected error when a blockdev-snapshot
3
Taking the address of a field in a packed struct is a bad idea, because
4
target already has a backing image, the backing chain is opened multiple
4
it might not be actually aligned enough for that pointer type (and
5
times. This will be a problem when we use image locking, so use a
5
thus cause a crash on dereference on some host architectures). Newer
6
different backing file that is not already open.
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
7
8
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
13
This patch was produced with the following spatch script:
14
15
@@
16
expression E;
17
@@
18
-be16_to_cpus(&E);
19
+E = be16_to_cpu(E);
20
@@
21
expression E;
22
@@
23
-be32_to_cpus(&E);
24
+E = be32_to_cpu(E);
25
@@
26
expression E;
27
@@
28
-be64_to_cpus(&E);
29
+E = be64_to_cpu(E);
30
@@
31
expression E;
32
@@
33
-cpu_to_be16s(&E);
34
+E = cpu_to_be16(E);
35
@@
36
expression E;
37
@@
38
-cpu_to_be32s(&E);
39
+E = cpu_to_be32(E);
40
@@
41
expression E;
42
@@
43
-cpu_to_be64s(&E);
44
+E = cpu_to_be64(E);
45
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
Tested-by: John Snow <jsnow@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
51
---
11
tests/qemu-iotests/085 | 33 +++++++++++++++++++--------------
52
block/qcow2-bitmap.c | 24 ++++++++++++------------
12
tests/qemu-iotests/085.out | 3 ++-
53
1 file changed, 12 insertions(+), 12 deletions(-)
13
2 files changed, 21 insertions(+), 15 deletions(-)
14
54
15
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
55
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
16
index XXXXXXX..XXXXXXX 100755
56
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/085
57
--- a/block/qcow2-bitmap.c
18
+++ b/tests/qemu-iotests/085
58
+++ b/block/qcow2-bitmap.c
19
@@ -XXX,XX +XXX,XX @@ _cleanup()
59
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
20
rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
60
size_t i;
21
rm -f "${TEST_DIR}/${i}-${snapshot_virt1}"
61
22
done
62
for (i = 0; i < size; ++i) {
23
- rm -f "${TEST_IMG}.1" "${TEST_IMG}.2"
63
- cpu_to_be64s(&bitmap_table[i]);
24
+ rm -f "${TEST_IMG}" "${TEST_IMG}.1" "${TEST_IMG}.2" "${TEST_IMG}.base"
64
+ bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
25
65
}
26
}
66
}
27
trap "_cleanup; exit \$status" 0 1 2 3 15
67
28
@@ -XXX,XX +XXX,XX @@ function create_group_snapshot()
68
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
69
}
70
71
for (i = 0; i < tb->size; ++i) {
72
- be64_to_cpus(&table[i]);
73
+ table[i] = be64_to_cpu(table[i]);
74
ret = check_table_entry(table[i], s->cluster_size);
75
if (ret < 0) {
76
goto fail;
77
@@ -XXX,XX +XXX,XX @@ fail:
78
79
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
80
{
81
- be64_to_cpus(&entry->bitmap_table_offset);
82
- be32_to_cpus(&entry->bitmap_table_size);
83
- be32_to_cpus(&entry->flags);
84
- be16_to_cpus(&entry->name_size);
85
- be32_to_cpus(&entry->extra_data_size);
86
+ entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
87
+ entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
88
+ entry->flags = be32_to_cpu(entry->flags);
89
+ entry->name_size = be16_to_cpu(entry->name_size);
90
+ entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
29
}
91
}
30
92
31
# ${1}: unique identifier for the snapshot filename
93
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
32
-# ${2}: true: open backing images; false: don't open them (default)
33
+# ${2}: extra_params to the blockdev-add command
34
+# ${3}: filename
35
+function do_blockdev_add()
36
+{
37
+ cmd="{ 'execute': 'blockdev-add', 'arguments':
38
+ { 'driver': 'qcow2', 'node-name': 'snap_${1}', ${2}
39
+ 'file':
40
+ { 'driver': 'file', 'filename': '${3}',
41
+ 'node-name': 'file_${1}' } } }"
42
+ _send_qemu_cmd $h "${cmd}" "return"
43
+}
44
+
45
+# ${1}: unique identifier for the snapshot filename
46
function add_snapshot_image()
47
{
94
{
48
- if [ "${2}" = "true" ]; then
95
- cpu_to_be64s(&entry->bitmap_table_offset);
49
- extra_params=""
96
- cpu_to_be32s(&entry->bitmap_table_size);
50
- else
97
- cpu_to_be32s(&entry->flags);
51
- extra_params="'backing': '', "
98
- cpu_to_be16s(&entry->name_size);
52
- fi
99
- cpu_to_be32s(&entry->extra_data_size);
53
base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
100
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
54
snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
101
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
55
_make_test_img -b "${base_image}" "$size"
102
+ entry->flags = cpu_to_be32(entry->flags);
56
mv "${TEST_IMG}" "${snapshot_file}"
103
+ entry->name_size = cpu_to_be16(entry->name_size);
57
- cmd="{ 'execute': 'blockdev-add', 'arguments':
104
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
58
- { 'driver': 'qcow2', 'node-name': 'snap_${1}', ${extra_params}
59
- 'file':
60
- { 'driver': 'file', 'filename': '${snapshot_file}',
61
- 'node-name': 'file_${1}' } } }"
62
- _send_qemu_cmd $h "${cmd}" "return"
63
+ do_blockdev_add "$1" "'backing': '', " "${snapshot_file}"
64
}
105
}
65
106
66
# ${1}: unique identifier for the snapshot filename
107
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
67
@@ -XXX,XX +XXX,XX @@ echo === Invalid command - snapshot node has a backing image ===
68
echo
69
70
SNAPSHOTS=$((${SNAPSHOTS}+1))
71
-add_snapshot_image ${SNAPSHOTS} true
72
+
73
+TEST_IMG="$TEST_IMG.base" _make_test_img "$size"
74
+_make_test_img -b "${TEST_IMG}.base" "$size"
75
+do_blockdev_add ${SNAPSHOTS} "" "${TEST_IMG}"
76
blockdev_snapshot ${SNAPSHOTS} error
77
78
echo
79
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
80
index XXXXXXX..XXXXXXX 100644
81
--- a/tests/qemu-iotests/085.out
82
+++ b/tests/qemu-iotests/085.out
83
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
84
85
=== Invalid command - snapshot node has a backing image ===
86
87
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/12-snapshot-v0.IMGFMT
88
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
89
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
90
{"return": {}}
91
{"error": {"class": "GenericError", "desc": "The snapshot already has a backing image"}}
92
93
--
108
--
94
1.8.3.1
109
2.19.1
95
110
96
111
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Daniel P. Berrangé <berrange@redhat.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
The qcow2 block driver expects to see a valid sector size even when it
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
has opened the crypto layer with QCRYPTO_BLOCK_OPEN_NO_IO.
5
6
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
9
---
7
tests/qemu-iotests/091 | 2 ++
10
crypto/block-qcow.c | 2 ++
8
1 file changed, 2 insertions(+)
11
1 file changed, 2 insertions(+)
9
12
10
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
13
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
11
index XXXXXXX..XXXXXXX 100755
14
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/qemu-iotests/091
15
--- a/crypto/block-qcow.c
13
+++ b/tests/qemu-iotests/091
16
+++ b/crypto/block-qcow.c
14
@@ -XXX,XX +XXX,XX @@ echo "vm2: qemu process running successfully"
17
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
15
echo "vm2: flush io, and quit"
18
Error **errp)
16
_send_qemu_cmd $h2 'qemu-io disk flush' "(qemu)"
19
{
17
_send_qemu_cmd $h2 'quit' ""
20
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
18
+_send_qemu_cmd $h1 'quit' ""
21
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
19
22
+ block->payload_offset = 0;
20
+wait
23
return 0;
21
echo "Check image pattern"
24
} else {
22
${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io
25
if (!options->u.qcow.key_secret) {
23
24
--
26
--
25
1.8.3.1
27
2.19.1
26
28
27
29
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
When calculating the number of reftable entries, we should actually use
3
This doesn't have any practical effect at the moment because the
4
the number of refblocks and not (wrongly[1]) re-calculate it.
4
values of BDRV_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE and
5
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE are all the same (512 bytes), but
6
future encryption methods could have different requirements.
5
7
6
[1] "Wrongly" means: Dividing the number of clusters by the number of
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
entries per refblock and rounding down instead of up.
9
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
8
9
Reported-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
11
---
14
block/qcow2.c | 9 +++++----
12
block/qcow2.c | 2 +-
15
1 file changed, 5 insertions(+), 4 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
16
14
17
diff --git a/block/qcow2.c b/block/qcow2.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2.c
17
--- a/block/qcow2.c
20
+++ b/block/qcow2.c
18
+++ b/block/qcow2.c
21
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
19
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
22
* too, as long as the bulk is allocated here). Therefore, using
20
23
* floating point arithmetic is fine. */
21
if (bs->encrypted) {
24
int64_t meta_size = 0;
22
/* Encryption works on a sector granularity */
25
- uint64_t nreftablee, nrefblocke, nl1e, nl2e;
23
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
26
+ uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count;
24
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
27
int64_t aligned_total_size = align_offset(total_size, cluster_size);
25
}
28
int refblock_bits, refblock_size;
26
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
29
/* refcount entry size in bytes */
27
bs->bl.pdiscard_alignment = s->cluster_size;
30
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
31
nrefblocke = (aligned_total_size + meta_size + cluster_size)
32
/ (cluster_size - rces - rces * sizeof(uint64_t)
33
/ cluster_size);
34
- meta_size += DIV_ROUND_UP(nrefblocke, refblock_size) * cluster_size;
35
+ refblock_count = DIV_ROUND_UP(nrefblocke, refblock_size);
36
+ meta_size += refblock_count * cluster_size;
37
38
/* total size of refcount tables */
39
- nreftablee = nrefblocke / refblock_size;
40
- nreftablee = align_offset(nreftablee, cluster_size / sizeof(uint64_t));
41
+ nreftablee = align_offset(refblock_count,
42
+ cluster_size / sizeof(uint64_t));
43
meta_size += nreftablee * sizeof(uint64_t);
44
45
qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
46
--
28
--
47
1.8.3.1
29
2.19.1
48
30
49
31
diff view generated by jsdifflib
1
Instead of manually calling blk_resume_after_migration() in migration
1
From: Li Qiang <liq3ea@163.com>
2
code after doing bdrv_invalidate_cache_all(), integrate the BlockBackend
3
activation with cache invalidation into a single function. This is
4
achieved with a new callback in BdrvChildRole that is called by
5
bdrv_invalidate_cache_all().
6
2
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
---
6
---
10
block.c | 12 +++++++++-
7
include/sysemu/block-backend.h | 6 +++---
11
block/block-backend.c | 56 +++++++++++++++++++++++------------------------
8
block/block-backend.c | 8 ++++----
12
include/block/block.h | 2 --
9
2 files changed, 7 insertions(+), 7 deletions(-)
13
include/block/block_int.h | 5 +++++
14
migration/migration.c | 3 ---
15
migration/savevm.c | 3 ---
16
qmp.c | 6 -----
17
7 files changed, 44 insertions(+), 43 deletions(-)
18
10
19
diff --git a/block.c b/block.c
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
20
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
13
--- a/include/sysemu/block-backend.h
22
+++ b/block.c
14
+++ b/include/sysemu/block-backend.h
23
@@ -XXX,XX +XXX,XX @@ void bdrv_init_with_whitelist(void)
15
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
24
16
int error);
25
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
17
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
26
{
18
bool is_read, int error);
27
- BdrvChild *child;
19
-int blk_is_read_only(BlockBackend *blk);
28
+ BdrvChild *child, *parent;
20
-int blk_is_sg(BlockBackend *blk);
29
Error *local_err = NULL;
21
-int blk_enable_write_cache(BlockBackend *blk);
30
int ret;
22
+bool blk_is_read_only(BlockBackend *blk);
31
23
+bool blk_is_sg(BlockBackend *blk);
32
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
24
+bool blk_enable_write_cache(BlockBackend *blk);
33
error_setg_errno(errp, -ret, "Could not refresh total sector count");
25
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
34
return;
26
void blk_invalidate_cache(BlockBackend *blk, Error **errp);
35
}
27
bool blk_is_inserted(BlockBackend *blk);
36
+
37
+ QLIST_FOREACH(parent, &bs->parents, next_parent) {
38
+ if (parent->role->activate) {
39
+ parent->role->activate(parent, &local_err);
40
+ if (local_err) {
41
+ error_propagate(errp, local_err);
42
+ return;
43
+ }
44
+ }
45
+ }
46
}
47
48
void bdrv_invalidate_cache_all(Error **errp)
49
diff --git a/block/block-backend.c b/block/block-backend.c
28
diff --git a/block/block-backend.c b/block/block-backend.c
50
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
51
--- a/block/block-backend.c
30
--- a/block/block-backend.c
52
+++ b/block/block-backend.c
31
+++ b/block/block-backend.c
53
@@ -XXX,XX +XXX,XX @@ static const char *blk_root_get_name(BdrvChild *child)
32
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
54
return blk_name(child->opaque);
33
}
55
}
34
}
56
35
57
+/*
36
-int blk_is_read_only(BlockBackend *blk)
58
+ * Notifies the user of the BlockBackend that migration has completed. qdev
37
+bool blk_is_read_only(BlockBackend *blk)
59
+ * devices can tighten their permissions in response (specifically revoke
38
{
60
+ * shared write permissions that we needed for storage migration).
39
BlockDriverState *bs = blk_bs(blk);
61
+ *
40
62
+ * If an error is returned, the VM cannot be allowed to be resumed.
41
@@ -XXX,XX +XXX,XX @@ int blk_is_read_only(BlockBackend *blk)
63
+ */
42
}
64
+static void blk_root_activate(BdrvChild *child, Error **errp)
65
+{
66
+ BlockBackend *blk = child->opaque;
67
+ Error *local_err = NULL;
68
+
69
+ if (!blk->disable_perm) {
70
+ return;
71
+ }
72
+
73
+ blk->disable_perm = false;
74
+
75
+ blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
76
+ if (local_err) {
77
+ error_propagate(errp, local_err);
78
+ blk->disable_perm = true;
79
+ return;
80
+ }
81
+}
82
+
83
static const BdrvChildRole child_root = {
84
.inherit_options = blk_root_inherit_options,
85
86
@@ -XXX,XX +XXX,XX @@ static const BdrvChildRole child_root = {
87
88
.drained_begin = blk_root_drained_begin,
89
.drained_end = blk_root_drained_end,
90
+
91
+ .activate = blk_root_activate,
92
};
93
94
/*
95
@@ -XXX,XX +XXX,XX @@ void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
96
*shared_perm = blk->shared_perm;
97
}
43
}
98
44
99
-/*
45
-int blk_is_sg(BlockBackend *blk)
100
- * Notifies the user of all BlockBackends that migration has completed. qdev
46
+bool blk_is_sg(BlockBackend *blk)
101
- * devices can tighten their permissions in response (specifically revoke
102
- * shared write permissions that we needed for storage migration).
103
- *
104
- * If an error is returned, the VM cannot be allowed to be resumed.
105
- */
106
-void blk_resume_after_migration(Error **errp)
107
-{
108
- BlockBackend *blk;
109
- Error *local_err = NULL;
110
-
111
- for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
112
- if (!blk->disable_perm) {
113
- continue;
114
- }
115
-
116
- blk->disable_perm = false;
117
-
118
- blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
119
- if (local_err) {
120
- error_propagate(errp, local_err);
121
- blk->disable_perm = true;
122
- return;
123
- }
124
- }
125
-}
126
-
127
static int blk_do_attach_dev(BlockBackend *blk, void *dev)
128
{
47
{
129
if (blk->dev) {
48
BlockDriverState *bs = blk_bs(blk);
130
diff --git a/include/block/block.h b/include/block/block.h
49
131
index XXXXXXX..XXXXXXX 100644
50
if (!bs) {
132
--- a/include/block/block.h
51
- return 0;
133
+++ b/include/block/block.h
52
+ return false;
134
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
135
void bdrv_invalidate_cache_all(Error **errp);
136
int bdrv_inactivate_all(void);
137
138
-void blk_resume_after_migration(Error **errp);
139
-
140
/* Ensure contents are flushed to disk. */
141
int bdrv_flush(BlockDriverState *bs);
142
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
143
diff --git a/include/block/block_int.h b/include/block/block_int.h
144
index XXXXXXX..XXXXXXX 100644
145
--- a/include/block/block_int.h
146
+++ b/include/block/block_int.h
147
@@ -XXX,XX +XXX,XX @@ struct BdrvChildRole {
148
void (*drained_begin)(BdrvChild *child);
149
void (*drained_end)(BdrvChild *child);
150
151
+ /* Notifies the parent that the child has been activated (e.g. when
152
+ * migration is completing) and it can start requesting permissions and
153
+ * doing I/O on it. */
154
+ void (*activate)(BdrvChild *child, Error **errp);
155
+
156
void (*attach)(BdrvChild *child);
157
void (*detach)(BdrvChild *child);
158
};
159
diff --git a/migration/migration.c b/migration/migration.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/migration/migration.c
162
+++ b/migration/migration.c
163
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_bh(void *opaque)
164
/* Make sure all file formats flush their mutable metadata.
165
* If we get an error here, just don't restart the VM yet. */
166
bdrv_invalidate_cache_all(&local_err);
167
- if (!local_err) {
168
- blk_resume_after_migration(&local_err);
169
- }
170
if (local_err) {
171
error_report_err(local_err);
172
local_err = NULL;
173
diff --git a/migration/savevm.c b/migration/savevm.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/migration/savevm.c
176
+++ b/migration/savevm.c
177
@@ -XXX,XX +XXX,XX @@ static void loadvm_postcopy_handle_run_bh(void *opaque)
178
/* Make sure all file formats flush their mutable metadata.
179
* If we get an error here, just don't restart the VM yet. */
180
bdrv_invalidate_cache_all(&local_err);
181
- if (!local_err) {
182
- blk_resume_after_migration(&local_err);
183
- }
184
if (local_err) {
185
error_report_err(local_err);
186
local_err = NULL;
187
diff --git a/qmp.c b/qmp.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/qmp.c
190
+++ b/qmp.c
191
@@ -XXX,XX +XXX,XX @@ void qmp_cont(Error **errp)
192
return;
193
}
53
}
194
54
195
- blk_resume_after_migration(&local_err);
55
return bdrv_is_sg(bs);
196
- if (local_err) {
56
}
197
- error_propagate(errp, local_err);
57
198
- return;
58
-int blk_enable_write_cache(BlockBackend *blk)
199
- }
59
+bool blk_enable_write_cache(BlockBackend *blk)
200
-
60
{
201
if (runstate_check(RUN_STATE_INMIGRATE)) {
61
return blk->enable_write_cache;
202
autostart = 1;
62
}
203
} else {
204
--
63
--
205
1.8.3.1
64
2.19.1
206
65
207
66
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Cleber Rosa <crosa@redhat.com>
2
2
3
The qemu-img info command is executed while VM is running, add -U option
3
While testing the Python 3 changes which touch the 083 test, I noticed
4
to avoid the image locking error.
4
that it would fail with qcow2. Expanding the testing, I noticed it
5
had nothing to do with the Python 3 changes, and in fact, it would not
6
pass on anything but raw:
5
7
6
Signed-off-by: Fam Zheng <famz@redhat.com>
8
raw: pass
9
bochs: not generic
10
cloop: not generic
11
parallels: fail
12
qcow: fail
13
qcow2: fail
14
qed: fail
15
vdi: fail
16
vhdx: fail
17
vmdk: fail
18
vpc: fail
19
luks: fail
20
21
The errors are a mixture I/O and "image not in xxx format", such as:
22
23
=== Check disconnect before data ===
24
25
Unexpected end-of-file before all bytes were read
26
-read failed: Input/output error
27
+can't open device nbd+tcp://127.0.0.1:PORT/foo: Could not open 'nbd://127.0.0.1:PORT/foo': Input/output error
28
29
=== Check disconnect after data ===
30
31
-read 512/512 bytes at offset 0
32
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
33
+can't open device nbd+tcp://127.0.0.1:PORT/foo: Image not in qcow format
34
35
I'm not aware if there's a quick fix, so, for the time being, it looks
36
like the honest approach is to make the test known to work on raw
37
only.
38
39
Signed-off-by: Cleber Rosa <crosa@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
41
---
9
tests/qemu-iotests/046 | 2 +-
42
tests/qemu-iotests/083 | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
43
1 file changed, 1 insertion(+), 1 deletion(-)
11
44
12
diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
45
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
13
index XXXXXXX..XXXXXXX 100755
46
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/046
47
--- a/tests/qemu-iotests/083
15
+++ b/tests/qemu-iotests/046
48
+++ b/tests/qemu-iotests/083
16
@@ -XXX,XX +XXX,XX @@ echo "== Verify image content =="
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
17
50
. ./common.rc
18
function verify_io()
51
. ./common.filter
19
{
52
20
- if ($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep "compat: 0.10" > /dev/null); then
53
-_supported_fmt generic
21
+ if ($QEMU_IMG info -U -f "$IMGFMT" "$TEST_IMG" | grep "compat: 0.10" > /dev/null); then
54
+_supported_fmt raw
22
# For v2 images, discarded clusters are read from the backing file
55
_supported_proto nbd
23
# Keep the variable empty so that the backing file value can be used as
56
_supported_os Linux
24
# the default below
57
25
--
58
--
26
1.8.3.1
59
2.19.1
27
60
28
61
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Alberto Garcia <berto@igalia.com>
3
---
4
block/vpc.c | 2 ++
5
1 file changed, 2 insertions(+)
2
6
3
Although it doesn't add all that much type safety (this is C, after
7
diff --git a/block/vpc.c b/block/vpc.c
4
all), it does add a bit of legibility to use the name QCow2ClusterType
5
instead of a plain int.
6
7
In particular, qcow2_get_cluster_offset() has an overloaded return
8
type; a QCow2ClusterType on success, and -errno on failure; keeping
9
the cluster type in a separate variable makes it slightly easier for
10
the next patch to make further computations based on the type.
11
12
Suggested-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Message-id: 20170507000552.20847-6-eblake@redhat.com
15
[mreitz: Use the new type in two more places (one of them pulled from
16
the next patch)]
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/qcow2-cluster.c | 21 +++++++++++----------
20
block/qcow2-refcount.c | 2 +-
21
block/qcow2.h | 6 +++---
22
3 files changed, 15 insertions(+), 14 deletions(-)
23
24
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
25
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2-cluster.c
9
--- a/block/vpc.c
27
+++ b/block/qcow2-cluster.c
10
+++ b/block/vpc.c
28
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
11
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
29
uint64_t *l2_table, uint64_t stop_flags)
30
{
31
int i;
32
- int first_cluster_type;
33
+ QCow2ClusterType first_cluster_type;
34
uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
35
uint64_t first_entry = be64_to_cpu(l2_table[0]);
36
uint64_t offset = first_entry & mask;
37
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
38
*/
39
static int count_contiguous_clusters_unallocated(int nb_clusters,
40
uint64_t *l2_table,
41
- int wanted_type)
42
+ QCow2ClusterType wanted_type)
43
{
44
int i;
45
46
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters_unallocated(int nb_clusters,
47
wanted_type == QCOW2_CLUSTER_UNALLOCATED);
48
for (i = 0; i < nb_clusters; i++) {
49
uint64_t entry = be64_to_cpu(l2_table[i]);
50
- int type = qcow2_get_cluster_type(entry);
51
+ QCow2ClusterType type = qcow2_get_cluster_type(entry);
52
53
if (type != wanted_type || entry & L2E_OFFSET_MASK) {
54
break;
55
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
56
int l1_bits, c;
57
unsigned int offset_in_cluster;
58
uint64_t bytes_available, bytes_needed, nb_clusters;
59
+ QCow2ClusterType type;
60
int ret;
61
62
offset_in_cluster = offset_into_cluster(s, offset);
63
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
64
65
l1_index = offset >> l1_bits;
66
if (l1_index >= s->l1_size) {
67
- ret = QCOW2_CLUSTER_UNALLOCATED;
68
+ type = QCOW2_CLUSTER_UNALLOCATED;
69
goto out;
70
}
12
}
71
13
72
l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
14
qemu_co_mutex_init(&s->lock);
73
if (!l2_offset) {
15
+ qemu_opts_del(opts);
74
- ret = QCOW2_CLUSTER_UNALLOCATED;
16
75
+ type = QCOW2_CLUSTER_UNALLOCATED;
17
return 0;
76
goto out;
77
}
78
79
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
80
* true */
81
assert(nb_clusters <= INT_MAX);
82
83
- ret = qcow2_get_cluster_type(*cluster_offset);
84
- switch (ret) {
85
+ type = qcow2_get_cluster_type(*cluster_offset);
86
+ switch (type) {
87
case QCOW2_CLUSTER_COMPRESSED:
88
/* Compressed clusters can only be processed one by one */
89
c = 1;
90
@@ -XXX,XX +XXX,XX @@ out:
91
assert(bytes_available - offset_in_cluster <= UINT_MAX);
92
*bytes = bytes_available - offset_in_cluster;
93
94
- return ret;
95
+ return type;
96
18
97
fail:
19
fail:
98
qcow2_cache_put(bs, s->l2_table_cache, (void **)&l2_table);
20
+ qemu_opts_del(opts);
99
@@ -XXX,XX +XXX,XX @@ static int count_cow_clusters(BDRVQcow2State *s, int nb_clusters,
21
qemu_vfree(s->pagetable);
100
22
#ifdef CACHE
101
for (i = 0; i < nb_clusters; i++) {
23
g_free(s->pageentry_u8);
102
uint64_t l2_entry = be64_to_cpu(l2_table[l2_index + i]);
103
- int cluster_type = qcow2_get_cluster_type(l2_entry);
104
+ QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
105
106
switch(cluster_type) {
107
case QCOW2_CLUSTER_NORMAL:
108
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
109
for (j = 0; j < s->l2_size; j++) {
110
uint64_t l2_entry = be64_to_cpu(l2_table[j]);
111
int64_t offset = l2_entry & L2E_OFFSET_MASK;
112
- int cluster_type = qcow2_get_cluster_type(l2_entry);
113
+ QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
114
bool preallocated = offset != 0;
115
116
if (cluster_type != QCOW2_CLUSTER_ZERO) {
117
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/qcow2-refcount.c
120
+++ b/block/qcow2-refcount.c
121
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
122
for (j = 0; j < s->l2_size; j++) {
123
uint64_t l2_entry = be64_to_cpu(l2_table[j]);
124
uint64_t data_offset = l2_entry & L2E_OFFSET_MASK;
125
- int cluster_type = qcow2_get_cluster_type(l2_entry);
126
+ QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
127
128
if ((cluster_type == QCOW2_CLUSTER_NORMAL) ||
129
((cluster_type == QCOW2_CLUSTER_ZERO) && (data_offset != 0))) {
130
diff --git a/block/qcow2.h b/block/qcow2.h
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/qcow2.h
133
+++ b/block/qcow2.h
134
@@ -XXX,XX +XXX,XX @@ typedef struct QCowL2Meta
135
QLIST_ENTRY(QCowL2Meta) next_in_flight;
136
} QCowL2Meta;
137
138
-enum {
139
+typedef enum QCow2ClusterType {
140
QCOW2_CLUSTER_UNALLOCATED,
141
QCOW2_CLUSTER_NORMAL,
142
QCOW2_CLUSTER_COMPRESSED,
143
QCOW2_CLUSTER_ZERO
144
-};
145
+} QCow2ClusterType;
146
147
typedef enum QCow2MetadataOverlap {
148
QCOW2_OL_MAIN_HEADER_BITNR = 0,
149
@@ -XXX,XX +XXX,XX @@ static inline uint64_t qcow2_max_refcount_clusters(BDRVQcow2State *s)
150
return QCOW_MAX_REFTABLE_SIZE >> s->cluster_bits;
151
}
152
153
-static inline int qcow2_get_cluster_type(uint64_t l2_entry)
154
+static inline QCow2ClusterType qcow2_get_cluster_type(uint64_t l2_entry)
155
{
156
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
157
return QCOW2_CLUSTER_COMPRESSED;
158
--
24
--
159
1.8.3.1
25
2.19.1
160
26
161
27
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
Rather than repeat the logic at each caller of checking if a Rule
3
Taking the address of a field in a packed struct is a bad idea, because
4
exists that warrants an error injection, fold that logic into
4
it might not be actually aligned enough for that pointer type (and
5
inject_error(); and rename it to rule_check() for legibility.
5
thus cause a crash on dereference on some host architectures). Newer
6
This will help the next patch, which adds two more callers that
6
versions of clang warn about this. Avoid the bug by not using the
7
need to check rules for the potential of injecting errors.
7
"modify in place" byte swapping functions.
8
8
9
Signed-off-by: Eric Blake <eblake@redhat.com>
9
There are a few places where the in-place swap function is
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
used on something other than a packed struct field; we convert
11
Message-id: 20170429191419.30051-6-eblake@redhat.com
11
those anyway, for consistency.
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
18
---
14
block/blkdebug.c | 74 +++++++++++++++++++++++++-------------------------------
19
block/vhdx.h | 12 ++---
15
1 file changed, 33 insertions(+), 41 deletions(-)
20
block/vhdx-endian.c | 118 ++++++++++++++++++++++----------------------
16
21
block/vhdx-log.c | 4 +-
17
diff --git a/block/blkdebug.c b/block/blkdebug.c
22
block/vhdx.c | 18 +++----
23
4 files changed, 76 insertions(+), 76 deletions(-)
24
25
diff --git a/block/vhdx.h b/block/vhdx.h
18
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkdebug.c
27
--- a/block/vhdx.h
20
+++ b/block/blkdebug.c
28
+++ b/block/vhdx.h
21
@@ -XXX,XX +XXX,XX @@ out:
29
@@ -XXX,XX +XXX,XX @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
22
return ret;
30
23
}
31
static inline void leguid_to_cpus(MSGUID *guid)
24
32
{
25
-static int inject_error(BlockDriverState *bs, BlkdebugRule *rule)
33
- le32_to_cpus(&guid->data1);
26
+static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes)
34
- le16_to_cpus(&guid->data2);
27
{
35
- le16_to_cpus(&guid->data3);
28
BDRVBlkdebugState *s = bs->opaque;
36
+ guid->data1 = le32_to_cpu(guid->data1);
29
- int error = rule->options.inject.error;
37
+ guid->data2 = le16_to_cpu(guid->data2);
30
- bool immediately = rule->options.inject.immediately;
38
+ guid->data3 = le16_to_cpu(guid->data3);
31
+ BlkdebugRule *rule = NULL;
39
}
32
+ int error;
40
33
+ bool immediately;
41
static inline void cpu_to_leguids(MSGUID *guid)
34
+
42
{
35
+ QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
43
- cpu_to_le32s(&guid->data1);
36
+ uint64_t inject_offset = rule->options.inject.offset;
44
- cpu_to_le16s(&guid->data2);
37
+
45
- cpu_to_le16s(&guid->data3);
38
+ if (inject_offset == -1 ||
46
+ guid->data1 = cpu_to_le32(guid->data1);
39
+ (bytes && inject_offset >= offset &&
47
+ guid->data2 = cpu_to_le16(guid->data2);
40
+ inject_offset < offset + bytes))
48
+ guid->data3 = cpu_to_le16(guid->data3);
41
+ {
49
}
42
+ break;
50
43
+ }
51
void vhdx_header_le_import(VHDXHeader *h);
44
+ }
52
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
45
+
53
index XXXXXXX..XXXXXXX 100644
46
+ if (!rule || !rule->options.inject.error) {
54
--- a/block/vhdx-endian.c
47
+ return 0;
55
+++ b/block/vhdx-endian.c
48
+ }
56
@@ -XXX,XX +XXX,XX @@ void vhdx_header_le_import(VHDXHeader *h)
49
+
57
{
50
+ immediately = rule->options.inject.immediately;
58
assert(h != NULL);
51
+ error = rule->options.inject.error;
59
52
60
- le32_to_cpus(&h->signature);
53
if (rule->options.inject.once) {
61
- le32_to_cpus(&h->checksum);
54
QSIMPLEQ_REMOVE(&s->active_rules, rule, BlkdebugRule, active_next);
62
- le64_to_cpus(&h->sequence_number);
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
63
+ h->signature = le32_to_cpu(h->signature);
56
blkdebug_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
64
+ h->checksum = le32_to_cpu(h->checksum);
57
QEMUIOVector *qiov, int flags)
65
+ h->sequence_number = le64_to_cpu(h->sequence_number);
58
{
66
59
- BDRVBlkdebugState *s = bs->opaque;
67
leguid_to_cpus(&h->file_write_guid);
60
- BlkdebugRule *rule = NULL;
68
leguid_to_cpus(&h->data_write_guid);
61
+ int err;
69
leguid_to_cpus(&h->log_guid);
62
70
63
/* Sanity check block layer guarantees */
71
- le16_to_cpus(&h->log_version);
64
assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
72
- le16_to_cpus(&h->version);
65
@@ -XXX,XX +XXX,XX @@ blkdebug_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
73
- le32_to_cpus(&h->log_length);
66
assert(bytes <= bs->bl.max_transfer);
74
- le64_to_cpus(&h->log_offset);
75
+ h->log_version = le16_to_cpu(h->log_version);
76
+ h->version = le16_to_cpu(h->version);
77
+ h->log_length = le32_to_cpu(h->log_length);
78
+ h->log_offset = le64_to_cpu(h->log_offset);
79
}
80
81
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
82
@@ -XXX,XX +XXX,XX @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
83
{
84
assert(d != NULL);
85
86
- le32_to_cpus(&d->signature);
87
- le64_to_cpus(&d->file_offset);
88
- le64_to_cpus(&d->sequence_number);
89
+ d->signature = le32_to_cpu(d->signature);
90
+ d->file_offset = le64_to_cpu(d->file_offset);
91
+ d->sequence_number = le64_to_cpu(d->sequence_number);
92
}
93
94
void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
95
{
96
assert(d != NULL);
97
98
- cpu_to_le32s(&d->signature);
99
- cpu_to_le32s(&d->trailing_bytes);
100
- cpu_to_le64s(&d->leading_bytes);
101
- cpu_to_le64s(&d->file_offset);
102
- cpu_to_le64s(&d->sequence_number);
103
+ d->signature = cpu_to_le32(d->signature);
104
+ d->trailing_bytes = cpu_to_le32(d->trailing_bytes);
105
+ d->leading_bytes = cpu_to_le64(d->leading_bytes);
106
+ d->file_offset = cpu_to_le64(d->file_offset);
107
+ d->sequence_number = cpu_to_le64(d->sequence_number);
108
}
109
110
void vhdx_log_data_le_import(VHDXLogDataSector *d)
111
{
112
assert(d != NULL);
113
114
- le32_to_cpus(&d->data_signature);
115
- le32_to_cpus(&d->sequence_high);
116
- le32_to_cpus(&d->sequence_low);
117
+ d->data_signature = le32_to_cpu(d->data_signature);
118
+ d->sequence_high = le32_to_cpu(d->sequence_high);
119
+ d->sequence_low = le32_to_cpu(d->sequence_low);
120
}
121
122
void vhdx_log_data_le_export(VHDXLogDataSector *d)
123
{
124
assert(d != NULL);
125
126
- cpu_to_le32s(&d->data_signature);
127
- cpu_to_le32s(&d->sequence_high);
128
- cpu_to_le32s(&d->sequence_low);
129
+ d->data_signature = cpu_to_le32(d->data_signature);
130
+ d->sequence_high = cpu_to_le32(d->sequence_high);
131
+ d->sequence_low = cpu_to_le32(d->sequence_low);
132
}
133
134
void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
135
{
136
assert(hdr != NULL);
137
138
- le32_to_cpus(&hdr->signature);
139
- le32_to_cpus(&hdr->checksum);
140
- le32_to_cpus(&hdr->entry_length);
141
- le32_to_cpus(&hdr->tail);
142
- le64_to_cpus(&hdr->sequence_number);
143
- le32_to_cpus(&hdr->descriptor_count);
144
+ hdr->signature = le32_to_cpu(hdr->signature);
145
+ hdr->checksum = le32_to_cpu(hdr->checksum);
146
+ hdr->entry_length = le32_to_cpu(hdr->entry_length);
147
+ hdr->tail = le32_to_cpu(hdr->tail);
148
+ hdr->sequence_number = le64_to_cpu(hdr->sequence_number);
149
+ hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count);
150
leguid_to_cpus(&hdr->log_guid);
151
- le64_to_cpus(&hdr->flushed_file_offset);
152
- le64_to_cpus(&hdr->last_file_offset);
153
+ hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset);
154
+ hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset);
155
}
156
157
void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
158
{
159
assert(hdr != NULL);
160
161
- cpu_to_le32s(&hdr->signature);
162
- cpu_to_le32s(&hdr->checksum);
163
- cpu_to_le32s(&hdr->entry_length);
164
- cpu_to_le32s(&hdr->tail);
165
- cpu_to_le64s(&hdr->sequence_number);
166
- cpu_to_le32s(&hdr->descriptor_count);
167
+ hdr->signature = cpu_to_le32(hdr->signature);
168
+ hdr->checksum = cpu_to_le32(hdr->checksum);
169
+ hdr->entry_length = cpu_to_le32(hdr->entry_length);
170
+ hdr->tail = cpu_to_le32(hdr->tail);
171
+ hdr->sequence_number = cpu_to_le64(hdr->sequence_number);
172
+ hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count);
173
cpu_to_leguids(&hdr->log_guid);
174
- cpu_to_le64s(&hdr->flushed_file_offset);
175
- cpu_to_le64s(&hdr->last_file_offset);
176
+ hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset);
177
+ hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset);
178
}
179
180
181
@@ -XXX,XX +XXX,XX @@ void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
182
{
183
assert(hdr != NULL);
184
185
- le32_to_cpus(&hdr->signature);
186
- le32_to_cpus(&hdr->checksum);
187
- le32_to_cpus(&hdr->entry_count);
188
+ hdr->signature = le32_to_cpu(hdr->signature);
189
+ hdr->checksum = le32_to_cpu(hdr->checksum);
190
+ hdr->entry_count = le32_to_cpu(hdr->entry_count);
191
}
192
193
void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
194
{
195
assert(hdr != NULL);
196
197
- cpu_to_le32s(&hdr->signature);
198
- cpu_to_le32s(&hdr->checksum);
199
- cpu_to_le32s(&hdr->entry_count);
200
+ hdr->signature = cpu_to_le32(hdr->signature);
201
+ hdr->checksum = cpu_to_le32(hdr->checksum);
202
+ hdr->entry_count = cpu_to_le32(hdr->entry_count);
203
}
204
205
void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
206
@@ -XXX,XX +XXX,XX @@ void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
207
assert(e != NULL);
208
209
leguid_to_cpus(&e->guid);
210
- le64_to_cpus(&e->file_offset);
211
- le32_to_cpus(&e->length);
212
- le32_to_cpus(&e->data_bits);
213
+ e->file_offset = le64_to_cpu(e->file_offset);
214
+ e->length = le32_to_cpu(e->length);
215
+ e->data_bits = le32_to_cpu(e->data_bits);
216
}
217
218
void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
219
@@ -XXX,XX +XXX,XX @@ void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
220
assert(e != NULL);
221
222
cpu_to_leguids(&e->guid);
223
- cpu_to_le64s(&e->file_offset);
224
- cpu_to_le32s(&e->length);
225
- cpu_to_le32s(&e->data_bits);
226
+ e->file_offset = cpu_to_le64(e->file_offset);
227
+ e->length = cpu_to_le32(e->length);
228
+ e->data_bits = cpu_to_le32(e->data_bits);
229
}
230
231
232
@@ -XXX,XX +XXX,XX @@ void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
233
{
234
assert(hdr != NULL);
235
236
- le64_to_cpus(&hdr->signature);
237
- le16_to_cpus(&hdr->entry_count);
238
+ hdr->signature = le64_to_cpu(hdr->signature);
239
+ hdr->entry_count = le16_to_cpu(hdr->entry_count);
240
}
241
242
void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
243
{
244
assert(hdr != NULL);
245
246
- cpu_to_le64s(&hdr->signature);
247
- cpu_to_le16s(&hdr->entry_count);
248
+ hdr->signature = cpu_to_le64(hdr->signature);
249
+ hdr->entry_count = cpu_to_le16(hdr->entry_count);
250
}
251
252
void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
253
@@ -XXX,XX +XXX,XX @@ void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
254
assert(e != NULL);
255
256
leguid_to_cpus(&e->item_id);
257
- le32_to_cpus(&e->offset);
258
- le32_to_cpus(&e->length);
259
- le32_to_cpus(&e->data_bits);
260
+ e->offset = le32_to_cpu(e->offset);
261
+ e->length = le32_to_cpu(e->length);
262
+ e->data_bits = le32_to_cpu(e->data_bits);
263
}
264
void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
265
{
266
assert(e != NULL);
267
268
cpu_to_leguids(&e->item_id);
269
- cpu_to_le32s(&e->offset);
270
- cpu_to_le32s(&e->length);
271
- cpu_to_le32s(&e->data_bits);
272
+ e->offset = cpu_to_le32(e->offset);
273
+ e->length = cpu_to_le32(e->length);
274
+ e->data_bits = cpu_to_le32(e->data_bits);
275
}
276
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/vhdx-log.c
279
+++ b/block/vhdx-log.c
280
@@ -XXX,XX +XXX,XX @@ static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc,
281
/* 8 + 4084 + 4 = 4096, 1 log sector */
282
memcpy(&desc->leading_bytes, data, 8);
283
data += 8;
284
- cpu_to_le64s(&desc->leading_bytes);
285
+ desc->leading_bytes = cpu_to_le64(desc->leading_bytes);
286
memcpy(sector->data, data, 4084);
287
data += 4084;
288
memcpy(&desc->trailing_bytes, data, 4);
289
- cpu_to_le32s(&desc->trailing_bytes);
290
+ desc->trailing_bytes = cpu_to_le32(desc->trailing_bytes);
291
data += 4;
292
293
sector->sequence_high = (uint32_t) (seq >> 32);
294
diff --git a/block/vhdx.c b/block/vhdx.c
295
index XXXXXXX..XXXXXXX 100644
296
--- a/block/vhdx.c
297
+++ b/block/vhdx.c
298
@@ -XXX,XX +XXX,XX @@ uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset)
299
300
memset(buf + crc_offset, 0, sizeof(crc));
301
crc = crc32c(0xffffffff, buf, size);
302
- cpu_to_le32s(&crc);
303
+ crc = cpu_to_le32(crc);
304
memcpy(buf + crc_offset, &crc, sizeof(crc));
305
306
return crc;
307
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
308
goto exit;
67
}
309
}
68
310
69
- QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
311
- le32_to_cpus(&s->params.block_size);
70
- uint64_t inject_offset = rule->options.inject.offset;
312
- le32_to_cpus(&s->params.data_bits);
71
-
313
+ s->params.block_size = le32_to_cpu(s->params.block_size);
72
- if (inject_offset == -1 ||
314
+ s->params.data_bits = le32_to_cpu(s->params.data_bits);
73
- (inject_offset >= offset && inject_offset < offset + bytes))
315
74
- {
316
75
- break;
317
/* We now have the file parameters, so we can tell if this is a
76
- }
318
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
77
- }
319
goto exit;
78
-
79
- if (rule && rule->options.inject.error) {
80
- return inject_error(bs, rule);
81
+ err = rule_check(bs, offset, bytes);
82
+ if (err) {
83
+ return err;
84
}
320
}
85
321
86
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
322
- le64_to_cpus(&s->virtual_disk_size);
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
323
- le32_to_cpus(&s->logical_sector_size);
88
blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
324
- le32_to_cpus(&s->physical_sector_size);
89
QEMUIOVector *qiov, int flags)
325
+ s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
90
{
326
+ s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
91
- BDRVBlkdebugState *s = bs->opaque;
327
+ s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
92
- BlkdebugRule *rule = NULL;
328
93
+ int err;
329
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
94
330
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
95
/* Sanity check block layer guarantees */
331
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
96
assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
332
/* endian convert, and verify populated BAT field file offsets against
97
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
333
* region table and log entries */
98
assert(bytes <= bs->bl.max_transfer);
334
for (i = 0; i < s->bat_entries; i++) {
335
- le64_to_cpus(&s->bat[i]);
336
+ s->bat[i] = le64_to_cpu(s->bat[i]);
337
if (payblocks--) {
338
/* payload bat entries */
339
if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
340
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_new_metadata(BlockBackend *blk,
341
mt_file_params->block_size = cpu_to_le32(block_size);
342
if (type == VHDX_TYPE_FIXED) {
343
mt_file_params->data_bits |= VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED;
344
- cpu_to_le32s(&mt_file_params->data_bits);
345
+ mt_file_params->data_bits = cpu_to_le32(mt_file_params->data_bits);
99
}
346
}
100
347
101
- QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
348
vhdx_guid_generate(&mt_page83->page_83_data);
102
- uint64_t inject_offset = rule->options.inject.offset;
349
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
103
-
350
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
104
- if (inject_offset == -1 ||
351
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
105
- (inject_offset >= offset && inject_offset < offset + bytes))
352
block_state);
106
- {
353
- cpu_to_le64s(&s->bat[sinfo.bat_idx]);
107
- break;
354
+ s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
108
- }
355
sector_num += s->sectors_per_block;
109
- }
356
}
110
-
357
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
111
- if (rule && rule->options.inject.error) {
112
- return inject_error(bs, rule);
113
+ err = rule_check(bs, offset, bytes);
114
+ if (err) {
115
+ return err;
116
}
117
118
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
119
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
120
121
static int blkdebug_co_flush(BlockDriverState *bs)
122
{
123
- BDRVBlkdebugState *s = bs->opaque;
124
- BlkdebugRule *rule = NULL;
125
-
126
- QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
127
- if (rule->options.inject.offset == -1) {
128
- break;
129
- }
130
- }
131
+ int err = rule_check(bs, 0, 0);
132
133
- if (rule && rule->options.inject.error) {
134
- return inject_error(bs, rule);
135
+ if (err) {
136
+ return err;
137
}
138
139
return bdrv_co_flush(bs->file->bs);
140
--
358
--
141
1.8.3.1
359
2.19.1
142
360
143
361
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
The test scenario doesn't require the same image, instead it focuses on
3
Taking the address of a field in a packed struct is a bad idea, because
4
the duplicated node-name, so use null-co to avoid locking conflict.
4
it might not be actually aligned enough for that pointer type (and
5
thus cause a crash on dereference on some host architectures). Newer
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
5
8
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
There are a few places where the in-place swap function is
7
Signed-off-by: Fam Zheng <famz@redhat.com>
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
14
15
There are other places where we take the address of a packed member
16
in this file for other purposes than passing it to a byteswap
17
function (all the calls to qemu_uuid_*()); we leave those for now.
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
22
---
10
tests/qemu-iotests/087 | 6 ++----
23
block/vdi.c | 64 ++++++++++++++++++++++++++---------------------------
11
1 file changed, 2 insertions(+), 4 deletions(-)
24
1 file changed, 32 insertions(+), 32 deletions(-)
12
25
13
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
26
diff --git a/block/vdi.c b/block/vdi.c
14
index XXXXXXX..XXXXXXX 100755
27
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/087
28
--- a/block/vdi.c
16
+++ b/tests/qemu-iotests/087
29
+++ b/block/vdi.c
17
@@ -XXX,XX +XXX,XX @@ run_qemu -drive driver=$IMGFMT,id=disk,node-name=test-node,file="$TEST_IMG" <<EO
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
"driver": "$IMGFMT",
31
19
"node-name": "disk",
32
static void vdi_header_to_cpu(VdiHeader *header)
20
"file": {
33
{
21
- "driver": "file",
34
- le32_to_cpus(&header->signature);
22
- "filename": "$TEST_IMG"
35
- le32_to_cpus(&header->version);
23
+ "driver": "null-co"
36
- le32_to_cpus(&header->header_size);
24
}
37
- le32_to_cpus(&header->image_type);
25
}
38
- le32_to_cpus(&header->image_flags);
26
}
39
- le32_to_cpus(&header->offset_bmap);
27
@@ -XXX,XX +XXX,XX @@ run_qemu -drive driver=$IMGFMT,id=disk,node-name=test-node,file="$TEST_IMG" <<EO
40
- le32_to_cpus(&header->offset_data);
28
"driver": "$IMGFMT",
41
- le32_to_cpus(&header->cylinders);
29
"node-name": "test-node",
42
- le32_to_cpus(&header->heads);
30
"file": {
43
- le32_to_cpus(&header->sectors);
31
- "driver": "file",
44
- le32_to_cpus(&header->sector_size);
32
- "filename": "$TEST_IMG"
45
- le64_to_cpus(&header->disk_size);
33
+ "driver": "null-co"
46
- le32_to_cpus(&header->block_size);
34
}
47
- le32_to_cpus(&header->block_extra);
35
}
48
- le32_to_cpus(&header->blocks_in_image);
36
}
49
- le32_to_cpus(&header->blocks_allocated);
50
+ header->signature = le32_to_cpu(header->signature);
51
+ header->version = le32_to_cpu(header->version);
52
+ header->header_size = le32_to_cpu(header->header_size);
53
+ header->image_type = le32_to_cpu(header->image_type);
54
+ header->image_flags = le32_to_cpu(header->image_flags);
55
+ header->offset_bmap = le32_to_cpu(header->offset_bmap);
56
+ header->offset_data = le32_to_cpu(header->offset_data);
57
+ header->cylinders = le32_to_cpu(header->cylinders);
58
+ header->heads = le32_to_cpu(header->heads);
59
+ header->sectors = le32_to_cpu(header->sectors);
60
+ header->sector_size = le32_to_cpu(header->sector_size);
61
+ header->disk_size = le64_to_cpu(header->disk_size);
62
+ header->block_size = le32_to_cpu(header->block_size);
63
+ header->block_extra = le32_to_cpu(header->block_extra);
64
+ header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
65
+ header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
66
qemu_uuid_bswap(&header->uuid_image);
67
qemu_uuid_bswap(&header->uuid_last_snap);
68
qemu_uuid_bswap(&header->uuid_link);
69
@@ -XXX,XX +XXX,XX @@ static void vdi_header_to_cpu(VdiHeader *header)
70
71
static void vdi_header_to_le(VdiHeader *header)
72
{
73
- cpu_to_le32s(&header->signature);
74
- cpu_to_le32s(&header->version);
75
- cpu_to_le32s(&header->header_size);
76
- cpu_to_le32s(&header->image_type);
77
- cpu_to_le32s(&header->image_flags);
78
- cpu_to_le32s(&header->offset_bmap);
79
- cpu_to_le32s(&header->offset_data);
80
- cpu_to_le32s(&header->cylinders);
81
- cpu_to_le32s(&header->heads);
82
- cpu_to_le32s(&header->sectors);
83
- cpu_to_le32s(&header->sector_size);
84
- cpu_to_le64s(&header->disk_size);
85
- cpu_to_le32s(&header->block_size);
86
- cpu_to_le32s(&header->block_extra);
87
- cpu_to_le32s(&header->blocks_in_image);
88
- cpu_to_le32s(&header->blocks_allocated);
89
+ header->signature = cpu_to_le32(header->signature);
90
+ header->version = cpu_to_le32(header->version);
91
+ header->header_size = cpu_to_le32(header->header_size);
92
+ header->image_type = cpu_to_le32(header->image_type);
93
+ header->image_flags = cpu_to_le32(header->image_flags);
94
+ header->offset_bmap = cpu_to_le32(header->offset_bmap);
95
+ header->offset_data = cpu_to_le32(header->offset_data);
96
+ header->cylinders = cpu_to_le32(header->cylinders);
97
+ header->heads = cpu_to_le32(header->heads);
98
+ header->sectors = cpu_to_le32(header->sectors);
99
+ header->sector_size = cpu_to_le32(header->sector_size);
100
+ header->disk_size = cpu_to_le64(header->disk_size);
101
+ header->block_size = cpu_to_le32(header->block_size);
102
+ header->block_extra = cpu_to_le32(header->block_extra);
103
+ header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
104
+ header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
105
qemu_uuid_bswap(&header->uuid_image);
106
qemu_uuid_bswap(&header->uuid_last_snap);
107
qemu_uuid_bswap(&header->uuid_link);
37
--
108
--
38
1.8.3.1
109
2.19.1
39
110
40
111
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
It can be used outside of block.c for making user friendly messages.
3
This is a static function with only one caller, so there's no need to
4
keep it. Inlining the code in quorum_compare() makes it much simpler.
4
5
5
Signed-off-by: Fam Zheng <famz@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reported-by: Markus Armbruster <armbru@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
9
---
8
block.c | 2 +-
10
block/quorum.c | 24 +++++-------------------
9
include/block/block.h | 2 ++
11
1 file changed, 5 insertions(+), 19 deletions(-)
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
12
diff --git a/block.c b/block.c
13
diff --git a/block/quorum.c b/block/quorum.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
15
--- a/block/quorum.c
15
+++ b/block.c
16
+++ b/block/quorum.c
16
@@ -XXX,XX +XXX,XX @@ static char *bdrv_child_user_desc(BdrvChild *c)
17
@@ -XXX,XX +XXX,XX @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
17
return g_strdup("another user");
18
return true;
18
}
19
}
19
20
20
-static char *bdrv_perm_names(uint64_t perm)
21
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
21
+char *bdrv_perm_names(uint64_t perm)
22
- const char *fmt, ...)
23
-{
24
- va_list ap;
25
-
26
- va_start(ap, fmt);
27
- fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
28
- acb->offset, acb->bytes);
29
- vfprintf(stderr, fmt, ap);
30
- fprintf(stderr, "\n");
31
- va_end(ap);
32
- exit(1);
33
-}
34
-
35
-static bool quorum_compare(QuorumAIOCB *acb,
36
- QEMUIOVector *a,
37
- QEMUIOVector *b)
38
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
22
{
39
{
23
struct perm_name {
40
BDRVQuorumState *s = acb->bs->opaque;
24
uint64_t perm;
41
ssize_t offset;
25
diff --git a/include/block/block.h b/include/block/block.h
42
@@ -XXX,XX +XXX,XX @@ static bool quorum_compare(QuorumAIOCB *acb,
26
index XXXXXXX..XXXXXXX 100644
43
if (s->is_blkverify) {
27
--- a/include/block/block.h
44
offset = qemu_iovec_compare(a, b);
28
+++ b/include/block/block.h
45
if (offset != -1) {
29
@@ -XXX,XX +XXX,XX @@ enum {
46
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
30
BLK_PERM_ALL = 0x1f,
47
- acb->offset + offset);
31
};
48
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
32
49
+ " contents mismatch at offset %" PRIu64 "\n",
33
+char *bdrv_perm_names(uint64_t perm);
50
+ acb->offset, acb->bytes, acb->offset + offset);
34
+
51
+ exit(1);
35
/* disk I/O throttling */
52
}
36
void bdrv_init(void);
53
return true;
37
void bdrv_init_with_whitelist(void);
54
}
38
--
55
--
39
1.8.3.1
56
2.19.1
40
57
41
58
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Fix a couple of inconsistent indentations, before an upcoming
3
The blkverify mode of Quorum can only be enabled if the number of
4
patch further tweaks the switch statements.
4
children is exactly two and the value of vote-threshold is also two.
5
(best viewed with 'git diff -b').
6
5
7
Signed-off-by: Eric Blake <eblake@redhat.com>
6
If the user tries to enable it but the other settings are incorrect
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
then QEMU simply prints an error message to stderr and carries on
9
Message-id: 20170507000552.20847-3-eblake@redhat.com
8
disabling the blkverify setting.
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
10
This patch makes quorum_open() fail and return an error in this case.
11
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Reported-by: Markus Armbruster <armbru@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
15
---
12
block/qcow2-cluster.c | 32 +++++++++----------
16
block/quorum.c | 13 ++++++-------
13
block/qcow2-refcount.c | 84 +++++++++++++++++++++++++-------------------------
17
1 file changed, 6 insertions(+), 7 deletions(-)
14
2 files changed, 58 insertions(+), 58 deletions(-)
15
18
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
19
diff --git a/block/quorum.c b/block/quorum.c
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cluster.c
21
--- a/block/quorum.c
19
+++ b/block/qcow2-cluster.c
22
+++ b/block/quorum.c
20
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
23
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
21
* but rather fall through to the backing file.
24
s->read_pattern = ret;
22
*/
25
23
switch (qcow2_get_cluster_type(old_l2_entry)) {
26
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
24
- case QCOW2_CLUSTER_UNALLOCATED:
27
- /* is the driver in blkverify mode */
25
- if (full_discard || !bs->backing) {
28
- if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
26
- continue;
29
- s->num_children == 2 && s->threshold == 2) {
27
- }
30
- s->is_blkverify = true;
28
- break;
31
- } else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
29
+ case QCOW2_CLUSTER_UNALLOCATED:
32
- fprintf(stderr, "blkverify mode is set by setting blkverify=on "
30
+ if (full_discard || !bs->backing) {
33
- "and using two files with vote_threshold=2\n");
31
+ continue;
34
+ s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
32
+ }
35
+ if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
33
+ break;
36
+ error_setg(&local_err, "blkverify=on can only be set if there are "
34
37
+ "exactly two files and vote-threshold is 2");
35
- case QCOW2_CLUSTER_ZERO:
38
+ ret = -EINVAL;
36
- /* Preallocated zero clusters should be discarded in any case */
39
+ goto exit;
37
- if (!full_discard && (old_l2_entry & L2E_OFFSET_MASK) == 0) {
38
- continue;
39
- }
40
- break;
41
+ case QCOW2_CLUSTER_ZERO:
42
+ /* Preallocated zero clusters should be discarded in any case */
43
+ if (!full_discard && (old_l2_entry & L2E_OFFSET_MASK) == 0) {
44
+ continue;
45
+ }
46
+ break;
47
48
- case QCOW2_CLUSTER_NORMAL:
49
- case QCOW2_CLUSTER_COMPRESSED:
50
- break;
51
+ case QCOW2_CLUSTER_NORMAL:
52
+ case QCOW2_CLUSTER_COMPRESSED:
53
+ break;
54
55
- default:
56
- abort();
57
+ default:
58
+ abort();
59
}
40
}
60
41
61
/* First remove L2 entries */
42
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
62
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/qcow2-refcount.c
65
+++ b/block/qcow2-refcount.c
66
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
67
offset = entry & L2E_OFFSET_MASK;
68
69
switch (qcow2_get_cluster_type(entry)) {
70
- case QCOW2_CLUSTER_COMPRESSED:
71
- nb_csectors = ((entry >> s->csize_shift) &
72
- s->csize_mask) + 1;
73
- if (addend != 0) {
74
- ret = update_refcount(bs,
75
+ case QCOW2_CLUSTER_COMPRESSED:
76
+ nb_csectors = ((entry >> s->csize_shift) &
77
+ s->csize_mask) + 1;
78
+ if (addend != 0) {
79
+ ret = update_refcount(bs,
80
(entry & s->cluster_offset_mask) & ~511,
81
nb_csectors * 512, abs(addend), addend < 0,
82
QCOW2_DISCARD_SNAPSHOT);
83
- if (ret < 0) {
84
- goto fail;
85
- }
86
- }
87
- /* compressed clusters are never modified */
88
- refcount = 2;
89
- break;
90
-
91
- case QCOW2_CLUSTER_NORMAL:
92
- case QCOW2_CLUSTER_ZERO:
93
- if (offset_into_cluster(s, offset)) {
94
- qcow2_signal_corruption(bs, true, -1, -1, "Data "
95
- "cluster offset %#" PRIx64
96
- " unaligned (L2 offset: %#"
97
- PRIx64 ", L2 index: %#x)",
98
- offset, l2_offset, j);
99
- ret = -EIO;
100
+ if (ret < 0) {
101
goto fail;
102
}
103
+ }
104
+ /* compressed clusters are never modified */
105
+ refcount = 2;
106
+ break;
107
+
108
+ case QCOW2_CLUSTER_NORMAL:
109
+ case QCOW2_CLUSTER_ZERO:
110
+ if (offset_into_cluster(s, offset)) {
111
+ qcow2_signal_corruption(bs, true, -1, -1, "Data "
112
+ "cluster offset %#" PRIx64
113
+ " unaligned (L2 offset: %#"
114
+ PRIx64 ", L2 index: %#x)",
115
+ offset, l2_offset, j);
116
+ ret = -EIO;
117
+ goto fail;
118
+ }
119
120
- cluster_index = offset >> s->cluster_bits;
121
- if (!cluster_index) {
122
- /* unallocated */
123
- refcount = 0;
124
- break;
125
- }
126
- if (addend != 0) {
127
- ret = qcow2_update_cluster_refcount(bs,
128
+ cluster_index = offset >> s->cluster_bits;
129
+ if (!cluster_index) {
130
+ /* unallocated */
131
+ refcount = 0;
132
+ break;
133
+ }
134
+ if (addend != 0) {
135
+ ret = qcow2_update_cluster_refcount(bs,
136
cluster_index, abs(addend), addend < 0,
137
QCOW2_DISCARD_SNAPSHOT);
138
- if (ret < 0) {
139
- goto fail;
140
- }
141
- }
142
-
143
- ret = qcow2_get_refcount(bs, cluster_index, &refcount);
144
if (ret < 0) {
145
goto fail;
146
}
147
- break;
148
+ }
149
150
- case QCOW2_CLUSTER_UNALLOCATED:
151
- refcount = 0;
152
- break;
153
+ ret = qcow2_get_refcount(bs, cluster_index, &refcount);
154
+ if (ret < 0) {
155
+ goto fail;
156
+ }
157
+ break;
158
+
159
+ case QCOW2_CLUSTER_UNALLOCATED:
160
+ refcount = 0;
161
+ break;
162
163
- default:
164
- abort();
165
+ default:
166
+ abort();
167
}
168
169
if (refcount == 1) {
170
--
43
--
171
1.8.3.1
44
2.19.1
172
45
173
46
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
We've already improved discards to operate efficiently on the tail
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
of an unaligned qcow2 image; it's time to make a similar improvement
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
to write zeroes. The special case is only valid at the tail
5
---
6
cluster of a file, where we must recognize that any sectors beyond
6
tests/qemu-iotests/081 | 30 ++++++++++++++++++++++++++++++
7
the image end would implicitly read as zero, and therefore should
7
tests/qemu-iotests/081.out | 16 ++++++++++++++++
8
not penalize our logic for widening a partial cluster into writing
8
2 files changed, 46 insertions(+)
9
the whole cluster as zero.
10
9
11
However, note that for now, the special case of end-of-file is only
10
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
12
recognized if there is no backing file, or if the backing file has
11
index XXXXXXX..XXXXXXX 100755
13
the same length; that's because when the backing file is shorter
12
--- a/tests/qemu-iotests/081
14
than the active layer, we don't have code in place to recognize
13
+++ b/tests/qemu-iotests/081
15
that reads of a sector unallocated at the top and beyond the backing
14
@@ -XXX,XX +XXX,XX @@ echo "== checking that quorum is broken =="
16
end-of-file are implicitly zero. It's not much of a real loss,
15
17
because most people don't use images that aren't cluster-aligned,
16
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
18
or where the active layer is a different size than the backing
17
19
layer (especially where the difference falls within a single cluster).
18
+echo
20
19
+echo "== checking the blkverify mode with broken content =="
21
Update test 154 to cover the new scenarios, using two images of
22
intentionally differing length.
23
24
While at it, fix the test to gracefully skip when run as
25
./check -qcow2 -o compat=0.10 154
26
since the older format lacks zero clusters already required earlier
27
in the test.
28
29
Signed-off-by: Eric Blake <eblake@redhat.com>
30
Reviewed-by: Max Reitz <mreitz@redhat.com>
31
Message-id: 20170507000552.20847-11-eblake@redhat.com
32
Signed-off-by: Max Reitz <mreitz@redhat.com>
33
---
34
block/qcow2.c | 7 ++
35
tests/qemu-iotests/154 | 160 ++++++++++++++++++++++++++++++++++++++++++++-
36
tests/qemu-iotests/154.out | 128 ++++++++++++++++++++++++++++++++++++
37
3 files changed, 293 insertions(+), 2 deletions(-)
38
39
diff --git a/block/qcow2.c b/block/qcow2.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2.c
42
+++ b/block/qcow2.c
43
@@ -XXX,XX +XXX,XX @@ static bool is_zero_sectors(BlockDriverState *bs, int64_t start,
44
BlockDriverState *file;
45
int64_t res;
46
47
+ if (start + count > bs->total_sectors) {
48
+ count = bs->total_sectors - start;
49
+ }
50
+
20
+
51
if (!count) {
21
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
52
return true;
22
+quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
53
}
23
+quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
54
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
24
+quorum="$quorum,file.children.0.driver=raw"
55
uint32_t tail = (offset + count) % s->cluster_size;
25
+quorum="$quorum,file.children.1.driver=raw"
56
57
trace_qcow2_pwrite_zeroes_start_req(qemu_coroutine_self(), offset, count);
58
+ if (offset + count == bs->total_sectors * BDRV_SECTOR_SIZE) {
59
+ tail = 0;
60
+ }
61
62
if (head || tail) {
63
int64_t cl_start = (offset - head) >> BDRV_SECTOR_BITS;
64
diff --git a/tests/qemu-iotests/154 b/tests/qemu-iotests/154
65
index XXXXXXX..XXXXXXX 100755
66
--- a/tests/qemu-iotests/154
67
+++ b/tests/qemu-iotests/154
68
@@ -XXX,XX +XXX,XX @@
69
#
70
# qcow2 specific bdrv_pwrite_zeroes tests with backing files (complements 034)
71
#
72
-# Copyright (C) 2016 Red Hat, Inc.
73
+# Copyright (C) 2016-2017 Red Hat, Inc.
74
#
75
# This program is free software; you can redistribute it and/or modify
76
# it under the terms of the GNU General Public License as published by
77
@@ -XXX,XX +XXX,XX @@ _supported_proto file
78
_supported_os Linux
79
80
CLUSTER_SIZE=4k
81
-size=128M
82
+size=$((128 * 1024 * 1024))
83
+
26
+
84
+# This test requires zero clusters, added in v3 images
27
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
85
+_unsupported_imgopts compat=0.10
86
87
echo
88
echo == backing file contains zeros ==
89
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 75k 1k" "$TEST_IMG" | _filter_qemu_io
90
91
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
92
93
+echo
94
+echo == unaligned image tail cluster, no allocation needed ==
95
+
96
+# With no backing file, write to all or part of unallocated partial cluster
97
+# will mark the cluster as zero, but does not allocate.
98
+# Re-create the image each time to get back to unallocated clusters.
99
+
100
+# Write at the front: sector-wise, the request is: 128m... | 00 -- -- --
101
+_make_test_img $((size + 2048))
102
+$QEMU_IO -c "write -z $size 512" "$TEST_IMG" | _filter_qemu_io
103
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
104
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
105
+
106
+# Write at the back: sector-wise, the request is: 128m... | -- -- -- 00
107
+_make_test_img $((size + 2048))
108
+$QEMU_IO -c "write -z $((size + 1536)) 512" "$TEST_IMG" | _filter_qemu_io
109
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
110
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
111
+
112
+# Write at middle: sector-wise, the request is: 128m... | -- 00 00 --
113
+_make_test_img $((size + 2048))
114
+$QEMU_IO -c "write -z $((size + 512)) 1024" "$TEST_IMG" | _filter_qemu_io
115
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
116
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
117
+
118
+# Write entire cluster: sector-wise, the request is: 128m... | 00 00 00 00
119
+_make_test_img $((size + 2048))
120
+$QEMU_IO -c "write -z $size 2048" "$TEST_IMG" | _filter_qemu_io
121
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
122
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
123
+
124
+# Repeat with backing file holding unallocated cluster.
125
+# TODO: Note that this forces an allocation, because we aren't yet able to
126
+# quickly detect that reads beyond EOF of the backing file are always zero
127
+CLUSTER_SIZE=2048 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024))
128
+
129
+# Write at the front: sector-wise, the request is:
130
+# backing: 128m... | -- --
131
+# active: 128m... | 00 -- -- --
132
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
133
+$QEMU_IO -c "write -z $size 512" "$TEST_IMG" | _filter_qemu_io
134
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
135
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
136
+
137
+# Write at the back: sector-wise, the request is:
138
+# backing: 128m... | -- --
139
+# active: 128m... | -- -- -- 00
140
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
141
+$QEMU_IO -c "write -z $((size + 1536)) 512" "$TEST_IMG" | _filter_qemu_io
142
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
143
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
144
+
145
+# Write at middle: sector-wise, the request is:
146
+# backing: 128m... | -- --
147
+# active: 128m... | -- 00 00 --
148
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
149
+$QEMU_IO -c "write -z $((size + 512)) 1024" "$TEST_IMG" | _filter_qemu_io
150
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
151
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
152
+
153
+# Write entire cluster: sector-wise, the request is:
154
+# backing: 128m... | -- --
155
+# active: 128m... | 00 00 00 00
156
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
157
+$QEMU_IO -c "write -z $size 2048" "$TEST_IMG" | _filter_qemu_io
158
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
159
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
160
+
161
+# Repeat with backing file holding zero'd cluster
162
+# TODO: Note that this forces an allocation, because we aren't yet able to
163
+# quickly detect that reads beyond EOF of the backing file are always zero
164
+$QEMU_IO -c "write -z $size 512" "$TEST_IMG.base" | _filter_qemu_io
165
+
166
+# Write at the front: sector-wise, the request is:
167
+# backing: 128m... | 00 00
168
+# active: 128m... | 00 -- -- --
169
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
170
+$QEMU_IO -c "write -z $size 512" "$TEST_IMG" | _filter_qemu_io
171
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
172
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
173
+
174
+# Write at the back: sector-wise, the request is:
175
+# backing: 128m... | 00 00
176
+# active: 128m... | -- -- -- 00
177
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
178
+$QEMU_IO -c "write -z $((size + 1536)) 512" "$TEST_IMG" | _filter_qemu_io
179
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
180
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
181
+
182
+# Write at middle: sector-wise, the request is:
183
+# backing: 128m... | 00 00
184
+# active: 128m... | -- 00 00 --
185
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
186
+$QEMU_IO -c "write -z $((size + 512)) 1024" "$TEST_IMG" | _filter_qemu_io
187
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
188
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
189
+
190
+# Write entire cluster: sector-wise, the request is:
191
+# backing: 128m... | 00 00
192
+# active: 128m... | 00 00 00 00
193
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
194
+$QEMU_IO -c "write -z $size 2048" "$TEST_IMG" | _filter_qemu_io
195
+$QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
196
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
197
+
198
+# A preallocated cluster maintains its allocation, whether it stays as
199
+# data due to a partial write:
200
+# Convert 128m... | XX XX => ... | XX 00
201
+_make_test_img $((size + 1024))
202
+$QEMU_IO -c "write -P 1 $((size)) 1024" "$TEST_IMG" | _filter_qemu_io
203
+$QEMU_IO -c "write -z $((size + 512)) 512" "$TEST_IMG" | _filter_qemu_io
204
+$QEMU_IO -c "read -P 1 $((size)) 512" "$TEST_IMG" | _filter_qemu_io
205
+$QEMU_IO -c "read -P 0 $((size + 512)) 512" "$TEST_IMG" | _filter_qemu_io
206
+$QEMU_IO -c "alloc $size 1024" "$TEST_IMG" | _filter_qemu_io
207
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
208
+
209
+# or because it is the entire cluster and can use the zero flag:
210
+# Convert 128m... | XX XX => ... | 00 00
211
+$QEMU_IO -c "write -z $((size)) 1024" "$TEST_IMG" | _filter_qemu_io
212
+$QEMU_IO -c "alloc $size 1024" "$TEST_IMG" | _filter_qemu_io
213
+$QEMU_IO -c "read -P 0 $size 1024" "$TEST_IMG" | _filter_qemu_io
214
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
215
+
28
+
216
+echo
29
+echo
217
+echo == unaligned image tail cluster, allocation required ==
30
+echo "== writing the same data to both files =="
218
+
31
+
219
+# Write beyond backing file must COW
32
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
220
+# Backing file: 128m... | XX --
33
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
221
+# Active layer: 128m... | -- -- 00 --
222
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024))
223
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
224
+$QEMU_IO -c "write -P 1 $((size)) 512" "$TEST_IMG.base" | _filter_qemu_io
225
+$QEMU_IO -c "write -z $((size + 1024)) 512" "$TEST_IMG" | _filter_qemu_io
226
+$QEMU_IO -c "read -P 1 $((size)) 512" "$TEST_IMG" | _filter_qemu_io
227
+$QEMU_IO -c "read -P 0 $((size + 512)) 1536" "$TEST_IMG" | _filter_qemu_io
228
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
229
+
34
+
230
+# Writes at boundaries of (partial) cluster must not lose mid-cluster data
35
+echo
231
+# Backing file: 128m: ... | -- XX
36
+echo "== checking the blkverify mode with valid content =="
232
+# Active layer: 128m: ... | 00 -- -- 00
37
+
233
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024))
38
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
234
+_make_test_img -b "$TEST_IMG.base" $((size + 2048))
39
+
235
+$QEMU_IO -c "write -P 1 $((size + 512)) 512" "$TEST_IMG.base" | _filter_qemu_io
40
+echo
236
+$QEMU_IO -c "write -z $((size)) 512" "$TEST_IMG" | _filter_qemu_io
41
+echo "== checking the blkverify mode with invalid settings =="
237
+$QEMU_IO -c "read -P 0 $((size)) 512" "$TEST_IMG" | _filter_qemu_io
42
+
238
+$QEMU_IO -c "read -P 1 $((size + 512)) 512" "$TEST_IMG" | _filter_qemu_io
43
+quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
239
+$QEMU_IO -c "read -P 0 $((size + 1024)) 1024" "$TEST_IMG" | _filter_qemu_io
44
+quorum="$quorum,file.children.2.driver=raw"
240
+$QEMU_IO -c "write -z $((size + 1536)) 512" "$TEST_IMG" | _filter_qemu_io
45
+
241
+$QEMU_IO -c "read -P 0 $((size)) 512" "$TEST_IMG" | _filter_qemu_io
46
+$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
242
+$QEMU_IO -c "read -P 1 $((size + 512)) 512" "$TEST_IMG" | _filter_qemu_io
243
+$QEMU_IO -c "read -P 0 $((size + 1024)) 1024" "$TEST_IMG" | _filter_qemu_io
244
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
245
+
47
+
246
# success, all done
48
# success, all done
247
echo "*** done"
49
echo "*** done"
248
rm -f $seq.full
50
rm -f $seq.full
249
diff --git a/tests/qemu-iotests/154.out b/tests/qemu-iotests/154.out
51
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
250
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
251
--- a/tests/qemu-iotests/154.out
53
--- a/tests/qemu-iotests/081.out
252
+++ b/tests/qemu-iotests/154.out
54
+++ b/tests/qemu-iotests/081.out
253
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 76800
55
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 0
254
{ "start": 69632, "length": 4096, "depth": 0, "zero": true, "data": false},
56
255
{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
57
== checking that quorum is broken ==
256
{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
58
read failed: Input/output error
257
+
59
+
258
+== unaligned image tail cluster, no allocation needed ==
60
+== checking the blkverify mode with broken content ==
259
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776
61
+quorum: offset=0 bytes=10485760 contents mismatch at offset 0
260
+wrote 512/512 bytes at offset 134217728
261
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
262
+2048/2048 bytes allocated at offset 128 MiB
263
+[{ "start": 0, "length": 134219776, "depth": 0, "zero": true, "data": false}]
264
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776
265
+wrote 512/512 bytes at offset 134219264
266
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
267
+2048/2048 bytes allocated at offset 128 MiB
268
+[{ "start": 0, "length": 134219776, "depth": 0, "zero": true, "data": false}]
269
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776
270
+wrote 1024/1024 bytes at offset 134218240
271
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
272
+2048/2048 bytes allocated at offset 128 MiB
273
+[{ "start": 0, "length": 134219776, "depth": 0, "zero": true, "data": false}]
274
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776
275
+wrote 2048/2048 bytes at offset 134217728
276
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
277
+2048/2048 bytes allocated at offset 128 MiB
278
+[{ "start": 0, "length": 134219776, "depth": 0, "zero": true, "data": false}]
279
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134218752
280
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
281
+wrote 512/512 bytes at offset 134217728
282
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+2048/2048 bytes allocated at offset 128 MiB
284
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
285
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
286
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
287
+wrote 512/512 bytes at offset 134219264
288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
289
+2048/2048 bytes allocated at offset 128 MiB
290
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
291
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
292
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
293
+wrote 1024/1024 bytes at offset 134218240
294
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
295
+2048/2048 bytes allocated at offset 128 MiB
296
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
297
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
298
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
299
+wrote 2048/2048 bytes at offset 134217728
300
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
301
+2048/2048 bytes allocated at offset 128 MiB
302
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
303
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
304
+wrote 512/512 bytes at offset 134217728
305
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
306
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
307
+wrote 512/512 bytes at offset 134217728
308
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
309
+2048/2048 bytes allocated at offset 128 MiB
310
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
311
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
312
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
313
+wrote 512/512 bytes at offset 134219264
314
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
315
+2048/2048 bytes allocated at offset 128 MiB
316
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
317
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
318
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
319
+wrote 1024/1024 bytes at offset 134218240
320
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
321
+2048/2048 bytes allocated at offset 128 MiB
322
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
323
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
324
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
325
+wrote 2048/2048 bytes at offset 134217728
326
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
327
+2048/2048 bytes allocated at offset 128 MiB
328
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
329
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
330
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134218752
331
+wrote 1024/1024 bytes at offset 134217728
332
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
333
+wrote 512/512 bytes at offset 134218240
334
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
335
+read 512/512 bytes at offset 134217728
336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
337
+read 512/512 bytes at offset 134218240
338
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
339
+1024/1024 bytes allocated at offset 128 MiB
340
+[{ "start": 0, "length": 134217728, "depth": 0, "zero": true, "data": false},
341
+{ "start": 134217728, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
342
+wrote 1024/1024 bytes at offset 134217728
343
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
344
+1024/1024 bytes allocated at offset 128 MiB
345
+read 1024/1024 bytes at offset 134217728
346
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
347
+[{ "start": 0, "length": 134217728, "depth": 0, "zero": true, "data": false},
348
+{ "start": 134217728, "length": 1024, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
349
+
62
+
350
+== unaligned image tail cluster, allocation required ==
63
+== writing the same data to both files ==
351
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134218752
64
+wrote 10485760/10485760 bytes at offset 0
352
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
65
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
353
+wrote 512/512 bytes at offset 134217728
66
+wrote 10485760/10485760 bytes at offset 0
354
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
355
+wrote 512/512 bytes at offset 134218752
68
+
356
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
69
+== checking the blkverify mode with valid content ==
357
+read 512/512 bytes at offset 134217728
70
+read 10485760/10485760 bytes at offset 0
358
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
359
+read 1536/1536 bytes at offset 134218240
72
+
360
+1.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+== checking the blkverify mode with invalid settings ==
361
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
74
+can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
362
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
363
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134218752
364
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
365
+wrote 512/512 bytes at offset 134218240
366
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
367
+wrote 512/512 bytes at offset 134217728
368
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
369
+read 512/512 bytes at offset 134217728
370
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
371
+read 512/512 bytes at offset 134218240
372
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
373
+read 1024/1024 bytes at offset 134218752
374
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
375
+wrote 512/512 bytes at offset 134219264
376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
377
+read 512/512 bytes at offset 134217728
378
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+read 512/512 bytes at offset 134218240
380
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
381
+read 1024/1024 bytes at offset 134218752
382
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
383
+[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
384
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
385
*** done
75
*** done
386
--
76
--
387
1.8.3.1
77
2.19.1
388
78
389
79
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
In order to keep checkpatch happy when the next patch changes
3
The blkverify mode of Quorum only works when the number of children is
4
indentation, we first have to shorten some long lines. The easiest
4
exactly two, so any attempt to add a new one must return an error.
5
approach is to use a new variable in place of
6
'offset & L2E_OFFSET_MASK', except that 'offset' is the best name
7
for that variable. Change '[old_]offset' to '[old_]entry' to
8
make room.
9
5
10
While touching things, also fix checkpatch warnings about unusual
6
quorum_del_child() on the other hand doesn't need any additional check
11
'for' statements.
7
because decreasing the number of children would make it go under the
8
vote threshold.
12
9
13
Suggested by Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
15
Message-id: 20170507000552.20847-2-eblake@redhat.com
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
13
---
19
block/qcow2-refcount.c | 42 ++++++++++++++++++++++--------------------
14
block/quorum.c | 8 ++++++++
20
1 file changed, 22 insertions(+), 20 deletions(-)
15
1 file changed, 8 insertions(+)
21
16
22
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
17
diff --git a/block/quorum.c b/block/quorum.c
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2-refcount.c
19
--- a/block/quorum.c
25
+++ b/block/qcow2-refcount.c
20
+++ b/block/quorum.c
26
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
27
int64_t l1_table_offset, int l1_size, int addend)
22
char indexstr[32];
28
{
29
BDRVQcow2State *s = bs->opaque;
30
- uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, refcount;
31
+ uint64_t *l1_table, *l2_table, l2_offset, entry, l1_size2, refcount;
32
bool l1_allocated = false;
33
- int64_t old_offset, old_l2_offset;
34
+ int64_t old_entry, old_l2_offset;
35
int i, j, l1_modified = 0, nb_csectors;
36
int ret;
23
int ret;
37
24
38
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
25
+ if (s->is_blkverify) {
39
goto fail;
26
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
40
}
27
+ return;
41
28
+ }
42
- for(i = 0;i < l1_size; i++)
29
+
43
+ for (i = 0; i < l1_size; i++) {
30
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
44
be64_to_cpus(&l1_table[i]);
31
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
45
+ }
32
s->next_child_index == UINT_MAX) {
46
} else {
33
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
47
assert(l1_size == s->l1_size);
34
return;
48
l1_table = s->l1_table;
49
l1_allocated = false;
50
}
35
}
51
36
52
- for(i = 0; i < l1_size; i++) {
37
+ /* We know now that num_children > threshold, so blkverify must be false */
53
+ for (i = 0; i < l1_size; i++) {
38
+ assert(!s->is_blkverify);
54
l2_offset = l1_table[i];
39
+
55
if (l2_offset) {
40
bdrv_drained_begin(bs);
56
old_l2_offset = l2_offset;
41
57
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
42
/* We can safely remove this child now */
58
goto fail;
59
}
60
61
- for(j = 0; j < s->l2_size; j++) {
62
+ for (j = 0; j < s->l2_size; j++) {
63
uint64_t cluster_index;
64
+ uint64_t offset;
65
66
- offset = be64_to_cpu(l2_table[j]);
67
- old_offset = offset;
68
- offset &= ~QCOW_OFLAG_COPIED;
69
+ entry = be64_to_cpu(l2_table[j]);
70
+ old_entry = entry;
71
+ entry &= ~QCOW_OFLAG_COPIED;
72
+ offset = entry & L2E_OFFSET_MASK;
73
74
- switch (qcow2_get_cluster_type(offset)) {
75
+ switch (qcow2_get_cluster_type(entry)) {
76
case QCOW2_CLUSTER_COMPRESSED:
77
- nb_csectors = ((offset >> s->csize_shift) &
78
+ nb_csectors = ((entry >> s->csize_shift) &
79
s->csize_mask) + 1;
80
if (addend != 0) {
81
ret = update_refcount(bs,
82
- (offset & s->cluster_offset_mask) & ~511,
83
+ (entry & s->cluster_offset_mask) & ~511,
84
nb_csectors * 512, abs(addend), addend < 0,
85
QCOW2_DISCARD_SNAPSHOT);
86
if (ret < 0) {
87
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
88
89
case QCOW2_CLUSTER_NORMAL:
90
case QCOW2_CLUSTER_ZERO:
91
- if (offset_into_cluster(s, offset & L2E_OFFSET_MASK)) {
92
+ if (offset_into_cluster(s, offset)) {
93
qcow2_signal_corruption(bs, true, -1, -1, "Data "
94
- "cluster offset %#llx "
95
- "unaligned (L2 offset: %#"
96
+ "cluster offset %#" PRIx64
97
+ " unaligned (L2 offset: %#"
98
PRIx64 ", L2 index: %#x)",
99
- offset & L2E_OFFSET_MASK,
100
- l2_offset, j);
101
+ offset, l2_offset, j);
102
ret = -EIO;
103
goto fail;
104
}
105
106
- cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits;
107
+ cluster_index = offset >> s->cluster_bits;
108
if (!cluster_index) {
109
/* unallocated */
110
refcount = 0;
111
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
112
}
113
114
if (refcount == 1) {
115
- offset |= QCOW_OFLAG_COPIED;
116
+ entry |= QCOW_OFLAG_COPIED;
117
}
118
- if (offset != old_offset) {
119
+ if (entry != old_entry) {
120
if (addend > 0) {
121
qcow2_cache_set_dependency(bs, s->l2_table_cache,
122
s->refcount_block_cache);
123
}
124
- l2_table[j] = cpu_to_be64(offset);
125
+ l2_table[j] = cpu_to_be64(entry);
126
qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache,
127
l2_table);
128
}
129
--
43
--
130
1.8.3.1
44
2.19.1
131
45
132
46
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This extends the permission bits of op blocker API to external using
3
This patch tests that you can add and remove drives from a Quorum
4
Linux OFD locks.
4
using the x-blockdev-change command.
5
5
6
Each permission in @perm and @shared_perm is represented by a locked
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
byte in the image file. Requesting a permission in @perm is translated
8
to a shared lock of the corresponding byte; rejecting to share the same
9
permission is translated to a shared lock of a separate byte. With that,
10
we use 2x number of bytes of distinct permission types.
11
12
virtlockd in libvirt locks the first byte, so we do locking from a
13
higher offset.
14
15
Suggested-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Fam Zheng <famz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
8
---
19
block/file-posix.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
9
tests/qemu-iotests/081 | 86 ++++++++++++++++++++++++++++++++++++++
20
1 file changed, 275 insertions(+), 1 deletion(-)
10
tests/qemu-iotests/081.out | 54 ++++++++++++++++++++++++
11
2 files changed, 140 insertions(+)
21
12
22
diff --git a/block/file-posix.c b/block/file-posix.c
13
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100755
24
--- a/block/file-posix.c
15
--- a/tests/qemu-iotests/081
25
+++ b/block/file-posix.c
16
+++ b/tests/qemu-iotests/081
26
@@ -XXX,XX +XXX,XX @@ do { \
17
@@ -XXX,XX +XXX,XX @@ quorum="$quorum,file.children.2.driver=raw"
27
18
28
#define MAX_BLOCKSIZE    4096
19
$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
29
20
30
+/* Posix file locking bytes. Libvirt takes byte 0, we start from higher bytes,
21
+echo
31
+ * leaving a few more bytes for its future use. */
22
+echo "== dynamically adding a child to a quorum =="
32
+#define RAW_LOCK_PERM_BASE 100
33
+#define RAW_LOCK_SHARED_BASE 200
34
+
23
+
35
typedef struct BDRVRawState {
24
+for verify in false true; do
36
int fd;
25
+ run_qemu <<EOF
37
+ int lock_fd;
26
+ { "execute": "qmp_capabilities" }
38
+ bool use_lock;
27
+ { "execute": "blockdev-add",
39
int type;
28
+ "arguments": {
40
int open_flags;
29
+ "driver": "quorum",
41
size_t buf_align;
30
+ "node-name": "drive0-quorum",
42
31
+ "vote-threshold": 2,
43
+ /* The current permissions. */
32
+ "blkverify": ${verify},
44
+ uint64_t perm;
33
+ "children": [
45
+ uint64_t shared_perm;
34
+ {
46
+
35
+ "driver": "$IMGFMT",
47
#ifdef CONFIG_XFS
36
+ "file": {
48
bool is_xfs:1;
37
+ "driver": "file",
49
#endif
38
+ "filename": "$TEST_DIR/1.raw"
50
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
39
+ }
51
BlockdevAioOptions aio, aio_default;
40
+ },
52
int fd, ret;
41
+ {
53
struct stat st;
42
+ "driver": "$IMGFMT",
54
+ OnOffAuto locking;
43
+ "file": {
55
44
+ "driver": "file",
56
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
45
+ "filename": "$TEST_DIR/2.raw"
57
qemu_opts_absorb_qdict(opts, options, &local_err);
46
+ }
58
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
47
+ }
59
}
48
+ ]
60
s->use_linux_aio = (aio == BLOCKDEV_AIO_OPTIONS_NATIVE);
49
+ }
61
62
+ locking = qapi_enum_parse(OnOffAuto_lookup, qemu_opt_get(opts, "locking"),
63
+ ON_OFF_AUTO__MAX, ON_OFF_AUTO_AUTO, &local_err);
64
+ if (local_err) {
65
+ error_propagate(errp, local_err);
66
+ ret = -EINVAL;
67
+ goto fail;
68
+ }
50
+ }
69
+ switch (locking) {
51
+ { "execute": "blockdev-add",
70
+ case ON_OFF_AUTO_ON:
52
+ "arguments": {
71
+ s->use_lock = true;
53
+ "node-name": "drive3",
72
+#ifndef F_OFD_SETLK
54
+ "driver": "$IMGFMT",
73
+ fprintf(stderr,
55
+ "file": {
74
+ "File lock requested but OFD locking syscall is unavailable, "
56
+ "driver": "file",
75
+ "falling back to POSIX file locks.\n"
57
+ "filename": "$TEST_DIR/2.raw"
76
+ "Due to the implementation, locks can be lost unexpectedly.\n");
77
+#endif
78
+ break;
79
+ case ON_OFF_AUTO_OFF:
80
+ s->use_lock = false;
81
+ break;
82
+ case ON_OFF_AUTO_AUTO:
83
+#ifdef F_OFD_SETLK
84
+ s->use_lock = true;
85
+#else
86
+ s->use_lock = false;
87
+#endif
88
+ break;
89
+ default:
90
+ abort();
91
+ }
92
+
93
s->open_flags = open_flags;
94
raw_parse_flags(bdrv_flags, &s->open_flags);
95
96
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
97
}
98
s->fd = fd;
99
100
+ s->lock_fd = -1;
101
+ if (s->use_lock) {
102
+ fd = qemu_open(filename, s->open_flags);
103
+ if (fd < 0) {
104
+ ret = -errno;
105
+ error_setg_errno(errp, errno, "Could not open '%s' for locking",
106
+ filename);
107
+ qemu_close(s->fd);
108
+ goto fail;
109
+ }
110
+ s->lock_fd = fd;
111
+ }
112
+ s->perm = 0;
113
+ s->shared_perm = BLK_PERM_ALL;
114
+
115
#ifdef CONFIG_LINUX_AIO
116
/* Currently Linux does AIO only for files opened with O_DIRECT */
117
if (s->use_linux_aio && !(s->open_flags & O_DIRECT)) {
118
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
119
return raw_open_common(bs, options, flags, 0, errp);
120
}
121
122
+typedef enum {
123
+ RAW_PL_PREPARE,
124
+ RAW_PL_COMMIT,
125
+ RAW_PL_ABORT,
126
+} RawPermLockOp;
127
+
128
+#define PERM_FOREACH(i) \
129
+ for ((i) = 0; (1ULL << (i)) <= BLK_PERM_ALL; i++)
130
+
131
+/* Lock bytes indicated by @perm_lock_bits and @shared_perm_lock_bits in the
132
+ * file; if @unlock == true, also unlock the unneeded bytes.
133
+ * @shared_perm_lock_bits is the mask of all permissions that are NOT shared.
134
+ */
135
+static int raw_apply_lock_bytes(BDRVRawState *s,
136
+ uint64_t perm_lock_bits,
137
+ uint64_t shared_perm_lock_bits,
138
+ bool unlock, Error **errp)
139
+{
140
+ int ret;
141
+ int i;
142
+
143
+ PERM_FOREACH(i) {
144
+ int off = RAW_LOCK_PERM_BASE + i;
145
+ if (perm_lock_bits & (1ULL << i)) {
146
+ ret = qemu_lock_fd(s->lock_fd, off, 1, false);
147
+ if (ret) {
148
+ error_setg(errp, "Failed to lock byte %d", off);
149
+ return ret;
150
+ }
151
+ } else if (unlock) {
152
+ ret = qemu_unlock_fd(s->lock_fd, off, 1);
153
+ if (ret) {
154
+ error_setg(errp, "Failed to unlock byte %d", off);
155
+ return ret;
156
+ }
58
+ }
157
+ }
59
+ }
158
+ }
60
+ }
159
+ PERM_FOREACH(i) {
61
+ { "execute": "x-blockdev-change",
160
+ int off = RAW_LOCK_SHARED_BASE + i;
62
+ "arguments": { "parent": "drive0-quorum",
161
+ if (shared_perm_lock_bits & (1ULL << i)) {
63
+ "node": "drive3" } }
162
+ ret = qemu_lock_fd(s->lock_fd, off, 1, false);
64
+ { "execute": "quit" }
163
+ if (ret) {
65
+EOF
164
+ error_setg(errp, "Failed to lock byte %d", off);
66
+done
165
+ return ret;
67
+
166
+ }
68
+echo
167
+ } else if (unlock) {
69
+echo "== dynamically removing a child from a quorum =="
168
+ ret = qemu_unlock_fd(s->lock_fd, off, 1);
70
+
169
+ if (ret) {
71
+for verify in false true; do
170
+ error_setg(errp, "Failed to unlock byte %d", off);
72
+ for vote_threshold in 1 2; do
171
+ return ret;
73
+ run_qemu <<EOF
74
+ { "execute": "qmp_capabilities" }
75
+ { "execute": "blockdev-add",
76
+ "arguments": {
77
+ "driver": "quorum",
78
+ "node-name": "drive0-quorum",
79
+ "vote-threshold": ${vote_threshold},
80
+ "blkverify": ${verify},
81
+ "children": [
82
+ {
83
+ "driver": "$IMGFMT",
84
+ "file": {
85
+ "driver": "file",
86
+ "filename": "$TEST_DIR/1.raw"
87
+ }
88
+ },
89
+ {
90
+ "driver": "$IMGFMT",
91
+ "file": {
92
+ "driver": "file",
93
+ "filename": "$TEST_DIR/2.raw"
94
+ }
95
+ }
96
+ ]
172
+ }
97
+ }
173
+ }
98
+ }
174
+ }
99
+ { "execute": "x-blockdev-change",
175
+ return 0;
100
+ "arguments": { "parent": "drive0-quorum",
176
+}
101
+ "child": "children.1" } }
102
+ { "execute": "quit" }
103
+EOF
104
+ done
105
+done
177
+
106
+
178
+/* Check "unshared" bytes implied by @perm and ~@shared_perm in the file. */
107
# success, all done
179
+static int raw_check_lock_bytes(BDRVRawState *s,
108
echo "*** done"
180
+ uint64_t perm, uint64_t shared_perm,
109
rm -f $seq.full
181
+ Error **errp)
110
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
182
+{
111
index XXXXXXX..XXXXXXX 100644
183
+ int ret;
112
--- a/tests/qemu-iotests/081.out
184
+ int i;
113
+++ b/tests/qemu-iotests/081.out
114
@@ -XXX,XX +XXX,XX @@ read 10485760/10485760 bytes at offset 0
115
116
== checking the blkverify mode with invalid settings ==
117
can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
185
+
118
+
186
+ PERM_FOREACH(i) {
119
+== dynamically adding a child to a quorum ==
187
+ int off = RAW_LOCK_SHARED_BASE + i;
120
+Testing:
188
+ uint64_t p = 1ULL << i;
121
+QMP_VERSION
189
+ if (perm & p) {
122
+{"return": {}}
190
+ ret = qemu_lock_fd_test(s->lock_fd, off, 1, true);
123
+{"return": {}}
191
+ if (ret) {
124
+{"return": {}}
192
+ char *perm_name = bdrv_perm_names(p);
125
+{"return": {}}
193
+ error_setg(errp,
126
+{"return": {}}
194
+ "Failed to get \"%s\" lock",
127
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
195
+ perm_name);
196
+ g_free(perm_name);
197
+ error_append_hint(errp,
198
+ "Is another process using the image?\n");
199
+ return ret;
200
+ }
201
+ }
202
+ }
203
+ PERM_FOREACH(i) {
204
+ int off = RAW_LOCK_PERM_BASE + i;
205
+ uint64_t p = 1ULL << i;
206
+ if (!(shared_perm & p)) {
207
+ ret = qemu_lock_fd_test(s->lock_fd, off, 1, true);
208
+ if (ret) {
209
+ char *perm_name = bdrv_perm_names(p);
210
+ error_setg(errp,
211
+ "Failed to get shared \"%s\" lock",
212
+ perm_name);
213
+ g_free(perm_name);
214
+ error_append_hint(errp,
215
+ "Is another process using the image?\n");
216
+ return ret;
217
+ }
218
+ }
219
+ }
220
+ return 0;
221
+}
222
+
128
+
223
+static int raw_handle_perm_lock(BlockDriverState *bs,
129
+Testing:
224
+ RawPermLockOp op,
130
+QMP_VERSION
225
+ uint64_t new_perm, uint64_t new_shared,
131
+{"return": {}}
226
+ Error **errp)
132
+{"return": {}}
227
+{
133
+{"return": {}}
228
+ BDRVRawState *s = bs->opaque;
134
+{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
229
+ int ret = 0;
135
+{"return": {}}
230
+ Error *local_err = NULL;
136
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
231
+
232
+ if (!s->use_lock) {
233
+ return 0;
234
+ }
235
+
236
+ if (bdrv_get_flags(bs) & BDRV_O_INACTIVE) {
237
+ return 0;
238
+ }
239
+
240
+ assert(s->lock_fd > 0);
241
+
242
+ switch (op) {
243
+ case RAW_PL_PREPARE:
244
+ ret = raw_apply_lock_bytes(s, s->perm | new_perm,
245
+ ~s->shared_perm | ~new_shared,
246
+ false, errp);
247
+ if (!ret) {
248
+ ret = raw_check_lock_bytes(s, new_perm, new_shared, errp);
249
+ if (!ret) {
250
+ return 0;
251
+ }
252
+ }
253
+ op = RAW_PL_ABORT;
254
+ /* fall through to unlock bytes. */
255
+ case RAW_PL_ABORT:
256
+ raw_apply_lock_bytes(s, s->perm, ~s->shared_perm, true, &local_err);
257
+ if (local_err) {
258
+ /* Theoretically the above call only unlocks bytes and it cannot
259
+ * fail. Something weird happened, report it.
260
+ */
261
+ error_report_err(local_err);
262
+ }
263
+ break;
264
+ case RAW_PL_COMMIT:
265
+ raw_apply_lock_bytes(s, new_perm, ~new_shared, true, &local_err);
266
+ if (local_err) {
267
+ /* Theoretically the above call only unlocks bytes and it cannot
268
+ * fail. Something weird happened, report it.
269
+ */
270
+ error_report_err(local_err);
271
+ }
272
+ break;
273
+ }
274
+ return ret;
275
+}
276
+
277
static int raw_reopen_prepare(BDRVReopenState *state,
278
BlockReopenQueue *queue, Error **errp)
279
{
280
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
281
qemu_close(s->fd);
282
s->fd = -1;
283
}
284
+ if (s->lock_fd >= 0) {
285
+ qemu_close(s->lock_fd);
286
+ s->lock_fd = -1;
287
+ }
288
}
289
290
static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
291
@@ -XXX,XX +XXX,XX @@ static QemuOptsList raw_create_opts = {
292
}
293
};
294
295
+static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
296
+ Error **errp)
297
+{
298
+ return raw_handle_perm_lock(bs, RAW_PL_PREPARE, perm, shared, errp);
299
+}
300
+
301
+static void raw_set_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared)
302
+{
303
+ BDRVRawState *s = bs->opaque;
304
+ raw_handle_perm_lock(bs, RAW_PL_COMMIT, perm, shared, NULL);
305
+ s->perm = perm;
306
+ s->shared_perm = shared;
307
+}
308
+
309
+static void raw_abort_perm_update(BlockDriverState *bs)
310
+{
311
+ raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
312
+}
313
+
314
+static int raw_inactivate(BlockDriverState *bs)
315
+{
316
+ int ret;
317
+ uint64_t perm = 0;
318
+ uint64_t shared = BLK_PERM_ALL;
319
+
320
+ ret = raw_handle_perm_lock(bs, RAW_PL_PREPARE, perm, shared, NULL);
321
+ if (ret) {
322
+ return ret;
323
+ }
324
+ raw_handle_perm_lock(bs, RAW_PL_COMMIT, perm, shared, NULL);
325
+ return 0;
326
+}
327
+
137
+
328
+
138
+
329
+static void raw_invalidate_cache(BlockDriverState *bs, Error **errp)
139
+== dynamically removing a child from a quorum ==
330
+{
140
+Testing:
331
+ BDRVRawState *s = bs->opaque;
141
+QMP_VERSION
332
+ int ret;
142
+{"return": {}}
143
+{"return": {}}
144
+{"return": {}}
145
+{"return": {}}
146
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
333
+
147
+
334
+ assert(!(bdrv_get_flags(bs) & BDRV_O_INACTIVE));
148
+Testing:
335
+ ret = raw_handle_perm_lock(bs, RAW_PL_PREPARE, s->perm, s->shared_perm,
149
+QMP_VERSION
336
+ errp);
150
+{"return": {}}
337
+ if (ret) {
151
+{"return": {}}
338
+ return;
152
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
339
+ }
153
+{"return": {}}
340
+ raw_handle_perm_lock(bs, RAW_PL_COMMIT, s->perm, s->shared_perm, NULL);
154
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
341
+}
342
+
155
+
343
BlockDriver bdrv_file = {
156
+Testing:
344
.format_name = "file",
157
+QMP_VERSION
345
.protocol_name = "file",
158
+{"return": {}}
346
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
159
+{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
347
.bdrv_get_info = raw_get_info,
160
+{"error": {"class": "GenericError", "desc": "Cannot find device=drive0-quorum nor node_name=drive0-quorum"}}
348
.bdrv_get_allocated_file_size
161
+{"return": {}}
349
= raw_get_allocated_file_size,
162
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
350
-
163
+
351
+ .bdrv_inactivate = raw_inactivate,
164
+Testing:
352
+ .bdrv_invalidate_cache = raw_invalidate_cache,
165
+QMP_VERSION
353
+ .bdrv_check_perm = raw_check_perm,
166
+{"return": {}}
354
+ .bdrv_set_perm = raw_set_perm,
167
+{"return": {}}
355
+ .bdrv_abort_perm_update = raw_abort_perm_update,
168
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
356
.create_opts = &raw_create_opts,
169
+{"return": {}}
357
};
170
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
358
171
+
359
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
172
*** done
360
.bdrv_get_info = raw_get_info,
361
.bdrv_get_allocated_file_size
362
= raw_get_allocated_file_size,
363
+ .bdrv_inactivate = raw_inactivate,
364
+ .bdrv_invalidate_cache = raw_invalidate_cache,
365
+ .bdrv_check_perm = raw_check_perm,
366
+ .bdrv_set_perm = raw_set_perm,
367
+ .bdrv_abort_perm_update = raw_abort_perm_update,
368
.bdrv_probe_blocksizes = hdev_probe_blocksizes,
369
.bdrv_probe_geometry = hdev_probe_geometry,
370
371
--
173
--
372
1.8.3.1
174
2.19.1
373
175
374
176
diff view generated by jsdifflib
1
Format drivers for inactive nodes don't need write/resize permissions on
1
To fully change the read-only state of a node, we must not only change
2
their bs->file and can share write/resize with another VM (in fact, this
2
bs->read_only, but also update bs->open_flags.
3
is the whole point of keeping images inactive). Represent this fact in
4
the op blocker system, so that image locking does the right thing
5
without special-casing inactive images.
6
3
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
---
7
---
10
block.c | 35 +++++++++++++++++++++++++++++++++--
8
block.c | 7 +++++++
11
include/block/block.h | 1 +
9
1 file changed, 7 insertions(+)
12
2 files changed, 34 insertions(+), 2 deletions(-)
13
10
14
diff --git a/block.c b/block.c
11
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
13
--- a/block.c
17
+++ b/block.c
14
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
15
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
19
}
16
}
20
}
17
21
18
bs->read_only = read_only;
22
+/* Returns whether the image file is opened as read-only. Note that this can
23
+ * return false and writing to the image file is still not possible because the
24
+ * image is inactivated. */
25
bool bdrv_is_read_only(BlockDriverState *bs)
26
{
27
return bs->read_only;
28
}
29
30
+/* Returns whether the image file can be written to right now */
31
+bool bdrv_is_writable(BlockDriverState *bs)
32
+{
33
+ return !bdrv_is_read_only(bs) && !(bs->open_flags & BDRV_O_INACTIVE);
34
+}
35
+
19
+
36
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
20
+ if (read_only) {
37
{
21
+ bs->open_flags &= ~BDRV_O_RDWR;
38
/* Do not set read_only if copy_on_read is enabled */
22
+ } else {
39
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms,
23
+ bs->open_flags |= BDRV_O_RDWR;
40
41
/* Write permissions never work with read-only images */
42
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
43
- bdrv_is_read_only(bs))
44
+ !bdrv_is_writable(bs))
45
{
46
error_setg(errp, "Block node is read-only");
47
return -EPERM;
48
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
49
bdrv_filter_default_perms(bs, c, role, perm, shared, &perm, &shared);
50
51
/* Format drivers may touch metadata even if the guest doesn't write */
52
- if (!bdrv_is_read_only(bs)) {
53
+ if (bdrv_is_writable(bs)) {
54
perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
55
}
56
57
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
58
BLK_PERM_WRITE_UNCHANGED;
59
}
60
61
+ if (bs->open_flags & BDRV_O_INACTIVE) {
62
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
63
+ }
24
+ }
64
+
25
+
65
*nperm = perm;
26
return 0;
66
*nshared = shared;
67
}
27
}
68
@@ -XXX,XX +XXX,XX @@ void bdrv_init_with_whitelist(void)
28
69
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
70
{
71
BdrvChild *child, *parent;
72
+ uint64_t perm, shared_perm;
73
Error *local_err = NULL;
74
int ret;
75
76
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
77
return;
78
}
79
80
+ /* Update permissions, they may differ for inactive nodes */
81
+ bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
82
+ ret = bdrv_check_perm(bs, perm, shared_perm, NULL, &local_err);
83
+ if (ret < 0) {
84
+ bs->open_flags |= BDRV_O_INACTIVE;
85
+ error_propagate(errp, local_err);
86
+ return;
87
+ }
88
+ bdrv_set_perm(bs, perm, shared_perm);
89
+
90
QLIST_FOREACH(parent, &bs->parents, next_parent) {
91
if (parent->role->activate) {
92
parent->role->activate(parent, &local_err);
93
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
94
}
95
96
if (setting_flag) {
97
+ uint64_t perm, shared_perm;
98
+
99
bs->open_flags |= BDRV_O_INACTIVE;
100
101
QLIST_FOREACH(parent, &bs->parents, next_parent) {
102
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
103
}
104
}
105
}
106
+
107
+ /* Update permissions, they may differ for inactive nodes */
108
+ bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
109
+ bdrv_check_perm(bs, perm, shared_perm, NULL, &error_abort);
110
+ bdrv_set_perm(bs, perm, shared_perm);
111
}
112
113
QLIST_FOREACH(child, &bs->children, next) {
114
diff --git a/include/block/block.h b/include/block/block.h
115
index XXXXXXX..XXXXXXX 100644
116
--- a/include/block/block.h
117
+++ b/include/block/block.h
118
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
119
int64_t sector_num, int nb_sectors, int *pnum);
120
121
bool bdrv_is_read_only(BlockDriverState *bs);
122
+bool bdrv_is_writable(BlockDriverState *bs);
123
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
124
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
125
bool bdrv_is_sg(BlockDriverState *bs);
126
--
29
--
127
1.8.3.1
30
2.19.1
128
31
129
32
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
If a management application builds the block graph node by node, the
2
protocol layer doesn't inherit its read-only option from the format
3
layer any more, so it must be set explicitly.
2
4
3
Signed-off-by: Fam Zheng <famz@redhat.com>
5
Backing files should work on read-only storage, but at the same time, a
6
block job like commit should be able to reopen them read-write if they
7
are on read-write storage. However, without option inheritance, reopen
8
only changes the read-only option for the root node (typically the
9
format layer), but not the protocol layer, so reopening fails (the
10
format layer wants to get write permissions, but the protocol layer is
11
still read-only).
12
13
A simple workaround for the problem in the management tool would be to
14
open the protocol layer always read-write and to make only the format
15
layer read-only for backing files. However, sometimes the file is
16
actually stored on read-only storage and we don't know whether the image
17
can be opened read-write (for example, for NBD it depends on the server
18
we're trying to connect to). This adds an option that makes QEMU try to
19
open the image read-write, but allows it to degrade to a read-only mode
20
without returning an error.
21
22
The documentation for this option is consciously phrased in a way that
23
allows QEMU to switch to a better model eventually: Instead of trying
24
when the image is first opened, making the read-only flag dynamic and
25
changing it automatically whenever the first BLK_PERM_WRITE user is
26
attached or the last one is detached would be much more useful
27
behaviour.
28
29
Unfortunately, this more useful behaviour is also a lot harder to
30
implement, and libvirt needs a solution now before it can switch to
31
-blockdev, so let's start with this easier approach for now.
32
33
Instead of adding a new auto-read-only option, turning the existing
34
read-only into an enum (with a bool alternate for compatibility) was
35
considered, but it complicated the implementation to the point that it
36
didn't seem to be worth it.
37
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
5
---
40
---
6
block.c | 17 +++++++++++++++++
41
qapi/block-core.json | 7 +++++++
7
include/block/block.h | 1 +
42
include/block/block.h | 2 ++
8
include/block/block_int.h | 1 +
43
block.c | 17 +++++++++++++++++
9
qapi/block-core.json | 3 +++
44
block/vvfat.c | 1 +
10
4 files changed, 22 insertions(+)
45
blockdev.c | 2 +-
46
5 files changed, 28 insertions(+), 1 deletion(-)
11
47
48
diff --git a/qapi/block-core.json b/qapi/block-core.json
49
index XXXXXXX..XXXXXXX 100644
50
--- a/qapi/block-core.json
51
+++ b/qapi/block-core.json
52
@@ -XXX,XX +XXX,XX @@
53
# either generally or in certain configurations. In this case,
54
# the default value does not work and the option must be
55
# specified explicitly.
56
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
57
+# decide not to open the image read-write as requested, but
58
+# fall back to read-only instead (and switch between the modes
59
+# later), e.g. depending on whether the image file is writable
60
+# or whether a writing user is attached to the node
61
+# (default: false, since 3.1)
62
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
63
# (default: off)
64
# @force-share: force share all permission on added nodes.
65
@@ -XXX,XX +XXX,XX @@
66
'*discard': 'BlockdevDiscardOptions',
67
'*cache': 'BlockdevCacheOptions',
68
'*read-only': 'bool',
69
+ '*auto-read-only': 'bool',
70
'*force-share': 'bool',
71
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
72
'discriminator': 'driver',
73
diff --git a/include/block/block.h b/include/block/block.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/block/block.h
76
+++ b/include/block/block.h
77
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
78
select an appropriate protocol driver,
79
ignoring the format layer */
80
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
81
+#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
82
83
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
84
85
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
86
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
87
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
88
#define BDRV_OPT_READ_ONLY "read-only"
89
+#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
90
#define BDRV_OPT_DISCARD "discard"
91
#define BDRV_OPT_FORCE_SHARE "force-share"
92
12
diff --git a/block.c b/block.c
93
diff --git a/block.c b/block.c
13
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
95
--- a/block.c
15
+++ b/block.c
96
+++ b/block.c
16
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
17
* the parent. */
18
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
19
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
20
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
21
98
22
/* Inherit the read-only option from the parent if it's not set */
99
/* Inherit the read-only option from the parent if it's not set */
23
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
100
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
101
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
102
103
/* Our block drivers take care to send flushes and respect unmap policy,
104
* so we can default to enable both on lower layers regardless of the
24
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
105
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
25
* which is only applied on the top level (BlockBackend) */
26
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
27
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
28
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
29
106
30
/* backing files always opened read-only */
107
/* backing files always opened read-only */
31
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
108
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
109
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
110
flags &= ~BDRV_O_COPY_ON_READ;
111
112
/* snapshot=on is handled on the top layer */
113
@@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
114
*flags |= BDRV_O_RDWR;
115
}
116
117
+ assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
118
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
119
+ *flags |= BDRV_O_AUTO_RDONLY;
120
+ }
121
}
122
123
static void update_options_from_flags(QDict *options, int flags)
124
@@ -XXX,XX +XXX,XX @@ static void update_options_from_flags(QDict *options, int flags)
125
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
126
qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
127
}
128
+ if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
129
+ qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
130
+ flags & BDRV_O_AUTO_RDONLY);
131
+ }
132
}
133
134
static void bdrv_assign_node_name(BlockDriverState *bs,
32
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
135
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
33
.type = QEMU_OPT_STRING,
136
.type = QEMU_OPT_BOOL,
34
.help = "discard operation (ignore/off, unmap/on)",
137
.help = "Node is opened in read-only mode",
35
},
138
},
36
+ {
139
+ {
37
+ .name = BDRV_OPT_FORCE_SHARE,
140
+ .name = BDRV_OPT_AUTO_READ_ONLY,
38
+ .type = QEMU_OPT_BOOL,
141
+ .type = QEMU_OPT_BOOL,
39
+ .help = "always accept other writers (default: off)",
142
+ .help = "Node can become read-only if opening read-write fails",
40
+ },
143
+ },
41
{ /* end of list */ }
144
{
42
},
145
.name = "detect-zeroes",
43
};
146
.type = QEMU_OPT_STRING,
44
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
147
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
45
drv = bdrv_find_format(driver_name);
148
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
46
assert(drv != NULL);
149
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
47
150
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
48
+ bs->force_share = qemu_opt_get_bool(opts, BDRV_OPT_FORCE_SHARE, false);
151
+ qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
49
+
152
+
50
+ if (bs->force_share && (bs->open_flags & BDRV_O_RDWR)) {
153
}
51
+ error_setg(errp,
154
52
+ BDRV_OPT_FORCE_SHARE
155
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
53
+ "=on can only be used with read-only images");
156
diff --git a/block/vvfat.c b/block/vvfat.c
54
+ ret = -EINVAL;
55
+ goto fail_opts;
56
+ }
57
+
58
if (file != NULL) {
59
filename = blk_bs(file)->filename;
60
} else {
61
diff --git a/include/block/block.h b/include/block/block.h
62
index XXXXXXX..XXXXXXX 100644
157
index XXXXXXX..XXXXXXX 100644
63
--- a/include/block/block.h
158
--- a/block/vvfat.c
64
+++ b/include/block/block.h
159
+++ b/block/vvfat.c
65
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
160
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
66
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
161
int parent_flags, QDict *parent_options)
67
#define BDRV_OPT_READ_ONLY "read-only"
162
{
68
#define BDRV_OPT_DISCARD "discard"
163
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
69
+#define BDRV_OPT_FORCE_SHARE "force-share"
164
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
70
165
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
71
166
}
72
#define BDRV_SECTOR_BITS 9
167
73
diff --git a/include/block/block_int.h b/include/block/block_int.h
168
diff --git a/blockdev.c b/blockdev.c
74
index XXXXXXX..XXXXXXX 100644
169
index XXXXXXX..XXXXXXX 100644
75
--- a/include/block/block_int.h
170
--- a/blockdev.c
76
+++ b/include/block/block_int.h
171
+++ b/blockdev.c
77
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
78
bool valid_key; /* if true, a valid encryption key has been set */
173
79
bool sg; /* if true, the device is a /dev/sg* */
174
bdrv_flags = blk_get_open_flags_from_root_state(blk);
80
bool probed; /* if true, format was probed rather than specified */
175
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
81
+ bool force_share; /* if true, always allow all shared permissions */
176
- BDRV_O_PROTOCOL);
82
177
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
83
BlockDriver *drv; /* NULL means no media */
178
84
void *opaque;
179
if (!has_read_only) {
85
diff --git a/qapi/block-core.json b/qapi/block-core.json
180
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
86
index XXXXXXX..XXXXXXX 100644
87
--- a/qapi/block-core.json
88
+++ b/qapi/block-core.json
89
@@ -XXX,XX +XXX,XX @@
90
# (default: false)
91
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
92
# (default: off)
93
+# @force-share: force share all permission on added nodes.
94
+# Requires read-only=true. (Since 2.10)
95
#
96
# Remaining options are determined by the block driver.
97
#
98
@@ -XXX,XX +XXX,XX @@
99
'*discard': 'BlockdevDiscardOptions',
100
'*cache': 'BlockdevCacheOptions',
101
'*read-only': 'bool',
102
+ '*force-share': 'bool',
103
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
104
'discriminator': 'driver',
105
'data': {
106
--
181
--
107
1.8.3.1
182
2.19.1
108
183
109
184
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
This will force the opened images to allow sharing all permissions with other
4
programs.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
qemu-img.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++---------------
10
1 file changed, 117 insertions(+), 36 deletions(-)
11
12
diff --git a/qemu-img.c b/qemu-img.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qemu-img.c
15
+++ b/qemu-img.c
16
@@ -XXX,XX +XXX,XX @@
17
#include "qapi/qobject-output-visitor.h"
18
#include "qapi/qmp/qerror.h"
19
#include "qapi/qmp/qjson.h"
20
+#include "qapi/qmp/qbool.h"
21
#include "qemu/cutils.h"
22
#include "qemu/config-file.h"
23
#include "qemu/option.h"
24
@@ -XXX,XX +XXX,XX @@ static int img_open_password(BlockBackend *blk, const char *filename,
25
26
static BlockBackend *img_open_opts(const char *optstr,
27
QemuOpts *opts, int flags, bool writethrough,
28
- bool quiet)
29
+ bool quiet, bool force_share)
30
{
31
QDict *options;
32
Error *local_err = NULL;
33
BlockBackend *blk;
34
options = qemu_opts_to_qdict(opts, NULL);
35
+ if (force_share) {
36
+ if (qdict_haskey(options, BDRV_OPT_FORCE_SHARE)
37
+ && !qdict_get_bool(options, BDRV_OPT_FORCE_SHARE)) {
38
+ error_report("--force-share/-U conflicts with image options");
39
+ return NULL;
40
+ }
41
+ qdict_put(options, BDRV_OPT_FORCE_SHARE, qbool_from_bool(true));
42
+ }
43
blk = blk_new_open(NULL, NULL, options, flags, &local_err);
44
if (!blk) {
45
error_reportf_err(local_err, "Could not open '%s': ", optstr);
46
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_opts(const char *optstr,
47
48
static BlockBackend *img_open_file(const char *filename,
49
const char *fmt, int flags,
50
- bool writethrough, bool quiet)
51
+ bool writethrough, bool quiet,
52
+ bool force_share)
53
{
54
BlockBackend *blk;
55
Error *local_err = NULL;
56
- QDict *options = NULL;
57
+ QDict *options = qdict_new();
58
59
if (fmt) {
60
- options = qdict_new();
61
qdict_put_str(options, "driver", fmt);
62
}
63
64
+ if (force_share) {
65
+ qdict_put(options, BDRV_OPT_FORCE_SHARE, qbool_from_bool(true));
66
+ }
67
blk = blk_new_open(filename, NULL, options, flags, &local_err);
68
if (!blk) {
69
error_reportf_err(local_err, "Could not open '%s': ", filename);
70
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_file(const char *filename,
71
static BlockBackend *img_open(bool image_opts,
72
const char *filename,
73
const char *fmt, int flags, bool writethrough,
74
- bool quiet)
75
+ bool quiet, bool force_share)
76
{
77
BlockBackend *blk;
78
if (image_opts) {
79
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open(bool image_opts,
80
if (!opts) {
81
return NULL;
82
}
83
- blk = img_open_opts(filename, opts, flags, writethrough, quiet);
84
+ blk = img_open_opts(filename, opts, flags, writethrough, quiet,
85
+ force_share);
86
} else {
87
- blk = img_open_file(filename, fmt, flags, writethrough, quiet);
88
+ blk = img_open_file(filename, fmt, flags, writethrough, quiet,
89
+ force_share);
90
}
91
return blk;
92
}
93
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
94
ImageCheck *check;
95
bool quiet = false;
96
bool image_opts = false;
97
+ bool force_share = false;
98
99
fmt = NULL;
100
output = NULL;
101
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
102
{"output", required_argument, 0, OPTION_OUTPUT},
103
{"object", required_argument, 0, OPTION_OBJECT},
104
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
105
+ {"force-share", no_argument, 0, 'U'},
106
{0, 0, 0, 0}
107
};
108
- c = getopt_long(argc, argv, ":hf:r:T:q",
109
+ c = getopt_long(argc, argv, ":hf:r:T:qU",
110
long_options, &option_index);
111
if (c == -1) {
112
break;
113
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
114
case 'q':
115
quiet = true;
116
break;
117
+ case 'U':
118
+ force_share = true;
119
+ break;
120
case OPTION_OBJECT: {
121
QemuOpts *opts;
122
opts = qemu_opts_parse_noisily(&qemu_object_opts,
123
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
124
return 1;
125
}
126
127
- blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
128
+ blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
129
+ force_share);
130
if (!blk) {
131
return 1;
132
}
133
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
134
return 1;
135
}
136
137
- blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
138
+ blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
139
+ false);
140
if (!blk) {
141
return 1;
142
}
143
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
144
int c, pnum;
145
uint64_t progress_base;
146
bool image_opts = false;
147
+ bool force_share = false;
148
149
cache = BDRV_DEFAULT_CACHE;
150
for (;;) {
151
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
152
{"help", no_argument, 0, 'h'},
153
{"object", required_argument, 0, OPTION_OBJECT},
154
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
155
+ {"force-share", no_argument, 0, 'U'},
156
{0, 0, 0, 0}
157
};
158
- c = getopt_long(argc, argv, ":hf:F:T:pqs",
159
+ c = getopt_long(argc, argv, ":hf:F:T:pqsU",
160
long_options, NULL);
161
if (c == -1) {
162
break;
163
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
164
case 's':
165
strict = true;
166
break;
167
+ case 'U':
168
+ force_share = true;
169
+ break;
170
case OPTION_OBJECT: {
171
QemuOpts *opts;
172
opts = qemu_opts_parse_noisily(&qemu_object_opts,
173
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
174
goto out3;
175
}
176
177
- blk1 = img_open(image_opts, filename1, fmt1, flags, writethrough, quiet);
178
+ blk1 = img_open(image_opts, filename1, fmt1, flags, writethrough, quiet,
179
+ force_share);
180
if (!blk1) {
181
ret = 2;
182
goto out3;
183
}
184
185
- blk2 = img_open(image_opts, filename2, fmt2, flags, writethrough, quiet);
186
+ blk2 = img_open(image_opts, filename2, fmt2, flags, writethrough, quiet,
187
+ force_share);
188
if (!blk2) {
189
ret = 2;
190
goto out2;
191
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
192
bool writethrough, src_writethrough, quiet = false, image_opts = false,
193
skip_create = false, progress = false;
194
int64_t ret = -EINVAL;
195
+ bool force_share = false;
196
197
ImgConvertState s = (ImgConvertState) {
198
/* Need at least 4k of zeros for sparse detection */
199
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
200
{"help", no_argument, 0, 'h'},
201
{"object", required_argument, 0, OPTION_OBJECT},
202
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
203
+ {"force-share", no_argument, 0, 'U'},
204
{0, 0, 0, 0}
205
};
206
- c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:W",
207
+ c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:WU",
208
long_options, NULL);
209
if (c == -1) {
210
break;
211
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
212
case 'W':
213
s.wr_in_order = false;
214
break;
215
+ case 'U':
216
+ force_share = true;
217
+ break;
218
case OPTION_OBJECT: {
219
QemuOpts *object_opts;
220
object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
221
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
222
223
for (bs_i = 0; bs_i < s.src_num; bs_i++) {
224
s.src[bs_i] = img_open(image_opts, argv[optind + bs_i],
225
- fmt, src_flags, src_writethrough, quiet);
226
+ fmt, src_flags, src_writethrough, quiet,
227
+ force_share);
228
if (!s.src[bs_i]) {
229
ret = -1;
230
goto out;
231
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
232
* the bdrv_create() call which takes different params.
233
* Not critical right now, so fix can wait...
234
*/
235
- s.target = img_open_file(out_filename, out_fmt, flags, writethrough, quiet);
236
+ s.target = img_open_file(out_filename, out_fmt, flags, writethrough, quiet,
237
+ false);
238
if (!s.target) {
239
ret = -1;
240
goto out;
241
@@ -XXX,XX +XXX,XX @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
242
static ImageInfoList *collect_image_info_list(bool image_opts,
243
const char *filename,
244
const char *fmt,
245
- bool chain)
246
+ bool chain, bool force_share)
247
{
248
ImageInfoList *head = NULL;
249
ImageInfoList **last = &head;
250
@@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts,
251
g_hash_table_insert(filenames, (gpointer)filename, NULL);
252
253
blk = img_open(image_opts, filename, fmt,
254
- BDRV_O_NO_BACKING | BDRV_O_NO_IO, false, false);
255
+ BDRV_O_NO_BACKING | BDRV_O_NO_IO, false, false,
256
+ force_share);
257
if (!blk) {
258
goto err;
259
}
260
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
261
const char *filename, *fmt, *output;
262
ImageInfoList *list;
263
bool image_opts = false;
264
+ bool force_share = false;
265
266
fmt = NULL;
267
output = NULL;
268
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
269
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
270
{"object", required_argument, 0, OPTION_OBJECT},
271
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
272
+ {"force-share", no_argument, 0, 'U'},
273
{0, 0, 0, 0}
274
};
275
- c = getopt_long(argc, argv, ":f:h",
276
+ c = getopt_long(argc, argv, ":f:hU",
277
long_options, &option_index);
278
if (c == -1) {
279
break;
280
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
281
case 'f':
282
fmt = optarg;
283
break;
284
+ case 'U':
285
+ force_share = true;
286
+ break;
287
case OPTION_OUTPUT:
288
output = optarg;
289
break;
290
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
291
return 1;
292
}
293
294
- list = collect_image_info_list(image_opts, filename, fmt, chain);
295
+ list = collect_image_info_list(image_opts, filename, fmt, chain,
296
+ force_share);
297
if (!list) {
298
return 1;
299
}
300
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
301
MapEntry curr = { .length = 0 }, next;
302
int ret = 0;
303
bool image_opts = false;
304
+ bool force_share = false;
305
306
fmt = NULL;
307
output = NULL;
308
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
309
{"output", required_argument, 0, OPTION_OUTPUT},
310
{"object", required_argument, 0, OPTION_OBJECT},
311
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
312
+ {"force-share", no_argument, 0, 'U'},
313
{0, 0, 0, 0}
314
};
315
- c = getopt_long(argc, argv, ":f:h",
316
+ c = getopt_long(argc, argv, ":f:hU",
317
long_options, &option_index);
318
if (c == -1) {
319
break;
320
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
321
case 'f':
322
fmt = optarg;
323
break;
324
+ case 'U':
325
+ force_share = true;
326
+ break;
327
case OPTION_OUTPUT:
328
output = optarg;
329
break;
330
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
331
return 1;
332
}
333
334
- blk = img_open(image_opts, filename, fmt, 0, false, false);
335
+ blk = img_open(image_opts, filename, fmt, 0, false, false, force_share);
336
if (!blk) {
337
return 1;
338
}
339
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
340
bool quiet = false;
341
Error *err = NULL;
342
bool image_opts = false;
343
+ bool force_share = false;
344
345
bdrv_oflags = BDRV_O_RDWR;
346
/* Parse commandline parameters */
347
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
348
{"help", no_argument, 0, 'h'},
349
{"object", required_argument, 0, OPTION_OBJECT},
350
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
351
+ {"force-share", no_argument, 0, 'U'},
352
{0, 0, 0, 0}
353
};
354
- c = getopt_long(argc, argv, ":la:c:d:hq",
355
+ c = getopt_long(argc, argv, ":la:c:d:hqU",
356
long_options, NULL);
357
if (c == -1) {
358
break;
359
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
360
case 'q':
361
quiet = true;
362
break;
363
+ case 'U':
364
+ force_share = true;
365
+ break;
366
case OPTION_OBJECT: {
367
QemuOpts *opts;
368
opts = qemu_opts_parse_noisily(&qemu_object_opts,
369
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
370
}
371
372
/* Open the image */
373
- blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet);
374
+ blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet,
375
+ force_share);
376
if (!blk) {
377
return 1;
378
}
379
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
380
int c, flags, src_flags, ret;
381
bool writethrough, src_writethrough;
382
int unsafe = 0;
383
+ bool force_share = false;
384
int progress = 0;
385
bool quiet = false;
386
Error *local_err = NULL;
387
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
388
{"help", no_argument, 0, 'h'},
389
{"object", required_argument, 0, OPTION_OBJECT},
390
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
391
+ {"force-share", no_argument, 0, 'U'},
392
{0, 0, 0, 0}
393
};
394
- c = getopt_long(argc, argv, ":hf:F:b:upt:T:q",
395
+ c = getopt_long(argc, argv, ":hf:F:b:upt:T:qU",
396
long_options, NULL);
397
if (c == -1) {
398
break;
399
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
400
case OPTION_IMAGE_OPTS:
401
image_opts = true;
402
break;
403
+ case 'U':
404
+ force_share = true;
405
+ break;
406
}
407
}
408
409
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
410
* Ignore the old backing file for unsafe rebase in case we want to correct
411
* the reference to a renamed or moved backing file.
412
*/
413
- blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
414
+ blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
415
+ false);
416
if (!blk) {
417
ret = -1;
418
goto out;
419
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
420
qdict_put_str(options, "driver", bs->backing_format);
421
}
422
423
+ if (force_share) {
424
+ if (!options) {
425
+ options = qdict_new();
426
+ }
427
+ qdict_put(options, BDRV_OPT_FORCE_SHARE,
428
+ qbool_from_bool(true));
429
+ }
430
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
431
blk_old_backing = blk_new_open(backing_name, NULL,
432
options, src_flags, &local_err);
433
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
434
}
435
436
if (out_baseimg[0]) {
437
+ options = qdict_new();
438
if (out_basefmt) {
439
- options = qdict_new();
440
qdict_put_str(options, "driver", out_basefmt);
441
- } else {
442
- options = NULL;
443
+ }
444
+ if (force_share) {
445
+ qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
446
}
447
448
blk_new_backing = blk_new_open(out_baseimg, NULL,
449
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
450
qemu_opts_del(param);
451
452
blk = img_open(image_opts, filename, fmt,
453
- BDRV_O_RDWR | BDRV_O_RESIZE, false, quiet);
454
+ BDRV_O_RDWR | BDRV_O_RESIZE, false, quiet,
455
+ false);
456
if (!blk) {
457
ret = -1;
458
goto out;
459
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
460
goto out;
461
}
462
463
- blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
464
+ blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
465
+ false);
466
if (!blk) {
467
ret = -1;
468
goto out;
469
@@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv)
470
bool writethrough = false;
471
struct timeval t1, t2;
472
int i;
473
+ bool force_share = false;
474
475
for (;;) {
476
static const struct option long_options[] = {
477
@@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv)
478
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
479
{"pattern", required_argument, 0, OPTION_PATTERN},
480
{"no-drain", no_argument, 0, OPTION_NO_DRAIN},
481
+ {"force-share", no_argument, 0, 'U'},
482
{0, 0, 0, 0}
483
};
484
- c = getopt_long(argc, argv, ":hc:d:f:no:qs:S:t:w", long_options, NULL);
485
+ c = getopt_long(argc, argv, ":hc:d:f:no:qs:S:t:wU", long_options, NULL);
486
if (c == -1) {
487
break;
488
}
489
@@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv)
490
flags |= BDRV_O_RDWR;
491
is_write = true;
492
break;
493
+ case 'U':
494
+ force_share = true;
495
+ break;
496
case OPTION_PATTERN:
497
{
498
unsigned long res;
499
@@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv)
500
goto out;
501
}
502
503
- blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
504
+ blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
505
+ force_share);
506
if (!blk) {
507
ret = -1;
508
goto out;
509
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
510
const char *fmt = NULL;
511
int64_t size = 0;
512
int64_t block_count = 0, out_pos, in_pos;
513
+ bool force_share = false;
514
struct DdInfo dd = {
515
.flags = 0,
516
.count = 0,
517
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
518
const struct option long_options[] = {
519
{ "help", no_argument, 0, 'h'},
520
{ "image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
521
+ { "force-share", no_argument, 0, 'U'},
522
{ 0, 0, 0, 0 }
523
};
524
525
- while ((c = getopt_long(argc, argv, ":hf:O:", long_options, NULL))) {
526
+ while ((c = getopt_long(argc, argv, ":hf:O:U", long_options, NULL))) {
527
if (c == EOF) {
528
break;
529
}
530
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
531
case 'h':
532
help();
533
break;
534
+ case 'U':
535
+ force_share = true;
536
+ break;
537
case OPTION_IMAGE_OPTS:
538
image_opts = true;
539
break;
540
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
541
ret = -1;
542
goto out;
543
}
544
- blk1 = img_open(image_opts, in.filename, fmt, 0, false, false);
545
+ blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
546
+ force_share);
547
548
if (!blk1) {
549
ret = -1;
550
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
551
}
552
553
blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR,
554
- false, false);
555
+ false, false, false);
556
557
if (!blk2) {
558
ret = -1;
559
--
560
1.8.3.1
561
562
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Signed-off-by: Fam Zheng <famz@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
qemu-img-cmds.hx | 36 ++++++++++++++++++------------------
7
1 file changed, 18 insertions(+), 18 deletions(-)
8
9
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
10
index XXXXXXX..XXXXXXX 100644
11
--- a/qemu-img-cmds.hx
12
+++ b/qemu-img-cmds.hx
13
@@ -XXX,XX +XXX,XX @@ STEXI
14
ETEXI
15
16
DEF("bench", img_bench,
17
- "bench [-c count] [-d depth] [-f fmt] [--flush-interval=flush_interval] [-n] [--no-drain] [-o offset] [--pattern=pattern] [-q] [-s buffer_size] [-S step_size] [-t cache] [-w] filename")
18
+ "bench [-c count] [-d depth] [-f fmt] [--flush-interval=flush_interval] [-n] [--no-drain] [-o offset] [--pattern=pattern] [-q] [-s buffer_size] [-S step_size] [-t cache] [-w] [-U] filename")
19
STEXI
20
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [--flush-interval=@var{flush_interval}] [-n] [--no-drain] [-o @var{offset}] [--pattern=@var{pattern}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
21
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [--flush-interval=@var{flush_interval}] [-n] [--no-drain] [-o @var{offset}] [--pattern=@var{pattern}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] [-U] @var{filename}
22
ETEXI
23
24
DEF("check", img_check,
25
- "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
26
+ "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] [-U] filename")
27
STEXI
28
-@item check [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
29
+@item check [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] [-U] @var{filename}
30
ETEXI
31
32
DEF("create", img_create,
33
@@ -XXX,XX +XXX,XX @@ STEXI
34
ETEXI
35
36
DEF("compare", img_compare,
37
- "compare [--object objectdef] [--image-opts] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
38
+ "compare [--object objectdef] [--image-opts] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] [-U] filename1 filename2")
39
STEXI
40
-@item compare [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2}
41
+@item compare [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] [-U] @var{filename1} @var{filename2}
42
ETEXI
43
44
DEF("convert", img_convert,
45
- "convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
46
+ "convert [--object objectdef] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
47
STEXI
48
-@item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
49
+@item convert [--object @var{objectdef}] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
50
ETEXI
51
52
DEF("dd", img_dd,
53
- "dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] if=input of=output")
54
+ "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] if=input of=output")
55
STEXI
56
-@item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
57
+@item dd [--image-opts] [-U] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
58
ETEXI
59
60
DEF("info", img_info,
61
- "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] filename")
62
+ "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [-U] filename")
63
STEXI
64
-@item info [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename}
65
+@item info [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] [-U] @var{filename}
66
ETEXI
67
68
DEF("map", img_map,
69
- "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] filename")
70
+ "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-U] filename")
71
STEXI
72
-@item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
73
+@item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [-U] @var{filename}
74
ETEXI
75
76
DEF("snapshot", img_snapshot,
77
- "snapshot [--object objectdef] [--image-opts] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
78
+ "snapshot [--object objectdef] [--image-opts] [-U] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
79
STEXI
80
-@item snapshot [--object @var{objectdef}] [--image-opts] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
81
+@item snapshot [--object @var{objectdef}] [--image-opts] [-U] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
82
ETEXI
83
84
DEF("rebase", img_rebase,
85
- "rebase [--object objectdef] [--image-opts] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
86
+ "rebase [--object objectdef] [--image-opts] [-U] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
87
STEXI
88
-@item rebase [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
89
+@item rebase [--object @var{objectdef}] [--image-opts] [-U] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
90
ETEXI
91
92
DEF("resize", img_resize,
93
--
94
1.8.3.1
95
96
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Commit e2b8247a322 introduced an error path in qemu_rbd_open() after
2
calling rbd_open(), but neglected to close the image again in this error
3
path. The error path should contain everything that the regular close
4
function qemu_rbd_close() contains.
2
5
3
util/qemu-progress.c is currently unmaintained. The only user of its
6
This adds the missing rbd_close() call.
4
functionality is qemu-img, so it effectively is part of the block layer.
5
7
6
Suggested-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20170428165517.30341-1-mreitz@redhat.com
9
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
10
---
13
MAINTAINERS | 1 +
11
block/rbd.c | 1 +
14
1 file changed, 1 insertion(+)
12
1 file changed, 1 insertion(+)
15
13
16
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/block/rbd.c b/block/rbd.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/MAINTAINERS
16
--- a/block/rbd.c
19
+++ b/MAINTAINERS
17
+++ b/block/rbd.c
20
@@ -XXX,XX +XXX,XX @@ F: include/block/
18
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
21
F: qemu-img*
19
"automatically marking the image read-only.");
22
F: qemu-io*
20
r = bdrv_set_read_only(bs, true, &local_err);
23
F: tests/qemu-iotests/
21
if (r < 0) {
24
+F: util/qemu-progress.c
22
+ rbd_close(s->image);
25
T: git git://repo.or.cz/qemu/kevin.git block
23
error_propagate(errp, local_err);
26
24
goto failed_open;
27
Block I/O path
25
}
28
--
26
--
29
1.8.3.1
27
2.19.1
30
28
31
29
diff view generated by jsdifflib
1
The proper order for inactivating block nodes is that first the parents
1
Some block drivers have traditionally changed their node to read-only
2
get inactivated and then the children. If we do things in this order, we
2
mode without asking the user. This behaviour has been marked deprecated
3
can assert that we didn't accidentally leave a parent activated when one
3
since 2.11, expecting users to provide an explicit read-only=on option.
4
of its child nodes is inactive.
4
5
Now that we have auto-read-only=on, enable these drivers to make use of
6
the option.
7
8
This is the only use of bdrv_set_read_only(), so we can make it a bit
9
more specific and turn it into a bdrv_apply_auto_read_only() that is
10
more convenient for drivers to use.
5
11
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
14
---
9
block.c | 25 ++++++++++++++++++-------
15
include/block/block.h | 3 ++-
10
1 file changed, 18 insertions(+), 7 deletions(-)
16
block.c | 42 +++++++++++++++++++++++++++---------------
11
17
block/bochs.c | 17 ++++++-----------
18
block/cloop.c | 16 +++++-----------
19
block/dmg.c | 16 +++++-----------
20
block/rbd.c | 15 ++++-----------
21
block/vvfat.c | 10 ++--------
22
7 files changed, 51 insertions(+), 68 deletions(-)
23
24
diff --git a/include/block/block.h b/include/block/block.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
27
+++ b/include/block/block.h
28
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
29
bool bdrv_is_read_only(BlockDriverState *bs);
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
31
bool ignore_allow_rdw, Error **errp);
32
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
33
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
34
+ Error **errp);
35
bool bdrv_is_writable(BlockDriverState *bs);
36
bool bdrv_is_sg(BlockDriverState *bs);
37
bool bdrv_is_inserted(BlockDriverState *bs);
12
diff --git a/block.c b/block.c
38
diff --git a/block.c b/block.c
13
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
40
--- a/block.c
15
+++ b/block.c
41
+++ b/block.c
16
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_drained_end(BdrvChild *child)
42
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
17
bdrv_drained_end(bs);
43
return 0;
18
}
44
}
19
45
20
+static int bdrv_child_cb_inactivate(BdrvChild *child)
46
-/* TODO Remove (deprecated since 2.11)
21
+{
47
- * Block drivers are not supposed to automatically change bs->read_only.
22
+ BlockDriverState *bs = child->opaque;
48
- * Instead, they should just check whether they can provide what the user
23
+ assert(bs->open_flags & BDRV_O_INACTIVE);
49
- * explicitly requested and error out if read-write is requested, but they can
24
+ return 0;
50
- * only provide read-only access. */
25
+}
51
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
26
+
52
+/*
27
/*
53
+ * Called by a driver that can only provide a read-only image.
28
* Returns the options and flags that a temporary snapshot should get, based on
54
+ *
29
* the originally requested flags (the originally requested image will have
55
+ * Returns 0 if the node is already read-only or it could switch the node to
30
@@ -XXX,XX +XXX,XX @@ const BdrvChildRole child_file = {
56
+ * read-only because BDRV_O_AUTO_RDONLY is set.
31
.inherit_options = bdrv_inherited_options,
57
+ *
32
.drained_begin = bdrv_child_cb_drained_begin,
58
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
33
.drained_end = bdrv_child_cb_drained_end,
59
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
34
+ .inactivate = bdrv_child_cb_inactivate,
60
+ * is not NULL, it is used as the error message for the Error object.
35
};
61
+ */
36
62
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
37
/*
63
+ Error **errp)
38
@@ -XXX,XX +XXX,XX @@ const BdrvChildRole child_format = {
64
{
39
.inherit_options = bdrv_inherited_fmt_options,
65
int ret = 0;
40
.drained_begin = bdrv_child_cb_drained_begin,
66
41
.drained_end = bdrv_child_cb_drained_end,
67
- ret = bdrv_can_set_read_only(bs, read_only, false, errp);
42
+ .inactivate = bdrv_child_cb_inactivate,
68
- if (ret < 0) {
43
};
69
- return ret;
44
70
+ if (!(bs->open_flags & BDRV_O_RDWR)) {
45
static void bdrv_backing_attach(BdrvChild *c)
71
+ return 0;
46
@@ -XXX,XX +XXX,XX @@ const BdrvChildRole child_backing = {
72
+ }
47
.inherit_options = bdrv_backing_options,
73
+ if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
48
.drained_begin = bdrv_child_cb_drained_begin,
74
+ goto fail;
49
.drained_end = bdrv_child_cb_drained_end,
75
}
50
+ .inactivate = bdrv_child_cb_inactivate,
76
51
};
77
- bs->read_only = read_only;
52
78
-
53
static int bdrv_open_flags(BlockDriverState *bs, int flags)
79
- if (read_only) {
54
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
80
- bs->open_flags &= ~BDRV_O_RDWR;
55
}
81
- } else {
56
}
82
- bs->open_flags |= BDRV_O_RDWR;
57
83
+ ret = bdrv_can_set_read_only(bs, true, false, NULL);
58
- QLIST_FOREACH(child, &bs->children, next) {
84
+ if (ret < 0) {
59
- ret = bdrv_inactivate_recurse(child->bs, setting_flag);
85
+ goto fail;
86
}
87
88
+ bs->read_only = true;
89
+ bs->open_flags &= ~BDRV_O_RDWR;
90
+
91
return 0;
92
+
93
+fail:
94
+ error_setg(errp, "%s", errmsg ?: "Image is read-only");
95
+ return -EACCES;
96
}
97
98
void bdrv_get_full_backing_filename_from_filename(const char *backed,
99
diff --git a/block/bochs.c b/block/bochs.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/bochs.c
102
+++ b/block/bochs.c
103
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
104
struct bochs_header bochs;
105
int ret;
106
107
+ /* No write support yet */
108
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
109
+ if (ret < 0) {
110
+ return ret;
111
+ }
112
+
113
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
114
false, errp);
115
if (!bs->file) {
116
return -EINVAL;
117
}
118
119
- if (!bdrv_is_read_only(bs)) {
120
- error_report("Opening bochs images without an explicit read-only=on "
121
- "option is deprecated. Future versions will refuse to "
122
- "open the image instead of automatically marking the "
123
- "image read-only.");
124
- ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
60
- if (ret < 0) {
125
- if (ret < 0) {
61
- return ret;
126
- return ret;
62
- }
127
- }
63
- }
128
- }
64
-
129
-
65
if (setting_flag) {
130
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
66
bs->open_flags |= BDRV_O_INACTIVE;
131
if (ret < 0) {
67
132
return ret;
68
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
133
diff --git a/block/cloop.c b/block/cloop.c
69
}
134
index XXXXXXX..XXXXXXX 100644
135
--- a/block/cloop.c
136
+++ b/block/cloop.c
137
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
138
uint32_t offsets_size, max_compressed_block_size = 1, i;
139
int ret;
140
141
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
142
+ if (ret < 0) {
143
+ return ret;
144
+ }
145
+
146
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
147
false, errp);
148
if (!bs->file) {
149
return -EINVAL;
150
}
151
152
- if (!bdrv_is_read_only(bs)) {
153
- error_report("Opening cloop images without an explicit read-only=on "
154
- "option is deprecated. Future versions will refuse to "
155
- "open the image instead of automatically marking the "
156
- "image read-only.");
157
- ret = bdrv_set_read_only(bs, true, errp);
158
- if (ret < 0) {
159
- return ret;
160
- }
161
- }
162
-
163
/* read header */
164
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
165
if (ret < 0) {
166
diff --git a/block/dmg.c b/block/dmg.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/dmg.c
169
+++ b/block/dmg.c
170
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
171
int64_t offset;
172
int ret;
173
174
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
175
+ if (ret < 0) {
176
+ return ret;
177
+ }
178
+
179
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
180
false, errp);
181
if (!bs->file) {
182
return -EINVAL;
183
}
184
185
- if (!bdrv_is_read_only(bs)) {
186
- error_report("Opening dmg images without an explicit read-only=on "
187
- "option is deprecated. Future versions will refuse to "
188
- "open the image instead of automatically marking the "
189
- "image read-only.");
190
- ret = bdrv_set_read_only(bs, true, errp);
191
- if (ret < 0) {
192
- return ret;
193
- }
194
- }
195
-
196
block_module_load_one("dmg-bz2");
197
198
s->n_chunks = 0;
199
diff --git a/block/rbd.c b/block/rbd.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/rbd.c
202
+++ b/block/rbd.c
203
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
204
/* If we are using an rbd snapshot, we must be r/o, otherwise
205
* leave as-is */
206
if (s->snap != NULL) {
207
- if (!bdrv_is_read_only(bs)) {
208
- error_report("Opening rbd snapshots without an explicit "
209
- "read-only=on option is deprecated. Future versions "
210
- "will refuse to open the image instead of "
211
- "automatically marking the image read-only.");
212
- r = bdrv_set_read_only(bs, true, &local_err);
213
- if (r < 0) {
214
- rbd_close(s->image);
215
- error_propagate(errp, local_err);
216
- goto failed_open;
217
- }
218
+ r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
219
+ if (r < 0) {
220
+ rbd_close(s->image);
221
+ goto failed_open;
70
}
222
}
71
}
223
}
72
+
224
73
+ QLIST_FOREACH(child, &bs->children, next) {
225
diff --git a/block/vvfat.c b/block/vvfat.c
74
+ ret = bdrv_inactivate_recurse(child->bs, setting_flag);
226
index XXXXXXX..XXXXXXX 100644
75
+ if (ret < 0) {
227
--- a/block/vvfat.c
76
+ return ret;
228
+++ b/block/vvfat.c
77
+ }
229
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
78
+ }
230
"Unable to set VVFAT to 'rw' when drive is read-only");
79
+
231
goto fail;
80
return 0;
232
}
81
}
233
- } else if (!bdrv_is_read_only(bs)) {
82
234
- error_report("Opening non-rw vvfat images without an explicit "
235
- "read-only=on option is deprecated. Future versions "
236
- "will refuse to open the image instead of "
237
- "automatically marking the image read-only.");
238
- /* read only is the default for safety */
239
- ret = bdrv_set_read_only(bs, true, &local_err);
240
+ } else {
241
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
242
if (ret < 0) {
243
- error_propagate(errp, local_err);
244
goto fail;
245
}
246
}
83
--
247
--
84
1.8.3.1
248
2.19.1
85
249
86
250
diff view generated by jsdifflib
1
With image locking, permissions affect other qemu processes as well. We
1
If read-only=off, but auto-read-only=on is given, open a read-write NBD
2
want to be sure that the destination can run, so let's drop permissions
2
connection if the server provides a read-write export, but instead of
3
on the source when migration completes.
3
erroring out for read-only exports, just degrade to read-only.
4
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
7
---
8
block.c | 12 +++++++++++-
8
block/nbd-client.c | 10 +++++-----
9
block/block-backend.c | 25 +++++++++++++++++++++++++
9
1 file changed, 5 insertions(+), 5 deletions(-)
10
include/block/block_int.h | 7 ++++---
11
3 files changed, 40 insertions(+), 4 deletions(-)
12
10
13
diff --git a/block.c b/block.c
11
diff --git a/block/nbd-client.c b/block/nbd-client.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
13
--- a/block/nbd-client.c
16
+++ b/block.c
14
+++ b/block/nbd-client.c
17
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache_all(Error **errp)
15
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
18
static int bdrv_inactivate_recurse(BlockDriverState *bs,
16
logout("Failed to negotiate with the NBD server\n");
19
bool setting_flag)
17
return ret;
20
{
18
}
21
- BdrvChild *child;
19
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
22
+ BdrvChild *child, *parent;
20
- !bdrv_is_read_only(bs)) {
23
int ret;
21
- error_setg(errp,
24
22
- "request for write access conflicts with read-only export");
25
if (!setting_flag && bs->drv->bdrv_inactivate) {
23
- return -EACCES;
26
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
24
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
27
25
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
28
if (setting_flag) {
26
+ if (ret < 0) {
29
bs->open_flags |= BDRV_O_INACTIVE;
27
+ return ret;
30
+
31
+ QLIST_FOREACH(parent, &bs->parents, next_parent) {
32
+ if (parent->role->inactivate) {
33
+ ret = parent->role->inactivate(parent);
34
+ if (ret < 0) {
35
+ bs->open_flags &= ~BDRV_O_INACTIVE;
36
+ return ret;
37
+ }
38
+ }
39
+ }
28
+ }
40
}
29
}
41
return 0;
30
if (client->info.flags & NBD_FLAG_SEND_FUA) {
42
}
31
bs->supported_write_flags = BDRV_REQ_FUA;
43
diff --git a/block/block-backend.c b/block/block-backend.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/block/block-backend.c
46
+++ b/block/block-backend.c
47
@@ -XXX,XX +XXX,XX @@ static void blk_root_activate(BdrvChild *child, Error **errp)
48
}
49
}
50
51
+static int blk_root_inactivate(BdrvChild *child)
52
+{
53
+ BlockBackend *blk = child->opaque;
54
+
55
+ if (blk->disable_perm) {
56
+ return 0;
57
+ }
58
+
59
+ /* Only inactivate BlockBackends for guest devices (which are inactive at
60
+ * this point because the VM is stopped) and unattached monitor-owned
61
+ * BlockBackends. If there is still any other user like a block job, then
62
+ * we simply can't inactivate the image. */
63
+ if (!blk->dev && !blk->name[0]) {
64
+ return -EPERM;
65
+ }
66
+
67
+ blk->disable_perm = true;
68
+ if (blk->root) {
69
+ bdrv_child_try_set_perm(blk->root, 0, BLK_PERM_ALL, &error_abort);
70
+ }
71
+
72
+ return 0;
73
+}
74
+
75
static const BdrvChildRole child_root = {
76
.inherit_options = blk_root_inherit_options,
77
78
@@ -XXX,XX +XXX,XX @@ static const BdrvChildRole child_root = {
79
.drained_end = blk_root_drained_end,
80
81
.activate = blk_root_activate,
82
+ .inactivate = blk_root_inactivate,
83
};
84
85
/*
86
diff --git a/include/block/block_int.h b/include/block/block_int.h
87
index XXXXXXX..XXXXXXX 100644
88
--- a/include/block/block_int.h
89
+++ b/include/block/block_int.h
90
@@ -XXX,XX +XXX,XX @@ struct BdrvChildRole {
91
void (*drained_begin)(BdrvChild *child);
92
void (*drained_end)(BdrvChild *child);
93
94
- /* Notifies the parent that the child has been activated (e.g. when
95
- * migration is completing) and it can start requesting permissions and
96
- * doing I/O on it. */
97
+ /* Notifies the parent that the child has been activated/inactivated (e.g.
98
+ * when migration is completing) and it can start/stop requesting
99
+ * permissions and doing I/O on it. */
100
void (*activate)(BdrvChild *child, Error **errp);
101
+ int (*inactivate)(BdrvChild *child);
102
103
void (*attach)(BdrvChild *child);
104
void (*detach)(BdrvChild *child);
105
--
32
--
106
1.8.3.1
33
2.19.1
107
34
108
35
diff view generated by jsdifflib
1
Now that the block layer takes care to request a lot less permissions
1
If read-only=off, but auto-read-only=on is given, open the file
2
for inactive nodes, the special-casing in file-posix isn't necessary any
2
read-write if we have the permissions, but instead of erroring out for
3
more.
3
read-only files, just degrade to read-only.
4
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
7
---
8
block/file-posix.c | 33 ---------------------------------
8
block/file-posix.c | 19 ++++++++++++++++---
9
1 file changed, 33 deletions(-)
9
1 file changed, 16 insertions(+), 3 deletions(-)
10
10
11
diff --git a/block/file-posix.c b/block/file-posix.c
11
diff --git a/block/file-posix.c b/block/file-posix.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
13
--- a/block/file-posix.c
14
+++ b/block/file-posix.c
14
+++ b/block/file-posix.c
15
@@ -XXX,XX +XXX,XX @@ static void raw_abort_perm_update(BlockDriverState *bs)
15
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
16
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
16
17
}
17
s->fd = -1;
18
18
fd = qemu_open(filename, s->open_flags, 0644);
19
-static int raw_inactivate(BlockDriverState *bs)
19
- if (fd < 0) {
20
-{
20
- ret = -errno;
21
- int ret;
21
- error_setg_errno(errp, errno, "Could not open '%s'", filename);
22
- uint64_t perm = 0;
22
+ ret = fd < 0 ? -errno : 0;
23
- uint64_t shared = BLK_PERM_ALL;
23
+
24
-
24
+ if (ret == -EACCES || ret == -EROFS) {
25
- ret = raw_handle_perm_lock(bs, RAW_PL_PREPARE, perm, shared, NULL);
25
+ /* Try to degrade to read-only, but if it doesn't work, still use the
26
- if (ret) {
26
+ * normal error message. */
27
- return ret;
27
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
28
- }
28
+ bdrv_flags &= ~BDRV_O_RDWR;
29
- raw_handle_perm_lock(bs, RAW_PL_COMMIT, perm, shared, NULL);
29
+ raw_parse_flags(bdrv_flags, &s->open_flags);
30
- return 0;
30
+ assert(!(s->open_flags & O_CREAT));
31
-}
31
+ fd = qemu_open(filename, s->open_flags);
32
-
32
+ ret = fd < 0 ? -errno : 0;
33
-
33
+ }
34
-static void raw_invalidate_cache(BlockDriverState *bs, Error **errp)
34
+ }
35
-{
35
+
36
- BDRVRawState *s = bs->opaque;
36
+ if (ret < 0) {
37
- int ret;
37
+ error_setg_errno(errp, -ret, "Could not open '%s'", filename);
38
-
38
if (ret == -EROFS) {
39
- assert(!(bdrv_get_flags(bs) & BDRV_O_INACTIVE));
39
ret = -EACCES;
40
- ret = raw_handle_perm_lock(bs, RAW_PL_PREPARE, s->perm, s->shared_perm,
40
}
41
- errp);
42
- if (ret) {
43
- return;
44
- }
45
- raw_handle_perm_lock(bs, RAW_PL_COMMIT, s->perm, s->shared_perm, NULL);
46
-}
47
-
48
BlockDriver bdrv_file = {
49
.format_name = "file",
50
.protocol_name = "file",
51
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
52
.bdrv_get_info = raw_get_info,
53
.bdrv_get_allocated_file_size
54
= raw_get_allocated_file_size,
55
- .bdrv_inactivate = raw_inactivate,
56
- .bdrv_invalidate_cache = raw_invalidate_cache,
57
.bdrv_check_perm = raw_check_perm,
58
.bdrv_set_perm = raw_set_perm,
59
.bdrv_abort_perm_update = raw_abort_perm_update,
60
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
61
.bdrv_get_info = raw_get_info,
62
.bdrv_get_allocated_file_size
63
= raw_get_allocated_file_size,
64
- .bdrv_inactivate = raw_inactivate,
65
- .bdrv_invalidate_cache = raw_invalidate_cache,
66
.bdrv_check_perm = raw_check_perm,
67
.bdrv_set_perm = raw_set_perm,
68
.bdrv_abort_perm_update = raw_abort_perm_update,
69
--
41
--
70
1.8.3.1
42
2.19.1
71
43
72
44
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
If read-only=off, but auto-read-only=on is given, just degrade to
2
read-only.
2
3
3
Rather than store into a local variable, then copy to the struct
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
if the value is valid, then reporting errors otherwise, it is
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
simpler to just store into the struct and report errors if the
6
---
6
value is invalid. This however requires that the struct store
7
block/curl.c | 8 ++++----
7
a 64-bit number, rather than a narrower type. Likewise, setting
8
1 file changed, 4 insertions(+), 4 deletions(-)
8
a sane errno value in ret prior to the sequence of parsing and
9
jumping to out: on error makes it easier for the next patch to
10
add a chain of similar checks.
11
9
12
Signed-off-by: Eric Blake <eblake@redhat.com>
10
diff --git a/block/curl.c b/block/curl.c
13
Message-id: 20170429191419.30051-8-eblake@redhat.com
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
block/blkdebug.c | 16 ++++++----------
18
1 file changed, 6 insertions(+), 10 deletions(-)
19
20
diff --git a/block/blkdebug.c b/block/blkdebug.c
21
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
22
--- a/block/blkdebug.c
12
--- a/block/curl.c
23
+++ b/block/blkdebug.c
13
+++ b/block/curl.c
24
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
25
typedef struct BDRVBlkdebugState {
15
const char *protocol_delimiter;
26
int state;
27
int new_state;
28
- int align;
29
+ uint64_t align;
30
31
/* For blkdebug_refresh_filename() */
32
char *config_file;
33
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
34
BDRVBlkdebugState *s = bs->opaque;
35
QemuOpts *opts;
36
Error *local_err = NULL;
37
- uint64_t align;
38
int ret;
16
int ret;
39
17
40
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
18
-
41
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
19
- if (flags & BDRV_O_RDWR) {
42
bs->file->bs->supported_write_flags;
20
- error_setg(errp, "curl block device does not support writes");
43
bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
21
- return -EROFS;
44
bs->file->bs->supported_zero_flags;
22
+ ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
45
+ ret = -EINVAL;
23
+ errp);
46
24
+ if (ret < 0) {
47
/* Set request alignment */
25
+ return ret;
48
- align = qemu_opt_get_size(opts, "align", 0);
49
- if (align < INT_MAX && is_power_of_2(align)) {
50
- s->align = align;
51
- } else if (align) {
52
- error_setg(errp, "Invalid alignment");
53
- ret = -EINVAL;
54
+ s->align = qemu_opt_get_size(opts, "align", 0);
55
+ if (s->align && (s->align >= INT_MAX || !is_power_of_2(s->align))) {
56
+ error_setg(errp, "Cannot meet constraints with align %" PRIu64,
57
+ s->align);
58
goto out;
59
}
26
}
60
27
61
ret = 0;
28
if (!libcurl_initialized) {
62
- goto out;
63
-
64
out:
65
if (ret < 0) {
66
g_free(s->config_file);
67
--
29
--
68
1.8.3.1
30
2.19.1
69
31
70
32
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
If read-only=off, but auto-read-only=on is given, open the file
2
read-write if we have the permissions, but instead of erroring out for
3
read-only files, just degrade to read-only.
2
4
3
In order to test the effects of artificial geometry constraints
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
on operations like write zero or discard, we first need blkdebug
6
Reviewed-by: Niels de Vos <ndevos@redhat.com>
5
to manage these actions. It also allows us to inject errors on
7
---
6
those operations, just like we can for read/write/flush.
8
block/gluster.c | 12 ++++++++++--
9
1 file changed, 10 insertions(+), 2 deletions(-)
7
10
8
We can also test the contract promised by the block layer; namely,
11
diff --git a/block/gluster.c b/block/gluster.c
9
if a device has specified limits on alignment or maximum size,
10
then those limits must be obeyed (for now, the blkdebug driver
11
merely inherits limits from whatever it is wrapping, but the next
12
patch will further enhance it to allow specific limit overrides).
13
14
This patch intentionally refuses to service requests smaller than
15
the requested alignments; this is because an upcoming patch adds
16
a qemu-iotest to prove that the block layer is correctly handling
17
fragmentation, but the test only works if there is a way to tell
18
the difference at artificial alignment boundaries when blkdebug is
19
using a larger-than-default alignment. If we let the blkdebug
20
layer always defer to the underlying layer, which potentially has
21
a smaller granularity, the iotest will be thwarted.
22
23
Tested by setting up an NBD server with export 'foo', then invoking:
24
$ ./qemu-io
25
qemu-io> open -o driver=blkdebug blkdebug::nbd://localhost:10809/foo
26
qemu-io> d 0 15M
27
qemu-io> w -z 0 15M
28
29
Pre-patch, the server never sees the discard (it was silently
30
eaten by the block layer); post-patch it is passed across the
31
wire. Likewise, pre-patch the write is always passed with
32
NBD_WRITE (with 15M of zeroes on the wire), while post-patch
33
it can utilize NBD_WRITE_ZEROES (for less traffic).
34
35
Signed-off-by: Eric Blake <eblake@redhat.com>
36
Reviewed-by: Max Reitz <mreitz@redhat.com>
37
Message-id: 20170429191419.30051-7-eblake@redhat.com
38
Signed-off-by: Max Reitz <mreitz@redhat.com>
39
---
40
block/blkdebug.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
41
1 file changed, 74 insertions(+)
42
43
diff --git a/block/blkdebug.c b/block/blkdebug.c
44
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
45
--- a/block/blkdebug.c
13
--- a/block/gluster.c
46
+++ b/block/blkdebug.c
14
+++ b/block/gluster.c
47
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
48
/*
16
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
49
* Block protocol for I/O error injection
17
50
*
18
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
51
+ * Copyright (C) 2016-2017 Red Hat, Inc.
19
- if (!s->fd) {
52
* Copyright (c) 2010 Kevin Wolf <kwolf@redhat.com>
20
- ret = -errno;
53
*
21
+ ret = s->fd ? 0 : -errno;
54
* Permission is hereby granted, free of charge, to any person obtaining a copy
22
+
55
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
23
+ if (ret == -EACCES || ret == -EROFS) {
56
goto out;
24
+ /* Try to degrade to read-only, but if it doesn't work, still use the
25
+ * normal error message. */
26
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
27
+ open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
28
+ s->fd = glfs_open(s->glfs, gconf->path, open_flags);
29
+ ret = s->fd ? 0 : -errno;
30
+ }
57
}
31
}
58
32
59
+ bs->supported_write_flags = BDRV_REQ_FUA &
33
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
60
+ bs->file->bs->supported_write_flags;
61
+ bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
62
+ bs->file->bs->supported_zero_flags;
63
+
64
/* Set request alignment */
65
align = qemu_opt_get_size(opts, "align", 0);
66
if (align < INT_MAX && is_power_of_2(align)) {
67
@@ -XXX,XX +XXX,XX @@ static int blkdebug_co_flush(BlockDriverState *bs)
68
return bdrv_co_flush(bs->file->bs);
69
}
70
71
+static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
72
+ int64_t offset, int count,
73
+ BdrvRequestFlags flags)
74
+{
75
+ uint32_t align = MAX(bs->bl.request_alignment,
76
+ bs->bl.pwrite_zeroes_alignment);
77
+ int err;
78
+
79
+ /* Only pass through requests that are larger than requested
80
+ * preferred alignment (so that we test the fallback to writes on
81
+ * unaligned portions), and check that the block layer never hands
82
+ * us anything unaligned that crosses an alignment boundary. */
83
+ if (count < align) {
84
+ assert(QEMU_IS_ALIGNED(offset, align) ||
85
+ QEMU_IS_ALIGNED(offset + count, align) ||
86
+ DIV_ROUND_UP(offset, align) ==
87
+ DIV_ROUND_UP(offset + count, align));
88
+ return -ENOTSUP;
89
+ }
90
+ assert(QEMU_IS_ALIGNED(offset, align));
91
+ assert(QEMU_IS_ALIGNED(count, align));
92
+ if (bs->bl.max_pwrite_zeroes) {
93
+ assert(count <= bs->bl.max_pwrite_zeroes);
94
+ }
95
+
96
+ err = rule_check(bs, offset, count);
97
+ if (err) {
98
+ return err;
99
+ }
100
+
101
+ return bdrv_co_pwrite_zeroes(bs->file, offset, count, flags);
102
+}
103
+
104
+static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
105
+ int64_t offset, int count)
106
+{
107
+ uint32_t align = bs->bl.pdiscard_alignment;
108
+ int err;
109
+
110
+ /* Only pass through requests that are larger than requested
111
+ * minimum alignment, and ensure that unaligned requests do not
112
+ * cross optimum discard boundaries. */
113
+ if (count < bs->bl.request_alignment) {
114
+ assert(QEMU_IS_ALIGNED(offset, align) ||
115
+ QEMU_IS_ALIGNED(offset + count, align) ||
116
+ DIV_ROUND_UP(offset, align) ==
117
+ DIV_ROUND_UP(offset + count, align));
118
+ return -ENOTSUP;
119
+ }
120
+ assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
121
+ assert(QEMU_IS_ALIGNED(count, bs->bl.request_alignment));
122
+ if (align && count >= align) {
123
+ assert(QEMU_IS_ALIGNED(offset, align));
124
+ assert(QEMU_IS_ALIGNED(count, align));
125
+ }
126
+ if (bs->bl.max_pdiscard) {
127
+ assert(count <= bs->bl.max_pdiscard);
128
+ }
129
+
130
+ err = rule_check(bs, offset, count);
131
+ if (err) {
132
+ return err;
133
+ }
134
+
135
+ return bdrv_co_pdiscard(bs->file->bs, offset, count);
136
+}
137
138
static void blkdebug_close(BlockDriverState *bs)
139
{
140
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
141
.bdrv_co_preadv = blkdebug_co_preadv,
142
.bdrv_co_pwritev = blkdebug_co_pwritev,
143
.bdrv_co_flush_to_disk = blkdebug_co_flush,
144
+ .bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
145
+ .bdrv_co_pdiscard = blkdebug_co_pdiscard,
146
147
.bdrv_debug_event = blkdebug_debug_event,
148
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
149
--
34
--
150
1.8.3.1
35
2.19.1
151
36
152
37
diff view generated by jsdifflib
1
Migration code activates all block driver nodes on the destination when
1
If read-only=off, but auto-read-only=on is given, open the volume
2
the migration completes. It does so by calling
2
read-write if we have the permissions, but instead of erroring out for
3
bdrv_invalidate_cache_all() and blk_resume_after_migration(). There is
3
read-only volumes, just degrade to read-only.
4
one code path for precopy and one for postcopy migration, resulting in
5
four function calls, which used to have three different failure modes.
6
7
This patch unifies the behaviour so that failure to activate all block
8
nodes is non-fatal, but the error message is logged and the VM isn't
9
automatically started. 'cont' will retry activating the block nodes.
10
4
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
13
---
7
---
14
migration/migration.c | 16 +++++-----------
8
block/iscsi.c | 8 +++++---
15
migration/savevm.c | 12 +++++-------
9
1 file changed, 5 insertions(+), 3 deletions(-)
16
qmp.c | 18 +++++++++---------
17
3 files changed, 19 insertions(+), 27 deletions(-)
18
10
19
diff --git a/migration/migration.c b/migration/migration.c
11
diff --git a/block/iscsi.c b/block/iscsi.c
20
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
21
--- a/migration/migration.c
13
--- a/block/iscsi.c
22
+++ b/migration/migration.c
14
+++ b/block/iscsi.c
23
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_bh(void *opaque)
15
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
24
Error *local_err = NULL;
16
/* Check the write protect flag of the LUN if we want to write */
25
MigrationIncomingState *mis = opaque;
17
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
26
18
iscsilun->write_protected) {
27
- /* Make sure all file formats flush their mutable metadata */
19
- error_setg(errp, "Cannot open a write protected LUN as read-write");
28
+ /* Make sure all file formats flush their mutable metadata.
20
- ret = -EACCES;
29
+ * If we get an error here, just don't restart the VM yet. */
21
- goto out;
30
bdrv_invalidate_cache_all(&local_err);
22
+ ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
31
- if (local_err) {
23
+ if (ret < 0) {
32
- migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
24
+ goto out;
33
- MIGRATION_STATUS_FAILED);
25
+ }
34
- error_report_err(local_err);
26
+ flags &= ~BDRV_O_RDWR;
35
- migrate_decompress_threads_join();
36
- exit(EXIT_FAILURE);
37
+ if (!local_err) {
38
+ blk_resume_after_migration(&local_err);
39
}
27
}
40
-
28
41
- /* If we get an error here, just don't restart the VM yet. */
29
iscsi_readcapacity_sync(iscsilun, &local_err);
42
- blk_resume_after_migration(&local_err);
43
if (local_err) {
44
- error_free(local_err);
45
+ error_report_err(local_err);
46
local_err = NULL;
47
autostart = false;
48
}
49
diff --git a/migration/savevm.c b/migration/savevm.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/migration/savevm.c
52
+++ b/migration/savevm.c
53
@@ -XXX,XX +XXX,XX @@ static void loadvm_postcopy_handle_run_bh(void *opaque)
54
55
qemu_announce_self();
56
57
- /* Make sure all file formats flush their mutable metadata */
58
+ /* Make sure all file formats flush their mutable metadata.
59
+ * If we get an error here, just don't restart the VM yet. */
60
bdrv_invalidate_cache_all(&local_err);
61
- if (local_err) {
62
- error_report_err(local_err);
63
+ if (!local_err) {
64
+ blk_resume_after_migration(&local_err);
65
}
66
-
67
- /* If we get an error here, just don't restart the VM yet. */
68
- blk_resume_after_migration(&local_err);
69
if (local_err) {
70
- error_free(local_err);
71
+ error_report_err(local_err);
72
local_err = NULL;
73
autostart = false;
74
}
75
diff --git a/qmp.c b/qmp.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/qmp.c
78
+++ b/qmp.c
79
@@ -XXX,XX +XXX,XX @@ void qmp_cont(Error **errp)
80
}
81
82
/* Continuing after completed migration. Images have been inactivated to
83
- * allow the destination to take control. Need to get control back now. */
84
- if (runstate_check(RUN_STATE_FINISH_MIGRATE) ||
85
- runstate_check(RUN_STATE_POSTMIGRATE))
86
- {
87
- bdrv_invalidate_cache_all(&local_err);
88
- if (local_err) {
89
- error_propagate(errp, local_err);
90
- return;
91
- }
92
+ * allow the destination to take control. Need to get control back now.
93
+ *
94
+ * If there are no inactive block nodes (e.g. because the VM was just
95
+ * paused rather than completing a migration), bdrv_inactivate_all() simply
96
+ * doesn't do anything. */
97
+ bdrv_invalidate_cache_all(&local_err);
98
+ if (local_err) {
99
+ error_propagate(errp, local_err);
100
+ return;
101
}
102
103
blk_resume_after_migration(&local_err);
104
--
30
--
105
1.8.3.1
31
2.19.1
106
32
107
33
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
While we want machine interfaces like -blockdev and QMP blockdev-add to
2
add as little auto-detection as possible so that management tools are
3
explicit about their needs, -drive is a convenience option for human
4
users. Enabling auto-read-only=on by default there enables users to use
5
read-only images for read-only guest devices without having to specify
6
read-only=on explicitly. If they try to attach the image to a read-write
7
device, they will still get an error message.
2
8
3
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1447551
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
5
If one tries to issue a block_resize while a guest is busy
6
accessing the disk, it is possible that qemu may deadlock
7
when invoking aio_poll from both the main loop and the iothread.
8
9
Replace another instance of bdrv_drain_all that doesn't
10
quite belong.
11
12
Cc: qemu-stable@nongnu.org
13
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
14
Signed-off-by: John Snow <jsnow@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
11
---
19
blockdev.c | 5 ++---
12
blockdev.c | 1 +
20
1 file changed, 2 insertions(+), 3 deletions(-)
13
1 file changed, 1 insertion(+)
21
14
22
diff --git a/blockdev.c b/blockdev.c
15
diff --git a/blockdev.c b/blockdev.c
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/blockdev.c
17
--- a/blockdev.c
25
+++ b/blockdev.c
18
+++ b/blockdev.c
26
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
19
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
27
goto out;
20
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
28
}
21
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
29
22
read_only ? "on" : "off");
30
- /* complete all in-flight operations before resizing the device */
23
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
31
- bdrv_drain_all();
24
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
32
-
25
33
+ bdrv_drained_begin(bs);
26
if (runstate_check(RUN_STATE_INMIGRATE)) {
34
ret = blk_truncate(blk, size, errp);
35
+ bdrv_drained_end(bs);
36
37
out:
38
blk_unref(blk);
39
--
27
--
40
1.8.3.1
28
2.19.1
41
29
42
30
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
4
tests/qemu-iotests/232 | 147 +++++++++++++++++++++++++++++++++++++
5
tests/qemu-iotests/232.out | 59 +++++++++++++++
6
tests/qemu-iotests/group | 1 +
7
3 files changed, 207 insertions(+)
8
create mode 100755 tests/qemu-iotests/232
9
create mode 100644 tests/qemu-iotests/232.out
2
10
3
Signed-off-by: Fam Zheng <famz@redhat.com>
11
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
tests/qemu-iotests/153 | 233 +++++++++++++++++++++++++++
7
tests/qemu-iotests/153.out | 390 +++++++++++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/group | 1 +
9
3 files changed, 624 insertions(+)
10
create mode 100755 tests/qemu-iotests/153
11
create mode 100644 tests/qemu-iotests/153.out
12
13
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
14
new file mode 100755
12
new file mode 100755
15
index XXXXXXX..XXXXXXX
13
index XXXXXXX..XXXXXXX
16
--- /dev/null
14
--- /dev/null
17
+++ b/tests/qemu-iotests/153
15
+++ b/tests/qemu-iotests/232
18
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
19
+#!/bin/bash
17
+#!/bin/bash
20
+#
18
+#
21
+# Test image locking
19
+# Test for auto-read-only
22
+#
20
+#
23
+# Copyright 2016, 2017 Red Hat, Inc.
21
+# Copyright (C) 2018 Red Hat, Inc.
24
+#
22
+#
25
+# This program is free software; you can redistribute it and/or modify
23
+# This program is free software; you can redistribute it and/or modify
26
+# it under the terms of the GNU General Public License as published by
24
+# it under the terms of the GNU General Public License as published by
27
+# the Free Software Foundation; either version 2 of the License, or
25
+# the Free Software Foundation; either version 2 of the License, or
28
+# (at your option) any later version.
26
+# (at your option) any later version.
...
...
35
+# You should have received a copy of the GNU General Public License
33
+# You should have received a copy of the GNU General Public License
36
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
34
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
37
+#
35
+#
38
+
36
+
39
+# creator
37
+# creator
40
+owner=famz@redhat.com
38
+owner=kwolf@redhat.com
41
+
39
+
42
+seq="$(basename $0)"
40
+seq=`basename $0`
43
+echo "QA output created by $seq"
41
+echo "QA output created by $seq"
44
+
42
+
45
+here="$PWD"
43
+here=`pwd`
46
+tmp=/tmp/$$
47
+status=1    # failure is the default!
44
+status=1    # failure is the default!
48
+
45
+
49
+_cleanup()
46
+_cleanup()
50
+{
47
+{
51
+ _cleanup_test_img
48
+ _cleanup_test_img
52
+ rm -f "${TEST_IMG}.base"
49
+ rm -f $TEST_IMG.snap
53
+ rm -f "${TEST_IMG}.convert"
54
+ rm -f "${TEST_IMG}.a"
55
+ rm -f "${TEST_IMG}.b"
56
+ rm -f "${TEST_IMG}.lnk"
57
+}
50
+}
58
+trap "_cleanup; exit \$status" 0 1 2 3 15
51
+trap "_cleanup; exit \$status" 0 1 2 3 15
59
+
52
+
60
+# get standard environment, filters and checks
53
+# get standard environment, filters and checks
61
+. ./common.rc
54
+. ./common.rc
62
+. ./common.filter
55
+. ./common.filter
63
+. ./common.qemu
56
+
64
+
57
+_supported_fmt generic
65
+size=32M
66
+
67
+_check_ofd()
68
+{
69
+ _make_test_img $size >/dev/null
70
+ if $QEMU_IMG_PROG info --image-opts "driver=file,locking=on,filename=$TEST_IMG" 2>&1 |
71
+ grep -q 'falling back to POSIX file'; then
72
+ return 1
73
+ else
74
+ return 0
75
+ fi
76
+}
77
+
78
+_check_ofd || _notrun "OFD lock not available"
79
+
80
+_supported_fmt qcow2
81
+_supported_proto file
58
+_supported_proto file
82
+_supported_os Linux
59
+_supported_os Linux
83
+
60
+
84
+_run_cmd()
61
+function do_run_qemu()
85
+{
62
+{
86
+ echo
63
+ echo Testing: "$@"
87
+ (echo "$@"; "$@" 2>&1 1>/dev/null) | _filter_testdir
88
+}
89
+
90
+function _do_run_qemu()
91
+{
92
+ (
64
+ (
93
+ if ! test -t 0; then
65
+ if ! test -t 0; then
94
+ while read cmd; do
66
+ while read cmd; do
95
+ echo $cmd
67
+ echo $cmd
96
+ done
68
+ done
97
+ fi
69
+ fi
98
+ echo quit
70
+ echo quit
99
+ ) | $QEMU -nographic -monitor stdio -serial none "$@" 1>/dev/null
71
+ ) | $QEMU -nographic -monitor stdio -nodefaults "$@"
100
+}
101
+
102
+function _run_qemu_with_images()
103
+{
104
+ _do_run_qemu \
105
+ $(for i in $@; do echo "-drive if=none,file=$i"; done) 2>&1 \
106
+ | _filter_testdir | _filter_qemu
107
+}
108
+
109
+echo "== readonly=off,force-share=on should be rejected =="
110
+_run_qemu_with_images null-co://,readonly=off,force-share=on
111
+
112
+for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
113
+ echo
72
+ echo
114
+ echo "== Creating base image =="
73
+}
115
+ TEST_IMG="${TEST_IMG}.base" _make_test_img $size
74
+
116
+
75
+function run_qemu()
117
+ echo
76
+{
118
+ echo "== Creating test image =="
77
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
119
+ $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" -b ${TEST_IMG}.base | _filter_img_create
78
+ _filter_generated_node_ids | _filter_imgfmt
120
+
79
+}
121
+ echo
80
+
122
+ echo "== Launching QEMU, opts: '$opts1' =="
81
+function run_qemu_info_block()
123
+ _launch_qemu -drive file="${TEST_IMG}",if=none,$opts1
82
+{
124
+ h=$QEMU_HANDLE
83
+ echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
125
+
84
+}
126
+ for opts2 in "" "read-only=on" "read-only=on,force-share=on"; do
85
+
127
+ echo
86
+size=128M
128
+ echo "== Launching another QEMU, opts: '$opts2' =="
87
+
129
+ echo "quit" | \
88
+_make_test_img $size
130
+ $QEMU -nographic -monitor stdio \
89
+
131
+ -drive file="${TEST_IMG}",if=none,$opts2 2>&1 1>/dev/null | \
90
+echo
132
+ _filter_testdir | _filter_qemu
91
+echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
133
+ done
92
+echo
134
+
93
+
135
+ for L in "" "-U"; do
94
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
136
+
95
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
137
+ echo
96
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
138
+ echo "== Running utility commands $L =="
97
+echo
139
+ _run_cmd $QEMU_IO $L -c "read 0 512" "${TEST_IMG}"
98
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
140
+ _run_cmd $QEMU_IO $L -r -c "read 0 512" "${TEST_IMG}"
99
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
141
+ _run_cmd $QEMU_IO -c "open $L ${TEST_IMG}" -c "read 0 512"
100
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
142
+ _run_cmd $QEMU_IO -c "open -r $L ${TEST_IMG}" -c "read 0 512"
101
+echo
143
+ _run_cmd $QEMU_IMG info $L "${TEST_IMG}"
102
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
144
+ _run_cmd $QEMU_IMG check $L "${TEST_IMG}"
103
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
145
+ _run_cmd $QEMU_IMG compare $L "${TEST_IMG}" "${TEST_IMG}"
104
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
146
+ _run_cmd $QEMU_IMG map $L "${TEST_IMG}"
105
+
147
+ _run_cmd $QEMU_IMG amend -o "" $L "${TEST_IMG}"
106
+echo
148
+ _run_cmd $QEMU_IMG commit $L "${TEST_IMG}"
107
+echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
149
+ _run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size
108
+echo
150
+ _run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base"
109
+
151
+ _run_cmd $QEMU_IMG snapshot -l $L "${TEST_IMG}"
110
+chmod a-w $TEST_IMG
152
+ _run_cmd $QEMU_IMG convert $L "${TEST_IMG}" "${TEST_IMG}.convert"
111
+
153
+ _run_cmd $QEMU_IMG dd $L if="${TEST_IMG}" of="${TEST_IMG}.convert" bs=512 count=1
112
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
154
+ _run_cmd $QEMU_IMG bench $L -c 1 "${TEST_IMG}"
113
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
155
+ _run_cmd $QEMU_IMG bench $L -w -c 1 "${TEST_IMG}"
114
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
156
+ done
115
+echo
157
+ _send_qemu_cmd $h "{ 'execute': 'quit', }" ""
116
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
158
+ echo
117
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
159
+ echo "Round done"
118
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
160
+ _cleanup_qemu
119
+echo
161
+done
120
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
162
+
121
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
163
+for opt1 in $test_opts; do
122
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
164
+ for opt2 in $test_opts; do
123
+
165
+ echo
124
+echo
166
+ echo "== Two devices with the same image ($opt1 - $opt2) =="
125
+echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
167
+ _run_qemu_with_images "${TEST_IMG},$opt1" "${TEST_IMG},$opt2"
126
+echo
168
+ done
127
+
169
+done
128
+chmod a+w $TEST_IMG
170
+
129
+
171
+echo "== Creating ${TEST_IMG}.[abc] ==" | _filter_testdir
130
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
172
+(
131
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
173
+ $QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}"
132
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
174
+ $QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}"
133
+echo
175
+ $QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b"
134
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
176
+) | _filter_img_create
135
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
177
+
136
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
178
+echo
137
+echo
179
+echo "== Two devices sharing the same file in backing chain =="
138
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
180
+_run_qemu_with_images "${TEST_IMG}.a" "${TEST_IMG}.b"
139
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
181
+_run_qemu_with_images "${TEST_IMG}.a" "${TEST_IMG}.c"
140
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
182
+
141
+
183
+echo
142
+echo
184
+echo "== Backing image also as an active device =="
143
+echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
185
+_run_qemu_with_images "${TEST_IMG}.a" "${TEST_IMG}"
144
+echo
186
+
145
+
187
+echo
146
+chmod a-w $TEST_IMG
188
+echo "== Backing image also as an active device (ro) =="
147
+
189
+_run_qemu_with_images "${TEST_IMG}.a" "${TEST_IMG},readonly=on"
148
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
190
+
149
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
191
+echo
150
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
192
+echo "== Symbolic link =="
151
+echo
193
+rm -f "${TEST_IMG}.lnk" &>/dev/null
152
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
194
+ln -s ${TEST_IMG} "${TEST_IMG}.lnk" || echo "Failed to create link"
153
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
195
+_run_qemu_with_images "${TEST_IMG}.lnk" "${TEST_IMG}"
154
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
196
+
155
+echo
197
+echo
156
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
198
+echo "== Closing an image should unlock it =="
157
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
199
+_launch_qemu
158
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
200
+
201
+_send_qemu_cmd $QEMU_HANDLE \
202
+ "{ 'execute': 'qmp_capabilities' }" \
203
+ 'return'
204
+
205
+echo "Adding drive"
206
+_send_qemu_cmd $QEMU_HANDLE \
207
+ "{ 'execute': 'human-monitor-command',
208
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=${TEST_IMG}' } }" \
209
+ ""
210
+
211
+_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
212
+
213
+echo "Closing drive"
214
+_send_qemu_cmd $QEMU_HANDLE \
215
+ "{ 'execute': 'human-monitor-command',
216
+ 'arguments': { 'command-line': 'drive_del d0' } }" \
217
+ ""
218
+
219
+_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
220
+
221
+echo "Adding two and closing one"
222
+for d in d0 d1; do
223
+ _send_qemu_cmd $QEMU_HANDLE \
224
+ "{ 'execute': 'human-monitor-command',
225
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=$d,file=${TEST_IMG},readonly=on' } }" \
226
+ ""
227
+done
228
+
229
+_run_cmd $QEMU_IMG info "${TEST_IMG}"
230
+
231
+_send_qemu_cmd $QEMU_HANDLE \
232
+ "{ 'execute': 'human-monitor-command',
233
+ 'arguments': { 'command-line': 'drive_del d0' } }" \
234
+ ""
235
+
236
+_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
237
+
238
+echo "Closing the other"
239
+_send_qemu_cmd $QEMU_HANDLE \
240
+ "{ 'execute': 'human-monitor-command',
241
+ 'arguments': { 'command-line': 'drive_del d1' } }" \
242
+ ""
243
+
244
+_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
245
+
246
+_cleanup_qemu
247
+
159
+
248
+# success, all done
160
+# success, all done
249
+echo "*** done"
161
+echo "*** done"
250
+rm -f $seq.full
162
+rm -f $seq.full
251
+status=0
163
+status=0
252
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
164
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
253
new file mode 100644
165
new file mode 100644
254
index XXXXXXX..XXXXXXX
166
index XXXXXXX..XXXXXXX
255
--- /dev/null
167
--- /dev/null
256
+++ b/tests/qemu-iotests/153.out
168
+++ b/tests/qemu-iotests/232.out
257
@@ -XXX,XX +XXX,XX @@
169
@@ -XXX,XX +XXX,XX @@
258
+QA output created by 153
170
+QA output created by 232
259
+== readonly=off,force-share=on should be rejected ==
171
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
260
+QEMU_PROG: -drive if=none,file=null-co://,readonly=off,force-share=on: force-share=on can only be used with read-only images
172
+
261
+
173
+=== -drive with read-write image: read-only/auto-read-only combinations ===
262
+== Creating base image ==
174
+
263
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432
175
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
264
+
176
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
265
+== Creating test image ==
177
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
266
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base
178
+
267
+
179
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
268
+== Launching QEMU, opts: '' ==
180
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
269
+
181
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
270
+== Launching another QEMU, opts: '' ==
182
+
271
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock
183
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
272
+Is another process using the image?
184
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
273
+
185
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
274
+== Launching another QEMU, opts: 'read-only=on' ==
186
+
275
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,read-only=on: Failed to get shared "write" lock
187
+=== -drive with read-only image: read-only/auto-read-only combinations ===
276
+Is another process using the image?
188
+
277
+
189
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
278
+== Launching another QEMU, opts: 'read-only=on,force-share=on' ==
190
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
279
+
191
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
280
+== Running utility commands ==
192
+
281
+
193
+QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
282
+_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
194
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
283
+can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
195
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
284
+Is another process using the image?
196
+
285
+
197
+QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
286
+_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
198
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
287
+can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
199
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
288
+Is another process using the image?
200
+
289
+
201
+=== -blockdev with read-write image: read-only/auto-read-only combinations ===
290
+_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
202
+
291
+can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
203
+node0: TEST_DIR/t.IMGFMT (file, read-only)
292
+Is another process using the image?
204
+node0: TEST_DIR/t.IMGFMT (file, read-only)
293
+
205
+node0: TEST_DIR/t.IMGFMT (file, read-only)
294
+_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
206
+
295
+can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
207
+node0: TEST_DIR/t.IMGFMT (file)
296
+Is another process using the image?
208
+node0: TEST_DIR/t.IMGFMT (file)
297
+
209
+node0: TEST_DIR/t.IMGFMT (file)
298
+_qemu_img_wrapper info TEST_DIR/t.qcow2
210
+
299
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
211
+node0: TEST_DIR/t.IMGFMT (file)
300
+Is another process using the image?
212
+node0: TEST_DIR/t.IMGFMT (file)
301
+
213
+node0: TEST_DIR/t.IMGFMT (file)
302
+_qemu_img_wrapper check TEST_DIR/t.qcow2
214
+
303
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
215
+=== -blockdev with read-only image: read-only/auto-read-only combinations ===
304
+Is another process using the image?
216
+
305
+
217
+node0: TEST_DIR/t.IMGFMT (file, read-only)
306
+_qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
218
+node0: TEST_DIR/t.IMGFMT (file, read-only)
307
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
219
+node0: TEST_DIR/t.IMGFMT (file, read-only)
308
+Is another process using the image?
220
+
309
+
221
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
310
+_qemu_img_wrapper map TEST_DIR/t.qcow2
222
+node0: TEST_DIR/t.IMGFMT (file, read-only)
311
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
223
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
312
+Is another process using the image?
224
+
313
+
225
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
314
+_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
226
+node0: TEST_DIR/t.IMGFMT (file, read-only)
315
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
227
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
316
+Is another process using the image?
317
+
318
+_qemu_img_wrapper commit TEST_DIR/t.qcow2
319
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
320
+Is another process using the image?
321
+
322
+_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
323
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
324
+Is another process using the image?
325
+
326
+_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
327
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
328
+Is another process using the image?
329
+
330
+_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
331
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
332
+Is another process using the image?
333
+
334
+_qemu_img_wrapper convert TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
335
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
336
+Is another process using the image?
337
+
338
+_qemu_img_wrapper dd if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
339
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
340
+Is another process using the image?
341
+
342
+_qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
343
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
344
+Is another process using the image?
345
+
346
+_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
347
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
348
+Is another process using the image?
349
+
350
+== Running utility commands -U ==
351
+
352
+_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
353
+can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
354
+
355
+_qemu_io_wrapper -U -r -c read 0 512 TEST_DIR/t.qcow2
356
+
357
+_qemu_io_wrapper -c open -U TEST_DIR/t.qcow2 -c read 0 512
358
+can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
359
+
360
+_qemu_io_wrapper -c open -r -U TEST_DIR/t.qcow2 -c read 0 512
361
+
362
+_qemu_img_wrapper info -U TEST_DIR/t.qcow2
363
+
364
+_qemu_img_wrapper check -U TEST_DIR/t.qcow2
365
+
366
+_qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
367
+
368
+_qemu_img_wrapper map -U TEST_DIR/t.qcow2
369
+
370
+_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
371
+qemu-img: unrecognized option '-U'
372
+Try 'qemu-img --help' for more information
373
+
374
+_qemu_img_wrapper commit -U TEST_DIR/t.qcow2
375
+qemu-img: unrecognized option '-U'
376
+Try 'qemu-img --help' for more information
377
+
378
+_qemu_img_wrapper resize -U TEST_DIR/t.qcow2 32M
379
+qemu-img: unrecognized option '-U'
380
+Try 'qemu-img --help' for more information
381
+
382
+_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
383
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
384
+Is another process using the image?
385
+
386
+_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
387
+
388
+_qemu_img_wrapper convert -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
389
+
390
+_qemu_img_wrapper dd -U if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
391
+
392
+_qemu_img_wrapper bench -U -c 1 TEST_DIR/t.qcow2
393
+
394
+_qemu_img_wrapper bench -U -w -c 1 TEST_DIR/t.qcow2
395
+qemu-img: Could not open 'TEST_DIR/t.qcow2': force-share=on can only be used with read-only images
396
+
397
+Round done
398
+
399
+== Creating base image ==
400
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432
401
+
402
+== Creating test image ==
403
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base
404
+
405
+== Launching QEMU, opts: 'read-only=on' ==
406
+
407
+== Launching another QEMU, opts: '' ==
408
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock
409
+Is another process using the image?
410
+
411
+== Launching another QEMU, opts: 'read-only=on' ==
412
+
413
+== Launching another QEMU, opts: 'read-only=on,force-share=on' ==
414
+
415
+== Running utility commands ==
416
+
417
+_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
418
+can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
419
+Is another process using the image?
420
+
421
+_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
422
+
423
+_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
424
+can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
425
+Is another process using the image?
426
+
427
+_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
428
+
429
+_qemu_img_wrapper info TEST_DIR/t.qcow2
430
+
431
+_qemu_img_wrapper check TEST_DIR/t.qcow2
432
+
433
+_qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
434
+
435
+_qemu_img_wrapper map TEST_DIR/t.qcow2
436
+
437
+_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
438
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
439
+Is another process using the image?
440
+
441
+_qemu_img_wrapper commit TEST_DIR/t.qcow2
442
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
443
+Is another process using the image?
444
+
445
+_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
446
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
447
+Is another process using the image?
448
+
449
+_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
450
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
451
+Is another process using the image?
452
+
453
+_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
454
+
455
+_qemu_img_wrapper convert TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
456
+
457
+_qemu_img_wrapper dd if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
458
+
459
+_qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
460
+
461
+_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
462
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
463
+Is another process using the image?
464
+
465
+== Running utility commands -U ==
466
+
467
+_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
468
+can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
469
+
470
+_qemu_io_wrapper -U -r -c read 0 512 TEST_DIR/t.qcow2
471
+
472
+_qemu_io_wrapper -c open -U TEST_DIR/t.qcow2 -c read 0 512
473
+can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
474
+
475
+_qemu_io_wrapper -c open -r -U TEST_DIR/t.qcow2 -c read 0 512
476
+
477
+_qemu_img_wrapper info -U TEST_DIR/t.qcow2
478
+
479
+_qemu_img_wrapper check -U TEST_DIR/t.qcow2
480
+
481
+_qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
482
+
483
+_qemu_img_wrapper map -U TEST_DIR/t.qcow2
484
+
485
+_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
486
+qemu-img: unrecognized option '-U'
487
+Try 'qemu-img --help' for more information
488
+
489
+_qemu_img_wrapper commit -U TEST_DIR/t.qcow2
490
+qemu-img: unrecognized option '-U'
491
+Try 'qemu-img --help' for more information
492
+
493
+_qemu_img_wrapper resize -U TEST_DIR/t.qcow2 32M
494
+qemu-img: unrecognized option '-U'
495
+Try 'qemu-img --help' for more information
496
+
497
+_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
498
+qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
499
+Is another process using the image?
500
+
501
+_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
502
+
503
+_qemu_img_wrapper convert -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
504
+
505
+_qemu_img_wrapper dd -U if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
506
+
507
+_qemu_img_wrapper bench -U -c 1 TEST_DIR/t.qcow2
508
+
509
+_qemu_img_wrapper bench -U -w -c 1 TEST_DIR/t.qcow2
510
+qemu-img: Could not open 'TEST_DIR/t.qcow2': force-share=on can only be used with read-only images
511
+
512
+Round done
513
+
514
+== Creating base image ==
515
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432
516
+
517
+== Creating test image ==
518
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base
519
+
520
+== Launching QEMU, opts: 'read-only=on,force-share=on' ==
521
+
522
+== Launching another QEMU, opts: '' ==
523
+
524
+== Launching another QEMU, opts: 'read-only=on' ==
525
+
526
+== Launching another QEMU, opts: 'read-only=on,force-share=on' ==
527
+
528
+== Running utility commands ==
529
+
530
+_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
531
+
532
+_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
533
+
534
+_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
535
+
536
+_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
537
+
538
+_qemu_img_wrapper info TEST_DIR/t.qcow2
539
+
540
+_qemu_img_wrapper check TEST_DIR/t.qcow2
541
+
542
+_qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
543
+
544
+_qemu_img_wrapper map TEST_DIR/t.qcow2
545
+
546
+_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
547
+
548
+_qemu_img_wrapper commit TEST_DIR/t.qcow2
549
+
550
+_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
551
+
552
+_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
553
+
554
+_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
555
+
556
+_qemu_img_wrapper convert TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
557
+
558
+_qemu_img_wrapper dd if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
559
+
560
+_qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
561
+
562
+_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
563
+
564
+== Running utility commands -U ==
565
+
566
+_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
567
+can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
568
+
569
+_qemu_io_wrapper -U -r -c read 0 512 TEST_DIR/t.qcow2
570
+
571
+_qemu_io_wrapper -c open -U TEST_DIR/t.qcow2 -c read 0 512
572
+can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
573
+
574
+_qemu_io_wrapper -c open -r -U TEST_DIR/t.qcow2 -c read 0 512
575
+
576
+_qemu_img_wrapper info -U TEST_DIR/t.qcow2
577
+
578
+_qemu_img_wrapper check -U TEST_DIR/t.qcow2
579
+
580
+_qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
581
+
582
+_qemu_img_wrapper map -U TEST_DIR/t.qcow2
583
+
584
+_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
585
+qemu-img: unrecognized option '-U'
586
+Try 'qemu-img --help' for more information
587
+
588
+_qemu_img_wrapper commit -U TEST_DIR/t.qcow2
589
+qemu-img: unrecognized option '-U'
590
+Try 'qemu-img --help' for more information
591
+
592
+_qemu_img_wrapper resize -U TEST_DIR/t.qcow2 32M
593
+qemu-img: unrecognized option '-U'
594
+Try 'qemu-img --help' for more information
595
+
596
+_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
597
+
598
+_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
599
+
600
+_qemu_img_wrapper convert -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
601
+
602
+_qemu_img_wrapper dd -U if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
603
+
604
+_qemu_img_wrapper bench -U -c 1 TEST_DIR/t.qcow2
605
+
606
+_qemu_img_wrapper bench -U -w -c 1 TEST_DIR/t.qcow2
607
+qemu-img: Could not open 'TEST_DIR/t.qcow2': force-share=on can only be used with read-only images
608
+
609
+Round done
610
+== Creating TEST_DIR/t.qcow2.[abc] ==
611
+Formatting 'TEST_DIR/t.IMGFMT.a', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT
612
+Formatting 'TEST_DIR/t.IMGFMT.b', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT
613
+Formatting 'TEST_DIR/t.IMGFMT.c', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.b
614
+
615
+== Two devices sharing the same file in backing chain ==
616
+
617
+== Backing image also as an active device ==
618
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
619
+Is another process using the image?
620
+
621
+== Backing image also as an active device (ro) ==
622
+
623
+== Symbolic link ==
624
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
625
+Is another process using the image?
626
+
627
+== Closing an image should unlock it ==
628
+{"return": {}}
629
+Adding drive
630
+
631
+_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
632
+can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
633
+Is another process using the image?
634
+Closing drive
635
+
636
+_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
637
+Adding two and closing one
638
+
639
+_qemu_img_wrapper info TEST_DIR/t.qcow2
640
+
641
+_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
642
+can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
643
+Is another process using the image?
644
+Closing the other
645
+
646
+_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
647
+*** done
228
+*** done
648
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
229
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
649
index XXXXXXX..XXXXXXX 100644
230
index XXXXXXX..XXXXXXX 100644
650
--- a/tests/qemu-iotests/group
231
--- a/tests/qemu-iotests/group
651
+++ b/tests/qemu-iotests/group
232
+++ b/tests/qemu-iotests/group
652
@@ -XXX,XX +XXX,XX @@
233
@@ -XXX,XX +XXX,XX @@
653
149 rw auto sudo
234
227 auto quick
654
150 rw auto quick
235
229 auto quick
655
152 rw auto quick
236
231 auto quick
656
+153 rw auto quick
237
+232 auto quick
657
154 rw auto backing quick
658
155 rw auto
659
156 rw auto quick
660
--
238
--
661
1.8.3.1
239
2.19.1
662
240
663
241
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
On error path (like i/o error in one of the coroutines), it's required to
3
This adds some whitespace into the option help (including indentation)
4
- wait for coroutines completion before cleaning the common structures
4
and puts angle brackets around the type names. Furthermore, the list
5
- reenter dependent coroutines so they ever finish
5
name is no longer printed as part of every line, but only once in
6
advance, and only if the caller did not print a caption already.
6
7
7
Introduced in 2d9187bc65.
8
This patch also restores the description alignment we had before commit
9
9cbef9d68ee1d8d0, just at 24 instead of 16 characters like we used to.
10
This increase is because now we have the type and two spaces of
11
indentation before the description, and with a usual type name length of
12
three chracters, this sums up to eight additional characters -- which
13
means that we now need 24 characters to get the same amount of padding
14
for most options. Also, 24 is a third of 80, which makes it kind of a
15
round number in terminal terms.
8
16
9
Cc: qemu-stable@nongnu.org
17
Finally, this patch amends the reference output of iotest 082 to match
10
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
18
the changes (and thus makes it pass again).
11
Reviewed-by: Peter Lieven <pl@kamp.de>
19
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
23
---
14
qemu-img.c | 26 +++++++++++---------------
24
include/qemu/option.h | 2 +-
15
1 file changed, 11 insertions(+), 15 deletions(-)
25
qemu-img.c | 4 +-
26
util/qemu-option.c | 32 +-
27
tests/qemu-iotests/082.out | 956 ++++++++++++++++++-------------------
28
4 files changed, 507 insertions(+), 487 deletions(-)
16
29
30
diff --git a/include/qemu/option.h b/include/qemu/option.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/qemu/option.h
33
+++ b/include/qemu/option.h
34
@@ -XXX,XX +XXX,XX @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
35
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
36
void *opaque, Error **errp);
37
void qemu_opts_print(QemuOpts *opts, const char *sep);
38
-void qemu_opts_print_help(QemuOptsList *list);
39
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
40
void qemu_opts_free(QemuOptsList *list);
41
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
42
17
diff --git a/qemu-img.c b/qemu-img.c
43
diff --git a/qemu-img.c b/qemu-img.c
18
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
19
--- a/qemu-img.c
45
--- a/qemu-img.c
20
+++ b/qemu-img.c
46
+++ b/qemu-img.c
21
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
47
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
22
qemu_co_mutex_lock(&s->lock);
48
}
23
if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) {
49
24
qemu_co_mutex_unlock(&s->lock);
50
printf("Supported options:\n");
25
- goto out;
51
- qemu_opts_print_help(create_opts);
26
+ break;
52
+ qemu_opts_print_help(create_opts, false);
53
qemu_opts_free(create_opts);
54
return 0;
55
}
56
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
57
assert(drv->create_opts);
58
59
printf("Creation options for '%s':\n", format);
60
- qemu_opts_print_help(drv->create_opts);
61
+ qemu_opts_print_help(drv->create_opts, false);
62
printf("\nNote that not all of these options may be amendable.\n");
63
return 0;
64
}
65
diff --git a/util/qemu-option.c b/util/qemu-option.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/util/qemu-option.c
68
+++ b/util/qemu-option.c
69
@@ -XXX,XX +XXX,XX @@ static const char *opt_type_to_string(enum QemuOptType type)
70
g_assert_not_reached();
71
}
72
73
-void qemu_opts_print_help(QemuOptsList *list)
74
+/**
75
+ * Print the list of options available in the given list. If
76
+ * @print_caption is true, a caption (including the list name, if it
77
+ * exists) is printed. The options itself will be indented, so
78
+ * @print_caption should only be set to false if the caller prints its
79
+ * own custom caption (so that the indentation makes sense).
80
+ */
81
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
82
{
83
QemuOptDesc *desc;
84
int i;
85
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
86
desc = list->desc;
87
while (desc && desc->name) {
88
GString *str = g_string_new(NULL);
89
- if (list->name) {
90
- g_string_append_printf(str, "%s.", list->name);
91
- }
92
- g_string_append_printf(str, "%s=%s", desc->name,
93
+ g_string_append_printf(str, " %s=<%s>", desc->name,
94
opt_type_to_string(desc->type));
95
if (desc->help) {
96
+ if (str->len < 24) {
97
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
98
+ }
99
g_string_append_printf(str, " - %s", desc->help);
27
}
100
}
28
n = convert_iteration_sectors(s, s->sector_num);
101
g_ptr_array_add(array, g_string_free(str, false));
29
if (n < 0) {
102
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
30
qemu_co_mutex_unlock(&s->lock);
31
s->ret = n;
32
- goto out;
33
+ break;
34
}
35
/* save current sector and allocation status to local variables */
36
sector_num = s->sector_num;
37
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
38
error_report("error while reading sector %" PRId64
39
": %s", sector_num, strerror(-ret));
40
s->ret = ret;
41
- goto out;
42
}
43
} else if (!s->min_sparse && status == BLK_ZERO) {
44
status = BLK_DATA;
45
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
46
47
if (s->wr_in_order) {
48
/* keep writes in order */
49
- while (s->wr_offs != sector_num) {
50
- if (s->ret != -EINPROGRESS) {
51
- goto out;
52
- }
53
+ while (s->wr_offs != sector_num && s->ret == -EINPROGRESS) {
54
s->wait_sector_num[index] = sector_num;
55
qemu_coroutine_yield();
56
}
57
s->wait_sector_num[index] = -1;
58
}
59
60
- ret = convert_co_write(s, sector_num, n, buf, status);
61
- if (ret < 0) {
62
- error_report("error while writing sector %" PRId64
63
- ": %s", sector_num, strerror(-ret));
64
- s->ret = ret;
65
- goto out;
66
+ if (s->ret == -EINPROGRESS) {
67
+ ret = convert_co_write(s, sector_num, n, buf, status);
68
+ if (ret < 0) {
69
+ error_report("error while writing sector %" PRId64
70
+ ": %s", sector_num, strerror(-ret));
71
+ s->ret = ret;
72
+ }
73
}
74
75
if (s->wr_in_order) {
76
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
77
}
78
}
103
}
79
104
80
-out:
105
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
81
qemu_vfree(buf);
106
+ if (print_caption && array->len > 0) {
82
s->co[index] = NULL;
107
+ if (list->name) {
83
s->running_coroutines--;
108
+ printf("%s options:\n", list->name);
84
@@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s)
109
+ } else {
85
qemu_coroutine_enter(s->co[i]);
110
+ printf("Options:\n");
111
+ }
112
+ } else if (array->len == 0) {
113
+ if (list->name) {
114
+ printf("There are no options for %s.\n", list->name);
115
+ } else {
116
+ printf("No options available.\n");
117
+ }
118
+ }
119
for (i = 0; i < array->len; i++) {
120
printf("%s\n", (char *)array->pdata[i]);
86
}
121
}
87
122
@@ -XXX,XX +XXX,XX @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
88
- while (s->ret == -EINPROGRESS) {
123
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
89
+ while (s->running_coroutines) {
124
if (err) {
90
main_loop_wait(false);
125
if (invalidp && has_help_option(params)) {
91
}
126
- qemu_opts_print_help(list);
92
127
+ qemu_opts_print_help(list, true);
128
error_free(err);
129
} else {
130
error_report_err(err);
131
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
132
index XXXXXXX..XXXXXXX 100644
133
--- a/tests/qemu-iotests/082.out
134
+++ b/tests/qemu-iotests/082.out
135
@@ -XXX,XX +XXX,XX @@ cluster_size: 8192
136
137
Testing: create -f qcow2 -o help TEST_DIR/t.qcow2 128M
138
Supported options:
139
-size Virtual disk size
140
-compat Compatibility level (0.10 or 1.1)
141
-backing_file File name of a base image
142
-backing_fmt Image format of the base image
143
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
144
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
145
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
146
-encrypt.cipher-alg Name of encryption cipher algorithm
147
-encrypt.cipher-mode Name of encryption cipher mode
148
-encrypt.ivgen-alg Name of IV generator algorithm
149
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
150
-encrypt.hash-alg Name of encryption hash algorithm
151
-encrypt.iter-time Time to spend in PBKDF in milliseconds
152
-cluster_size qcow2 cluster size
153
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
154
-lazy_refcounts Postpone refcount updates
155
-refcount_bits Width of a reference count entry in bits
156
-nocow Turn off copy-on-write (valid only on btrfs)
157
+ backing_file=<str> - File name of a base image
158
+ backing_fmt=<str> - Image format of the base image
159
+ cluster_size=<size> - qcow2 cluster size
160
+ compat=<str> - Compatibility level (0.10 or 1.1)
161
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
162
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
163
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
164
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
165
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
166
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
167
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
168
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
169
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
170
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
171
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
172
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
173
+ refcount_bits=<num> - Width of a reference count entry in bits
174
+ size=<size> - Virtual disk size
175
176
Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M
177
Supported options:
178
-size Virtual disk size
179
-compat Compatibility level (0.10 or 1.1)
180
-backing_file File name of a base image
181
-backing_fmt Image format of the base image
182
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
183
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
184
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
185
-encrypt.cipher-alg Name of encryption cipher algorithm
186
-encrypt.cipher-mode Name of encryption cipher mode
187
-encrypt.ivgen-alg Name of IV generator algorithm
188
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
189
-encrypt.hash-alg Name of encryption hash algorithm
190
-encrypt.iter-time Time to spend in PBKDF in milliseconds
191
-cluster_size qcow2 cluster size
192
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
193
-lazy_refcounts Postpone refcount updates
194
-refcount_bits Width of a reference count entry in bits
195
-nocow Turn off copy-on-write (valid only on btrfs)
196
+ backing_file=<str> - File name of a base image
197
+ backing_fmt=<str> - Image format of the base image
198
+ cluster_size=<size> - qcow2 cluster size
199
+ compat=<str> - Compatibility level (0.10 or 1.1)
200
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
201
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
202
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
203
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
204
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
205
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
206
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
207
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
208
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
209
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
210
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
211
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
212
+ refcount_bits=<num> - Width of a reference count entry in bits
213
+ size=<size> - Virtual disk size
214
215
Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M
216
Supported options:
217
-size Virtual disk size
218
-compat Compatibility level (0.10 or 1.1)
219
-backing_file File name of a base image
220
-backing_fmt Image format of the base image
221
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
222
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
223
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
224
-encrypt.cipher-alg Name of encryption cipher algorithm
225
-encrypt.cipher-mode Name of encryption cipher mode
226
-encrypt.ivgen-alg Name of IV generator algorithm
227
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
228
-encrypt.hash-alg Name of encryption hash algorithm
229
-encrypt.iter-time Time to spend in PBKDF in milliseconds
230
-cluster_size qcow2 cluster size
231
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
232
-lazy_refcounts Postpone refcount updates
233
-refcount_bits Width of a reference count entry in bits
234
-nocow Turn off copy-on-write (valid only on btrfs)
235
+ backing_file=<str> - File name of a base image
236
+ backing_fmt=<str> - Image format of the base image
237
+ cluster_size=<size> - qcow2 cluster size
238
+ compat=<str> - Compatibility level (0.10 or 1.1)
239
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
240
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
241
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
242
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
243
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
244
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
245
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
246
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
247
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
248
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
249
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
250
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
251
+ refcount_bits=<num> - Width of a reference count entry in bits
252
+ size=<size> - Virtual disk size
253
254
Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M
255
Supported options:
256
-size Virtual disk size
257
-compat Compatibility level (0.10 or 1.1)
258
-backing_file File name of a base image
259
-backing_fmt Image format of the base image
260
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
261
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
262
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
263
-encrypt.cipher-alg Name of encryption cipher algorithm
264
-encrypt.cipher-mode Name of encryption cipher mode
265
-encrypt.ivgen-alg Name of IV generator algorithm
266
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
267
-encrypt.hash-alg Name of encryption hash algorithm
268
-encrypt.iter-time Time to spend in PBKDF in milliseconds
269
-cluster_size qcow2 cluster size
270
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
271
-lazy_refcounts Postpone refcount updates
272
-refcount_bits Width of a reference count entry in bits
273
-nocow Turn off copy-on-write (valid only on btrfs)
274
+ backing_file=<str> - File name of a base image
275
+ backing_fmt=<str> - Image format of the base image
276
+ cluster_size=<size> - qcow2 cluster size
277
+ compat=<str> - Compatibility level (0.10 or 1.1)
278
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
279
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
280
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
281
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
282
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
283
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
284
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
285
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
286
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
287
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
288
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
289
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
290
+ refcount_bits=<num> - Width of a reference count entry in bits
291
+ size=<size> - Virtual disk size
292
293
Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M
294
Supported options:
295
-size Virtual disk size
296
-compat Compatibility level (0.10 or 1.1)
297
-backing_file File name of a base image
298
-backing_fmt Image format of the base image
299
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
300
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
301
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
302
-encrypt.cipher-alg Name of encryption cipher algorithm
303
-encrypt.cipher-mode Name of encryption cipher mode
304
-encrypt.ivgen-alg Name of IV generator algorithm
305
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
306
-encrypt.hash-alg Name of encryption hash algorithm
307
-encrypt.iter-time Time to spend in PBKDF in milliseconds
308
-cluster_size qcow2 cluster size
309
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
310
-lazy_refcounts Postpone refcount updates
311
-refcount_bits Width of a reference count entry in bits
312
-nocow Turn off copy-on-write (valid only on btrfs)
313
+ backing_file=<str> - File name of a base image
314
+ backing_fmt=<str> - Image format of the base image
315
+ cluster_size=<size> - qcow2 cluster size
316
+ compat=<str> - Compatibility level (0.10 or 1.1)
317
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
318
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
319
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
320
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
321
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
322
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
323
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
324
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
325
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
326
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
327
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
328
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
329
+ refcount_bits=<num> - Width of a reference count entry in bits
330
+ size=<size> - Virtual disk size
331
332
Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M
333
Supported options:
334
-size Virtual disk size
335
-compat Compatibility level (0.10 or 1.1)
336
-backing_file File name of a base image
337
-backing_fmt Image format of the base image
338
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
339
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
340
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
341
-encrypt.cipher-alg Name of encryption cipher algorithm
342
-encrypt.cipher-mode Name of encryption cipher mode
343
-encrypt.ivgen-alg Name of IV generator algorithm
344
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
345
-encrypt.hash-alg Name of encryption hash algorithm
346
-encrypt.iter-time Time to spend in PBKDF in milliseconds
347
-cluster_size qcow2 cluster size
348
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
349
-lazy_refcounts Postpone refcount updates
350
-refcount_bits Width of a reference count entry in bits
351
-nocow Turn off copy-on-write (valid only on btrfs)
352
+ backing_file=<str> - File name of a base image
353
+ backing_fmt=<str> - Image format of the base image
354
+ cluster_size=<size> - qcow2 cluster size
355
+ compat=<str> - Compatibility level (0.10 or 1.1)
356
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
357
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
358
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
359
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
360
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
361
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
362
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
363
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
364
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
365
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
366
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
367
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
368
+ refcount_bits=<num> - Width of a reference count entry in bits
369
+ size=<size> - Virtual disk size
370
371
Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M
372
Supported options:
373
-size Virtual disk size
374
-compat Compatibility level (0.10 or 1.1)
375
-backing_file File name of a base image
376
-backing_fmt Image format of the base image
377
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
378
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
379
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
380
-encrypt.cipher-alg Name of encryption cipher algorithm
381
-encrypt.cipher-mode Name of encryption cipher mode
382
-encrypt.ivgen-alg Name of IV generator algorithm
383
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
384
-encrypt.hash-alg Name of encryption hash algorithm
385
-encrypt.iter-time Time to spend in PBKDF in milliseconds
386
-cluster_size qcow2 cluster size
387
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
388
-lazy_refcounts Postpone refcount updates
389
-refcount_bits Width of a reference count entry in bits
390
-nocow Turn off copy-on-write (valid only on btrfs)
391
+ backing_file=<str> - File name of a base image
392
+ backing_fmt=<str> - Image format of the base image
393
+ cluster_size=<size> - qcow2 cluster size
394
+ compat=<str> - Compatibility level (0.10 or 1.1)
395
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
396
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
397
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
398
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
399
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
400
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
401
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
402
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
403
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
404
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
405
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
406
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
407
+ refcount_bits=<num> - Width of a reference count entry in bits
408
+ size=<size> - Virtual disk size
409
410
Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M
411
Supported options:
412
-size Virtual disk size
413
-compat Compatibility level (0.10 or 1.1)
414
-backing_file File name of a base image
415
-backing_fmt Image format of the base image
416
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
417
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
418
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
419
-encrypt.cipher-alg Name of encryption cipher algorithm
420
-encrypt.cipher-mode Name of encryption cipher mode
421
-encrypt.ivgen-alg Name of IV generator algorithm
422
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
423
-encrypt.hash-alg Name of encryption hash algorithm
424
-encrypt.iter-time Time to spend in PBKDF in milliseconds
425
-cluster_size qcow2 cluster size
426
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
427
-lazy_refcounts Postpone refcount updates
428
-refcount_bits Width of a reference count entry in bits
429
-nocow Turn off copy-on-write (valid only on btrfs)
430
+ backing_file=<str> - File name of a base image
431
+ backing_fmt=<str> - Image format of the base image
432
+ cluster_size=<size> - qcow2 cluster size
433
+ compat=<str> - Compatibility level (0.10 or 1.1)
434
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
435
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
436
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
437
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
438
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
439
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
440
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
441
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
442
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
443
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
444
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
445
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
446
+ refcount_bits=<num> - Width of a reference count entry in bits
447
+ size=<size> - Virtual disk size
448
449
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
450
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16
451
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
452
453
Testing: create -f qcow2 -o help
454
Supported options:
455
-size Virtual disk size
456
-compat Compatibility level (0.10 or 1.1)
457
-backing_file File name of a base image
458
-backing_fmt Image format of the base image
459
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
460
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
461
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
462
-encrypt.cipher-alg Name of encryption cipher algorithm
463
-encrypt.cipher-mode Name of encryption cipher mode
464
-encrypt.ivgen-alg Name of IV generator algorithm
465
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
466
-encrypt.hash-alg Name of encryption hash algorithm
467
-encrypt.iter-time Time to spend in PBKDF in milliseconds
468
-cluster_size qcow2 cluster size
469
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
470
-lazy_refcounts Postpone refcount updates
471
-refcount_bits Width of a reference count entry in bits
472
+ backing_file=<str> - File name of a base image
473
+ backing_fmt=<str> - Image format of the base image
474
+ cluster_size=<size> - qcow2 cluster size
475
+ compat=<str> - Compatibility level (0.10 or 1.1)
476
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
477
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
478
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
479
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
480
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
481
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
482
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
483
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
484
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
485
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
486
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
487
+ refcount_bits=<num> - Width of a reference count entry in bits
488
+ size=<size> - Virtual disk size
489
490
Testing: create -o help
491
Supported options:
492
-size Virtual disk size
493
+ size=<size> - Virtual disk size
494
495
Testing: create -f bochs -o help
496
qemu-img: Format driver 'bochs' does not support image creation
497
@@ -XXX,XX +XXX,XX @@ cluster_size: 8192
498
499
Testing: convert -O qcow2 -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
500
Supported options:
501
-size Virtual disk size
502
-compat Compatibility level (0.10 or 1.1)
503
-backing_file File name of a base image
504
-backing_fmt Image format of the base image
505
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
506
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
507
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
508
-encrypt.cipher-alg Name of encryption cipher algorithm
509
-encrypt.cipher-mode Name of encryption cipher mode
510
-encrypt.ivgen-alg Name of IV generator algorithm
511
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
512
-encrypt.hash-alg Name of encryption hash algorithm
513
-encrypt.iter-time Time to spend in PBKDF in milliseconds
514
-cluster_size qcow2 cluster size
515
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
516
-lazy_refcounts Postpone refcount updates
517
-refcount_bits Width of a reference count entry in bits
518
-nocow Turn off copy-on-write (valid only on btrfs)
519
+ backing_file=<str> - File name of a base image
520
+ backing_fmt=<str> - Image format of the base image
521
+ cluster_size=<size> - qcow2 cluster size
522
+ compat=<str> - Compatibility level (0.10 or 1.1)
523
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
524
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
525
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
526
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
527
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
528
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
529
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
530
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
531
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
532
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
533
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
534
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
535
+ refcount_bits=<num> - Width of a reference count entry in bits
536
+ size=<size> - Virtual disk size
537
538
Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
539
Supported options:
540
-size Virtual disk size
541
-compat Compatibility level (0.10 or 1.1)
542
-backing_file File name of a base image
543
-backing_fmt Image format of the base image
544
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
545
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
546
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
547
-encrypt.cipher-alg Name of encryption cipher algorithm
548
-encrypt.cipher-mode Name of encryption cipher mode
549
-encrypt.ivgen-alg Name of IV generator algorithm
550
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
551
-encrypt.hash-alg Name of encryption hash algorithm
552
-encrypt.iter-time Time to spend in PBKDF in milliseconds
553
-cluster_size qcow2 cluster size
554
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
555
-lazy_refcounts Postpone refcount updates
556
-refcount_bits Width of a reference count entry in bits
557
-nocow Turn off copy-on-write (valid only on btrfs)
558
+ backing_file=<str> - File name of a base image
559
+ backing_fmt=<str> - Image format of the base image
560
+ cluster_size=<size> - qcow2 cluster size
561
+ compat=<str> - Compatibility level (0.10 or 1.1)
562
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
563
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
564
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
565
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
566
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
567
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
568
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
569
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
570
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
571
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
572
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
573
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
574
+ refcount_bits=<num> - Width of a reference count entry in bits
575
+ size=<size> - Virtual disk size
576
577
Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
578
Supported options:
579
-size Virtual disk size
580
-compat Compatibility level (0.10 or 1.1)
581
-backing_file File name of a base image
582
-backing_fmt Image format of the base image
583
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
584
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
585
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
586
-encrypt.cipher-alg Name of encryption cipher algorithm
587
-encrypt.cipher-mode Name of encryption cipher mode
588
-encrypt.ivgen-alg Name of IV generator algorithm
589
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
590
-encrypt.hash-alg Name of encryption hash algorithm
591
-encrypt.iter-time Time to spend in PBKDF in milliseconds
592
-cluster_size qcow2 cluster size
593
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
594
-lazy_refcounts Postpone refcount updates
595
-refcount_bits Width of a reference count entry in bits
596
-nocow Turn off copy-on-write (valid only on btrfs)
597
+ backing_file=<str> - File name of a base image
598
+ backing_fmt=<str> - Image format of the base image
599
+ cluster_size=<size> - qcow2 cluster size
600
+ compat=<str> - Compatibility level (0.10 or 1.1)
601
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
602
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
603
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
604
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
605
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
606
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
607
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
608
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
609
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
610
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
611
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
612
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
613
+ refcount_bits=<num> - Width of a reference count entry in bits
614
+ size=<size> - Virtual disk size
615
616
Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
617
Supported options:
618
-size Virtual disk size
619
-compat Compatibility level (0.10 or 1.1)
620
-backing_file File name of a base image
621
-backing_fmt Image format of the base image
622
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
623
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
624
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
625
-encrypt.cipher-alg Name of encryption cipher algorithm
626
-encrypt.cipher-mode Name of encryption cipher mode
627
-encrypt.ivgen-alg Name of IV generator algorithm
628
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
629
-encrypt.hash-alg Name of encryption hash algorithm
630
-encrypt.iter-time Time to spend in PBKDF in milliseconds
631
-cluster_size qcow2 cluster size
632
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
633
-lazy_refcounts Postpone refcount updates
634
-refcount_bits Width of a reference count entry in bits
635
-nocow Turn off copy-on-write (valid only on btrfs)
636
+ backing_file=<str> - File name of a base image
637
+ backing_fmt=<str> - Image format of the base image
638
+ cluster_size=<size> - qcow2 cluster size
639
+ compat=<str> - Compatibility level (0.10 or 1.1)
640
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
641
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
642
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
643
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
644
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
645
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
646
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
647
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
648
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
649
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
650
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
651
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
652
+ refcount_bits=<num> - Width of a reference count entry in bits
653
+ size=<size> - Virtual disk size
654
655
Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
656
Supported options:
657
-size Virtual disk size
658
-compat Compatibility level (0.10 or 1.1)
659
-backing_file File name of a base image
660
-backing_fmt Image format of the base image
661
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
662
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
663
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
664
-encrypt.cipher-alg Name of encryption cipher algorithm
665
-encrypt.cipher-mode Name of encryption cipher mode
666
-encrypt.ivgen-alg Name of IV generator algorithm
667
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
668
-encrypt.hash-alg Name of encryption hash algorithm
669
-encrypt.iter-time Time to spend in PBKDF in milliseconds
670
-cluster_size qcow2 cluster size
671
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
672
-lazy_refcounts Postpone refcount updates
673
-refcount_bits Width of a reference count entry in bits
674
-nocow Turn off copy-on-write (valid only on btrfs)
675
+ backing_file=<str> - File name of a base image
676
+ backing_fmt=<str> - Image format of the base image
677
+ cluster_size=<size> - qcow2 cluster size
678
+ compat=<str> - Compatibility level (0.10 or 1.1)
679
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
680
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
681
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
682
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
683
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
684
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
685
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
686
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
687
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
688
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
689
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
690
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
691
+ refcount_bits=<num> - Width of a reference count entry in bits
692
+ size=<size> - Virtual disk size
693
694
Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
695
Supported options:
696
-size Virtual disk size
697
-compat Compatibility level (0.10 or 1.1)
698
-backing_file File name of a base image
699
-backing_fmt Image format of the base image
700
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
701
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
702
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
703
-encrypt.cipher-alg Name of encryption cipher algorithm
704
-encrypt.cipher-mode Name of encryption cipher mode
705
-encrypt.ivgen-alg Name of IV generator algorithm
706
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
707
-encrypt.hash-alg Name of encryption hash algorithm
708
-encrypt.iter-time Time to spend in PBKDF in milliseconds
709
-cluster_size qcow2 cluster size
710
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
711
-lazy_refcounts Postpone refcount updates
712
-refcount_bits Width of a reference count entry in bits
713
-nocow Turn off copy-on-write (valid only on btrfs)
714
+ backing_file=<str> - File name of a base image
715
+ backing_fmt=<str> - Image format of the base image
716
+ cluster_size=<size> - qcow2 cluster size
717
+ compat=<str> - Compatibility level (0.10 or 1.1)
718
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
719
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
720
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
721
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
722
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
723
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
724
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
725
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
726
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
727
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
728
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
729
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
730
+ refcount_bits=<num> - Width of a reference count entry in bits
731
+ size=<size> - Virtual disk size
732
733
Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
734
Supported options:
735
-size Virtual disk size
736
-compat Compatibility level (0.10 or 1.1)
737
-backing_file File name of a base image
738
-backing_fmt Image format of the base image
739
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
740
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
741
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
742
-encrypt.cipher-alg Name of encryption cipher algorithm
743
-encrypt.cipher-mode Name of encryption cipher mode
744
-encrypt.ivgen-alg Name of IV generator algorithm
745
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
746
-encrypt.hash-alg Name of encryption hash algorithm
747
-encrypt.iter-time Time to spend in PBKDF in milliseconds
748
-cluster_size qcow2 cluster size
749
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
750
-lazy_refcounts Postpone refcount updates
751
-refcount_bits Width of a reference count entry in bits
752
-nocow Turn off copy-on-write (valid only on btrfs)
753
+ backing_file=<str> - File name of a base image
754
+ backing_fmt=<str> - Image format of the base image
755
+ cluster_size=<size> - qcow2 cluster size
756
+ compat=<str> - Compatibility level (0.10 or 1.1)
757
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
758
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
759
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
760
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
761
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
762
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
763
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
764
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
765
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
766
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
767
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
768
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
769
+ refcount_bits=<num> - Width of a reference count entry in bits
770
+ size=<size> - Virtual disk size
771
772
Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
773
Supported options:
774
-size Virtual disk size
775
-compat Compatibility level (0.10 or 1.1)
776
-backing_file File name of a base image
777
-backing_fmt Image format of the base image
778
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
779
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
780
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
781
-encrypt.cipher-alg Name of encryption cipher algorithm
782
-encrypt.cipher-mode Name of encryption cipher mode
783
-encrypt.ivgen-alg Name of IV generator algorithm
784
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
785
-encrypt.hash-alg Name of encryption hash algorithm
786
-encrypt.iter-time Time to spend in PBKDF in milliseconds
787
-cluster_size qcow2 cluster size
788
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
789
-lazy_refcounts Postpone refcount updates
790
-refcount_bits Width of a reference count entry in bits
791
-nocow Turn off copy-on-write (valid only on btrfs)
792
+ backing_file=<str> - File name of a base image
793
+ backing_fmt=<str> - Image format of the base image
794
+ cluster_size=<size> - qcow2 cluster size
795
+ compat=<str> - Compatibility level (0.10 or 1.1)
796
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
797
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
798
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
799
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
800
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
801
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
802
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
803
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
804
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
805
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
806
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
807
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
808
+ refcount_bits=<num> - Width of a reference count entry in bits
809
+ size=<size> - Virtual disk size
810
811
Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
812
qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory
813
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
814
815
Testing: convert -O qcow2 -o help
816
Supported options:
817
-size Virtual disk size
818
-compat Compatibility level (0.10 or 1.1)
819
-backing_file File name of a base image
820
-backing_fmt Image format of the base image
821
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
822
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
823
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
824
-encrypt.cipher-alg Name of encryption cipher algorithm
825
-encrypt.cipher-mode Name of encryption cipher mode
826
-encrypt.ivgen-alg Name of IV generator algorithm
827
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
828
-encrypt.hash-alg Name of encryption hash algorithm
829
-encrypt.iter-time Time to spend in PBKDF in milliseconds
830
-cluster_size qcow2 cluster size
831
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
832
-lazy_refcounts Postpone refcount updates
833
-refcount_bits Width of a reference count entry in bits
834
+ backing_file=<str> - File name of a base image
835
+ backing_fmt=<str> - Image format of the base image
836
+ cluster_size=<size> - qcow2 cluster size
837
+ compat=<str> - Compatibility level (0.10 or 1.1)
838
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
839
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
840
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
841
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
842
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
843
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
844
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
845
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
846
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
847
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
848
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
849
+ refcount_bits=<num> - Width of a reference count entry in bits
850
+ size=<size> - Virtual disk size
851
852
Testing: convert -o help
853
Supported options:
854
-size Virtual disk size
855
+ size=<size> - Virtual disk size
856
857
Testing: convert -O bochs -o help
858
qemu-img: Format driver 'bochs' does not support image creation
859
@@ -XXX,XX +XXX,XX @@ cluster_size: 65536
860
861
Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2
862
Creation options for 'qcow2':
863
-size Virtual disk size
864
-compat Compatibility level (0.10 or 1.1)
865
-backing_file File name of a base image
866
-backing_fmt Image format of the base image
867
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
868
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
869
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
870
-encrypt.cipher-alg Name of encryption cipher algorithm
871
-encrypt.cipher-mode Name of encryption cipher mode
872
-encrypt.ivgen-alg Name of IV generator algorithm
873
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
874
-encrypt.hash-alg Name of encryption hash algorithm
875
-encrypt.iter-time Time to spend in PBKDF in milliseconds
876
-cluster_size qcow2 cluster size
877
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
878
-lazy_refcounts Postpone refcount updates
879
-refcount_bits Width of a reference count entry in bits
880
+ backing_file=<str> - File name of a base image
881
+ backing_fmt=<str> - Image format of the base image
882
+ cluster_size=<size> - qcow2 cluster size
883
+ compat=<str> - Compatibility level (0.10 or 1.1)
884
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
885
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
886
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
887
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
888
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
889
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
890
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
891
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
892
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
893
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
894
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
895
+ refcount_bits=<num> - Width of a reference count entry in bits
896
+ size=<size> - Virtual disk size
897
898
Note that not all of these options may be amendable.
899
900
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
901
Creation options for 'qcow2':
902
-size Virtual disk size
903
-compat Compatibility level (0.10 or 1.1)
904
-backing_file File name of a base image
905
-backing_fmt Image format of the base image
906
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
907
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
908
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
909
-encrypt.cipher-alg Name of encryption cipher algorithm
910
-encrypt.cipher-mode Name of encryption cipher mode
911
-encrypt.ivgen-alg Name of IV generator algorithm
912
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
913
-encrypt.hash-alg Name of encryption hash algorithm
914
-encrypt.iter-time Time to spend in PBKDF in milliseconds
915
-cluster_size qcow2 cluster size
916
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
917
-lazy_refcounts Postpone refcount updates
918
-refcount_bits Width of a reference count entry in bits
919
+ backing_file=<str> - File name of a base image
920
+ backing_fmt=<str> - Image format of the base image
921
+ cluster_size=<size> - qcow2 cluster size
922
+ compat=<str> - Compatibility level (0.10 or 1.1)
923
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
924
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
925
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
926
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
927
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
928
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
929
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
930
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
931
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
932
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
933
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
934
+ refcount_bits=<num> - Width of a reference count entry in bits
935
+ size=<size> - Virtual disk size
936
937
Note that not all of these options may be amendable.
938
939
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
940
Creation options for 'qcow2':
941
-size Virtual disk size
942
-compat Compatibility level (0.10 or 1.1)
943
-backing_file File name of a base image
944
-backing_fmt Image format of the base image
945
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
946
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
947
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
948
-encrypt.cipher-alg Name of encryption cipher algorithm
949
-encrypt.cipher-mode Name of encryption cipher mode
950
-encrypt.ivgen-alg Name of IV generator algorithm
951
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
952
-encrypt.hash-alg Name of encryption hash algorithm
953
-encrypt.iter-time Time to spend in PBKDF in milliseconds
954
-cluster_size qcow2 cluster size
955
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
956
-lazy_refcounts Postpone refcount updates
957
-refcount_bits Width of a reference count entry in bits
958
+ backing_file=<str> - File name of a base image
959
+ backing_fmt=<str> - Image format of the base image
960
+ cluster_size=<size> - qcow2 cluster size
961
+ compat=<str> - Compatibility level (0.10 or 1.1)
962
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
963
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
964
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
965
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
966
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
967
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
968
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
969
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
970
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
971
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
972
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
973
+ refcount_bits=<num> - Width of a reference count entry in bits
974
+ size=<size> - Virtual disk size
975
976
Note that not all of these options may be amendable.
977
978
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
979
Creation options for 'qcow2':
980
-size Virtual disk size
981
-compat Compatibility level (0.10 or 1.1)
982
-backing_file File name of a base image
983
-backing_fmt Image format of the base image
984
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
985
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
986
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
987
-encrypt.cipher-alg Name of encryption cipher algorithm
988
-encrypt.cipher-mode Name of encryption cipher mode
989
-encrypt.ivgen-alg Name of IV generator algorithm
990
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
991
-encrypt.hash-alg Name of encryption hash algorithm
992
-encrypt.iter-time Time to spend in PBKDF in milliseconds
993
-cluster_size qcow2 cluster size
994
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
995
-lazy_refcounts Postpone refcount updates
996
-refcount_bits Width of a reference count entry in bits
997
+ backing_file=<str> - File name of a base image
998
+ backing_fmt=<str> - Image format of the base image
999
+ cluster_size=<size> - qcow2 cluster size
1000
+ compat=<str> - Compatibility level (0.10 or 1.1)
1001
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1002
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1003
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1004
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1005
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1006
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1007
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1008
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1009
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1010
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1011
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1012
+ refcount_bits=<num> - Width of a reference count entry in bits
1013
+ size=<size> - Virtual disk size
1014
1015
Note that not all of these options may be amendable.
1016
1017
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
1018
Creation options for 'qcow2':
1019
-size Virtual disk size
1020
-compat Compatibility level (0.10 or 1.1)
1021
-backing_file File name of a base image
1022
-backing_fmt Image format of the base image
1023
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1024
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1025
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1026
-encrypt.cipher-alg Name of encryption cipher algorithm
1027
-encrypt.cipher-mode Name of encryption cipher mode
1028
-encrypt.ivgen-alg Name of IV generator algorithm
1029
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1030
-encrypt.hash-alg Name of encryption hash algorithm
1031
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1032
-cluster_size qcow2 cluster size
1033
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1034
-lazy_refcounts Postpone refcount updates
1035
-refcount_bits Width of a reference count entry in bits
1036
+ backing_file=<str> - File name of a base image
1037
+ backing_fmt=<str> - Image format of the base image
1038
+ cluster_size=<size> - qcow2 cluster size
1039
+ compat=<str> - Compatibility level (0.10 or 1.1)
1040
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1041
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1042
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1043
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1044
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1045
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1046
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1047
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1048
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1049
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1050
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1051
+ refcount_bits=<num> - Width of a reference count entry in bits
1052
+ size=<size> - Virtual disk size
1053
1054
Note that not all of these options may be amendable.
1055
1056
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
1057
Creation options for 'qcow2':
1058
-size Virtual disk size
1059
-compat Compatibility level (0.10 or 1.1)
1060
-backing_file File name of a base image
1061
-backing_fmt Image format of the base image
1062
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1063
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1064
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1065
-encrypt.cipher-alg Name of encryption cipher algorithm
1066
-encrypt.cipher-mode Name of encryption cipher mode
1067
-encrypt.ivgen-alg Name of IV generator algorithm
1068
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1069
-encrypt.hash-alg Name of encryption hash algorithm
1070
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1071
-cluster_size qcow2 cluster size
1072
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1073
-lazy_refcounts Postpone refcount updates
1074
-refcount_bits Width of a reference count entry in bits
1075
+ backing_file=<str> - File name of a base image
1076
+ backing_fmt=<str> - Image format of the base image
1077
+ cluster_size=<size> - qcow2 cluster size
1078
+ compat=<str> - Compatibility level (0.10 or 1.1)
1079
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1080
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1081
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1082
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1083
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1084
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1085
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1086
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1087
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1088
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1089
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1090
+ refcount_bits=<num> - Width of a reference count entry in bits
1091
+ size=<size> - Virtual disk size
1092
1093
Note that not all of these options may be amendable.
1094
1095
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
1096
Creation options for 'qcow2':
1097
-size Virtual disk size
1098
-compat Compatibility level (0.10 or 1.1)
1099
-backing_file File name of a base image
1100
-backing_fmt Image format of the base image
1101
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1102
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1103
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1104
-encrypt.cipher-alg Name of encryption cipher algorithm
1105
-encrypt.cipher-mode Name of encryption cipher mode
1106
-encrypt.ivgen-alg Name of IV generator algorithm
1107
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1108
-encrypt.hash-alg Name of encryption hash algorithm
1109
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1110
-cluster_size qcow2 cluster size
1111
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1112
-lazy_refcounts Postpone refcount updates
1113
-refcount_bits Width of a reference count entry in bits
1114
+ backing_file=<str> - File name of a base image
1115
+ backing_fmt=<str> - Image format of the base image
1116
+ cluster_size=<size> - qcow2 cluster size
1117
+ compat=<str> - Compatibility level (0.10 or 1.1)
1118
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1119
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1120
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1121
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1122
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1123
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1124
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1125
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1126
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1127
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1128
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1129
+ refcount_bits=<num> - Width of a reference count entry in bits
1130
+ size=<size> - Virtual disk size
1131
1132
Note that not all of these options may be amendable.
1133
1134
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
1135
Creation options for 'qcow2':
1136
-size Virtual disk size
1137
-compat Compatibility level (0.10 or 1.1)
1138
-backing_file File name of a base image
1139
-backing_fmt Image format of the base image
1140
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1141
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1142
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1143
-encrypt.cipher-alg Name of encryption cipher algorithm
1144
-encrypt.cipher-mode Name of encryption cipher mode
1145
-encrypt.ivgen-alg Name of IV generator algorithm
1146
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1147
-encrypt.hash-alg Name of encryption hash algorithm
1148
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1149
-cluster_size qcow2 cluster size
1150
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1151
-lazy_refcounts Postpone refcount updates
1152
-refcount_bits Width of a reference count entry in bits
1153
+ backing_file=<str> - File name of a base image
1154
+ backing_fmt=<str> - Image format of the base image
1155
+ cluster_size=<size> - qcow2 cluster size
1156
+ compat=<str> - Compatibility level (0.10 or 1.1)
1157
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1158
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1159
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1160
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1161
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1162
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1163
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1164
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1165
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1166
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1167
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1168
+ refcount_bits=<num> - Width of a reference count entry in bits
1169
+ size=<size> - Virtual disk size
1170
1171
Note that not all of these options may be amendable.
1172
1173
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
1174
1175
Testing: amend -f qcow2 -o help
1176
Creation options for 'qcow2':
1177
-size Virtual disk size
1178
-compat Compatibility level (0.10 or 1.1)
1179
-backing_file File name of a base image
1180
-backing_fmt Image format of the base image
1181
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1182
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1183
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1184
-encrypt.cipher-alg Name of encryption cipher algorithm
1185
-encrypt.cipher-mode Name of encryption cipher mode
1186
-encrypt.ivgen-alg Name of IV generator algorithm
1187
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1188
-encrypt.hash-alg Name of encryption hash algorithm
1189
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1190
-cluster_size qcow2 cluster size
1191
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1192
-lazy_refcounts Postpone refcount updates
1193
-refcount_bits Width of a reference count entry in bits
1194
+ backing_file=<str> - File name of a base image
1195
+ backing_fmt=<str> - Image format of the base image
1196
+ cluster_size=<size> - qcow2 cluster size
1197
+ compat=<str> - Compatibility level (0.10 or 1.1)
1198
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1199
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1200
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1201
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1202
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1203
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1204
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1205
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1206
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1207
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1208
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1209
+ refcount_bits=<num> - Width of a reference count entry in bits
1210
+ size=<size> - Virtual disk size
1211
1212
Note that not all of these options may be amendable.
1213
1214
Testing: convert -o help
1215
Supported options:
1216
-size Virtual disk size
1217
+ size=<size> - Virtual disk size
1218
1219
Testing: amend -f bochs -o help
1220
qemu-img: Format driver 'bochs' does not support option amendment
93
--
1221
--
94
1.8.3.1
1222
2.19.1
95
1223
96
1224
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
In discard_single_l2(), we completely discard normal clusters instead of
3
Following the example of qemu_opts_print_help(), indent all entries in
4
simply turning them into preallocated zero clusters. That means we
4
the list of character devices.
5
should probably do the same with such preallocated zero clusters:
6
Discard them instead of keeping them allocated.
7
5
8
Reported-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
block/qcow2-cluster.c | 3 ++-
10
chardev/char.c | 2 +-
14
1 file changed, 2 insertions(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
15
12
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
13
diff --git a/chardev/char.c b/chardev/char.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cluster.c
15
--- a/chardev/char.c
19
+++ b/block/qcow2-cluster.c
16
+++ b/chardev/char.c
20
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
17
@@ -XXX,XX +XXX,XX @@ help_string_append(const char *name, void *opaque)
21
break;
18
{
22
19
GString *str = opaque;
23
case QCOW2_CLUSTER_ZERO:
20
24
- if (!full_discard) {
21
- g_string_append_printf(str, "\n%s", name);
25
+ /* Preallocated zero clusters should be discarded in any case */
22
+ g_string_append_printf(str, "\n %s", name);
26
+ if (!full_discard && (old_l2_entry & L2E_OFFSET_MASK) == 0) {
23
}
27
continue;
24
28
}
25
static const char *chardev_alias_translate(const char *name)
29
break;
30
--
26
--
31
1.8.3.1
27
2.19.1
32
28
33
29
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Add --force-share/-U to program options and -U to open subcommand.
3
Just like in qemu_opts_print_help(), print the device name as a caption
4
instead of on every single line, indent all options, add angle brackets
5
around types, and align the descriptions after 24 characters. Also,
6
separate the descriptions with " - " instead of putting them in
7
parentheses, because that is what we do everywhere else. This does look
8
a bit funny here because basically all bits have the description
9
"on/off", but funny does not mean it is less readable.
4
10
5
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
14
---
8
qemu-io.c | 42 ++++++++++++++++++++++++++++++++++--------
15
qdev-monitor.c | 13 +++++++++++--
9
1 file changed, 34 insertions(+), 8 deletions(-)
16
1 file changed, 11 insertions(+), 2 deletions(-)
10
17
11
diff --git a/qemu-io.c b/qemu-io.c
18
diff --git a/qdev-monitor.c b/qdev-monitor.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/qemu-io.c
20
--- a/qdev-monitor.c
14
+++ b/qemu-io.c
21
+++ b/qdev-monitor.c
15
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ int qdev_device_help(QemuOpts *opts)
16
#include "qemu/readline.h"
23
goto error;
17
#include "qemu/log.h"
18
#include "qapi/qmp/qstring.h"
19
+#include "qapi/qmp/qbool.h"
20
#include "qom/object_interfaces.h"
21
#include "sysemu/block-backend.h"
22
#include "block/block_int.h"
23
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t close_cmd = {
24
.oneline = "close the current open file",
25
};
26
27
-static int openfile(char *name, int flags, bool writethrough, QDict *opts)
28
+static int openfile(char *name, int flags, bool writethrough, bool force_share,
29
+ QDict *opts)
30
{
31
Error *local_err = NULL;
32
BlockDriverState *bs;
33
@@ -XXX,XX +XXX,XX @@ static int openfile(char *name, int flags, bool writethrough, QDict *opts)
34
return 1;
35
}
24
}
36
25
37
+ if (force_share) {
26
+ if (prop_list) {
38
+ if (!opts) {
27
+ out_printf("%s options:\n", driver);
39
+ opts = qdict_new();
28
+ } else {
40
+ }
29
+ out_printf("There are no options for %s.\n", driver);
41
+ if (qdict_haskey(opts, BDRV_OPT_FORCE_SHARE)
42
+ && !qdict_get_bool(opts, BDRV_OPT_FORCE_SHARE)) {
43
+ error_report("-U conflicts with image options");
44
+ QDECREF(opts);
45
+ return 1;
46
+ }
47
+ qdict_put(opts, BDRV_OPT_FORCE_SHARE, qbool_from_bool(true));
48
+ }
30
+ }
49
qemuio_blk = blk_new_open(name, NULL, opts, flags, &local_err);
31
for (prop = prop_list; prop; prop = prop->next) {
50
if (!qemuio_blk) {
32
- out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
51
error_reportf_err(local_err, "can't open%s%s: ",
33
+ int len;
52
@@ -XXX,XX +XXX,XX @@ static void open_help(void)
34
+ out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
53
" -r, -- open file read-only\n"
35
if (prop->value->has_description) {
54
" -s, -- use snapshot file\n"
36
- out_printf(" (%s)\n", prop->value->description);
55
" -n, -- disable host cache, short for -t none\n"
37
+ if (len < 24) {
56
+" -U, -- force shared permissions\n"
38
+ out_printf("%*s", 24 - len, "");
57
" -k, -- use kernel AIO implementation (on Linux only)\n"
39
+ }
58
" -t, -- use the given cache mode for the image\n"
40
+ out_printf(" - %s\n", prop->value->description);
59
" -d, -- use the given discard mode for the image\n"
60
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t open_cmd = {
61
.argmin = 1,
62
.argmax = -1,
63
.flags = CMD_NOFILE_OK,
64
- .args = "[-rsnk] [-t cache] [-d discard] [-o options] [path]",
65
+ .args = "[-rsnkU] [-t cache] [-d discard] [-o options] [path]",
66
.oneline = "open the file specified by path",
67
.help = open_help,
68
};
69
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
70
int c;
71
QemuOpts *qopts;
72
QDict *opts;
73
+ bool force_share = false;
74
75
- while ((c = getopt(argc, argv, "snro:kt:d:")) != -1) {
76
+ while ((c = getopt(argc, argv, "snro:kt:d:U")) != -1) {
77
switch (c) {
78
case 's':
79
flags |= BDRV_O_SNAPSHOT;
80
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
81
return 0;
82
}
83
break;
84
+ case 'U':
85
+ force_share = true;
86
+ break;
87
default:
88
qemu_opts_reset(&empty_opts);
89
return qemuio_command_usage(&open_cmd);
90
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
91
qemu_opts_reset(&empty_opts);
92
93
if (optind == argc - 1) {
94
- return openfile(argv[optind], flags, writethrough, opts);
95
+ return openfile(argv[optind], flags, writethrough, force_share, opts);
96
} else if (optind == argc) {
97
- return openfile(NULL, flags, writethrough, opts);
98
+ return openfile(NULL, flags, writethrough, force_share, opts);
99
} else {
100
QDECREF(opts);
101
return qemuio_command_usage(&open_cmd);
102
@@ -XXX,XX +XXX,XX @@ static void usage(const char *name)
103
" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
104
" specify tracing options\n"
105
" see qemu-img(1) man page for full description\n"
106
+" -U, --force-share force shared permissions\n"
107
" -h, --help display this help and exit\n"
108
" -V, --version output version information and exit\n"
109
"\n"
110
@@ -XXX,XX +XXX,XX @@ static QemuOptsList file_opts = {
111
int main(int argc, char **argv)
112
{
113
int readonly = 0;
114
- const char *sopt = "hVc:d:f:rsnmkt:T:";
115
+ const char *sopt = "hVc:d:f:rsnmkt:T:U";
116
const struct option lopt[] = {
117
{ "help", no_argument, NULL, 'h' },
118
{ "version", no_argument, NULL, 'V' },
119
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
120
{ "trace", required_argument, NULL, 'T' },
121
{ "object", required_argument, NULL, OPTION_OBJECT },
122
{ "image-opts", no_argument, NULL, OPTION_IMAGE_OPTS },
123
+ { "force-share", no_argument, 0, 'U'},
124
{ NULL, 0, NULL, 0 }
125
};
126
int c;
127
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
128
QDict *opts = NULL;
129
const char *format = NULL;
130
char *trace_file = NULL;
131
+ bool force_share = false;
132
133
#ifdef CONFIG_POSIX
134
signal(SIGPIPE, SIG_IGN);
135
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
136
case 'h':
137
usage(progname);
138
exit(0);
139
+ case 'U':
140
+ force_share = true;
141
+ break;
142
case OPTION_OBJECT: {
143
QemuOpts *qopts;
144
qopts = qemu_opts_parse_noisily(&qemu_object_opts,
145
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
146
exit(1);
147
}
148
opts = qemu_opts_to_qdict(qopts, NULL);
149
- if (openfile(NULL, flags, writethrough, opts)) {
150
+ if (openfile(NULL, flags, writethrough, force_share, opts)) {
151
exit(1);
152
}
153
} else {
41
} else {
154
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
42
out_printf("\n");
155
opts = qdict_new();
156
qdict_put_str(opts, "driver", format);
157
}
158
- if (openfile(argv[optind], flags, writethrough, opts)) {
159
+ if (openfile(argv[optind], flags, writethrough,
160
+ force_share, opts)) {
161
exit(1);
162
}
163
}
43
}
164
--
44
--
165
1.8.3.1
45
2.19.1
166
46
167
47
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
qemu-img and qemu-io commands when guest is running need "-U" option,
4
add it.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/030 | 18 +++++++++---------
10
1 file changed, 9 insertions(+), 9 deletions(-)
11
12
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/030
15
+++ b/tests/qemu-iotests/030
16
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
17
def test_stream_intermediate(self):
18
self.assert_no_active_block_jobs()
19
20
- self.assertNotEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
21
- qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
22
+ self.assertNotEqual(qemu_io('-f', 'raw', '-rU', '-c', 'map', backing_img),
23
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', mid_img),
24
'image file map matches backing file before streaming')
25
26
result = self.vm.qmp('block-stream', device='mid', job_id='stream-mid')
27
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
28
self.assert_no_active_block_jobs()
29
30
# The image map is empty before the operation
31
- empty_map = qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img)
32
+ empty_map = qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', test_img)
33
34
# This is a no-op: no data should ever be copied from the base image
35
result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
36
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
37
38
# Check that the maps don't match before the streaming operations
39
for i in range(2, self.num_imgs, 2):
40
- self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i]),
41
- qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i-1]),
42
+ self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i]),
43
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i-1]),
44
'image file map matches backing file before streaming')
45
46
# Create all streaming jobs
47
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
48
def test_stream_base_node_name(self):
49
self.assert_no_active_block_jobs()
50
51
- self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[4]),
52
- qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[3]),
53
+ self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[4]),
54
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[3]),
55
'image file map matches backing file before streaming')
56
57
# Error: the base node does not exist
58
@@ -XXX,XX +XXX,XX @@ class TestQuorum(iotests.QMPTestCase):
59
if not iotests.supports_quorum():
60
return
61
62
- self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.children[0]),
63
- qemu_io('-f', iotests.imgfmt, '-c', 'map', self.backing[0]),
64
+ self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]),
65
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]),
66
'image file map matches backing file before streaming')
67
68
self.assert_no_active_block_jobs()
69
--
70
1.8.3.1
71
72
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Instead of just freeing preallocated zero clusters and completely
3
Just like in qemu_opts_print_help(), print the object name as a caption
4
allocating them from scratch, reuse them.
4
instead of on every single line, indent all options, add angle brackets
5
around types, and align the descriptions after 24 characters.
5
6
6
We cannot do this in handle_copied(), however, since this is a COW
7
Also, indent every object name in the list of available objects.
7
operation. Therefore, we have to add the new logic to handle_alloc() and
8
simply return the existing offset if it exists. The only catch is that
9
we have to convince qcow2_alloc_cluster_link_l2() not to free the old
10
clusters (because we have reused them).
11
8
12
Reported-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
12
---
17
block/qcow2-cluster.c | 80 +++++++++++++++++++++++++++++++++++----------------
13
vl.c | 13 ++++++++++---
18
block/qcow2.h | 3 ++
14
1 file changed, 10 insertions(+), 3 deletions(-)
19
2 files changed, 59 insertions(+), 24 deletions(-)
20
15
21
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
16
diff --git a/vl.c b/vl.c
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-cluster.c
18
--- a/vl.c
24
+++ b/block/qcow2-cluster.c
19
+++ b/vl.c
25
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
20
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
26
uint64_t *l2_table, uint64_t stop_flags)
21
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
27
{
22
for (l = list; l != NULL; l = l->next) {
28
int i;
23
ObjectClass *oc = OBJECT_CLASS(l->data);
29
+ int first_cluster_type;
24
- printf("%s\n", object_class_get_name(oc));
30
uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
25
+ printf(" %s\n", object_class_get_name(oc));
31
uint64_t first_entry = be64_to_cpu(l2_table[0]);
26
}
32
uint64_t offset = first_entry & mask;
27
g_slist_free(list);
33
28
exit(0);
34
- if (!offset)
29
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
35
+ if (!offset) {
30
}
36
return 0;
31
37
+ }
32
str = g_string_new(NULL);
38
33
- g_string_append_printf(str, "%s.%s=%s", type,
39
- assert(qcow2_get_cluster_type(first_entry) == QCOW2_CLUSTER_NORMAL);
34
- prop->name, prop->type);
40
+ /* must be allocated */
35
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
41
+ first_cluster_type = qcow2_get_cluster_type(first_entry);
36
if (prop->description) {
42
+ assert(first_cluster_type == QCOW2_CLUSTER_NORMAL ||
37
+ if (str->len < 24) {
43
+ (first_cluster_type == QCOW2_CLUSTER_ZERO &&
38
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
44
+ (first_entry & L2E_OFFSET_MASK) != 0));
39
+ }
45
40
g_string_append_printf(str, " - %s", prop->description);
46
for (i = 0; i < nb_clusters; i++) {
41
}
47
uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
42
g_ptr_array_add(array, g_string_free(str, false));
48
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
43
}
49
* Don't discard clusters that reach a refcount of 0 (e.g. compressed
44
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
50
* clusters), the next write will reuse them anyway.
45
+ if (array->len > 0) {
51
*/
46
+ printf("%s options:\n", type);
52
- if (j != 0) {
47
+ } else {
53
+ if (!m->keep_old_clusters && j != 0) {
48
+ printf("There are no options for %s.\n", type);
54
for (i = 0; i < j; i++) {
55
qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1,
56
QCOW2_DISCARD_NEVER);
57
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
58
uint64_t entry;
59
uint64_t nb_clusters;
60
int ret;
61
+ bool keep_old_clusters = false;
62
63
- uint64_t alloc_cluster_offset;
64
+ uint64_t alloc_cluster_offset = 0;
65
66
trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
67
*bytes);
68
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
69
* wrong with our code. */
70
assert(nb_clusters > 0);
71
72
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
73
+ if (qcow2_get_cluster_type(entry) == QCOW2_CLUSTER_ZERO &&
74
+ (entry & L2E_OFFSET_MASK) != 0 && (entry & QCOW_OFLAG_COPIED) &&
75
+ (!*host_offset ||
76
+ start_of_cluster(s, *host_offset) == (entry & L2E_OFFSET_MASK)))
77
+ {
78
+ /* Try to reuse preallocated zero clusters; contiguous normal clusters
79
+ * would be fine, too, but count_cow_clusters() above has limited
80
+ * nb_clusters already to a range of COW clusters */
81
+ int preallocated_nb_clusters =
82
+ count_contiguous_clusters(nb_clusters, s->cluster_size,
83
+ &l2_table[l2_index], QCOW_OFLAG_COPIED);
84
+ assert(preallocated_nb_clusters > 0);
85
86
- /* Allocate, if necessary at a given offset in the image file */
87
- alloc_cluster_offset = start_of_cluster(s, *host_offset);
88
- ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
89
- &nb_clusters);
90
- if (ret < 0) {
91
- goto fail;
92
- }
93
+ nb_clusters = preallocated_nb_clusters;
94
+ alloc_cluster_offset = entry & L2E_OFFSET_MASK;
95
96
- /* Can't extend contiguous allocation */
97
- if (nb_clusters == 0) {
98
- *bytes = 0;
99
- return 0;
100
+ /* We want to reuse these clusters, so qcow2_alloc_cluster_link_l2()
101
+ * should not free them. */
102
+ keep_old_clusters = true;
103
}
104
105
- /* !*host_offset would overwrite the image header and is reserved for "no
106
- * host offset preferred". If 0 was a valid host offset, it'd trigger the
107
- * following overlap check; do that now to avoid having an invalid value in
108
- * *host_offset. */
109
+ qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
110
+
111
if (!alloc_cluster_offset) {
112
- ret = qcow2_pre_write_overlap_check(bs, 0, alloc_cluster_offset,
113
- nb_clusters * s->cluster_size);
114
- assert(ret < 0);
115
- goto fail;
116
+ /* Allocate, if necessary at a given offset in the image file */
117
+ alloc_cluster_offset = start_of_cluster(s, *host_offset);
118
+ ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
119
+ &nb_clusters);
120
+ if (ret < 0) {
121
+ goto fail;
122
+ }
49
+ }
123
+
50
for (i = 0; i < array->len; i++) {
124
+ /* Can't extend contiguous allocation */
51
printf("%s\n", (char *)array->pdata[i]);
125
+ if (nb_clusters == 0) {
52
}
126
+ *bytes = 0;
127
+ return 0;
128
+ }
129
+
130
+ /* !*host_offset would overwrite the image header and is reserved for
131
+ * "no host offset preferred". If 0 was a valid host offset, it'd
132
+ * trigger the following overlap check; do that now to avoid having an
133
+ * invalid value in *host_offset. */
134
+ if (!alloc_cluster_offset) {
135
+ ret = qcow2_pre_write_overlap_check(bs, 0, alloc_cluster_offset,
136
+ nb_clusters * s->cluster_size);
137
+ assert(ret < 0);
138
+ goto fail;
139
+ }
140
}
141
142
/*
143
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
144
.offset = start_of_cluster(s, guest_offset),
145
.nb_clusters = nb_clusters,
146
147
+ .keep_old_clusters = keep_old_clusters,
148
+
149
.cow_start = {
150
.offset = 0,
151
.nb_bytes = offset_into_cluster(s, guest_offset),
152
diff --git a/block/qcow2.h b/block/qcow2.h
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/qcow2.h
155
+++ b/block/qcow2.h
156
@@ -XXX,XX +XXX,XX @@ typedef struct QCowL2Meta
157
/** Number of newly allocated clusters */
158
int nb_clusters;
159
160
+ /** Do not free the old clusters */
161
+ bool keep_old_clusters;
162
+
163
/**
164
* Requests that overlap with this allocation and wait to be restarted
165
* when the allocating request has completed.
166
--
53
--
167
1.8.3.1
54
2.19.1
168
55
169
56
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
066 was supposed to be a test "for discarding preallocated zero
3
There is no good reason why there should be a newline in this
4
clusters", but it did so incompletely: While it did check the image
4
description, so remove it.
5
file's integrity after the operation, it did not confirm that the
6
clusters are indeed freed. This patch adds this test.
7
8
In addition, new cases for writing to preallocated zero clusters are
9
added.
10
5
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
10
---
15
tests/qemu-iotests/066 | 128 ++++++++++++++++++++++++++++++++++++++++++++-
11
vl.c | 2 +-
16
tests/qemu-iotests/066.out | 46 ++++++++++++++++
12
1 file changed, 1 insertion(+), 1 deletion(-)
17
2 files changed, 173 insertions(+), 1 deletion(-)
18
13
19
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
14
diff --git a/vl.c b/vl.c
20
index XXXXXXX..XXXXXXX 100755
21
--- a/tests/qemu-iotests/066
22
+++ b/tests/qemu-iotests/066
23
@@ -XXX,XX +XXX,XX @@
24
#!/bin/bash
25
#
26
-# Test case for discarding preallocated zero clusters in qcow2
27
+# Test case for preallocated zero clusters in qcow2
28
#
29
# Copyright (C) 2013 Red Hat, Inc.
30
#
31
@@ -XXX,XX +XXX,XX @@ _make_test_img $IMG_SIZE
32
$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "write 64M 512" \
33
     -c "discard 0 $IMG_SIZE" -c "read -P 0 0 $IMG_SIZE" "$TEST_IMG" \
34
| _filter_qemu_io
35
+
36
# Check the image (there shouldn't be any leaks)
37
_check_test_img
38
+# Map the image (we want all clusters to be gone)
39
+$QEMU_IMG map "$TEST_IMG"
40
+
41
+_cleanup_test_img
42
+
43
+
44
+echo
45
+echo '=== Writing to preallocated zero clusters ==='
46
+echo
47
+
48
+_make_test_img $IMG_SIZE
49
+
50
+# Create data clusters (not aligned to an L2 table)
51
+$QEMU_IO -c 'write -P 42 1M 256k' "$TEST_IMG" | _filter_qemu_io
52
+orig_map=$($QEMU_IMG map --output=json "$TEST_IMG")
53
+
54
+# Convert the data clusters to preallocated zero clusters
55
+$QEMU_IO -c 'write -z 1M 256k' "$TEST_IMG" | _filter_qemu_io
56
+
57
+# Now write to them (with a COW needed for the head and tail)
58
+$QEMU_IO -c "write -P 23 $(((1024 + 32) * 1024)) 192k" "$TEST_IMG" \
59
+ | _filter_qemu_io
60
+
61
+# Check metadata correctness
62
+_check_test_img
63
+
64
+# Check data correctness
65
+$QEMU_IO -c "read -P 0 $(( 1024 * 1024)) 32k" \
66
+ -c "read -P 23 $(((1024 + 32) * 1024)) 192k" \
67
+ -c "read -P 0 $(((1024 + 32 + 192) * 1024)) 32k" \
68
+ "$TEST_IMG" \
69
+ | _filter_qemu_io
70
+
71
+# Check that we have actually reused the original area
72
+new_map=$($QEMU_IMG map --output=json "$TEST_IMG")
73
+if [ "$new_map" = "$orig_map" ]; then
74
+ echo 'Successfully reused original clusters.'
75
+else
76
+ echo 'Failed to reuse original clusters.'
77
+ echo 'Original map:'
78
+ echo "$orig_map"
79
+ echo 'New map:'
80
+ echo "$new_map"
81
+fi
82
+
83
+_cleanup_test_img
84
+
85
+
86
+echo
87
+echo '=== Writing to a snapshotted preallocated zero cluster ==='
88
+echo
89
+
90
+_make_test_img 64k
91
+
92
+# Create a preallocated zero cluster
93
+$QEMU_IO -c 'write -P 42 0 64k' -c 'write -z 0 64k' "$TEST_IMG" \
94
+ | _filter_qemu_io
95
+
96
+# Snapshot it
97
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
98
+
99
+# Write to the cluster
100
+$QEMU_IO -c 'write -P 23 0 64k' "$TEST_IMG" | _filter_qemu_io
101
+
102
+# Check metadata correctness
103
+_check_test_img
104
+
105
+# Check data correctness
106
+$QEMU_IO -c 'read -P 23 0 64k' "$TEST_IMG" | _filter_qemu_io
107
+$QEMU_IMG snapshot -a foo "$TEST_IMG"
108
+$QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
109
+
110
+_cleanup_test_img
111
+
112
+
113
+echo
114
+echo '=== Consecutive write to a preallocated zero cluster ==='
115
+echo
116
+
117
+_make_test_img 192k
118
+
119
+# Create three normal clusters
120
+$QEMU_IO -c 'write -P 42 0 192k' "$TEST_IMG" | _filter_qemu_io
121
+orig_map=$($QEMU_IMG map --output=json "$TEST_IMG")
122
+
123
+# Make the middle cluster a preallocated zero cluster
124
+$QEMU_IO -c 'write -z 64k 64k' "$TEST_IMG" | _filter_qemu_io
125
+
126
+# Try to overwrite everything: This should reuse the whole range. To test that
127
+# this only issues a single continuous write request, use blkdebug.
128
+$QEMU_IO -c 'write -P 42 0 192k' \
129
+ "json:{
130
+ 'driver': '$IMGFMT',
131
+ 'file': {
132
+ 'driver': 'blkdebug',
133
+ 'image.filename': '$TEST_IMG',
134
+ 'set-state': [{
135
+ 'event': 'write_aio',
136
+ 'new_state': 2
137
+ }],
138
+ 'inject-error': [{
139
+ 'event': 'write_aio',
140
+ 'state': 2
141
+ }]
142
+ }
143
+ }" \
144
+ | _filter_qemu_io
145
+
146
+# Check metadata correctness
147
+_check_test_img
148
+
149
+# Check that we have actually reused the original area
150
+new_map=$($QEMU_IMG map --output=json "$TEST_IMG")
151
+if [ "$new_map" = "$orig_map" ]; then
152
+ echo 'Successfully reused original clusters.'
153
+else
154
+ echo 'Failed to reuse original clusters.'
155
+ echo 'Original map:'
156
+ echo "$orig_map"
157
+ echo 'New map:'
158
+ echo "$new_map"
159
+fi
160
+
161
+_cleanup_test_img
162
+
163
164
# success, all done
165
echo "*** done"
166
diff --git a/tests/qemu-iotests/066.out b/tests/qemu-iotests/066.out
167
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
168
--- a/tests/qemu-iotests/066.out
16
--- a/vl.c
169
+++ b/tests/qemu-iotests/066.out
17
+++ b/vl.c
170
@@ -XXX,XX +XXX,XX @@ discard 67109376/67109376 bytes at offset 0
18
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_fw_cfg_opts = {
171
read 67109376/67109376 bytes at offset 0
19
}, {
172
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
20
.name = "file",
173
No errors were found on the image.
21
.type = QEMU_OPT_STRING,
174
+Offset Length Mapped to File
22
- .help = "Sets the name of the file from which\n"
175
+
23
+ .help = "Sets the name of the file from which "
176
+=== Writing to preallocated zero clusters ===
24
"the fw_cfg blob will be loaded",
177
+
25
}, {
178
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67109376
26
.name = "string",
179
+wrote 262144/262144 bytes at offset 1048576
180
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
181
+wrote 262144/262144 bytes at offset 1048576
182
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
183
+wrote 196608/196608 bytes at offset 1081344
184
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
185
+No errors were found on the image.
186
+read 32768/32768 bytes at offset 1048576
187
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
188
+read 196608/196608 bytes at offset 1081344
189
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+read 32768/32768 bytes at offset 1277952
191
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
192
+Successfully reused original clusters.
193
+
194
+=== Writing to a snapshotted preallocated zero cluster ===
195
+
196
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
197
+wrote 65536/65536 bytes at offset 0
198
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
199
+wrote 65536/65536 bytes at offset 0
200
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
201
+wrote 65536/65536 bytes at offset 0
202
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
203
+No errors were found on the image.
204
+read 65536/65536 bytes at offset 0
205
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
206
+read 65536/65536 bytes at offset 0
207
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
208
+
209
+=== Consecutive write to a preallocated zero cluster ===
210
+
211
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=196608
212
+wrote 196608/196608 bytes at offset 0
213
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
214
+wrote 65536/65536 bytes at offset 65536
215
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
216
+wrote 196608/196608 bytes at offset 0
217
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
218
+No errors were found on the image.
219
+Successfully reused original clusters.
220
*** done
221
--
27
--
222
1.8.3.1
28
2.19.1
223
29
224
30
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
Double attach is not a valid usage of the target image, drive-backup
3
If an expression is used to define DEFAULT_CLUSTER_SIZE, when compiled,
4
will open the blockdev itself so skip the add_drive call in this case.
4
it will be embedded as a literal expression in the binary (as the
5
default value) because it is stringified to mark the size of the default
6
value. Now this is fixed by using a defined number to define this value.
5
7
6
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Stefan Weil <sw@weilnetz.de>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
11
---
10
tests/qemu-iotests/055 | 32 ++++++++++++++++++--------------
12
block/vdi.c | 4 ++--
11
1 file changed, 18 insertions(+), 14 deletions(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
14
13
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
15
diff --git a/block/vdi.c b/block/vdi.c
14
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/055
17
--- a/block/vdi.c
16
+++ b/tests/qemu-iotests/055
18
+++ b/block/vdi.c
17
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
19
@@ -XXX,XX +XXX,XX @@
18
except OSError:
20
#define BLOCK_OPT_STATIC "static"
19
pass
21
20
22
#define SECTOR_SIZE 512
21
- def do_prepare_drives(self, fmt, args):
23
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
22
+ def do_prepare_drives(self, fmt, args, attach_target):
24
+#define DEFAULT_CLUSTER_SIZE S_1MiB
23
self.vm = iotests.VM().add_drive(test_img)
25
24
26
#if defined(CONFIG_VDI_DEBUG)
25
qemu_img('create', '-f', fmt, blockdev_target_img,
27
#define VDI_DEBUG 1
26
str(TestDriveCompression.image_len), *args)
28
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
27
- self.vm.add_drive(blockdev_target_img, format=fmt, interface="none")
29
goto fail;
28
+ if attach_target:
30
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
29
+ self.vm.add_drive(blockdev_target_img, format=fmt, interface="none")
31
error_setg(errp, "unsupported VDI image (block size %" PRIu32
30
32
- " is not %" PRIu64 ")",
31
self.vm.launch()
33
+ " is not %" PRIu32 ")",
32
34
header.block_size, DEFAULT_CLUSTER_SIZE);
33
- def do_test_compress_complete(self, cmd, format, **args):
35
ret = -ENOTSUP;
34
- self.do_prepare_drives(format['type'], format['args'])
36
goto fail;
35
+ def do_test_compress_complete(self, cmd, format, attach_target, **args):
36
+ self.do_prepare_drives(format['type'], format['args'], attach_target)
37
38
self.assert_no_active_block_jobs()
39
40
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
41
42
def test_complete_compress_drive_backup(self):
43
for format in TestDriveCompression.fmt_supports_compression:
44
- self.do_test_compress_complete('drive-backup', format,
45
+ self.do_test_compress_complete('drive-backup', format, False,
46
target=blockdev_target_img, mode='existing')
47
48
def test_complete_compress_blockdev_backup(self):
49
for format in TestDriveCompression.fmt_supports_compression:
50
- self.do_test_compress_complete('blockdev-backup', format, target='drive1')
51
+ self.do_test_compress_complete('blockdev-backup', format, True,
52
+ target='drive1')
53
54
- def do_test_compress_cancel(self, cmd, format, **args):
55
- self.do_prepare_drives(format['type'], format['args'])
56
+ def do_test_compress_cancel(self, cmd, format, attach_target, **args):
57
+ self.do_prepare_drives(format['type'], format['args'], attach_target)
58
59
self.assert_no_active_block_jobs()
60
61
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
62
63
def test_compress_cancel_drive_backup(self):
64
for format in TestDriveCompression.fmt_supports_compression:
65
- self.do_test_compress_cancel('drive-backup', format,
66
+ self.do_test_compress_cancel('drive-backup', format, False,
67
target=blockdev_target_img, mode='existing')
68
69
def test_compress_cancel_blockdev_backup(self):
70
for format in TestDriveCompression.fmt_supports_compression:
71
- self.do_test_compress_cancel('blockdev-backup', format, target='drive1')
72
+ self.do_test_compress_cancel('blockdev-backup', format, True,
73
+ target='drive1')
74
75
- def do_test_compress_pause(self, cmd, format, **args):
76
- self.do_prepare_drives(format['type'], format['args'])
77
+ def do_test_compress_pause(self, cmd, format, attach_target, **args):
78
+ self.do_prepare_drives(format['type'], format['args'], attach_target)
79
80
self.assert_no_active_block_jobs()
81
82
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
83
84
def test_compress_pause_drive_backup(self):
85
for format in TestDriveCompression.fmt_supports_compression:
86
- self.do_test_compress_pause('drive-backup', format,
87
+ self.do_test_compress_pause('drive-backup', format, False,
88
target=blockdev_target_img, mode='existing')
89
90
def test_compress_pause_blockdev_backup(self):
91
for format in TestDriveCompression.fmt_supports_compression:
92
- self.do_test_compress_pause('blockdev-backup', format, target='drive1')
93
+ self.do_test_compress_pause('blockdev-backup', format, True,
94
+ target='drive1')
95
96
if __name__ == '__main__':
97
iotests.main(supported_fmts=['raw', 'qcow2'])
98
--
37
--
99
1.8.3.1
38
2.19.1
100
39
101
40
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
To avoid image lock failures.
4
5
Signed-off-by: Fam Zheng <famz@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
tests/qemu-iotests/172 | 55 +++++++++++++++++++++++++---------------------
9
tests/qemu-iotests/172.out | 50 +++++++++++++++++++++--------------------
10
2 files changed, 56 insertions(+), 49 deletions(-)
11
12
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/172
15
+++ b/tests/qemu-iotests/172
16
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
17
_cleanup()
18
{
19
    _cleanup_test_img
20
+ rm -f "$TEST_IMG.2"
21
+ rm -f "$TEST_IMG.3"
22
}
23
trap "_cleanup; exit \$status" 0 1 2 3 15
24
25
@@ -XXX,XX +XXX,XX @@ size=720k
26
27
_make_test_img $size
28
29
+TEST_IMG="$TEST_IMG.2" _make_test_img $size
30
+TEST_IMG="$TEST_IMG.3" _make_test_img $size
31
+
32
# Default drive semantics:
33
#
34
# By default you get a single empty floppy drive. You can override it with
35
@@ -XXX,XX +XXX,XX @@ echo === Using -fda/-fdb options ===
36
37
check_floppy_qtree -fda "$TEST_IMG"
38
check_floppy_qtree -fdb "$TEST_IMG"
39
-check_floppy_qtree -fda "$TEST_IMG" -fdb "$TEST_IMG"
40
+check_floppy_qtree -fda "$TEST_IMG" -fdb "$TEST_IMG.2"
41
42
43
echo
44
@@ -XXX,XX +XXX,XX @@ echo === Using -drive options ===
45
46
check_floppy_qtree -drive if=floppy,file="$TEST_IMG"
47
check_floppy_qtree -drive if=floppy,file="$TEST_IMG",index=1
48
-check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=floppy,file="$TEST_IMG",index=1
49
+check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=floppy,file="$TEST_IMG.2",index=1
50
51
echo
52
echo
53
@@ -XXX,XX +XXX,XX @@ echo === Using -drive if=none and -global ===
54
55
check_floppy_qtree -drive if=none,file="$TEST_IMG" -global isa-fdc.driveA=none0
56
check_floppy_qtree -drive if=none,file="$TEST_IMG" -global isa-fdc.driveB=none0
57
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
58
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
59
-global isa-fdc.driveA=none0 -global isa-fdc.driveB=none1
60
61
echo
62
@@ -XXX,XX +XXX,XX @@ echo === Using -drive if=none and -device ===
63
64
check_floppy_qtree -drive if=none,file="$TEST_IMG" -device floppy,drive=none0
65
check_floppy_qtree -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=1
66
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
67
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
68
-device floppy,drive=none0 -device floppy,drive=none1,unit=1
69
70
echo
71
@@ -XXX,XX +XXX,XX @@ echo
72
echo === Mixing -fdX and -global ===
73
74
# Working
75
-check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG" -global isa-fdc.driveB=none0
76
-check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG" -global isa-fdc.driveA=none0
77
+check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveB=none0
78
+check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveA=none0
79
80
# Conflicting (-fdX wins)
81
-check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG" -global isa-fdc.driveA=none0
82
-check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG" -global isa-fdc.driveB=none0
83
+check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveA=none0
84
+check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveB=none0
85
86
echo
87
echo
88
echo === Mixing -fdX and -device ===
89
90
# Working
91
-check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0
92
-check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=1
93
+check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0
94
+check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0,unit=1
95
96
-check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0
97
-check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=0
98
+check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0
99
+check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0,unit=0
100
101
# Conflicting
102
-check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=0
103
-check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=1
104
+check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0,unit=0
105
+check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0,unit=1
106
107
echo
108
echo
109
echo === Mixing -drive and -device ===
110
111
# Working
112
-check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0
113
-check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=1
114
+check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0
115
+check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0,unit=1
116
117
# Conflicting
118
-check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" -device floppy,drive=none0,unit=0
119
+check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -device floppy,drive=none0,unit=0
120
121
echo
122
echo
123
echo === Mixing -global and -device ===
124
125
# Working
126
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
127
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
128
-global isa-fdc.driveA=none0 -device floppy,drive=none1
129
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
130
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
131
-global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=1
132
133
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
134
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
135
-global isa-fdc.driveB=none0 -device floppy,drive=none1
136
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
137
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
138
-global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0
139
140
# Conflicting
141
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
142
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
143
-global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0
144
-check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG" \
145
+check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \
146
-global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1
147
148
echo
149
@@ -XXX,XX +XXX,XX @@ echo === Too many floppy drives ===
150
151
# Working
152
check_floppy_qtree -drive if=floppy,file="$TEST_IMG" \
153
- -drive if=none,file="$TEST_IMG" \
154
- -drive if=none,file="$TEST_IMG" \
155
+ -drive if=none,file="$TEST_IMG.2" \
156
+ -drive if=none,file="$TEST_IMG.3" \
157
-global isa-fdc.driveB=none0 \
158
-device floppy,drive=none1
159
160
diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out
161
index XXXXXXX..XXXXXXX 100644
162
--- a/tests/qemu-iotests/172.out
163
+++ b/tests/qemu-iotests/172.out
164
@@ -XXX,XX +XXX,XX @@
165
QA output created by 172
166
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=737280
167
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=737280
168
+Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=737280
169
170
171
=== Default ===
172
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2
173
share-rw = false
174
drive-type = "288"
175
176
-Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2
177
+Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
178
179
dev: isa-fdc, id ""
180
iobase = 1008 (0x3f0)
181
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
182
share-rw = false
183
drive-type = "288"
184
185
-Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
186
+Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t.qcow2.2,index=1
187
188
dev: isa-fdc, id ""
189
iobase = 1008 (0x3f0)
190
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0
191
share-rw = false
192
drive-type = "144"
193
194
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 -global isa-fdc.driveB=none1
195
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -global isa-fdc.driveB=none1
196
197
dev: isa-fdc, id ""
198
iobase = 1008 (0x3f0)
199
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
200
share-rw = false
201
drive-type = "144"
202
203
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0 -device floppy,drive=none1,unit=1
204
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0 -device floppy,drive=none1,unit=1
205
206
dev: isa-fdc, id ""
207
iobase = 1008 (0x3f0)
208
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
209
210
=== Mixing -fdX and -global ===
211
212
-Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0
213
+Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0
214
215
dev: isa-fdc, id ""
216
iobase = 1008 (0x3f0)
217
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-
218
share-rw = false
219
drive-type = "144"
220
221
-Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0
222
+Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0
223
224
dev: isa-fdc, id ""
225
iobase = 1008 (0x3f0)
226
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-
227
share-rw = false
228
drive-type = "144"
229
230
-Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0
231
+Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0
232
233
dev: isa-fdc, id ""
234
iobase = 1008 (0x3f0)
235
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-
236
share-rw = false
237
drive-type = "144"
238
239
-Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0
240
+Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0
241
242
dev: isa-fdc, id ""
243
iobase = 1008 (0x3f0)
244
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-
245
246
=== Mixing -fdX and -device ===
247
248
-Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
249
+Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0
250
251
dev: isa-fdc, id ""
252
iobase = 1008 (0x3f0)
253
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device flop
254
share-rw = false
255
drive-type = "144"
256
257
-Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
258
+Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=1
259
260
dev: isa-fdc, id ""
261
iobase = 1008 (0x3f0)
262
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device flop
263
share-rw = false
264
drive-type = "144"
265
266
-Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
267
+Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0
268
269
dev: isa-fdc, id ""
270
iobase = 1008 (0x3f0)
271
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device flop
272
share-rw = false
273
drive-type = "144"
274
275
-Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=0
276
+Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0
277
278
dev: isa-fdc, id ""
279
iobase = 1008 (0x3f0)
280
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device flop
281
share-rw = false
282
drive-type = "144"
283
284
-Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=0
285
+Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0
286
QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use
287
QEMU_PROG: -device floppy,drive=none0,unit=0: Device initialization failed.
288
289
-Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
290
+Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=1
291
QEMU_PROG: -device floppy,drive=none0,unit=1: Floppy unit 1 is in use
292
QEMU_PROG: -device floppy,drive=none0,unit=1: Device initialization failed.
293
294
295
=== Mixing -drive and -device ===
296
297
-Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
298
+Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0
299
300
dev: isa-fdc, id ""
301
iobase = 1008 (0x3f0)
302
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
303
share-rw = false
304
drive-type = "144"
305
306
-Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
307
+Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=1
308
309
dev: isa-fdc, id ""
310
iobase = 1008 (0x3f0)
311
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
312
share-rw = false
313
drive-type = "144"
314
315
-Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=0
316
+Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0
317
QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use
318
QEMU_PROG: -device floppy,drive=none0,unit=0: Device initialization failed.
319
320
321
=== Mixing -global and -device ===
322
323
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 -device floppy,drive=none1
324
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1
325
326
dev: isa-fdc, id ""
327
iobase = 1008 (0x3f0)
328
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
329
share-rw = false
330
drive-type = "144"
331
332
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=1
333
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=1
334
335
dev: isa-fdc, id ""
336
iobase = 1008 (0x3f0)
337
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
338
share-rw = false
339
drive-type = "144"
340
341
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 -device floppy,drive=none1
342
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1
343
344
dev: isa-fdc, id ""
345
iobase = 1008 (0x3f0)
346
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
347
share-rw = false
348
drive-type = "144"
349
350
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0
351
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0
352
353
dev: isa-fdc, id ""
354
iobase = 1008 (0x3f0)
355
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
356
share-rw = false
357
drive-type = "144"
358
359
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0
360
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0
361
QEMU_PROG: -device floppy,drive=none1,unit=0: Floppy unit 0 is in use
362
QEMU_PROG: -device floppy,drive=none1,unit=0: Device initialization failed.
363
364
-Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1
365
+Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1
366
QEMU_PROG: -device floppy,drive=none1,unit=1: Floppy unit 1 is in use
367
QEMU_PROG: -device floppy,drive=none1,unit=1: Device initialization failed.
368
369
370
=== Too many floppy drives ===
371
372
-Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 -device floppy,drive=none1
373
+Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -drive if=none,file=TEST_DIR/t.qcow2.3 -global isa-fdc.driveB=none0 -device floppy,drive=none1
374
QEMU_PROG: -device floppy,drive=none1: Can't create floppy unit 2, bus supports only 2 units
375
QEMU_PROG: -device floppy,drive=none1: Device initialization failed.
376
377
--
378
1.8.3.1
379
380
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Signed-off-by: Fam Zheng <famz@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/drive_del-test.c | 2 +-
8
tests/nvme-test.c | 2 +-
9
tests/usb-hcd-uhci-test.c | 2 +-
10
tests/usb-hcd-xhci-test.c | 2 +-
11
tests/virtio-blk-test.c | 2 +-
12
tests/virtio-scsi-test.c | 5 +++--
13
6 files changed, 8 insertions(+), 7 deletions(-)
14
15
diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/drive_del-test.c
18
+++ b/tests/drive_del-test.c
19
@@ -XXX,XX +XXX,XX @@ static void test_after_failed_device_add(void)
20
static void test_drive_del_device_del(void)
21
{
22
/* Start with a drive used by a device that unplugs instantaneously */
23
- qtest_start("-drive if=none,id=drive0,file=/dev/null,format=raw"
24
+ qtest_start("-drive if=none,id=drive0,file=null-co://,format=raw"
25
" -device virtio-scsi-pci"
26
" -device scsi-hd,drive=drive0,id=dev0");
27
28
diff --git a/tests/nvme-test.c b/tests/nvme-test.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/nvme-test.c
31
+++ b/tests/nvme-test.c
32
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
33
g_test_init(&argc, &argv, NULL);
34
qtest_add_func("/nvme/nop", nop);
35
36
- qtest_start("-drive id=drv0,if=none,file=/dev/null,format=raw "
37
+ qtest_start("-drive id=drv0,if=none,file=null-co://,format=raw "
38
"-device nvme,drive=drv0,serial=foo");
39
ret = g_test_run();
40
41
diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/tests/usb-hcd-uhci-test.c
44
+++ b/tests/usb-hcd-uhci-test.c
45
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
46
{
47
const char *arch = qtest_get_arch();
48
const char *cmd = "-device piix3-usb-uhci,id=uhci,addr=1d.0"
49
- " -drive id=drive0,if=none,file=/dev/null,format=raw"
50
+ " -drive id=drive0,if=none,file=null-co://,format=raw"
51
" -device usb-tablet,bus=uhci.0,port=1";
52
int ret;
53
54
diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/tests/usb-hcd-xhci-test.c
57
+++ b/tests/usb-hcd-xhci-test.c
58
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
59
qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug);
60
61
qtest_start("-device nec-usb-xhci,id=xhci"
62
- " -drive id=drive0,if=none,file=/dev/null,format=raw");
63
+ " -drive id=drive0,if=none,file=null-co://,format=raw");
64
ret = g_test_run();
65
qtest_end();
66
67
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/tests/virtio-blk-test.c
70
+++ b/tests/virtio-blk-test.c
71
@@ -XXX,XX +XXX,XX @@ static QOSState *pci_test_start(void)
72
const char *arch = qtest_get_arch();
73
char *tmp_path;
74
const char *cmd = "-drive if=none,id=drive0,file=%s,format=raw "
75
- "-drive if=none,id=drive1,file=/dev/null,format=raw "
76
+ "-drive if=none,id=drive1,file=null-co://,format=raw "
77
"-device virtio-blk-pci,id=drv0,drive=drive0,"
78
"addr=%x.%x";
79
80
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/tests/virtio-scsi-test.c
83
+++ b/tests/virtio-scsi-test.c
84
@@ -XXX,XX +XXX,XX @@ typedef struct {
85
static QOSState *qvirtio_scsi_start(const char *extra_opts)
86
{
87
const char *arch = qtest_get_arch();
88
- const char *cmd = "-drive id=drv0,if=none,file=/dev/null,format=raw "
89
+ const char *cmd = "-drive id=drv0,if=none,file=null-co://,format=raw "
90
"-device virtio-scsi-pci,id=vs0 "
91
"-device scsi-hd,bus=vs0.0,drive=drv0 %s";
92
93
@@ -XXX,XX +XXX,XX @@ static void hotplug(void)
94
QDict *response;
95
QOSState *qs;
96
97
- qs = qvirtio_scsi_start("-drive id=drv1,if=none,file=/dev/null,format=raw");
98
+ qs = qvirtio_scsi_start(
99
+ "-drive id=drv1,if=none,file=null-co://,format=raw");
100
response = qmp("{\"execute\": \"device_add\","
101
" \"arguments\": {"
102
" \"driver\": \"scsi-hd\","
103
--
104
1.8.3.1
105
106
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Making this option available even before implementing it will let
4
converting tests easier: in coming patches they can specify the option
5
already when necessary, before we actually write code to lock the
6
images.
7
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/file-posix.c | 5 +++++
12
qapi/block-core.json | 4 ++++
13
2 files changed, 9 insertions(+)
14
15
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ static QemuOptsList raw_runtime_opts = {
20
.type = QEMU_OPT_STRING,
21
.help = "host AIO implementation (threads, native)",
22
},
23
+ {
24
+ .name = "locking",
25
+ .type = QEMU_OPT_STRING,
26
+ .help = "file locking mode (on/off/auto, default: auto)",
27
+ },
28
{ /* end of list */ }
29
},
30
};
31
diff --git a/qapi/block-core.json b/qapi/block-core.json
32
index XXXXXXX..XXXXXXX 100644
33
--- a/qapi/block-core.json
34
+++ b/qapi/block-core.json
35
@@ -XXX,XX +XXX,XX @@
36
#
37
# @filename: path to the image file
38
# @aio: AIO backend (default: threads) (since: 2.8)
39
+# @locking: whether to enable file locking. If set to 'auto', only enable
40
+# when Open File Descriptor (OFD) locking API is available
41
+# (default: auto, since 2.10)
42
#
43
# Since: 2.9
44
##
45
{ 'struct': 'BlockdevOptionsFile',
46
'data': { 'filename': 'str',
47
+ '*locking': 'OnOffAuto',
48
'*aio': 'BlockdevAioOptions' } }
49
50
##
51
--
52
1.8.3.1
53
54
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
We share the same set of QAPI options with file-posix, but locking is
4
not supported here. So error out if it is specified as 'on' for now.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/file-win32.c | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/block/file-win32.c b/block/file-win32.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/file-win32.c
15
+++ b/block/file-win32.c
16
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
17
goto fail;
18
}
19
20
+ if (qdict_get_try_bool(options, "locking", false)) {
21
+ error_setg(errp, "locking=on is not supported on Windows");
22
+ goto fail;
23
+ }
24
+
25
filename = qemu_opt_get(opts, "filename");
26
27
use_aio = get_aio_option(opts, flags, &local_err);
28
--
29
1.8.3.1
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
The COLO block replication architecture requires one disk to be shared
4
between primary and secondary, in the test both processes use posix file
5
protocol (instead of over NBD) so it is affected by image locking.
6
Disable the lock.
7
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/test-replication.c | 9 +++++++--
12
1 file changed, 7 insertions(+), 2 deletions(-)
13
14
diff --git a/tests/test-replication.c b/tests/test-replication.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/test-replication.c
17
+++ b/tests/test-replication.c
18
@@ -XXX,XX +XXX,XX @@ static BlockBackend *start_primary(void)
19
char *cmdline;
20
21
cmdline = g_strdup_printf("driver=replication,mode=primary,node-name=xxx,"
22
- "file.driver=qcow2,file.file.filename=%s"
23
+ "file.driver=qcow2,file.file.filename=%s,"
24
+ "file.file.locking=off"
25
, p_local_disk);
26
opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
27
g_free(cmdline);
28
@@ -XXX,XX +XXX,XX @@ static BlockBackend *start_secondary(void)
29
Error *local_err = NULL;
30
31
/* add s_local_disk and forge S_LOCAL_DISK_ID */
32
- cmdline = g_strdup_printf("file.filename=%s,driver=qcow2", s_local_disk);
33
+ cmdline = g_strdup_printf("file.filename=%s,driver=qcow2,"
34
+ "file.locking=off",
35
+ s_local_disk);
36
opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
37
g_free(cmdline);
38
39
@@ -XXX,XX +XXX,XX @@ static BlockBackend *start_secondary(void)
40
/* add S_(ACTIVE/HIDDEN)_DISK and forge S_ID */
41
cmdline = g_strdup_printf("driver=replication,mode=secondary,top-id=%s,"
42
"file.driver=qcow2,file.file.filename=%s,"
43
+ "file.file.locking=off,"
44
"file.backing.driver=qcow2,"
45
"file.backing.file.filename=%s,"
46
+ "file.backing.file.locking=off,"
47
"file.backing.backing=%s"
48
, S_ID, s_active_disk, s_hidden_disk
49
, S_LOCAL_DISK_ID);
50
--
51
1.8.3.1
52
53
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
They are wrappers of POSIX fcntl "file private locking", with a
4
convenient "try lock" wrapper implemented with F_OFD_GETLK.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/qemu/osdep.h | 3 +++
11
util/osdep.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
12
2 files changed, 51 insertions(+)
13
14
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu/osdep.h
17
+++ b/include/qemu/osdep.h
18
@@ -XXX,XX +XXX,XX @@ int qemu_close(int fd);
19
#ifndef _WIN32
20
int qemu_dup(int fd);
21
#endif
22
+int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive);
23
+int qemu_unlock_fd(int fd, int64_t start, int64_t len);
24
+int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive);
25
26
#if defined(__HAIKU__) && defined(__i386__)
27
#define FMT_pid "%ld"
28
diff --git a/util/osdep.c b/util/osdep.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/util/osdep.c
31
+++ b/util/osdep.c
32
@@ -XXX,XX +XXX,XX @@ static int qemu_parse_fdset(const char *param)
33
{
34
return qemu_parse_fd(param);
35
}
36
+
37
+static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
38
+{
39
+#ifdef F_OFD_SETLK
40
+ int ret;
41
+ struct flock fl = {
42
+ .l_whence = SEEK_SET,
43
+ .l_start = start,
44
+ .l_len = len,
45
+ .l_type = fl_type,
46
+ };
47
+ ret = fcntl(fd, F_OFD_SETLK, &fl);
48
+ return ret == -1 ? -errno : 0;
49
+#else
50
+ return -ENOTSUP;
51
+#endif
52
+}
53
+
54
+int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive)
55
+{
56
+ return qemu_lock_fcntl(fd, start, len, exclusive ? F_WRLCK : F_RDLCK);
57
+}
58
+
59
+int qemu_unlock_fd(int fd, int64_t start, int64_t len)
60
+{
61
+ return qemu_lock_fcntl(fd, start, len, F_UNLCK);
62
+}
63
+
64
+int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
65
+{
66
+#ifdef F_OFD_SETLK
67
+ int ret;
68
+ struct flock fl = {
69
+ .l_whence = SEEK_SET,
70
+ .l_start = start,
71
+ .l_len = len,
72
+ .l_type = exclusive ? F_WRLCK : F_RDLCK,
73
+ };
74
+ ret = fcntl(fd, F_OFD_GETLK, &fl);
75
+ if (ret == -1) {
76
+ return -errno;
77
+ } else {
78
+ return fl.l_type == F_UNLCK ? 0 : -EAGAIN;
79
+ }
80
+#else
81
+ return -ENOTSUP;
82
+#endif
83
+}
84
#endif
85
86
/*
87
--
88
1.8.3.1
89
90
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Signed-off-by: Fam Zheng <famz@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
util/osdep.c | 20 ++++++++++----------
7
1 file changed, 10 insertions(+), 10 deletions(-)
8
9
diff --git a/util/osdep.c b/util/osdep.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/util/osdep.c
12
+++ b/util/osdep.c
13
@@ -XXX,XX +XXX,XX @@ extern int madvise(caddr_t, size_t, int);
14
#include "qemu/error-report.h"
15
#include "monitor/monitor.h"
16
17
+#ifdef F_OFD_SETLK
18
+#define QEMU_SETLK F_OFD_SETLK
19
+#define QEMU_GETLK F_OFD_GETLK
20
+#else
21
+#define QEMU_SETLK F_SETLK
22
+#define QEMU_GETLK F_GETLK
23
+#endif
24
+
25
static bool fips_enabled = false;
26
27
static const char *hw_version = QEMU_HW_VERSION;
28
@@ -XXX,XX +XXX,XX @@ static int qemu_parse_fdset(const char *param)
29
30
static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
31
{
32
-#ifdef F_OFD_SETLK
33
int ret;
34
struct flock fl = {
35
.l_whence = SEEK_SET,
36
@@ -XXX,XX +XXX,XX @@ static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
37
.l_len = len,
38
.l_type = fl_type,
39
};
40
- ret = fcntl(fd, F_OFD_SETLK, &fl);
41
+ ret = fcntl(fd, QEMU_SETLK, &fl);
42
return ret == -1 ? -errno : 0;
43
-#else
44
- return -ENOTSUP;
45
-#endif
46
}
47
48
int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive)
49
@@ -XXX,XX +XXX,XX @@ int qemu_unlock_fd(int fd, int64_t start, int64_t len)
50
51
int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
52
{
53
-#ifdef F_OFD_SETLK
54
int ret;
55
struct flock fl = {
56
.l_whence = SEEK_SET,
57
@@ -XXX,XX +XXX,XX @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
58
.l_len = len,
59
.l_type = exclusive ? F_WRLCK : F_RDLCK,
60
};
61
- ret = fcntl(fd, F_OFD_GETLK, &fl);
62
+ ret = fcntl(fd, QEMU_GETLK, &fl);
63
if (ret == -1) {
64
return -errno;
65
} else {
66
return fl.l_type == F_UNLCK ? 0 : -EAGAIN;
67
}
68
-#else
69
- return -ENOTSUP;
70
-#endif
71
}
72
#endif
73
74
--
75
1.8.3.1
76
77
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
The lookup table for power-of-two sizes was added in commit 540b8492618eb
4
for the purpose of having convenient shortcuts for these sizes in cases
5
when the literal number has to be present at compile time, and
6
expressions as '(1 * KiB)' can not be used. One such case is the
7
stringification of sizes. Beyond that, it is convenient to use these
8
shortcuts for all power-of-two sizes, even if they don't have to be
9
literal numbers.
10
11
Despite its convenience, this table introduced 55 lines of "dumb" code,
12
the purpose and origin of which are obscure without reading the message
13
of the commit which introduced it. This patch fixes that by adding a
14
comment to the code itself with a brief explanation for the reasoning
15
behind this table. This comment includes the short AWK script that
16
generated the table, so that anyone who's interested could make sure
17
that the values in it are correct (otherwise these values look as if
18
they were typed manually).
19
20
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
22
---
6
tests/qemu-iotests/182 | 68 ++++++++++++++++++++++++++++++++++++++++++++++
23
include/qemu/units.h | 18 ++++++++++++++++++
7
tests/qemu-iotests/182.out | 8 ++++++
24
1 file changed, 18 insertions(+)
8
tests/qemu-iotests/group | 1 +
9
3 files changed, 77 insertions(+)
10
create mode 100755 tests/qemu-iotests/182
11
create mode 100644 tests/qemu-iotests/182.out
12
25
13
diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182
26
diff --git a/include/qemu/units.h b/include/qemu/units.h
14
new file mode 100755
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX
28
--- a/include/qemu/units.h
16
--- /dev/null
29
+++ b/include/qemu/units.h
17
+++ b/tests/qemu-iotests/182
18
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
19
+#!/bin/bash
31
#define PiB (INT64_C(1) << 50)
20
+#
32
#define EiB (INT64_C(1) << 60)
21
+# Test image locking for POSIX locks
33
22
+#
34
+/*
23
+# Copyright 2017 Red Hat, Inc.
35
+ * The following lookup table is intended to be used when a literal string of
24
+#
36
+ * the number of bytes is required (for example if it needs to be stringified).
25
+# This program is free software; you can redistribute it and/or modify
37
+ * It can also be used for generic shortcuts of power-of-two sizes.
26
+# it under the terms of the GNU General Public License as published by
38
+ * This table is generated using the AWK script below:
27
+# the Free Software Foundation; either version 2 of the License, or
39
+ *
28
+# (at your option) any later version.
40
+ * BEGIN {
29
+#
41
+ * suffix="KMGTPE";
30
+# This program is distributed in the hope that it will be useful,
42
+ * for(i=10; i<64; i++) {
31
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+ * val=2**i;
32
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44
+ * s=substr(suffix, int(i/10), 1);
33
+# GNU General Public License for more details.
45
+ * n=2**(i%10);
34
+#
46
+ * pad=21-int(log(n)/log(10));
35
+# You should have received a copy of the GNU General Public License
47
+ * printf("#define S_%d%siB %*d\n", n, s, pad, val);
36
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
48
+ * }
37
+#
49
+ * }
50
+ */
38
+
51
+
39
+# creator
52
#define S_1KiB 1024
40
+owner=famz@redhat.com
53
#define S_2KiB 2048
41
+
54
#define S_4KiB 4096
42
+seq="$(basename $0)"
43
+echo "QA output created by $seq"
44
+
45
+here="$PWD"
46
+tmp=/tmp/$$
47
+status=1    # failure is the default!
48
+
49
+_cleanup()
50
+{
51
+ _cleanup_test_img
52
+}
53
+trap "_cleanup; exit \$status" 0 1 2 3 15
54
+
55
+# get standard environment, filters and checks
56
+. ./common.rc
57
+. ./common.filter
58
+. ./common.qemu
59
+
60
+_supported_fmt qcow2
61
+_supported_proto file
62
+_supported_os Linux
63
+
64
+size=32M
65
+
66
+_make_test_img $size
67
+
68
+echo "Starting QEMU"
69
+_launch_qemu -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \
70
+ -device virtio-blk-pci,drive=drive0
71
+
72
+echo
73
+echo "Starting a second QEMU using the same image should fail"
74
+echo 'quit' | $QEMU -monitor stdio \
75
+ -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \
76
+ -device virtio-blk-pci,drive=drive0 2>&1 | _filter_testdir 2>&1 |
77
+ _filter_qemu |
78
+ sed -e '/falling back to POSIX file/d' \
79
+ -e '/locks can be lost unexpectedly/d'
80
+
81
+_cleanup_qemu
82
+
83
+# success, all done
84
+echo "*** done"
85
+rm -f $seq.full
86
+status=0
87
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
88
new file mode 100644
89
index XXXXXXX..XXXXXXX
90
--- /dev/null
91
+++ b/tests/qemu-iotests/182.out
92
@@ -XXX,XX +XXX,XX @@
93
+QA output created by 182
94
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432
95
+Starting QEMU
96
+
97
+Starting a second QEMU using the same image should fail
98
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0,file.locking=on: Failed to get "write" lock
99
+Is another process using the image?
100
+*** done
101
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
102
index XXXXXXX..XXXXXXX 100644
103
--- a/tests/qemu-iotests/group
104
+++ b/tests/qemu-iotests/group
105
@@ -XXX,XX +XXX,XX @@
106
175 auto quick
107
176 rw auto backing
108
181 rw auto migration
109
+182 rw auto quick
110
--
55
--
111
1.8.3.1
56
2.19.1
112
57
113
58
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
For the 'alloc' command, accepting an offset in bytes but a length
4
in sectors, and reporting output in sectors, is confusing. Do
5
everything in bytes, and adjust the expected output accordingly.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Message-id: 20170429191419.30051-3-eblake@redhat.com
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
qemu-io-cmds.c | 30 ++++++++++++++++++------------
13
tests/qemu-iotests/019.out | 8 ++++----
14
tests/qemu-iotests/common.pattern | 2 +-
15
3 files changed, 23 insertions(+), 17 deletions(-)
16
17
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/qemu-io-cmds.c
20
+++ b/qemu-io-cmds.c
21
@@ -XXX,XX +XXX,XX @@ out:
22
static int alloc_f(BlockBackend *blk, int argc, char **argv)
23
{
24
BlockDriverState *bs = blk_bs(blk);
25
- int64_t offset, sector_num, nb_sectors, remaining;
26
+ int64_t offset, sector_num, nb_sectors, remaining, count;
27
char s1[64];
28
int num, ret;
29
int64_t sum_alloc;
30
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
31
}
32
33
if (argc == 3) {
34
- nb_sectors = cvtnum(argv[2]);
35
- if (nb_sectors < 0) {
36
- print_cvtnum_err(nb_sectors, argv[2]);
37
+ count = cvtnum(argv[2]);
38
+ if (count < 0) {
39
+ print_cvtnum_err(count, argv[2]);
40
return 0;
41
- } else if (nb_sectors > INT_MAX) {
42
- printf("length argument cannot exceed %d, given %s\n",
43
- INT_MAX, argv[2]);
44
+ } else if (count > INT_MAX * BDRV_SECTOR_SIZE) {
45
+ printf("length argument cannot exceed %llu, given %s\n",
46
+ INT_MAX * BDRV_SECTOR_SIZE, argv[2]);
47
return 0;
48
}
49
} else {
50
- nb_sectors = 1;
51
+ count = BDRV_SECTOR_SIZE;
52
+ }
53
+ if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
54
+ printf("%" PRId64 " is not a sector-aligned value for 'count'\n",
55
+ count);
56
+ return 0;
57
}
58
+ nb_sectors = count >> BDRV_SECTOR_BITS;
59
60
remaining = nb_sectors;
61
sum_alloc = 0;
62
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
63
64
cvtstr(offset, s1, sizeof(s1));
65
66
- printf("%"PRId64"/%"PRId64" sectors allocated at offset %s\n",
67
- sum_alloc, nb_sectors, s1);
68
+ printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
69
+ sum_alloc << BDRV_SECTOR_BITS, nb_sectors << BDRV_SECTOR_BITS, s1);
70
return 0;
71
}
72
73
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t alloc_cmd = {
74
.argmin = 1,
75
.argmax = 2,
76
.cfunc = alloc_f,
77
- .args = "off [sectors]",
78
- .oneline = "checks if a sector is present in the file",
79
+ .args = "offset [count]",
80
+ .oneline = "checks if offset is allocated in the file",
81
};
82
83
84
diff --git a/tests/qemu-iotests/019.out b/tests/qemu-iotests/019.out
85
index XXXXXXX..XXXXXXX 100644
86
--- a/tests/qemu-iotests/019.out
87
+++ b/tests/qemu-iotests/019.out
88
@@ -XXX,XX +XXX,XX @@ Testing conversion with -B TEST_DIR/t.IMGFMT.base
89
90
Checking if backing clusters are allocated when they shouldn't
91
92
-0/128 sectors allocated at offset 1 MiB
93
-0/128 sectors allocated at offset 4.001 GiB
94
+0/65536 bytes allocated at offset 1 MiB
95
+0/65536 bytes allocated at offset 4.001 GiB
96
Reading
97
98
=== IO: pattern 42
99
@@ -XXX,XX +XXX,XX @@ Testing conversion with -o backing_file=TEST_DIR/t.IMGFMT.base
100
101
Checking if backing clusters are allocated when they shouldn't
102
103
-0/128 sectors allocated at offset 1 MiB
104
-0/128 sectors allocated at offset 4.001 GiB
105
+0/65536 bytes allocated at offset 1 MiB
106
+0/65536 bytes allocated at offset 4.001 GiB
107
Reading
108
109
=== IO: pattern 42
110
diff --git a/tests/qemu-iotests/common.pattern b/tests/qemu-iotests/common.pattern
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/common.pattern
113
+++ b/tests/qemu-iotests/common.pattern
114
@@ -XXX,XX +XXX,XX @@
115
116
function do_is_allocated() {
117
local start=$1
118
- local size=$(( $2 / 512))
119
+ local size=$2
120
local step=$3
121
local count=$4
122
123
--
124
1.8.3.1
125
126
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Mixing byte offset and sector allocation counts is a bit
4
confusing. Also, reporting n/m sectors, where m decreases
5
according to the remaining size of the file, isn't really
6
adding any useful information; and reporting an offset at
7
both the front and end of the line, with large amounts of
8
whitespace, is pointless. Update the output to use byte
9
counts and shorter lines, then adjust the affected tests
10
(./check -qcow2 102, ./check -vpc 146).
11
12
Note that 'qemu-io map' is MUCH weaker than 'qemu-img map';
13
the former only shows which regions of the active layer are
14
allocated, without regards to where the allocation comes from
15
or whether the allocated portion is known to read as zero
16
(because it is using the weaker bdrv_is_allocated()); while the
17
latter (especially in --output=json mode) reports more details
18
from bdrv_get_block_status().
19
20
Signed-off-by: Eric Blake <eblake@redhat.com>
21
Message-id: 20170429191419.30051-4-eblake@redhat.com
22
Reviewed-by: Max Reitz <mreitz@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
qemu-io-cmds.c | 11 ++++++-----
26
tests/qemu-iotests/102.out | 4 ++--
27
tests/qemu-iotests/146.out | 30 +++++++++++++++---------------
28
3 files changed, 23 insertions(+), 22 deletions(-)
29
30
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/qemu-io-cmds.c
33
+++ b/qemu-io-cmds.c
34
@@ -XXX,XX +XXX,XX @@ static int map_f(BlockBackend *blk, int argc, char **argv)
35
{
36
int64_t offset;
37
int64_t nb_sectors, total_sectors;
38
- char s1[64];
39
+ char s1[64], s2[64];
40
int64_t num;
41
int ret;
42
const char *retstr;
43
@@ -XXX,XX +XXX,XX @@ static int map_f(BlockBackend *blk, int argc, char **argv)
44
}
45
46
retstr = ret ? " allocated" : "not allocated";
47
- cvtstr(offset << 9ULL, s1, sizeof(s1));
48
- printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
49
- "at offset %s (%d)\n",
50
- offset << 9ULL, num, nb_sectors, retstr, s1, ret);
51
+ cvtstr(num << BDRV_SECTOR_BITS, s1, sizeof(s1));
52
+ cvtstr(offset << BDRV_SECTOR_BITS, s2, sizeof(s2));
53
+ printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
54
+ s1, num << BDRV_SECTOR_BITS, retstr,
55
+ s2, offset << BDRV_SECTOR_BITS);
56
57
offset += num;
58
nb_sectors -= num;
59
diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out
60
index XXXXXXX..XXXXXXX 100644
61
--- a/tests/qemu-iotests/102.out
62
+++ b/tests/qemu-iotests/102.out
63
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
64
wrote 65536/65536 bytes at offset 0
65
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
66
Image resized.
67
-[ 0] 128/ 128 sectors allocated at offset 0 bytes (1)
68
+64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0)
69
Offset Length Mapped to File
70
71
=== Testing map on an image file truncated outside of qemu ===
72
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 0
73
Image resized.
74
QEMU X.Y.Z monitor - type 'help' for more information
75
(qemu) qemu-io drv0 map
76
-[ 0] 128/ 128 sectors allocated at offset 0 bytes (1)
77
+64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0)
78
*** done
79
diff --git a/tests/qemu-iotests/146.out b/tests/qemu-iotests/146.out
80
index XXXXXXX..XXXXXXX 100644
81
--- a/tests/qemu-iotests/146.out
82
+++ b/tests/qemu-iotests/146.out
83
@@ -XXX,XX +XXX,XX @@ QA output created by 146
84
85
=== Testing VPC Autodetect ===
86
87
-[ 0] 266334240/ 266334240 sectors not allocated at offset 0 bytes (0)
88
+126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0)
89
90
=== Testing VPC with current_size force ===
91
92
-[ 0] 266338304/ 266338304 sectors not allocated at offset 0 bytes (0)
93
+127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0)
94
95
=== Testing VPC with chs force ===
96
97
-[ 0] 266334240/ 266334240 sectors not allocated at offset 0 bytes (0)
98
+126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0)
99
100
=== Testing Hyper-V Autodetect ===
101
102
-[ 0] 266338304/ 266338304 sectors not allocated at offset 0 bytes (0)
103
+127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0)
104
105
=== Testing Hyper-V with current_size force ===
106
107
-[ 0] 266338304/ 266338304 sectors not allocated at offset 0 bytes (0)
108
+127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0)
109
110
=== Testing Hyper-V with chs force ===
111
112
-[ 0] 266334240/ 266334240 sectors not allocated at offset 0 bytes (0)
113
+126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0)
114
115
=== Testing d2v Autodetect ===
116
117
-[ 0] 514560/ 514560 sectors allocated at offset 0 bytes (1)
118
+251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0)
119
120
=== Testing d2v with current_size force ===
121
122
-[ 0] 514560/ 514560 sectors allocated at offset 0 bytes (1)
123
+251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0)
124
125
=== Testing d2v with chs force ===
126
127
-[ 0] 514560/ 514560 sectors allocated at offset 0 bytes (1)
128
+251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0)
129
130
=== Testing Image create, default ===
131
132
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
133
134
=== Read created image, default opts ====
135
136
-[ 0] 8389584/ 8389584 sectors not allocated at offset 0 bytes (0)
137
+4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0)
138
139
=== Read created image, force_size_calc=chs ====
140
141
-[ 0] 8389584/ 8389584 sectors not allocated at offset 0 bytes (0)
142
+4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0)
143
144
=== Read created image, force_size_calc=current_size ====
145
146
-[ 0] 8389584/ 8389584 sectors not allocated at offset 0 bytes (0)
147
+4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0)
148
149
=== Testing Image create, force_size ===
150
151
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296 forc
152
153
=== Read created image, default opts ====
154
155
-[ 0] 8388608/ 8388608 sectors not allocated at offset 0 bytes (0)
156
+4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0)
157
158
=== Read created image, force_size_calc=chs ====
159
160
-[ 0] 8388608/ 8388608 sectors not allocated at offset 0 bytes (0)
161
+4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0)
162
163
=== Read created image, force_size_calc=current_size ====
164
165
-[ 0] 8388608/ 8388608 sectors not allocated at offset 0 bytes (0)
166
+4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0)
167
*** done
168
--
169
1.8.3.1
170
171
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Commits 04ed95f4 and 1a62d0ac updated the block layer to auto-fragment
4
any I/O to fit within device boundaries. Additionally, when using a
5
minimum alignment of 4k, we want to ensure the block layer does proper
6
read-modify-write rather than requesting I/O on a slice of a sector.
7
Let's enforce that the contract is obeyed when using blkdebug. For
8
now, blkdebug only allows alignment overrides, and just inherits other
9
limits from whatever device it is wrapping, but a future patch will
10
further enhance things.
11
12
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Message-id: 20170429191419.30051-5-eblake@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/blkdebug.c | 14 ++++++++++++++
19
1 file changed, 14 insertions(+)
20
21
diff --git a/block/blkdebug.c b/block/blkdebug.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/blkdebug.c
24
+++ b/block/blkdebug.c
25
@@ -XXX,XX +XXX,XX @@ blkdebug_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
26
BDRVBlkdebugState *s = bs->opaque;
27
BlkdebugRule *rule = NULL;
28
29
+ /* Sanity check block layer guarantees */
30
+ assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
31
+ assert(QEMU_IS_ALIGNED(bytes, bs->bl.request_alignment));
32
+ if (bs->bl.max_transfer) {
33
+ assert(bytes <= bs->bl.max_transfer);
34
+ }
35
+
36
QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
37
uint64_t inject_offset = rule->options.inject.offset;
38
39
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
40
BDRVBlkdebugState *s = bs->opaque;
41
BlkdebugRule *rule = NULL;
42
43
+ /* Sanity check block layer guarantees */
44
+ assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
45
+ assert(QEMU_IS_ALIGNED(bytes, bs->bl.request_alignment));
46
+ if (bs->bl.max_transfer) {
47
+ assert(bytes <= bs->bl.max_transfer);
48
+ }
49
+
50
QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
51
uint64_t inject_offset = rule->options.inject.offset;
52
53
--
54
1.8.3.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Make it easier to simulate various unusual hardware setups (for
4
example, recent commits 3482b9b and b8d0a98 affect the Dell
5
Equallogic iSCSI with its 15M preferred and maximum unmap and
6
write zero sizing, or b2f95fe deals with the Linux loopback
7
block device having a max_transfer of 64k), by allowing blkdebug
8
to wrap any other device with further restrictions on various
9
alignments.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20170429191419.30051-9-eblake@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/blkdebug.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++-
17
qapi/block-core.json | 33 ++++++++++++++++--
18
2 files changed, 125 insertions(+), 4 deletions(-)
19
20
diff --git a/block/blkdebug.c b/block/blkdebug.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/blkdebug.c
23
+++ b/block/blkdebug.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVBlkdebugState {
25
int state;
26
int new_state;
27
uint64_t align;
28
+ uint64_t max_transfer;
29
+ uint64_t opt_write_zero;
30
+ uint64_t max_write_zero;
31
+ uint64_t opt_discard;
32
+ uint64_t max_discard;
33
34
/* For blkdebug_refresh_filename() */
35
char *config_file;
36
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
37
.type = QEMU_OPT_SIZE,
38
.help = "Required alignment in bytes",
39
},
40
+ {
41
+ .name = "max-transfer",
42
+ .type = QEMU_OPT_SIZE,
43
+ .help = "Maximum transfer size in bytes",
44
+ },
45
+ {
46
+ .name = "opt-write-zero",
47
+ .type = QEMU_OPT_SIZE,
48
+ .help = "Optimum write zero alignment in bytes",
49
+ },
50
+ {
51
+ .name = "max-write-zero",
52
+ .type = QEMU_OPT_SIZE,
53
+ .help = "Maximum write zero size in bytes",
54
+ },
55
+ {
56
+ .name = "opt-discard",
57
+ .type = QEMU_OPT_SIZE,
58
+ .help = "Optimum discard alignment in bytes",
59
+ },
60
+ {
61
+ .name = "max-discard",
62
+ .type = QEMU_OPT_SIZE,
63
+ .help = "Maximum discard size in bytes",
64
+ },
65
{ /* end of list */ }
66
},
67
};
68
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
69
QemuOpts *opts;
70
Error *local_err = NULL;
71
int ret;
72
+ uint64_t align;
73
74
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
75
qemu_opts_absorb_qdict(opts, options, &local_err);
76
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
77
bs->file->bs->supported_zero_flags;
78
ret = -EINVAL;
79
80
- /* Set request alignment */
81
+ /* Set alignment overrides */
82
s->align = qemu_opt_get_size(opts, "align", 0);
83
if (s->align && (s->align >= INT_MAX || !is_power_of_2(s->align))) {
84
error_setg(errp, "Cannot meet constraints with align %" PRIu64,
85
s->align);
86
goto out;
87
}
88
+ align = MAX(s->align, bs->file->bs->bl.request_alignment);
89
+
90
+ s->max_transfer = qemu_opt_get_size(opts, "max-transfer", 0);
91
+ if (s->max_transfer &&
92
+ (s->max_transfer >= INT_MAX ||
93
+ !QEMU_IS_ALIGNED(s->max_transfer, align))) {
94
+ error_setg(errp, "Cannot meet constraints with max-transfer %" PRIu64,
95
+ s->max_transfer);
96
+ goto out;
97
+ }
98
+
99
+ s->opt_write_zero = qemu_opt_get_size(opts, "opt-write-zero", 0);
100
+ if (s->opt_write_zero &&
101
+ (s->opt_write_zero >= INT_MAX ||
102
+ !QEMU_IS_ALIGNED(s->opt_write_zero, align))) {
103
+ error_setg(errp, "Cannot meet constraints with opt-write-zero %" PRIu64,
104
+ s->opt_write_zero);
105
+ goto out;
106
+ }
107
+
108
+ s->max_write_zero = qemu_opt_get_size(opts, "max-write-zero", 0);
109
+ if (s->max_write_zero &&
110
+ (s->max_write_zero >= INT_MAX ||
111
+ !QEMU_IS_ALIGNED(s->max_write_zero,
112
+ MAX(s->opt_write_zero, align)))) {
113
+ error_setg(errp, "Cannot meet constraints with max-write-zero %" PRIu64,
114
+ s->max_write_zero);
115
+ goto out;
116
+ }
117
+
118
+ s->opt_discard = qemu_opt_get_size(opts, "opt-discard", 0);
119
+ if (s->opt_discard &&
120
+ (s->opt_discard >= INT_MAX ||
121
+ !QEMU_IS_ALIGNED(s->opt_discard, align))) {
122
+ error_setg(errp, "Cannot meet constraints with opt-discard %" PRIu64,
123
+ s->opt_discard);
124
+ goto out;
125
+ }
126
+
127
+ s->max_discard = qemu_opt_get_size(opts, "max-discard", 0);
128
+ if (s->max_discard &&
129
+ (s->max_discard >= INT_MAX ||
130
+ !QEMU_IS_ALIGNED(s->max_discard,
131
+ MAX(s->opt_discard, align)))) {
132
+ error_setg(errp, "Cannot meet constraints with max-discard %" PRIu64,
133
+ s->max_discard);
134
+ goto out;
135
+ }
136
137
ret = 0;
138
out:
139
@@ -XXX,XX +XXX,XX @@ static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
140
if (s->align) {
141
bs->bl.request_alignment = s->align;
142
}
143
+ if (s->max_transfer) {
144
+ bs->bl.max_transfer = s->max_transfer;
145
+ }
146
+ if (s->opt_write_zero) {
147
+ bs->bl.pwrite_zeroes_alignment = s->opt_write_zero;
148
+ }
149
+ if (s->max_write_zero) {
150
+ bs->bl.max_pwrite_zeroes = s->max_write_zero;
151
+ }
152
+ if (s->opt_discard) {
153
+ bs->bl.pdiscard_alignment = s->opt_discard;
154
+ }
155
+ if (s->max_discard) {
156
+ bs->bl.max_pdiscard = s->max_discard;
157
+ }
158
}
159
160
static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
161
diff --git a/qapi/block-core.json b/qapi/block-core.json
162
index XXXXXXX..XXXXXXX 100644
163
--- a/qapi/block-core.json
164
+++ b/qapi/block-core.json
165
@@ -XXX,XX +XXX,XX @@
166
#
167
# @config: filename of the configuration file
168
#
169
-# @align: required alignment for requests in bytes,
170
-# must be power of 2, or 0 for default
171
+# @align: required alignment for requests in bytes, must be
172
+# positive power of 2, or 0 for default
173
+#
174
+# @max-transfer: maximum size for I/O transfers in bytes, must be
175
+# positive multiple of @align and of the underlying
176
+# file's request alignment (but need not be a power of
177
+# 2), or 0 for default (since 2.10)
178
+#
179
+# @opt-write-zero: preferred alignment for write zero requests in bytes,
180
+# must be positive multiple of @align and of the
181
+# underlying file's request alignment (but need not be a
182
+# power of 2), or 0 for default (since 2.10)
183
+#
184
+# @max-write-zero: maximum size for write zero requests in bytes, must be
185
+# positive multiple of @align, of @opt-write-zero, and of
186
+# the underlying file's request alignment (but need not
187
+# be a power of 2), or 0 for default (since 2.10)
188
+#
189
+# @opt-discard: preferred alignment for discard requests in bytes, must
190
+# be positive multiple of @align and of the underlying
191
+# file's request alignment (but need not be a power of
192
+# 2), or 0 for default (since 2.10)
193
+#
194
+# @max-discard: maximum size for discard requests in bytes, must be
195
+# positive multiple of @align, of @opt-discard, and of
196
+# the underlying file's request alignment (but need not
197
+# be a power of 2), or 0 for default (since 2.10)
198
#
199
# @inject-error: array of error injection descriptions
200
#
201
@@ -XXX,XX +XXX,XX @@
202
{ 'struct': 'BlockdevOptionsBlkdebug',
203
'data': { 'image': 'BlockdevRef',
204
'*config': 'str',
205
- '*align': 'int',
206
+ '*align': 'int', '*max-transfer': 'int32',
207
+ '*opt-write-zero': 'int32', '*max-write-zero': 'int32',
208
+ '*opt-discard': 'int32', '*max-discard': 'int32',
209
'*inject-error': ['BlkdebugInjectErrorOptions'],
210
'*set-state': ['BlkdebugSetStateOptions'] } }
211
212
--
213
1.8.3.1
214
215
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Use blkdebug's new geometry constraints to emulate setups that
4
have needed past regression fixes: write zeroes asserting
5
when running through a loopback block device with max-transfer
6
smaller than cluster size, and discard rounding away portions
7
of requests not aligned to preferred boundaries. Also, add
8
coverage that the block layer is honoring max transfer limits.
9
10
For now, a single iotest performs all actions, with the idea
11
that we can add future blkdebug constraint test cases in the
12
same file; but it can be split into multiple iotests if we find
13
reason to run one portion of the test in more setups than what
14
are possible in the other.
15
16
For reference, the final portion of the test (checking whether
17
discard passes as much as possible to the lowest layers of the
18
stack) works as follows:
19
20
qemu-io: discard 30M at 80000001, passed to blkdebug
21
blkdebug: discard 511 bytes at 80000001, -ENOTSUP (smaller than
22
blkdebug's 512 align)
23
blkdebug: discard 14371328 bytes at 80000512, passed to qcow2
24
qcow2: discard 739840 bytes at 80000512, -ENOTSUP (smaller than
25
qcow2's 1M align)
26
qcow2: discard 13M bytes at 77M, succeeds
27
blkdebug: discard 15M bytes at 90M, passed to qcow2
28
qcow2: discard 15M bytes at 90M, succeeds
29
blkdebug: discard 1356800 bytes at 105M, passed to qcow2
30
qcow2: discard 1M at 105M, succeeds
31
qcow2: discard 308224 bytes at 106M, -ENOTSUP (smaller than qcow2's
32
1M align)
33
blkdebug: discard 1 byte at 111457280, -ENOTSUP (smaller than
34
blkdebug's 512 align)
35
36
Signed-off-by: Eric Blake <eblake@redhat.com>
37
Reviewed-by: Max Reitz <mreitz@redhat.com>
38
Message-id: 20170429191419.30051-10-eblake@redhat.com
39
[mreitz: For cooperation with image locking, add -r to the qemu-io
40
invocation which verifies the image content]
41
Signed-off-by: Max Reitz <mreitz@redhat.com>
42
---
43
tests/qemu-iotests/177 | 114 +++++++++++++++++++++++++++++++++++++++++++++
44
tests/qemu-iotests/177.out | 49 +++++++++++++++++++
45
tests/qemu-iotests/group | 1 +
46
3 files changed, 164 insertions(+)
47
create mode 100755 tests/qemu-iotests/177
48
create mode 100644 tests/qemu-iotests/177.out
49
50
diff --git a/tests/qemu-iotests/177 b/tests/qemu-iotests/177
51
new file mode 100755
52
index XXXXXXX..XXXXXXX
53
--- /dev/null
54
+++ b/tests/qemu-iotests/177
55
@@ -XXX,XX +XXX,XX @@
56
+#!/bin/bash
57
+#
58
+# Test corner cases with unusual block geometries
59
+#
60
+# Copyright (C) 2016-2017 Red Hat, Inc.
61
+#
62
+# This program is free software; you can redistribute it and/or modify
63
+# it under the terms of the GNU General Public License as published by
64
+# the Free Software Foundation; either version 2 of the License, or
65
+# (at your option) any later version.
66
+#
67
+# This program is distributed in the hope that it will be useful,
68
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
69
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70
+# GNU General Public License for more details.
71
+#
72
+# You should have received a copy of the GNU General Public License
73
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
74
+#
75
+
76
+# creator
77
+owner=eblake@redhat.com
78
+
79
+seq=`basename $0`
80
+echo "QA output created by $seq"
81
+
82
+here=`pwd`
83
+status=1    # failure is the default!
84
+
85
+_cleanup()
86
+{
87
+    _cleanup_test_img
88
+}
89
+trap "_cleanup; exit \$status" 0 1 2 3 15
90
+
91
+# get standard environment, filters and checks
92
+. ./common.rc
93
+. ./common.filter
94
+
95
+_supported_fmt qcow2
96
+_supported_proto file
97
+
98
+CLUSTER_SIZE=1M
99
+size=128M
100
+options=driver=blkdebug,image.driver=qcow2
101
+
102
+echo
103
+echo "== setting up files =="
104
+
105
+TEST_IMG="$TEST_IMG.base" _make_test_img $size
106
+$QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io
107
+_make_test_img -b "$TEST_IMG.base"
108
+$QEMU_IO -c "write -P 22 0 $size" "$TEST_IMG" | _filter_qemu_io
109
+
110
+# Limited to 64k max-transfer
111
+echo
112
+echo "== constrained alignment and max-transfer =="
113
+limits=align=4k,max-transfer=64k
114
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
115
+ -c "write -P 33 1000 128k" -c "read -P 33 1000 128k" | _filter_qemu_io
116
+
117
+echo
118
+echo "== write zero with constrained max-transfer =="
119
+limits=align=512,max-transfer=64k,opt-write-zero=$CLUSTER_SIZE
120
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
121
+ -c "write -z 8003584 2093056" | _filter_qemu_io
122
+
123
+# non-power-of-2 write-zero/discard alignments
124
+echo
125
+echo "== non-power-of-2 write zeroes limits =="
126
+
127
+limits=align=512,opt-write-zero=15M,max-write-zero=15M,opt-discard=15M,max-discard=15M
128
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
129
+ -c "write -z 32M 32M" | _filter_qemu_io
130
+
131
+echo
132
+echo "== non-power-of-2 discard limits =="
133
+
134
+limits=align=512,opt-write-zero=15M,max-write-zero=15M,opt-discard=15M,max-discard=15M
135
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
136
+ -c "discard 80000001 30M" | _filter_qemu_io
137
+
138
+echo
139
+echo "== verify image content =="
140
+
141
+function verify_io()
142
+{
143
+ if ($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" |
144
+     grep "compat: 0.10" > /dev/null); then
145
+ # For v2 images, discarded clusters are read from the backing file
146
+ discarded=11
147
+ else
148
+ # Discarded clusters are zeroed for v3 or later
149
+ discarded=0
150
+ fi
151
+
152
+ echo read -P 22 0 1000
153
+ echo read -P 33 1000 128k
154
+ echo read -P 22 132072 7871512
155
+ echo read -P 0 8003584 2093056
156
+ echo read -P 22 10096640 23457792
157
+ echo read -P 0 32M 32M
158
+ echo read -P 22 64M 13M
159
+ echo read -P $discarded 77M 29M
160
+ echo read -P 22 106M 22M
161
+}
162
+
163
+verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io
164
+
165
+_check_test_img
166
+
167
+# success, all done
168
+echo "*** done"
169
+status=0
170
diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out
171
new file mode 100644
172
index XXXXXXX..XXXXXXX
173
--- /dev/null
174
+++ b/tests/qemu-iotests/177.out
175
@@ -XXX,XX +XXX,XX @@
176
+QA output created by 177
177
+
178
+== setting up files ==
179
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
180
+wrote 134217728/134217728 bytes at offset 0
181
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
182
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
183
+wrote 134217728/134217728 bytes at offset 0
184
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
185
+
186
+== constrained alignment and max-transfer ==
187
+wrote 131072/131072 bytes at offset 1000
188
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
189
+read 131072/131072 bytes at offset 1000
190
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
191
+
192
+== write zero with constrained max-transfer ==
193
+wrote 2093056/2093056 bytes at offset 8003584
194
+1.996 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
195
+
196
+== non-power-of-2 write zeroes limits ==
197
+wrote 33554432/33554432 bytes at offset 33554432
198
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
199
+
200
+== non-power-of-2 discard limits ==
201
+discard 31457280/31457280 bytes at offset 80000001
202
+30 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
203
+
204
+== verify image content ==
205
+read 1000/1000 bytes at offset 0
206
+1000 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
207
+read 131072/131072 bytes at offset 1000
208
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
209
+read 7871512/7871512 bytes at offset 132072
210
+7.507 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
211
+read 2093056/2093056 bytes at offset 8003584
212
+1.996 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
213
+read 23457792/23457792 bytes at offset 10096640
214
+22.371 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
215
+read 33554432/33554432 bytes at offset 33554432
216
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
217
+read 13631488/13631488 bytes at offset 67108864
218
+13 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
219
+read 30408704/30408704 bytes at offset 80740352
220
+29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
221
+read 23068672/23068672 bytes at offset 111149056
222
+22 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
223
+No errors were found on the image.
224
+*** done
225
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
226
index XXXXXXX..XXXXXXX 100644
227
--- a/tests/qemu-iotests/group
228
+++ b/tests/qemu-iotests/group
229
@@ -XXX,XX +XXX,XX @@
230
174 auto
231
175 auto quick
232
176 rw auto backing
233
+177 rw auto quick
234
181 rw auto migration
235
182 rw auto quick
236
--
237
1.8.3.1
238
239
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We had some conflicting documentation: a nice 8-way table that
4
described all possible combinations of DATA, ZERO, and
5
OFFSET_VALID, contrasted with text that implied that OFFSET_VALID
6
always meant raw data could be read directly. Furthermore, the
7
text refers a lot to bs->file, even though the interface was
8
updated back in 67a0fd2a to let the driver pass back a specific
9
BDS (not necessarily bs->file). As the 8-way table is the
10
intended semantics, simplify the rest of the text to get rid of
11
the confusion.
12
13
ALLOCATED is always set by the block layer for convenience (drivers
14
do not have to worry about it). RAW is used only internally, but
15
by more than the raw driver. Document these additional items on
16
the driver callback.
17
18
Suggested-by: Max Reitz <mreitz@redhat.com>
19
Signed-off-by: Eric Blake <eblake@redhat.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Message-id: 20170507000552.20847-4-eblake@redhat.com
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
include/block/block.h | 35 +++++++++++++++++++----------------
25
include/block/block_int.h | 7 +++++++
26
2 files changed, 26 insertions(+), 16 deletions(-)
27
28
diff --git a/include/block/block.h b/include/block/block.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block.h
31
+++ b/include/block/block.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
33
#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
34
35
/*
36
- * Allocation status flags
37
- * BDRV_BLOCK_DATA: data is read from a file returned by bdrv_get_block_status.
38
- * BDRV_BLOCK_ZERO: sectors read as zero
39
- * BDRV_BLOCK_OFFSET_VALID: sector stored as raw data in a file returned by
40
- * bdrv_get_block_status.
41
+ * Allocation status flags for bdrv_get_block_status() and friends.
42
+ *
43
+ * Public flags:
44
+ * BDRV_BLOCK_DATA: allocation for data at offset is tied to this layer
45
+ * BDRV_BLOCK_ZERO: offset reads as zero
46
+ * BDRV_BLOCK_OFFSET_VALID: an associated offset exists for accessing raw data
47
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
48
- * layer (as opposed to the backing file)
49
- * BDRV_BLOCK_RAW: used internally to indicate that the request
50
- * was answered by the raw driver and that one
51
- * should look in bs->file directly.
52
+ * layer (short for DATA || ZERO), set by block layer
53
*
54
- * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 represent the offset in
55
- * bs->file where sector data can be read from as raw data.
56
+ * Internal flag:
57
+ * BDRV_BLOCK_RAW: used internally to indicate that the request was
58
+ * answered by a passthrough driver such as raw and that the
59
+ * block layer should recompute the answer from bs->file.
60
*
61
- * DATA == 0 && ZERO == 0 means that data is read from backing_hd if present.
62
+ * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK)
63
+ * represent the offset in the returned BDS that is allocated for the
64
+ * corresponding raw data; however, whether that offset actually contains
65
+ * data also depends on BDRV_BLOCK_DATA and BDRV_BLOCK_ZERO, as follows:
66
*
67
* DATA ZERO OFFSET_VALID
68
- * t t t sectors read as zero, bs->file is zero at offset
69
- * t f t sectors read as valid from bs->file at offset
70
- * f t t sectors preallocated, read as zero, bs->file not
71
+ * t t t sectors read as zero, returned file is zero at offset
72
+ * t f t sectors read as valid from file at offset
73
+ * f t t sectors preallocated, read as zero, returned file not
74
* necessarily zero at offset
75
* f f t sectors preallocated but read from backing_hd,
76
- * bs->file contains garbage at offset
77
+ * returned file contains garbage at offset
78
* t t f sectors preallocated, read as zero, unknown offset
79
* t f f sectors read from unknown file or offset
80
* f t f not allocated or unknown offset, read as zero
81
diff --git a/include/block/block_int.h b/include/block/block_int.h
82
index XXXXXXX..XXXXXXX 100644
83
--- a/include/block/block_int.h
84
+++ b/include/block/block_int.h
85
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
86
int64_t offset, int count, BdrvRequestFlags flags);
87
int coroutine_fn (*bdrv_co_pdiscard)(BlockDriverState *bs,
88
int64_t offset, int count);
89
+
90
+ /*
91
+ * Building block for bdrv_block_status[_above]. The driver should
92
+ * answer only according to the current layer, and should not
93
+ * set BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
94
+ * for the meaning of _DATA, _ZERO, and _OFFSET_VALID.
95
+ */
96
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
97
int64_t sector_num, int nb_sectors, int *pnum,
98
BlockDriverState **file);
99
--
100
1.8.3.1
101
102
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We were throwing away the preallocation information associated with
4
zero clusters. But we should be matching the well-defined semantics
5
in bdrv_get_block_status(), where (BDRV_BLOCK_ZERO |
6
BDRV_BLOCK_OFFSET_VALID) informs the user which offset is reserved,
7
while still reminding the user that reading from that offset is
8
likely to read garbage.
9
10
count_contiguous_clusters_by_type() is now used only for unallocated
11
cluster runs, hence it gets renamed and tightened.
12
13
Making this change lets us see which portions of an image are zero
14
but preallocated, when using qemu-img map --output=json. The
15
--output=human side intentionally ignores all zero clusters, whether
16
or not they are preallocated.
17
18
The fact that there is no change to qemu-iotests './check -qcow2'
19
merely means that we aren't yet testing this aspect of qemu-img;
20
a later patch will add a test.
21
22
Signed-off-by: Eric Blake <eblake@redhat.com>
23
Reviewed-by: Max Reitz <mreitz@redhat.com>
24
Message-id: 20170507000552.20847-5-eblake@redhat.com
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
block/qcow2-cluster.c | 45 +++++++++++++++++++++++++++++++++++----------
28
1 file changed, 35 insertions(+), 10 deletions(-)
29
30
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2-cluster.c
33
+++ b/block/qcow2-cluster.c
34
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
35
    return i;
36
}
37
38
-static int count_contiguous_clusters_by_type(int nb_clusters,
39
- uint64_t *l2_table,
40
- int wanted_type)
41
+/*
42
+ * Checks how many consecutive unallocated clusters in a given L2
43
+ * table have the same cluster type.
44
+ */
45
+static int count_contiguous_clusters_unallocated(int nb_clusters,
46
+ uint64_t *l2_table,
47
+ int wanted_type)
48
{
49
int i;
50
51
+ assert(wanted_type == QCOW2_CLUSTER_ZERO ||
52
+ wanted_type == QCOW2_CLUSTER_UNALLOCATED);
53
for (i = 0; i < nb_clusters; i++) {
54
- int type = qcow2_get_cluster_type(be64_to_cpu(l2_table[i]));
55
+ uint64_t entry = be64_to_cpu(l2_table[i]);
56
+ int type = qcow2_get_cluster_type(entry);
57
58
- if (type != wanted_type) {
59
+ if (type != wanted_type || entry & L2E_OFFSET_MASK) {
60
break;
61
}
62
}
63
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
64
ret = -EIO;
65
goto fail;
66
}
67
- c = count_contiguous_clusters_by_type(nb_clusters, &l2_table[l2_index],
68
- QCOW2_CLUSTER_ZERO);
69
- *cluster_offset = 0;
70
+ /* Distinguish between pure zero clusters and pre-allocated ones */
71
+ if (*cluster_offset & L2E_OFFSET_MASK) {
72
+ c = count_contiguous_clusters(nb_clusters, s->cluster_size,
73
+ &l2_table[l2_index], QCOW_OFLAG_ZERO);
74
+ *cluster_offset &= L2E_OFFSET_MASK;
75
+ if (offset_into_cluster(s, *cluster_offset)) {
76
+ qcow2_signal_corruption(bs, true, -1, -1,
77
+ "Preallocated zero cluster offset %#"
78
+ PRIx64 " unaligned (L2 offset: %#"
79
+ PRIx64 ", L2 index: %#x)",
80
+ *cluster_offset, l2_offset, l2_index);
81
+ ret = -EIO;
82
+ goto fail;
83
+ }
84
+ } else {
85
+ c = count_contiguous_clusters_unallocated(nb_clusters,
86
+ &l2_table[l2_index],
87
+ QCOW2_CLUSTER_ZERO);
88
+ *cluster_offset = 0;
89
+ }
90
break;
91
case QCOW2_CLUSTER_UNALLOCATED:
92
/* how many empty clusters ? */
93
- c = count_contiguous_clusters_by_type(nb_clusters, &l2_table[l2_index],
94
- QCOW2_CLUSTER_UNALLOCATED);
95
+ c = count_contiguous_clusters_unallocated(nb_clusters,
96
+ &l2_table[l2_index],
97
+ QCOW2_CLUSTER_UNALLOCATED);
98
*cluster_offset = 0;
99
break;
100
case QCOW2_CLUSTER_NORMAL:
101
--
102
1.8.3.1
103
104
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Treat plain zero clusters differently from allocated ones, so that
4
we can simplify the logic of checking whether an offset is present.
5
Do this by splitting QCOW2_CLUSTER_ZERO into two new enums,
6
QCOW2_CLUSTER_ZERO_PLAIN and QCOW2_CLUSTER_ZERO_ALLOC.
7
8
I tried to arrange the enum so that we could use
9
'ret <= QCOW2_CLUSTER_ZERO_PLAIN' for all unallocated types, and
10
'ret >= QCOW2_CLUSTER_ZERO_ALLOC' for allocated types, although
11
I didn't actually end up taking advantage of the layout.
12
13
In many cases, this leads to simpler code, by properly combining
14
cases (sometimes, both zero types pair together, other times,
15
plain zero is more like unallocated while allocated zero is more
16
like normal).
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Message-id: 20170507000552.20847-7-eblake@redhat.com
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
---
23
block/qcow2-cluster.c | 79 ++++++++++++++++++----------------------------
24
block/qcow2-refcount.c | 44 +++++++++++---------------
25
block/qcow2.c | 9 ++++--
26
block/qcow2.h | 8 +++--
27
tests/qemu-iotests/060.out | 6 ++--
28
5 files changed, 63 insertions(+), 83 deletions(-)
29
30
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2-cluster.c
33
+++ b/block/qcow2-cluster.c
34
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
35
/* must be allocated */
36
first_cluster_type = qcow2_get_cluster_type(first_entry);
37
assert(first_cluster_type == QCOW2_CLUSTER_NORMAL ||
38
- (first_cluster_type == QCOW2_CLUSTER_ZERO &&
39
- (first_entry & L2E_OFFSET_MASK) != 0));
40
+ first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
41
42
for (i = 0; i < nb_clusters; i++) {
43
uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
44
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters_unallocated(int nb_clusters,
45
{
46
int i;
47
48
- assert(wanted_type == QCOW2_CLUSTER_ZERO ||
49
+ assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN ||
50
wanted_type == QCOW2_CLUSTER_UNALLOCATED);
51
for (i = 0; i < nb_clusters; i++) {
52
uint64_t entry = be64_to_cpu(l2_table[i]);
53
QCow2ClusterType type = qcow2_get_cluster_type(entry);
54
55
- if (type != wanted_type || entry & L2E_OFFSET_MASK) {
56
+ if (type != wanted_type) {
57
break;
58
}
59
}
60
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
61
assert(nb_clusters <= INT_MAX);
62
63
type = qcow2_get_cluster_type(*cluster_offset);
64
+ if (s->qcow_version < 3 && (type == QCOW2_CLUSTER_ZERO_PLAIN ||
65
+ type == QCOW2_CLUSTER_ZERO_ALLOC)) {
66
+ qcow2_signal_corruption(bs, true, -1, -1, "Zero cluster entry found"
67
+ " in pre-v3 image (L2 offset: %#" PRIx64
68
+ ", L2 index: %#x)", l2_offset, l2_index);
69
+ ret = -EIO;
70
+ goto fail;
71
+ }
72
switch (type) {
73
case QCOW2_CLUSTER_COMPRESSED:
74
/* Compressed clusters can only be processed one by one */
75
c = 1;
76
*cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK;
77
break;
78
- case QCOW2_CLUSTER_ZERO:
79
- if (s->qcow_version < 3) {
80
- qcow2_signal_corruption(bs, true, -1, -1, "Zero cluster entry found"
81
- " in pre-v3 image (L2 offset: %#" PRIx64
82
- ", L2 index: %#x)", l2_offset, l2_index);
83
- ret = -EIO;
84
- goto fail;
85
- }
86
- /* Distinguish between pure zero clusters and pre-allocated ones */
87
- if (*cluster_offset & L2E_OFFSET_MASK) {
88
- c = count_contiguous_clusters(nb_clusters, s->cluster_size,
89
- &l2_table[l2_index], QCOW_OFLAG_ZERO);
90
- *cluster_offset &= L2E_OFFSET_MASK;
91
- if (offset_into_cluster(s, *cluster_offset)) {
92
- qcow2_signal_corruption(bs, true, -1, -1,
93
- "Preallocated zero cluster offset %#"
94
- PRIx64 " unaligned (L2 offset: %#"
95
- PRIx64 ", L2 index: %#x)",
96
- *cluster_offset, l2_offset, l2_index);
97
- ret = -EIO;
98
- goto fail;
99
- }
100
- } else {
101
- c = count_contiguous_clusters_unallocated(nb_clusters,
102
- &l2_table[l2_index],
103
- QCOW2_CLUSTER_ZERO);
104
- *cluster_offset = 0;
105
- }
106
- break;
107
+ case QCOW2_CLUSTER_ZERO_PLAIN:
108
case QCOW2_CLUSTER_UNALLOCATED:
109
/* how many empty clusters ? */
110
c = count_contiguous_clusters_unallocated(nb_clusters,
111
- &l2_table[l2_index],
112
- QCOW2_CLUSTER_UNALLOCATED);
113
+ &l2_table[l2_index], type);
114
*cluster_offset = 0;
115
break;
116
+ case QCOW2_CLUSTER_ZERO_ALLOC:
117
case QCOW2_CLUSTER_NORMAL:
118
/* how many allocated clusters ? */
119
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
120
- &l2_table[l2_index], QCOW_OFLAG_ZERO);
121
+ &l2_table[l2_index], QCOW_OFLAG_ZERO);
122
*cluster_offset &= L2E_OFFSET_MASK;
123
if (offset_into_cluster(s, *cluster_offset)) {
124
- qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset %#"
125
+ qcow2_signal_corruption(bs, true, -1, -1,
126
+ "Cluster allocation offset %#"
127
PRIx64 " unaligned (L2 offset: %#" PRIx64
128
", L2 index: %#x)", *cluster_offset,
129
l2_offset, l2_index);
130
@@ -XXX,XX +XXX,XX @@ static int count_cow_clusters(BDRVQcow2State *s, int nb_clusters,
131
break;
132
case QCOW2_CLUSTER_UNALLOCATED:
133
case QCOW2_CLUSTER_COMPRESSED:
134
- case QCOW2_CLUSTER_ZERO:
135
+ case QCOW2_CLUSTER_ZERO_PLAIN:
136
+ case QCOW2_CLUSTER_ZERO_ALLOC:
137
break;
138
default:
139
abort();
140
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
141
* wrong with our code. */
142
assert(nb_clusters > 0);
143
144
- if (qcow2_get_cluster_type(entry) == QCOW2_CLUSTER_ZERO &&
145
- (entry & L2E_OFFSET_MASK) != 0 && (entry & QCOW_OFLAG_COPIED) &&
146
+ if (qcow2_get_cluster_type(entry) == QCOW2_CLUSTER_ZERO_ALLOC &&
147
+ (entry & QCOW_OFLAG_COPIED) &&
148
(!*host_offset ||
149
start_of_cluster(s, *host_offset) == (entry & L2E_OFFSET_MASK)))
150
{
151
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
152
}
153
break;
154
155
- case QCOW2_CLUSTER_ZERO:
156
- /* Preallocated zero clusters should be discarded in any case */
157
- if (!full_discard && (old_l2_entry & L2E_OFFSET_MASK) == 0) {
158
+ case QCOW2_CLUSTER_ZERO_PLAIN:
159
+ if (!full_discard) {
160
continue;
161
}
162
break;
163
164
+ case QCOW2_CLUSTER_ZERO_ALLOC:
165
case QCOW2_CLUSTER_NORMAL:
166
case QCOW2_CLUSTER_COMPRESSED:
167
break;
168
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
169
uint64_t l2_entry = be64_to_cpu(l2_table[j]);
170
int64_t offset = l2_entry & L2E_OFFSET_MASK;
171
QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
172
- bool preallocated = offset != 0;
173
174
- if (cluster_type != QCOW2_CLUSTER_ZERO) {
175
+ if (cluster_type != QCOW2_CLUSTER_ZERO_PLAIN &&
176
+ cluster_type != QCOW2_CLUSTER_ZERO_ALLOC) {
177
continue;
178
}
179
180
- if (!preallocated) {
181
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
182
if (!bs->backing) {
183
/* not backed; therefore we can simply deallocate the
184
* cluster */
185
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
186
"%#" PRIx64 " unaligned (L2 offset: %#"
187
PRIx64 ", L2 index: %#x)", offset,
188
l2_offset, j);
189
- if (!preallocated) {
190
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
191
qcow2_free_clusters(bs, offset, s->cluster_size,
192
QCOW2_DISCARD_ALWAYS);
193
}
194
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
195
196
ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
197
if (ret < 0) {
198
- if (!preallocated) {
199
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
200
qcow2_free_clusters(bs, offset, s->cluster_size,
201
QCOW2_DISCARD_ALWAYS);
202
}
203
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
204
205
ret = bdrv_pwrite_zeroes(bs->file, offset, s->cluster_size, 0);
206
if (ret < 0) {
207
- if (!preallocated) {
208
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
209
qcow2_free_clusters(bs, offset, s->cluster_size,
210
QCOW2_DISCARD_ALWAYS);
211
}
212
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/qcow2-refcount.c
215
+++ b/block/qcow2-refcount.c
216
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry,
217
}
218
break;
219
case QCOW2_CLUSTER_NORMAL:
220
- case QCOW2_CLUSTER_ZERO:
221
- if (l2_entry & L2E_OFFSET_MASK) {
222
- if (offset_into_cluster(s, l2_entry & L2E_OFFSET_MASK)) {
223
- qcow2_signal_corruption(bs, false, -1, -1,
224
- "Cannot free unaligned cluster %#llx",
225
- l2_entry & L2E_OFFSET_MASK);
226
- } else {
227
- qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,
228
- nb_clusters << s->cluster_bits, type);
229
- }
230
+ case QCOW2_CLUSTER_ZERO_ALLOC:
231
+ if (offset_into_cluster(s, l2_entry & L2E_OFFSET_MASK)) {
232
+ qcow2_signal_corruption(bs, false, -1, -1,
233
+ "Cannot free unaligned cluster %#llx",
234
+ l2_entry & L2E_OFFSET_MASK);
235
+ } else {
236
+ qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,
237
+ nb_clusters << s->cluster_bits, type);
238
}
239
break;
240
+ case QCOW2_CLUSTER_ZERO_PLAIN:
241
case QCOW2_CLUSTER_UNALLOCATED:
242
break;
243
default:
244
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
245
break;
246
247
case QCOW2_CLUSTER_NORMAL:
248
- case QCOW2_CLUSTER_ZERO:
249
+ case QCOW2_CLUSTER_ZERO_ALLOC:
250
if (offset_into_cluster(s, offset)) {
251
- qcow2_signal_corruption(bs, true, -1, -1, "Data "
252
- "cluster offset %#" PRIx64
253
+ qcow2_signal_corruption(bs, true, -1, -1, "Cluster "
254
+ "allocation offset %#" PRIx64
255
" unaligned (L2 offset: %#"
256
PRIx64 ", L2 index: %#x)",
257
offset, l2_offset, j);
258
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
259
}
260
261
cluster_index = offset >> s->cluster_bits;
262
- if (!cluster_index) {
263
- /* unallocated */
264
- refcount = 0;
265
- break;
266
- }
267
+ assert(cluster_index);
268
if (addend != 0) {
269
ret = qcow2_update_cluster_refcount(bs,
270
cluster_index, abs(addend), addend < 0,
271
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
272
}
273
break;
274
275
+ case QCOW2_CLUSTER_ZERO_PLAIN:
276
case QCOW2_CLUSTER_UNALLOCATED:
277
refcount = 0;
278
break;
279
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
280
}
281
break;
282
283
- case QCOW2_CLUSTER_ZERO:
284
- if ((l2_entry & L2E_OFFSET_MASK) == 0) {
285
- break;
286
- }
287
- /* fall through */
288
-
289
+ case QCOW2_CLUSTER_ZERO_ALLOC:
290
case QCOW2_CLUSTER_NORMAL:
291
{
292
uint64_t offset = l2_entry & L2E_OFFSET_MASK;
293
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
294
break;
295
}
296
297
+ case QCOW2_CLUSTER_ZERO_PLAIN:
298
case QCOW2_CLUSTER_UNALLOCATED:
299
break;
300
301
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
302
uint64_t data_offset = l2_entry & L2E_OFFSET_MASK;
303
QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
304
305
- if ((cluster_type == QCOW2_CLUSTER_NORMAL) ||
306
- ((cluster_type == QCOW2_CLUSTER_ZERO) && (data_offset != 0))) {
307
+ if (cluster_type == QCOW2_CLUSTER_NORMAL ||
308
+ cluster_type == QCOW2_CLUSTER_ZERO_ALLOC) {
309
ret = qcow2_get_refcount(bs,
310
data_offset >> s->cluster_bits,
311
&refcount);
312
diff --git a/block/qcow2.c b/block/qcow2.c
313
index XXXXXXX..XXXXXXX 100644
314
--- a/block/qcow2.c
315
+++ b/block/qcow2.c
316
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
317
*file = bs->file->bs;
318
status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;
319
}
320
- if (ret == QCOW2_CLUSTER_ZERO) {
321
+ if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) {
322
status |= BDRV_BLOCK_ZERO;
323
} else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
324
status |= BDRV_BLOCK_DATA;
325
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
326
}
327
break;
328
329
- case QCOW2_CLUSTER_ZERO:
330
+ case QCOW2_CLUSTER_ZERO_PLAIN:
331
+ case QCOW2_CLUSTER_ZERO_ALLOC:
332
qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes);
333
break;
334
335
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
336
count = s->cluster_size;
337
nr = s->cluster_size;
338
ret = qcow2_get_cluster_offset(bs, offset, &nr, &off);
339
- if (ret != QCOW2_CLUSTER_UNALLOCATED && ret != QCOW2_CLUSTER_ZERO) {
340
+ if (ret != QCOW2_CLUSTER_UNALLOCATED &&
341
+ ret != QCOW2_CLUSTER_ZERO_PLAIN &&
342
+ ret != QCOW2_CLUSTER_ZERO_ALLOC) {
343
qemu_co_mutex_unlock(&s->lock);
344
return -ENOTSUP;
345
}
346
diff --git a/block/qcow2.h b/block/qcow2.h
347
index XXXXXXX..XXXXXXX 100644
348
--- a/block/qcow2.h
349
+++ b/block/qcow2.h
350
@@ -XXX,XX +XXX,XX @@ typedef struct QCowL2Meta
351
352
typedef enum QCow2ClusterType {
353
QCOW2_CLUSTER_UNALLOCATED,
354
+ QCOW2_CLUSTER_ZERO_PLAIN,
355
+ QCOW2_CLUSTER_ZERO_ALLOC,
356
QCOW2_CLUSTER_NORMAL,
357
QCOW2_CLUSTER_COMPRESSED,
358
- QCOW2_CLUSTER_ZERO
359
} QCow2ClusterType;
360
361
typedef enum QCow2MetadataOverlap {
362
@@ -XXX,XX +XXX,XX @@ static inline QCow2ClusterType qcow2_get_cluster_type(uint64_t l2_entry)
363
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
364
return QCOW2_CLUSTER_COMPRESSED;
365
} else if (l2_entry & QCOW_OFLAG_ZERO) {
366
- return QCOW2_CLUSTER_ZERO;
367
+ if (l2_entry & L2E_OFFSET_MASK) {
368
+ return QCOW2_CLUSTER_ZERO_ALLOC;
369
+ }
370
+ return QCOW2_CLUSTER_ZERO_PLAIN;
371
} else if (!(l2_entry & L2E_OFFSET_MASK)) {
372
return QCOW2_CLUSTER_UNALLOCATED;
373
} else {
374
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
375
index XXXXXXX..XXXXXXX 100644
376
--- a/tests/qemu-iotests/060.out
377
+++ b/tests/qemu-iotests/060.out
378
@@ -XXX,XX +XXX,XX @@ qemu-img: Error while amending options: Input/output error
379
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
380
wrote 65536/65536 bytes at offset 0
381
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
382
-qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
383
+qcow2: Marking image as corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
384
read failed: Input/output error
385
386
=== Testing unaligned pre-allocated zero cluster ===
387
@@ -XXX,XX +XXX,XX @@ discard 65536/65536 bytes at offset 0
388
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
389
wrote 65536/65536 bytes at offset 0
390
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
391
-qcow2: Image is corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further non-fatal corruption events will be suppressed
392
+qcow2: Image is corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further non-fatal corruption events will be suppressed
393
read failed: Input/output error
394
read failed: Input/output error
395
396
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
397
wrote 131072/131072 bytes at offset 0
398
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
399
qcow2: Image is corrupt: Cannot free unaligned cluster 0x52a00; further non-fatal corruption events will be suppressed
400
-qcow2: Marking image as corrupt: Data cluster offset 0x62a00 unaligned (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
401
+qcow2: Marking image as corrupt: Cluster allocation offset 0x62a00 unaligned (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
402
discard 65536/65536 bytes at offset 0
403
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
404
read failed: Input/output error
405
--
406
1.8.3.1
407
408
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Similar to discard_single_l2(), we should try to avoid dirtying
4
the L2 cache when the cluster we are changing already has the
5
right characteristics.
6
7
Note that by the time we get to zero_single_l2(), BDRV_REQ_MAY_UNMAP
8
is a requirement to unallocate a cluster (this is because the block
9
layer clears that flag if discard.* flags during open requested that
10
we never punch holes - see the conversation around commit 170f4b2e,
11
https://lists.gnu.org/archive/html/qemu-devel/2016-09/msg07306.html).
12
Therefore, this patch can only reuse a zero cluster as-is if either
13
unmapping is not requested, or if the zero cluster was not associated
14
with an allocation.
15
16
Technically, there are some cases where an unallocated cluster
17
already reads as all zeroes (namely, when there is no backing file
18
[easy: check bs->backing], or when the backing file also reads as
19
zeroes [harder: we can't check bdrv_get_block_status since we are
20
already holding the lock]), where the guest would not immediately see
21
a difference if we left that cluster unallocated. But if the user
22
did not request unmapping, leaving an unallocated cluster is wrong;
23
and even if the user DID request unmapping, keeping a cluster
24
unallocated risks a subtle semantic change of guest-visible contents
25
if a backing file is later added, and it is not worth auditing
26
whether all internal uses such as mirror properly avoid an unmap
27
request. Thus, this patch is intentionally limited to just clusters
28
that are already marked as zero.
29
30
Signed-off-by: Eric Blake <eblake@redhat.com>
31
Reviewed-by: Max Reitz <mreitz@redhat.com>
32
Message-id: 20170507000552.20847-8-eblake@redhat.com
33
Signed-off-by: Max Reitz <mreitz@redhat.com>
34
---
35
block/qcow2-cluster.c | 15 +++++++++++++--
36
1 file changed, 13 insertions(+), 2 deletions(-)
37
38
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/qcow2-cluster.c
41
+++ b/block/qcow2-cluster.c
42
@@ -XXX,XX +XXX,XX @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
43
int l2_index;
44
int ret;
45
int i;
46
+ bool unmap = !!(flags & BDRV_REQ_MAY_UNMAP);
47
48
ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
49
if (ret < 0) {
50
@@ -XXX,XX +XXX,XX @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
51
52
for (i = 0; i < nb_clusters; i++) {
53
uint64_t old_offset;
54
+ QCow2ClusterType cluster_type;
55
56
old_offset = be64_to_cpu(l2_table[l2_index + i]);
57
58
- /* Update L2 entries */
59
+ /*
60
+ * Minimize L2 changes if the cluster already reads back as
61
+ * zeroes with correct allocation.
62
+ */
63
+ cluster_type = qcow2_get_cluster_type(old_offset);
64
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN ||
65
+ (cluster_type == QCOW2_CLUSTER_ZERO_ALLOC && !unmap)) {
66
+ continue;
67
+ }
68
+
69
qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
70
- if (old_offset & QCOW_OFLAG_COMPRESSED || flags & BDRV_REQ_MAY_UNMAP) {
71
+ if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
72
l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
73
qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
74
} else {
75
--
76
1.8.3.1
77
78
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Although _filter_qemu_img_map documents that it scrubs offsets, it
4
was only doing so for human mode. Of the existing tests using the
5
filter (97, 122, 150, 154, 176), two of them are affected, but it
6
does not hurt the validity of the tests to not require particular
7
mappings (another test, 66, uses offsets but intentionally does not
8
pass through _filter_qemu_img_map, because it checks that offsets
9
are unchanged before and after an operation).
10
11
Another justification for this patch is that it will allow a future
12
patch to utilize 'qemu-img map --output=json' to check the status of
13
preallocated zero clusters without regards to the mapping (since
14
the qcow2 mapping can be very sensitive to the chosen cluster size,
15
when preallocation is not in use).
16
17
Signed-off-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Message-id: 20170507000552.20847-9-eblake@redhat.com
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
tests/qemu-iotests/122.out | 16 ++++++++--------
23
tests/qemu-iotests/154.out | 30 +++++++++++++++---------------
24
tests/qemu-iotests/common.filter | 4 +++-
25
3 files changed, 26 insertions(+), 24 deletions(-)
26
27
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/122.out
30
+++ b/tests/qemu-iotests/122.out
31
@@ -XXX,XX +XXX,XX @@ read 3145728/3145728 bytes at offset 0
32
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
33
read 63963136/63963136 bytes at offset 3145728
34
61 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
35
-[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": 327680}]
36
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
37
38
convert -c -S 0:
39
read 3145728/3145728 bytes at offset 0
40
@@ -XXX,XX +XXX,XX @@ read 30408704/30408704 bytes at offset 3145728
41
29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
42
read 33554432/33554432 bytes at offset 33554432
43
32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
44
-[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": 327680}]
45
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
46
47
convert -c -S 0 with source backing file:
48
read 3145728/3145728 bytes at offset 0
49
@@ -XXX,XX +XXX,XX @@ read 30408704/30408704 bytes at offset 3145728
50
29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
51
read 33554432/33554432 bytes at offset 33554432
52
32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
-[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": 327680}]
54
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
55
56
convert -c -S 0 -B ...
57
read 3145728/3145728 bytes at offset 0
58
@@ -XXX,XX +XXX,XX @@ wrote 1024/1024 bytes at offset 17408
59
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
60
61
convert -S 4k
62
-[{ "start": 0, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": 8192},
63
+[{ "start": 0, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
64
{ "start": 1024, "length": 7168, "depth": 0, "zero": true, "data": false},
65
-{ "start": 8192, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": 9216},
66
+{ "start": 8192, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
67
{ "start": 9216, "length": 8192, "depth": 0, "zero": true, "data": false},
68
-{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": 10240},
69
+{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
70
{ "start": 18432, "length": 67090432, "depth": 0, "zero": true, "data": false}]
71
72
convert -c -S 4k
73
@@ -XXX,XX +XXX,XX @@ convert -c -S 4k
74
{ "start": 18432, "length": 67090432, "depth": 0, "zero": true, "data": false}]
75
76
convert -S 8k
77
-[{ "start": 0, "length": 9216, "depth": 0, "zero": false, "data": true, "offset": 8192},
78
+[{ "start": 0, "length": 9216, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
79
{ "start": 9216, "length": 8192, "depth": 0, "zero": true, "data": false},
80
-{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": 17408},
81
+{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
82
{ "start": 18432, "length": 67090432, "depth": 0, "zero": true, "data": false}]
83
84
convert -c -S 8k
85
diff --git a/tests/qemu-iotests/154.out b/tests/qemu-iotests/154.out
86
index XXXXXXX..XXXXXXX 100644
87
--- a/tests/qemu-iotests/154.out
88
+++ b/tests/qemu-iotests/154.out
89
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 65536
90
read 2048/2048 bytes at offset 67584
91
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
92
[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
93
-{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
94
+{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
95
{ "start": 36864, "length": 28672, "depth": 1, "zero": true, "data": false},
96
-{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
97
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
98
{ "start": 69632, "length": 134148096, "depth": 1, "zero": true, "data": false}]
99
100
== backing file contains non-zero data after write_zeroes ==
101
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 44032
102
read 3072/3072 bytes at offset 40960
103
3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
104
[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
105
-{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
106
+{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
107
{ "start": 36864, "length": 4096, "depth": 1, "zero": true, "data": false},
108
-{ "start": 40960, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
109
+{ "start": 40960, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
110
{ "start": 45056, "length": 134172672, "depth": 1, "zero": true, "data": false}]
111
112
== write_zeroes covers non-zero data ==
113
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 67584
114
read 5120/5120 bytes at offset 68608
115
5 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
116
[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
117
-{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
118
+{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
119
{ "start": 36864, "length": 4096, "depth": 0, "zero": true, "data": false},
120
{ "start": 40960, "length": 8192, "depth": 1, "zero": true, "data": false},
121
-{ "start": 49152, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
122
+{ "start": 49152, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
123
{ "start": 53248, "length": 4096, "depth": 0, "zero": true, "data": false},
124
{ "start": 57344, "length": 8192, "depth": 1, "zero": true, "data": false},
125
-{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 28672},
126
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
127
{ "start": 69632, "length": 4096, "depth": 0, "zero": true, "data": false},
128
{ "start": 73728, "length": 134144000, "depth": 1, "zero": true, "data": false}]
129
130
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 72704
131
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
132
[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
133
{ "start": 32768, "length": 4096, "depth": 0, "zero": true, "data": false},
134
-{ "start": 36864, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
135
+{ "start": 36864, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
136
{ "start": 40960, "length": 8192, "depth": 1, "zero": true, "data": false},
137
{ "start": 49152, "length": 4096, "depth": 0, "zero": true, "data": false},
138
-{ "start": 53248, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
139
+{ "start": 53248, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
140
{ "start": 57344, "length": 8192, "depth": 1, "zero": true, "data": false},
141
{ "start": 65536, "length": 4096, "depth": 0, "zero": true, "data": false},
142
-{ "start": 69632, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 28672},
143
+{ "start": 69632, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
144
{ "start": 73728, "length": 134144000, "depth": 1, "zero": true, "data": false}]
145
146
== spanning two clusters, partially overwriting backing file ==
147
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 5120
148
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
149
read 2048/2048 bytes at offset 6144
150
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
151
-[{ "start": 0, "length": 8192, "depth": 0, "zero": false, "data": true, "offset": 20480},
152
+[{ "start": 0, "length": 8192, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
153
{ "start": 8192, "length": 134209536, "depth": 1, "zero": true, "data": false}]
154
155
== spanning multiple clusters, non-zero in first cluster ==
156
@@ -XXX,XX +XXX,XX @@ read 2048/2048 bytes at offset 65536
157
read 10240/10240 bytes at offset 67584
158
10 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
159
[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
160
-{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
161
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
162
{ "start": 69632, "length": 8192, "depth": 0, "zero": true, "data": false},
163
{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
164
165
@@ -XXX,XX +XXX,XX @@ read 2048/2048 bytes at offset 75776
166
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
167
[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
168
{ "start": 65536, "length": 8192, "depth": 0, "zero": true, "data": false},
169
-{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
170
+{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
171
{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
172
173
== spanning multiple clusters, partially overwriting backing file ==
174
@@ -XXX,XX +XXX,XX @@ read 2048/2048 bytes at offset 74752
175
read 1024/1024 bytes at offset 76800
176
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
177
[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
178
-{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
179
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
180
{ "start": 69632, "length": 4096, "depth": 0, "zero": true, "data": false},
181
-{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
182
+{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
183
{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
184
*** done
185
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
186
index XXXXXXX..XXXXXXX 100644
187
--- a/tests/qemu-iotests/common.filter
188
+++ b/tests/qemu-iotests/common.filter
189
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
190
-e "/log_size: [0-9]\\+/d"
191
}
192
193
-# filter out offsets and file names from qemu-img map
194
+# filter out offsets and file names from qemu-img map; good for both
195
+# human and json output
196
_filter_qemu_img_map()
197
{
198
sed -e 's/\([0-9a-fx]* *[0-9a-fx]* *\)[0-9a-fx]* */\1/g' \
199
+ -e 's/"offset": [0-9]\+/"offset": OFFSET/g' \
200
-e 's/Mapped to *//' | _filter_testdir | _filter_imgfmt
201
}
202
203
--
204
1.8.3.1
205
206
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
No tests were covering write zeroes with unmap. Additionally,
4
I needed to prove that my previous patches for correct status
5
reporting and write zeroes optimizations actually had an impact.
6
7
The test works for cluster_size between 8k and 2M (for smaller
8
sizes, it fails because our allocation patterns are not contiguous
9
with small clusters - in part, the largest consecutive allocation
10
we tend to get is often bounded by the size covered by one L2
11
table).
12
13
Note that testing for zero clusters is tricky: 'qemu-io map'
14
reports whether data comes from the current layer of the image
15
(useful for sniffing out which regions of the file have
16
QCOW_OFLAG_ZERO) - but doesn't show which clusters have mappings;
17
while 'qemu-img map' sees "zero":true for both unallocated and
18
zero clusters for any qcow2 with no backing layer (so less useful
19
at detecting true zero clusters), but reliably shows mappings.
20
So we have to rely on both queries side-by-side at each point of
21
the test.
22
23
Signed-off-by: Eric Blake <eblake@redhat.com>
24
Reviewed-by: Max Reitz <mreitz@redhat.com>
25
Message-id: 20170507000552.20847-10-eblake@redhat.com
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
tests/qemu-iotests/179 | 130 +++++++++++++++++++++++++++++++++++++
29
tests/qemu-iotests/179.out | 156 +++++++++++++++++++++++++++++++++++++++++++++
30
tests/qemu-iotests/group | 1 +
31
3 files changed, 287 insertions(+)
32
create mode 100755 tests/qemu-iotests/179
33
create mode 100644 tests/qemu-iotests/179.out
34
35
diff --git a/tests/qemu-iotests/179 b/tests/qemu-iotests/179
36
new file mode 100755
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/tests/qemu-iotests/179
40
@@ -XXX,XX +XXX,XX @@
41
+#!/bin/bash
42
+#
43
+# Test case for write zeroes with unmap
44
+#
45
+# Copyright (C) 2017 Red Hat, Inc.
46
+#
47
+# This program is free software; you can redistribute it and/or modify
48
+# it under the terms of the GNU General Public License as published by
49
+# the Free Software Foundation; either version 2 of the License, or
50
+# (at your option) any later version.
51
+#
52
+# This program is distributed in the hope that it will be useful,
53
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
54
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55
+# GNU General Public License for more details.
56
+#
57
+# You should have received a copy of the GNU General Public License
58
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
59
+#
60
+
61
+# creator
62
+owner=eblake@redhat.com
63
+
64
+seq="$(basename $0)"
65
+echo "QA output created by $seq"
66
+
67
+here="$PWD"
68
+status=1    # failure is the default!
69
+
70
+_cleanup()
71
+{
72
+    _cleanup_test_img
73
+}
74
+trap "_cleanup; exit \$status" 0 1 2 3 15
75
+
76
+# get standard environment, filters and checks
77
+. ./common.rc
78
+. ./common.filter
79
+
80
+_supported_fmt qcow2
81
+_supported_proto file
82
+_supported_os Linux
83
+
84
+# v2 images can't mark clusters as zero
85
+_unsupported_imgopts compat=0.10
86
+
87
+echo
88
+echo '=== Testing write zeroes with unmap ==='
89
+echo
90
+
91
+TEST_IMG="$TEST_IMG.base" _make_test_img 64M
92
+_make_test_img -b "$TEST_IMG.base"
93
+
94
+# Offsets chosen at or near 2M boundaries so test works at all cluster sizes
95
+# 8k and larger (smaller clusters fail due to non-contiguous allocations)
96
+
97
+# Aligned writes to unallocated cluster should not allocate mapping, but must
98
+# mark cluster as zero, whether or not unmap was requested
99
+$QEMU_IO -c "write -z -u 2M 2M" "$TEST_IMG.base" | _filter_qemu_io
100
+$QEMU_IO -c "write -z 6M 2M" "$TEST_IMG.base" | _filter_qemu_io
101
+$QEMU_IO -c "map" "$TEST_IMG.base" | _filter_qemu_io
102
+$QEMU_IMG map --output=json "$TEST_IMG.base" | _filter_qemu_img_map
103
+
104
+# Unaligned writes need not allocate mapping if the cluster already reads
105
+# as zero, but must mark cluster as zero, whether or not unmap was requested
106
+$QEMU_IO -c "write -z -u 10485761 2097150" "$TEST_IMG.base" | _filter_qemu_io
107
+$QEMU_IO -c "write -z 14680065 2097150" "$TEST_IMG.base" | _filter_qemu_io
108
+$QEMU_IO -c "map" "$TEST_IMG.base" | _filter_qemu_io
109
+$QEMU_IMG map --output=json "$TEST_IMG.base" | _filter_qemu_img_map
110
+
111
+# Requesting unmap of normal data must deallocate; omitting unmap should
112
+# preserve the mapping
113
+$QEMU_IO -c "write 18M 14M" "$TEST_IMG.base" | _filter_qemu_io
114
+$QEMU_IO -c "write -z -u 20M 2M" "$TEST_IMG.base" | _filter_qemu_io
115
+$QEMU_IO -c "write -z 24M 6M" "$TEST_IMG.base" | _filter_qemu_io
116
+$QEMU_IO -c "map" "$TEST_IMG.base" | _filter_qemu_io
117
+$QEMU_IMG map --output=json "$TEST_IMG.base" | _filter_qemu_img_map
118
+
119
+# Likewise when writing on already-mapped zero data
120
+$QEMU_IO -c "write -z -u 26M 2M" "$TEST_IMG.base" | _filter_qemu_io
121
+$QEMU_IO -c "write -z 28M 2M" "$TEST_IMG.base" | _filter_qemu_io
122
+$QEMU_IO -c "map" "$TEST_IMG.base" | _filter_qemu_io
123
+$QEMU_IMG map --output=json "$TEST_IMG.base" | _filter_qemu_img_map
124
+
125
+# Writing on unmapped zeroes does not allocate
126
+$QEMU_IO -c "write -z 32M 8M" "$TEST_IMG.base" | _filter_qemu_io
127
+$QEMU_IO -c "write -z -u 34M 2M" "$TEST_IMG.base" | _filter_qemu_io
128
+$QEMU_IO -c "write -z 36M 2M" "$TEST_IMG.base" | _filter_qemu_io
129
+$QEMU_IO -c "map" "$TEST_IMG.base" | _filter_qemu_io
130
+$QEMU_IMG map --output=json "$TEST_IMG.base" | _filter_qemu_img_map
131
+
132
+# Writing zero overrides a backing file, regardless of backing cluster type
133
+$QEMU_IO -c "write -z 40M 8M" "$TEST_IMG.base" | _filter_qemu_io
134
+$QEMU_IO -c "write 48M 8M" "$TEST_IMG.base" | _filter_qemu_io
135
+$QEMU_IO -c "write -z -u 42M 2M" "$TEST_IMG" | _filter_qemu_io
136
+$QEMU_IO -c "write -z 44M 2M" "$TEST_IMG" | _filter_qemu_io
137
+$QEMU_IO -c "write -z -u 50M 2M" "$TEST_IMG" | _filter_qemu_io
138
+$QEMU_IO -c "write -z 52M 2M" "$TEST_IMG" | _filter_qemu_io
139
+$QEMU_IO -c "write -z -u 58M 2M" "$TEST_IMG" | _filter_qemu_io
140
+$QEMU_IO -c "write -z 60M 2M" "$TEST_IMG" | _filter_qemu_io
141
+$QEMU_IO -c "map" "$TEST_IMG" | _filter_qemu_io
142
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
143
+
144
+# Final check that mappings are correct and images are still sane
145
+TEST_IMG="$TEST_IMG.base" _check_test_img
146
+_check_test_img
147
+
148
+echo
149
+echo '=== Testing cache optimization ==='
150
+echo
151
+
152
+BLKDBG_TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG.base"
153
+
154
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
155
+[inject-error]
156
+event = "l2_update"
157
+errno = "5"
158
+immediately = "on"
159
+once = "off"
160
+EOF
161
+
162
+# None of the following writes should trigger an L2 update, because the
163
+# cluster already reads as zero, and we don't have to change allocation
164
+$QEMU_IO -c "w -z -u 20M 2M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
165
+$QEMU_IO -c "w -z 20M 2M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
166
+$QEMU_IO -c "w -z 28M 2M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
167
+
168
+# success, all done
169
+echo '*** done'
170
+status=0
171
diff --git a/tests/qemu-iotests/179.out b/tests/qemu-iotests/179.out
172
new file mode 100644
173
index XXXXXXX..XXXXXXX
174
--- /dev/null
175
+++ b/tests/qemu-iotests/179.out
176
@@ -XXX,XX +XXX,XX @@
177
+QA output created by 179
178
+
179
+=== Testing write zeroes with unmap ===
180
+
181
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
182
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
183
+wrote 2097152/2097152 bytes at offset 2097152
184
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
185
+wrote 2097152/2097152 bytes at offset 6291456
186
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
187
+2 MiB (0x200000) bytes not allocated at offset 0 bytes (0x0)
188
+2 MiB (0x200000) bytes allocated at offset 2 MiB (0x200000)
189
+2 MiB (0x200000) bytes not allocated at offset 4 MiB (0x400000)
190
+2 MiB (0x200000) bytes allocated at offset 6 MiB (0x600000)
191
+56 MiB (0x3800000) bytes not allocated at offset 8 MiB (0x800000)
192
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}]
193
+wrote 2097150/2097150 bytes at offset 10485761
194
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
195
+wrote 2097150/2097150 bytes at offset 14680065
196
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+2 MiB (0x200000) bytes not allocated at offset 0 bytes (0x0)
198
+2 MiB (0x200000) bytes allocated at offset 2 MiB (0x200000)
199
+2 MiB (0x200000) bytes not allocated at offset 4 MiB (0x400000)
200
+2 MiB (0x200000) bytes allocated at offset 6 MiB (0x600000)
201
+2 MiB (0x200000) bytes not allocated at offset 8 MiB (0x800000)
202
+2 MiB (0x200000) bytes allocated at offset 10 MiB (0xa00000)
203
+2 MiB (0x200000) bytes not allocated at offset 12 MiB (0xc00000)
204
+2 MiB (0x200000) bytes allocated at offset 14 MiB (0xe00000)
205
+48 MiB (0x3000000) bytes not allocated at offset 16 MiB (0x1000000)
206
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}]
207
+wrote 14680064/14680064 bytes at offset 18874368
208
+14 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
209
+wrote 2097152/2097152 bytes at offset 20971520
210
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
211
+wrote 6291456/6291456 bytes at offset 25165824
212
+6 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
213
+2 MiB (0x200000) bytes not allocated at offset 0 bytes (0x0)
214
+2 MiB (0x200000) bytes allocated at offset 2 MiB (0x200000)
215
+2 MiB (0x200000) bytes not allocated at offset 4 MiB (0x400000)
216
+2 MiB (0x200000) bytes allocated at offset 6 MiB (0x600000)
217
+2 MiB (0x200000) bytes not allocated at offset 8 MiB (0x800000)
218
+2 MiB (0x200000) bytes allocated at offset 10 MiB (0xa00000)
219
+2 MiB (0x200000) bytes not allocated at offset 12 MiB (0xc00000)
220
+2 MiB (0x200000) bytes allocated at offset 14 MiB (0xe00000)
221
+2 MiB (0x200000) bytes not allocated at offset 16 MiB (0x1000000)
222
+14 MiB (0xe00000) bytes allocated at offset 18 MiB (0x1200000)
223
+32 MiB (0x2000000) bytes not allocated at offset 32 MiB (0x2000000)
224
+[{ "start": 0, "length": 18874368, "depth": 0, "zero": true, "data": false},
225
+{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
226
+{ "start": 20971520, "length": 2097152, "depth": 0, "zero": true, "data": false},
227
+{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
228
+{ "start": 25165824, "length": 6291456, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
229
+{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
230
+{ "start": 33554432, "length": 33554432, "depth": 0, "zero": true, "data": false}]
231
+wrote 2097152/2097152 bytes at offset 27262976
232
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
233
+wrote 2097152/2097152 bytes at offset 29360128
234
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
235
+2 MiB (0x200000) bytes not allocated at offset 0 bytes (0x0)
236
+2 MiB (0x200000) bytes allocated at offset 2 MiB (0x200000)
237
+2 MiB (0x200000) bytes not allocated at offset 4 MiB (0x400000)
238
+2 MiB (0x200000) bytes allocated at offset 6 MiB (0x600000)
239
+2 MiB (0x200000) bytes not allocated at offset 8 MiB (0x800000)
240
+2 MiB (0x200000) bytes allocated at offset 10 MiB (0xa00000)
241
+2 MiB (0x200000) bytes not allocated at offset 12 MiB (0xc00000)
242
+2 MiB (0x200000) bytes allocated at offset 14 MiB (0xe00000)
243
+2 MiB (0x200000) bytes not allocated at offset 16 MiB (0x1000000)
244
+14 MiB (0xe00000) bytes allocated at offset 18 MiB (0x1200000)
245
+32 MiB (0x2000000) bytes not allocated at offset 32 MiB (0x2000000)
246
+[{ "start": 0, "length": 18874368, "depth": 0, "zero": true, "data": false},
247
+{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
248
+{ "start": 20971520, "length": 2097152, "depth": 0, "zero": true, "data": false},
249
+{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
250
+{ "start": 25165824, "length": 2097152, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
251
+{ "start": 27262976, "length": 2097152, "depth": 0, "zero": true, "data": false},
252
+{ "start": 29360128, "length": 2097152, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
253
+{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
254
+{ "start": 33554432, "length": 33554432, "depth": 0, "zero": true, "data": false}]
255
+wrote 8388608/8388608 bytes at offset 33554432
256
+8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
257
+wrote 2097152/2097152 bytes at offset 35651584
258
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
259
+wrote 2097152/2097152 bytes at offset 37748736
260
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
261
+2 MiB (0x200000) bytes not allocated at offset 0 bytes (0x0)
262
+2 MiB (0x200000) bytes allocated at offset 2 MiB (0x200000)
263
+2 MiB (0x200000) bytes not allocated at offset 4 MiB (0x400000)
264
+2 MiB (0x200000) bytes allocated at offset 6 MiB (0x600000)
265
+2 MiB (0x200000) bytes not allocated at offset 8 MiB (0x800000)
266
+2 MiB (0x200000) bytes allocated at offset 10 MiB (0xa00000)
267
+2 MiB (0x200000) bytes not allocated at offset 12 MiB (0xc00000)
268
+2 MiB (0x200000) bytes allocated at offset 14 MiB (0xe00000)
269
+2 MiB (0x200000) bytes not allocated at offset 16 MiB (0x1000000)
270
+22 MiB (0x1600000) bytes allocated at offset 18 MiB (0x1200000)
271
+24 MiB (0x1800000) bytes not allocated at offset 40 MiB (0x2800000)
272
+[{ "start": 0, "length": 18874368, "depth": 0, "zero": true, "data": false},
273
+{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
274
+{ "start": 20971520, "length": 2097152, "depth": 0, "zero": true, "data": false},
275
+{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
276
+{ "start": 25165824, "length": 2097152, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
277
+{ "start": 27262976, "length": 2097152, "depth": 0, "zero": true, "data": false},
278
+{ "start": 29360128, "length": 2097152, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
279
+{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
280
+{ "start": 33554432, "length": 33554432, "depth": 0, "zero": true, "data": false}]
281
+wrote 8388608/8388608 bytes at offset 41943040
282
+8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+wrote 8388608/8388608 bytes at offset 50331648
284
+8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
285
+wrote 2097152/2097152 bytes at offset 44040192
286
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
287
+wrote 2097152/2097152 bytes at offset 46137344
288
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
289
+wrote 2097152/2097152 bytes at offset 52428800
290
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
291
+wrote 2097152/2097152 bytes at offset 54525952
292
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
293
+wrote 2097152/2097152 bytes at offset 60817408
294
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
295
+wrote 2097152/2097152 bytes at offset 62914560
296
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
297
+42 MiB (0x2a00000) bytes not allocated at offset 0 bytes (0x0)
298
+4 MiB (0x400000) bytes allocated at offset 42 MiB (0x2a00000)
299
+4 MiB (0x400000) bytes not allocated at offset 46 MiB (0x2e00000)
300
+4 MiB (0x400000) bytes allocated at offset 50 MiB (0x3200000)
301
+4 MiB (0x400000) bytes not allocated at offset 54 MiB (0x3600000)
302
+4 MiB (0x400000) bytes allocated at offset 58 MiB (0x3a00000)
303
+2 MiB (0x200000) bytes not allocated at offset 62 MiB (0x3e00000)
304
+[{ "start": 0, "length": 18874368, "depth": 1, "zero": true, "data": false},
305
+{ "start": 18874368, "length": 2097152, "depth": 1, "zero": false, "data": true, "offset": OFFSET},
306
+{ "start": 20971520, "length": 2097152, "depth": 1, "zero": true, "data": false},
307
+{ "start": 23068672, "length": 2097152, "depth": 1, "zero": false, "data": true, "offset": OFFSET},
308
+{ "start": 25165824, "length": 2097152, "depth": 1, "zero": true, "data": false, "offset": OFFSET},
309
+{ "start": 27262976, "length": 2097152, "depth": 1, "zero": true, "data": false},
310
+{ "start": 29360128, "length": 2097152, "depth": 1, "zero": true, "data": false, "offset": OFFSET},
311
+{ "start": 31457280, "length": 2097152, "depth": 1, "zero": false, "data": true, "offset": OFFSET},
312
+{ "start": 33554432, "length": 10485760, "depth": 1, "zero": true, "data": false},
313
+{ "start": 44040192, "length": 4194304, "depth": 0, "zero": true, "data": false},
314
+{ "start": 48234496, "length": 2097152, "depth": 1, "zero": true, "data": false},
315
+{ "start": 50331648, "length": 2097152, "depth": 1, "zero": false, "data": true, "offset": OFFSET},
316
+{ "start": 52428800, "length": 4194304, "depth": 0, "zero": true, "data": false},
317
+{ "start": 56623104, "length": 2097152, "depth": 1, "zero": false, "data": true, "offset": OFFSET},
318
+{ "start": 58720256, "length": 2097152, "depth": 1, "zero": true, "data": false},
319
+{ "start": 60817408, "length": 4194304, "depth": 0, "zero": true, "data": false},
320
+{ "start": 65011712, "length": 2097152, "depth": 1, "zero": true, "data": false}]
321
+No errors were found on the image.
322
+No errors were found on the image.
323
+
324
+=== Testing cache optimization ===
325
+
326
+wrote 2097152/2097152 bytes at offset 20971520
327
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
328
+wrote 2097152/2097152 bytes at offset 20971520
329
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
330
+wrote 2097152/2097152 bytes at offset 29360128
331
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
332
+*** done
333
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
334
index XXXXXXX..XXXXXXX 100644
335
--- a/tests/qemu-iotests/group
336
+++ b/tests/qemu-iotests/group
337
@@ -XXX,XX +XXX,XX @@
338
175 auto quick
339
176 rw auto backing
340
177 rw auto quick
341
+179 rw auto quick
342
181 rw auto migration
343
182 rw auto quick
344
--
345
1.8.3.1
346
347
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We already audited (in commit 0c1bd469) that qcow2_discard_clusters()
4
is only passed cluster-aligned start values; but we can further
5
tighten the assertion that the only unaligned end value is at EOF.
6
7
Recent commits have taken advantage of an unaligned tail cluster,
8
for both discard and write zeroes.
9
10
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 20170507000552.20847-12-eblake@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/qcow2-cluster.c | 15 +++++++++++----
16
1 file changed, 11 insertions(+), 4 deletions(-)
17
18
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2-cluster.c
21
+++ b/block/qcow2-cluster.c
22
@@ -XXX,XX +XXX,XX @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
23
24
end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
25
26
- /* The caller must cluster-align start; round end down except at EOF */
27
+ /* Caller must pass aligned values, except at image end */
28
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
29
- if (end_offset != bs->total_sectors * BDRV_SECTOR_SIZE) {
30
- end_offset = start_of_cluster(s, end_offset);
31
- }
32
+ assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
33
+ end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
34
35
nb_clusters = size_to_clusters(s, end_offset - offset);
36
37
@@ -XXX,XX +XXX,XX @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors,
38
int flags)
39
{
40
BDRVQcow2State *s = bs->opaque;
41
+ uint64_t end_offset;
42
uint64_t nb_clusters;
43
int ret;
44
45
+ end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
46
+
47
+ /* Caller must pass aligned values, except at image end */
48
+ assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
49
+ assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
50
+ end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
51
+
52
/* The zero flag is only supported by version 3 and newer */
53
if (s->qcow_version < 3) {
54
return -ENOTSUP;
55
--
56
1.8.3.1
57
58
diff view generated by jsdifflib