1
The following changes since commit b2f7a038bb4c4fc5ce6b8486e8513dfd97665e2a:
1
The following changes since commit eda1df0345f5a1e337e30367124dcb0e802bdfde:
2
2
3
Merge remote-tracking branch 'remotes/rth/tags/pull-softfloat-20181104' into staging (2018-11-05 10:32:49 +0000)
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-pflash-2019-03-11' into staging (2019-03-12 11:12:36 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 1240ac558d348f6c7a5752b1a57c1da58e4efe3e:
9
for you to fetch changes up to c31dfeb02a1d155bdb961edeb61a137a589c174b:
10
10
11
include: Add a comment to explain the origin of sizes' lookup table (2018-11-05 15:29:59 +0100)
11
qemu-iotests: Test the x-blockdev-reopen QMP command (2019-03-12 17:58:37 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- auto-read-only option to fix commit job when used with -blockdev
16
- file-posix: Make auto-read-only dynamic
17
- Fix help text related qemu-iotests failure (by improving the help text
17
- Add x-blockdev-reopen QMP command
18
and updating the reference output)
18
- Finalize block-latency-histogram QMP command
19
- quorum: Add missing checks when adding/removing child nodes
19
- gluster: Build fixes for newer lib version
20
- Don't take address of fields in packed structs
21
- vvfat: Fix crash when reporting error about too many files in directory
22
20
23
----------------------------------------------------------------
21
----------------------------------------------------------------
24
Alberto Garcia (7):
22
Alberto Garcia (13):
25
block: replace "discard" literal with BDRV_OPT_DISCARD macro
23
block: Allow freezing BdrvChild links
26
qcow2: Get the request alignment for encrypted images from QCryptoBlock
24
block: Freeze the backing chain for the duration of the commit job
27
quorum: Remove quorum_err()
25
block: Freeze the backing chain for the duration of the mirror job
28
quorum: Return an error if the blkverify mode has invalid settings
26
block: Freeze the backing chain for the duration of the stream job
29
iotest: Test the blkverify mode of the Quorum driver
27
block: Add 'keep_old_opts' parameter to bdrv_reopen_queue()
30
quorum: Forbid adding children in blkverify mode
28
block: Handle child references in bdrv_reopen_queue()
31
iotest: Test x-blockdev-change on a Quorum
29
block: Allow omitting the 'backing' option in certain cases
30
block: Allow changing the backing file on reopen
31
block: Add a 'mutable_opts' field to BlockDriver
32
block: Add bdrv_reset_options_allowed()
33
block: Remove the AioContext parameter from bdrv_reopen_multiple()
34
block: Add an 'x-blockdev-reopen' QMP command
35
qemu-iotests: Test the x-blockdev-reopen QMP command
32
36
33
Cleber Rosa (1):
37
Keith Busch (1):
34
iotests: make 083 specific to raw
38
nvme: fix write zeroes offset and count
35
39
36
Daniel P. Berrangé (1):
40
Kevin Wolf (10):
37
crypto: initialize sector size even when opening with no IO flag
41
tests/virtio-blk-test: Disable auto-read-only
42
qemu-iotests: commit to backing file with auto-read-only
43
block: Avoid useless local_err
44
block: Make permission changes in reopen less wrong
45
file-posix: Fix bdrv_open_flags() for snapshot=on
46
file-posix: Factor out raw_reconfigure_getfd()
47
file-posix: Store BDRVRawState.reopen_state during reopen
48
file-posix: Lock new fd in raw_reopen_prepare()
49
file-posix: Prepare permission code for fd switching
50
file-posix: Make auto-read-only dynamic
38
51
39
Kevin Wolf (12):
52
Niels de Vos (1):
40
vpc: Don't leak opts in vpc_open()
53
gluster: the glfs_io_cbk callback function pointer adds pre/post stat args
41
block: Update flags in bdrv_set_read_only()
42
block: Add auto-read-only option
43
rbd: Close image in qemu_rbd_open() error path
44
block: Require auto-read-only for existing fallbacks
45
nbd: Support auto-read-only option
46
file-posix: Support auto-read-only option
47
curl: Support auto-read-only option
48
gluster: Support auto-read-only option
49
iscsi: Support auto-read-only option
50
block: Make auto-read-only=on default for -drive
51
qemu-iotests: Test auto-read-only with -drive and -blockdev
52
54
53
Leonid Bloch (2):
55
Prasanna Kumar Kalever (1):
54
vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE
56
gluster: Handle changed glfs_ftruncate signature
55
include: Add a comment to explain the origin of sizes' lookup table
56
57
57
Li Qiang (1):
58
Vladimir Sementsov-Ogievskiy (2):
58
block: change some function return type to bool
59
qapi: move to QOM path for x-block-latency-histogram-set
60
qapi: drop x- from x-block-latency-histogram-set
59
61
60
Max Reitz (5):
62
qapi/block-core.json | 66 ++-
61
option: Make option help nicer to read
63
configure | 42 ++
62
chardev: Indent list of chardevs
64
include/block/block.h | 13 +-
63
qdev-monitor: Make device options help nicer
65
include/block/block_int.h | 14 +
64
object: Make option help nicer to read
66
block.c | 440 +++++++++++++++++--
65
fw_cfg: Drop newline in @file description
67
block/commit.c | 16 +
68
block/file-posix.c | 254 ++++++++---
69
block/gluster.c | 10 +-
70
block/mirror.c | 8 +
71
block/qapi.c | 12 +-
72
block/qcow2.c | 25 ++
73
block/raw-format.c | 3 +
74
block/replication.c | 7 +-
75
block/stream.c | 21 +
76
blockdev.c | 61 ++-
77
hw/block/nvme.c | 6 +-
78
qemu-io-cmds.c | 4 +-
79
tests/virtio-blk-test.c | 2 +-
80
tests/qemu-iotests/051 | 7 +
81
tests/qemu-iotests/051.out | 9 +
82
tests/qemu-iotests/051.pc.out | 9 +
83
tests/qemu-iotests/232 | 31 ++
84
tests/qemu-iotests/232.out | 32 +-
85
tests/qemu-iotests/245 | 991 ++++++++++++++++++++++++++++++++++++++++++
86
tests/qemu-iotests/245.out | 5 +
87
tests/qemu-iotests/group | 1 +
88
26 files changed, 1929 insertions(+), 160 deletions(-)
89
create mode 100644 tests/qemu-iotests/245
90
create mode 100644 tests/qemu-iotests/245.out
66
91
67
Peter Maydell (5):
68
block/qcow2: Don't take address of fields in packed structs
69
block/qcow: Don't take address of fields in packed structs
70
block/qcow2-bitmap: Don't take address of fields in packed structs
71
block/vhdx: Don't take address of fields in packed structs
72
block/vdi: Don't take address of fields in packed structs
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
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
When using the vvfat driver with a directory that contains too many files,
4
QEMU currently crashes. This can be triggered like this for example:
5
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>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block/vvfat.c | 4 ++--
19
1 file changed, 2 insertions(+), 2 deletions(-)
20
21
diff --git a/block/vvfat.c b/block/vvfat.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/vvfat.c
24
+++ b/block/vvfat.c
25
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
26
mapping = array_get(&(s->mapping), i);
27
28
if (mapping->mode & MODE_DIRECTORY) {
29
+ char *path = mapping->path;
30
mapping->begin = cluster;
31
if(read_directory(s, i)) {
32
- error_setg(errp, "Could not read directory %s",
33
- mapping->path);
34
+ error_setg(errp, "Could not read directory %s", path);
35
return -1;
36
}
37
mapping = array_get(&(s->mapping), i);
38
--
39
2.19.1
40
41
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open the file
1
From: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
2
read-write if we have the permissions, but instead of erroring out for
3
read-only files, just degrade to read-only.
4
2
3
New versions of Glusters libgfapi.so have an updated glfs_ftruncate()
4
function that returns additional 'struct stat' structures to enable
5
advanced caching of attributes. This is useful for file servers, not so
6
much for QEMU. Nevertheless, the API has changed and needs to be
7
adopted.
8
9
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
10
Signed-off-by: Niels de Vos <ndevos@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Niels de Vos <ndevos@redhat.com>
7
---
12
---
8
block/gluster.c | 12 ++++++++++--
13
configure | 18 ++++++++++++++++++
9
1 file changed, 10 insertions(+), 2 deletions(-)
14
block/gluster.c | 4 ++++
15
2 files changed, 22 insertions(+)
10
16
17
diff --git a/configure b/configure
18
index XXXXXXX..XXXXXXX 100755
19
--- a/configure
20
+++ b/configure
21
@@ -XXX,XX +XXX,XX @@ glusterfs_xlator_opt="no"
22
glusterfs_discard="no"
23
glusterfs_fallocate="no"
24
glusterfs_zerofill="no"
25
+glusterfs_ftruncate_has_stat="no"
26
gtk=""
27
gtk_gl="no"
28
tls_priority="NORMAL"
29
@@ -XXX,XX +XXX,XX @@ if test "$glusterfs" != "no" ; then
30
glusterfs_fallocate="yes"
31
glusterfs_zerofill="yes"
32
fi
33
+ cat > $TMPC << EOF
34
+#include <glusterfs/api/glfs.h>
35
+
36
+int
37
+main(void)
38
+{
39
+    /* new glfs_ftruncate() passes two additional args */
40
+    return glfs_ftruncate(NULL, 0, NULL, NULL);
41
+}
42
+EOF
43
+ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then
44
+ glusterfs_ftruncate_has_stat="yes"
45
+ fi
46
else
47
if test "$glusterfs" = "yes" ; then
48
feature_not_found "GlusterFS backend support" \
49
@@ -XXX,XX +XXX,XX @@ if test "$glusterfs_zerofill" = "yes" ; then
50
echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak
51
fi
52
53
+if test "$glusterfs_ftruncate_has_stat" = "yes" ; then
54
+ echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak
55
+fi
56
+
57
if test "$libssh2" = "yes" ; then
58
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
59
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
11
diff --git a/block/gluster.c b/block/gluster.c
60
diff --git a/block/gluster.c b/block/gluster.c
12
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
13
--- a/block/gluster.c
62
--- a/block/gluster.c
14
+++ b/block/gluster.c
63
+++ b/block/gluster.c
15
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
64
@@ -XXX,XX +XXX,XX @@
16
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
65
#include "qemu/option.h"
17
66
#include "qemu/cutils.h"
18
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
67
19
- if (!s->fd) {
68
+#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT
20
- ret = -errno;
69
+# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL)
21
+ ret = s->fd ? 0 : -errno;
70
+#endif
22
+
71
+
23
+ if (ret == -EACCES || ret == -EROFS) {
72
#define GLUSTER_OPT_FILENAME "filename"
24
+ /* Try to degrade to read-only, but if it doesn't work, still use the
73
#define GLUSTER_OPT_VOLUME "volume"
25
+ * normal error message. */
74
#define GLUSTER_OPT_PATH "path"
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
+ }
31
}
32
33
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
34
--
75
--
35
2.19.1
76
2.20.1
36
77
37
78
diff view generated by jsdifflib
1
From: Cleber Rosa <crosa@redhat.com>
1
From: Niels de Vos <ndevos@redhat.com>
2
2
3
While testing the Python 3 changes which touch the 083 test, I noticed
3
The glfs_*_async() functions do a callback once finished. This callback
4
that it would fail with qcow2. Expanding the testing, I noticed it
4
has changed its arguments, pre- and post-stat structures have been
5
had nothing to do with the Python 3 changes, and in fact, it would not
5
added. This makes it possible to improve caching, which is useful for
6
pass on anything but raw:
6
Samba and NFS-Ganesha, but not so much for QEMU. Gluster 6 is the first
7
release that includes these new arguments.
7
8
8
raw: pass
9
With an additional detection in ./configure, the new arguments can
9
bochs: not generic
10
conditionally get included in the glfs_io_cbk handler.
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
11
21
The errors are a mixture I/O and "image not in xxx format", such as:
12
Signed-off-by: Niels de Vos <ndevos@redhat.com>
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>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
41
---
14
---
42
tests/qemu-iotests/083 | 2 +-
15
configure | 24 ++++++++++++++++++++++++
43
1 file changed, 1 insertion(+), 1 deletion(-)
16
block/gluster.c | 6 +++++-
17
2 files changed, 29 insertions(+), 1 deletion(-)
44
18
45
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
19
diff --git a/configure b/configure
46
index XXXXXXX..XXXXXXX 100755
20
index XXXXXXX..XXXXXXX 100755
47
--- a/tests/qemu-iotests/083
21
--- a/configure
48
+++ b/tests/qemu-iotests/083
22
+++ b/configure
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
23
@@ -XXX,XX +XXX,XX @@ glusterfs_discard="no"
50
. ./common.rc
24
glusterfs_fallocate="no"
51
. ./common.filter
25
glusterfs_zerofill="no"
52
26
glusterfs_ftruncate_has_stat="no"
53
-_supported_fmt generic
27
+glusterfs_iocb_has_stat="no"
54
+_supported_fmt raw
28
gtk=""
55
_supported_proto nbd
29
gtk_gl="no"
56
_supported_os Linux
30
tls_priority="NORMAL"
31
@@ -XXX,XX +XXX,XX @@ EOF
32
if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then
33
glusterfs_ftruncate_has_stat="yes"
34
fi
35
+ cat > $TMPC << EOF
36
+#include <glusterfs/api/glfs.h>
37
+
38
+/* new glfs_io_cbk() passes two additional glfs_stat structs */
39
+static void
40
+glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
41
+{}
42
+
43
+int
44
+main(void)
45
+{
46
+    glfs_io_cbk iocb = &glusterfs_iocb;
47
+    iocb(NULL, 0 , NULL, NULL, NULL);
48
+    return 0;
49
+}
50
+EOF
51
+ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then
52
+ glusterfs_iocb_has_stat="yes"
53
+ fi
54
else
55
if test "$glusterfs" = "yes" ; then
56
feature_not_found "GlusterFS backend support" \
57
@@ -XXX,XX +XXX,XX @@ if test "$glusterfs_ftruncate_has_stat" = "yes" ; then
58
echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak
59
fi
60
61
+if test "$glusterfs_iocb_has_stat" = "yes" ; then
62
+ echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak
63
+fi
64
+
65
if test "$libssh2" = "yes" ; then
66
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
67
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
68
diff --git a/block/gluster.c b/block/gluster.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/gluster.c
71
+++ b/block/gluster.c
72
@@ -XXX,XX +XXX,XX @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
73
/*
74
* AIO callback routine called from GlusterFS thread.
75
*/
76
-static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
77
+static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret,
78
+#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT
79
+ struct glfs_stat *pre, struct glfs_stat *post,
80
+#endif
81
+ void *arg)
82
{
83
GlusterAIOCB *acb = (GlusterAIOCB *)arg;
57
84
58
--
85
--
59
2.19.1
86
2.20.1
60
87
61
88
diff view generated by jsdifflib
1
While we want machine interfaces like -blockdev and QMP blockdev-add to
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
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.
8
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
---
5
---
12
blockdev.c | 1 +
6
qapi/block-core.json | 4 ++--
13
1 file changed, 1 insertion(+)
7
blockdev.c | 12 ++++++------
8
2 files changed, 8 insertions(+), 8 deletions(-)
14
9
10
diff --git a/qapi/block-core.json b/qapi/block-core.json
11
index XXXXXXX..XXXXXXX 100644
12
--- a/qapi/block-core.json
13
+++ b/qapi/block-core.json
14
@@ -XXX,XX +XXX,XX @@
15
# If only @device parameter is specified, remove all present latency histograms
16
# for the device. Otherwise, add/reset some of (or all) latency histograms.
17
#
18
-# @device: device name to set latency histogram for.
19
+# @id: The name or QOM path of the guest device.
20
#
21
# @boundaries: list of interval boundary values (see description in
22
# BlockLatencyHistogramInfo definition). If specified, all
23
@@ -XXX,XX +XXX,XX @@
24
# <- { "return": {} }
25
##
26
{ 'command': 'x-block-latency-histogram-set',
27
- 'data': {'device': 'str',
28
+ 'data': {'id': 'str',
29
'*boundaries': ['uint64'],
30
'*boundaries-read': ['uint64'],
31
'*boundaries-write': ['uint64'],
15
diff --git a/blockdev.c b/blockdev.c
32
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
17
--- a/blockdev.c
34
--- a/blockdev.c
18
+++ b/blockdev.c
35
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
36
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
20
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
37
}
21
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
38
22
read_only ? "on" : "off");
39
void qmp_x_block_latency_histogram_set(
23
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
40
- const char *device,
24
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
41
+ const char *id,
25
42
bool has_boundaries, uint64List *boundaries,
26
if (runstate_check(RUN_STATE_INMIGRATE)) {
43
bool has_boundaries_read, uint64List *boundaries_read,
44
bool has_boundaries_write, uint64List *boundaries_write,
45
bool has_boundaries_flush, uint64List *boundaries_flush,
46
Error **errp)
47
{
48
- BlockBackend *blk = blk_by_name(device);
49
+ BlockBackend *blk = qmp_get_blk(NULL, id, errp);
50
BlockAcctStats *stats;
51
int ret;
52
53
if (!blk) {
54
- error_setg(errp, "Device '%s' not found", device);
55
return;
56
}
57
+
58
stats = blk_get_stats(blk);
59
60
if (!has_boundaries && !has_boundaries_read && !has_boundaries_write &&
61
@@ -XXX,XX +XXX,XX @@ void qmp_x_block_latency_histogram_set(
62
stats, BLOCK_ACCT_READ,
63
has_boundaries_read ? boundaries_read : boundaries);
64
if (ret) {
65
- error_setg(errp, "Device '%s' set read boundaries fail", device);
66
+ error_setg(errp, "Device '%s' set read boundaries fail", id);
67
return;
68
}
69
}
70
@@ -XXX,XX +XXX,XX @@ void qmp_x_block_latency_histogram_set(
71
stats, BLOCK_ACCT_WRITE,
72
has_boundaries_write ? boundaries_write : boundaries);
73
if (ret) {
74
- error_setg(errp, "Device '%s' set write boundaries fail", device);
75
+ error_setg(errp, "Device '%s' set write boundaries fail", id);
76
return;
77
}
78
}
79
@@ -XXX,XX +XXX,XX @@ void qmp_x_block_latency_histogram_set(
80
stats, BLOCK_ACCT_FLUSH,
81
has_boundaries_flush ? boundaries_flush : boundaries);
82
if (ret) {
83
- error_setg(errp, "Device '%s' set flush boundaries fail", device);
84
+ error_setg(errp, "Device '%s' set flush boundaries fail", id);
85
return;
86
}
87
}
27
--
88
--
28
2.19.1
89
2.20.1
29
90
30
91
diff view generated by jsdifflib
1
If a management application builds the block graph node by node, the
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
protocol layer doesn't inherit its read-only option from the format
3
layer any more, so it must be set explicitly.
4
2
5
Backing files should work on read-only storage, but at the same time, a
3
Drop x- and x_ prefixes for latency histograms and update version to
6
block job like commit should be able to reopen them read-write if they
4
3.1
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
5
13
A simple workaround for the problem in the management tool would be to
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
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
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
40
---
8
---
41
qapi/block-core.json | 7 +++++++
9
qapi/block-core.json | 20 ++++++++++----------
42
include/block/block.h | 2 ++
10
block/qapi.c | 12 ++++++------
43
block.c | 17 +++++++++++++++++
11
blockdev.c | 2 +-
44
block/vvfat.c | 1 +
12
3 files changed, 17 insertions(+), 17 deletions(-)
45
blockdev.c | 2 +-
46
5 files changed, 28 insertions(+), 1 deletion(-)
47
13
48
diff --git a/qapi/block-core.json b/qapi/block-core.json
14
diff --git a/qapi/block-core.json b/qapi/block-core.json
49
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
50
--- a/qapi/block-core.json
16
--- a/qapi/block-core.json
51
+++ b/qapi/block-core.json
17
+++ b/qapi/block-core.json
52
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
53
# either generally or in certain configurations. In this case,
19
# +------------------
54
# the default value does not work and the option must be
20
# 10 50 100
55
# specified explicitly.
21
#
56
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
22
-# Since: 2.12
57
+# decide not to open the image read-write as requested, but
23
+# Since: 4.0
58
+# fall back to read-only instead (and switch between the modes
24
##
59
+# later), e.g. depending on whether the image file is writable
25
{ 'struct': 'BlockLatencyHistogramInfo',
60
+# or whether a writing user is attached to the node
26
'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }
61
+# (default: false, since 3.1)
27
62
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
28
##
63
# (default: off)
29
-# @x-block-latency-histogram-set:
64
# @force-share: force share all permission on added nodes.
30
+# @block-latency-histogram-set:
31
#
32
# Manage read, write and flush latency histograms for the device.
33
#
65
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
66
'*discard': 'BlockdevDiscardOptions',
35
#
67
'*cache': 'BlockdevCacheOptions',
36
# Returns: error if device is not found or any boundary arrays are invalid.
68
'*read-only': 'bool',
37
#
69
+ '*auto-read-only': 'bool',
38
-# Since: 2.12
70
'*force-share': 'bool',
39
+# Since: 4.0
71
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
40
#
72
'discriminator': 'driver',
41
# Example: set new histograms for all io types with intervals
73
diff --git a/include/block/block.h b/include/block/block.h
42
# [0, 10), [10, 50), [50, 100), [100, +inf):
43
@@ -XXX,XX +XXX,XX @@
44
# "arguments": { "device": "drive0" } }
45
# <- { "return": {} }
46
##
47
-{ 'command': 'x-block-latency-histogram-set',
48
+{ 'command': 'block-latency-histogram-set',
49
'data': {'id': 'str',
50
'*boundaries': ['uint64'],
51
'*boundaries-read': ['uint64'],
52
@@ -XXX,XX +XXX,XX @@
53
# @timed_stats: Statistics specific to the set of previously defined
54
# intervals of time (Since 2.5)
55
#
56
-# @x_rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)
57
+# @rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
58
#
59
-# @x_wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)
60
+# @wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
61
#
62
-# @x_flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)
63
+# @flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
64
#
65
# Since: 0.14.0
66
##
67
@@ -XXX,XX +XXX,XX @@
68
'invalid_wr_operations': 'int', 'invalid_flush_operations': 'int',
69
'account_invalid': 'bool', 'account_failed': 'bool',
70
'timed_stats': ['BlockDeviceTimedStats'],
71
- '*x_rd_latency_histogram': 'BlockLatencyHistogramInfo',
72
- '*x_wr_latency_histogram': 'BlockLatencyHistogramInfo',
73
- '*x_flush_latency_histogram': 'BlockLatencyHistogramInfo' } }
74
+ '*rd_latency_histogram': 'BlockLatencyHistogramInfo',
75
+ '*wr_latency_histogram': 'BlockLatencyHistogramInfo',
76
+ '*flush_latency_histogram': 'BlockLatencyHistogramInfo' } }
77
78
##
79
# @BlockStats:
80
diff --git a/block/qapi.c b/block/qapi.c
74
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX 100644
75
--- a/include/block/block.h
82
--- a/block/qapi.c
76
+++ b/include/block/block.h
83
+++ b/block/qapi.c
77
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
84
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
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
93
diff --git a/block.c b/block.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/block.c
96
+++ b/block.c
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
98
99
/* Inherit the read-only option from the parent if it's not set */
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
105
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
106
107
/* backing files always opened read-only */
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
}
85
}
116
86
117
+ assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
87
bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_READ],
118
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
88
- &ds->has_x_rd_latency_histogram,
119
+ *flags |= BDRV_O_AUTO_RDONLY;
89
- &ds->x_rd_latency_histogram);
120
+ }
90
+ &ds->has_rd_latency_histogram,
91
+ &ds->rd_latency_histogram);
92
bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_WRITE],
93
- &ds->has_x_wr_latency_histogram,
94
- &ds->x_wr_latency_histogram);
95
+ &ds->has_wr_latency_histogram,
96
+ &ds->wr_latency_histogram);
97
bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_FLUSH],
98
- &ds->has_x_flush_latency_histogram,
99
- &ds->x_flush_latency_histogram);
100
+ &ds->has_flush_latency_histogram,
101
+ &ds->flush_latency_histogram);
121
}
102
}
122
103
123
static void update_options_from_flags(QDict *options, int flags)
104
static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
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,
135
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
136
.type = QEMU_OPT_BOOL,
137
.help = "Node is opened in read-only mode",
138
},
139
+ {
140
+ .name = BDRV_OPT_AUTO_READ_ONLY,
141
+ .type = QEMU_OPT_BOOL,
142
+ .help = "Node can become read-only if opening read-write fails",
143
+ },
144
{
145
.name = "detect-zeroes",
146
.type = QEMU_OPT_STRING,
147
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
148
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
149
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
150
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
151
+ qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
152
+
153
}
154
155
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
156
diff --git a/block/vvfat.c b/block/vvfat.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/vvfat.c
159
+++ b/block/vvfat.c
160
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
161
int parent_flags, QDict *parent_options)
162
{
163
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
164
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
165
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
166
}
167
168
diff --git a/blockdev.c b/blockdev.c
105
diff --git a/blockdev.c b/blockdev.c
169
index XXXXXXX..XXXXXXX 100644
106
index XXXXXXX..XXXXXXX 100644
170
--- a/blockdev.c
107
--- a/blockdev.c
171
+++ b/blockdev.c
108
+++ b/blockdev.c
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
109
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
173
110
aio_context_release(old_context);
174
bdrv_flags = blk_get_open_flags_from_root_state(blk);
111
}
175
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
112
176
- BDRV_O_PROTOCOL);
113
-void qmp_x_block_latency_histogram_set(
177
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
114
+void qmp_block_latency_histogram_set(
178
115
const char *id,
179
if (!has_read_only) {
116
bool has_boundaries, uint64List *boundaries,
180
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
117
bool has_boundaries_read, uint64List *boundaries_read,
181
--
118
--
182
2.19.1
119
2.20.1
183
120
184
121
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open the volume
1
tests/virtio-blk-test uses a temporary image file that it deletes while
2
read-write if we have the permissions, but instead of erroring out for
2
QEMU is still running, so it can't be reopened when writers are
3
read-only volumes, just degrade to read-only.
3
attached or detached. Disable auto-read-only to keep it always writable.
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/iscsi.c | 8 +++++---
8
tests/virtio-blk-test.c | 2 +-
9
1 file changed, 5 insertions(+), 3 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
10
11
diff --git a/block/iscsi.c b/block/iscsi.c
11
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/iscsi.c
13
--- a/tests/virtio-blk-test.c
14
+++ b/block/iscsi.c
14
+++ b/tests/virtio-blk-test.c
15
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
15
@@ -XXX,XX +XXX,XX @@ static void *virtio_blk_test_setup(GString *cmd_line, void *arg)
16
/* Check the write protect flag of the LUN if we want to write */
16
char *tmp_path = drive_create();
17
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
17
18
iscsilun->write_protected) {
18
g_string_append_printf(cmd_line,
19
- error_setg(errp, "Cannot open a write protected LUN as read-write");
19
- " -drive if=none,id=drive0,file=%s,format=raw "
20
- ret = -EACCES;
20
+ " -drive if=none,id=drive0,file=%s,format=raw,auto-read-only=off "
21
- goto out;
21
"-drive if=none,id=drive1,file=null-co://,format=raw ",
22
+ ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
22
tmp_path);
23
+ if (ret < 0) {
23
24
+ goto out;
25
+ }
26
+ flags &= ~BDRV_O_RDWR;
27
}
28
29
iscsi_readcapacity_sync(iscsilun, &local_err);
30
--
24
--
31
2.19.1
25
2.20.1
32
26
33
27
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, just degrade to
2
read-only.
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
6
---
3
---
7
block/curl.c | 8 ++++----
4
tests/qemu-iotests/232 | 31 +++++++++++++++++++++++++++++++
8
1 file changed, 4 insertions(+), 4 deletions(-)
5
tests/qemu-iotests/232.out | 20 ++++++++++++++++++++
6
2 files changed, 51 insertions(+)
9
7
10
diff --git a/block/curl.c b/block/curl.c
8
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
9
index XXXXXXX..XXXXXXX 100755
10
--- a/tests/qemu-iotests/232
11
+++ b/tests/qemu-iotests/232
12
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
13
_cleanup()
14
{
15
_cleanup_test_img
16
+ rm -f $TEST_IMG.[01234]
17
}
18
trap "_cleanup; exit \$status" 0 1 2 3 15
19
20
@@ -XXX,XX +XXX,XX @@ run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,a
21
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
22
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
23
24
+echo
25
+echo "=== Try commit to backing file with auto-read-only ==="
26
+echo
27
+
28
+TEST_IMG="$TEST_IMG.0" _make_test_img $size
29
+TEST_IMG="$TEST_IMG.1" _make_test_img $size
30
+TEST_IMG="$TEST_IMG.2" _make_test_img $size
31
+TEST_IMG="$TEST_IMG.3" _make_test_img $size
32
+TEST_IMG="$TEST_IMG.4" _make_test_img $size
33
+
34
+(cat <<EOF
35
+{"execute":"qmp_capabilities"}
36
+{"execute":"block-commit",
37
+ "arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}}
38
+EOF
39
+sleep 1
40
+echo '{"execute":"quit"}'
41
+) | $QEMU -qmp stdio -nographic -nodefaults \
42
+ -blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \
43
+ -blockdev qcow2,node-name=format-0,file=file-0,read-only=on \
44
+ -blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \
45
+ -blockdev qcow2,node-name=format-1,file=file-1,read-only=on,backing=format-0 \
46
+ -blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \
47
+ -blockdev qcow2,node-name=format-2,file=file-2,read-only=on,backing=format-1 \
48
+ -blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \
49
+ -blockdev qcow2,node-name=format-3,file=file-3,read-only=on,backing=format-2 \
50
+ -blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \
51
+ -blockdev qcow2,node-name=format-4,file=file-4,read-only=on,backing=format-3 |
52
+ _filter_qmp
53
+
54
# success, all done
55
echo "*** done"
56
rm -f $seq.full
57
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
11
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
12
--- a/block/curl.c
59
--- a/tests/qemu-iotests/232.out
13
+++ b/block/curl.c
60
+++ b/tests/qemu-iotests/232.out
14
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
61
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read
15
const char *protocol_delimiter;
62
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
16
int ret;
63
node0: TEST_DIR/t.IMGFMT (file, read-only)
17
64
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
18
-
65
+
19
- if (flags & BDRV_O_RDWR) {
66
+=== Try commit to backing file with auto-read-only ===
20
- error_setg(errp, "curl block device does not support writes");
67
+
21
- return -EROFS;
68
+Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728
22
+ ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
69
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
23
+ errp);
70
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
24
+ if (ret < 0) {
71
+Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728
25
+ return ret;
72
+Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728
26
}
73
+QMP_VERSION
27
74
+{"return": {}}
28
if (!libcurl_initialized) {
75
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
76
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
77
+{"return": {}}
78
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
79
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
80
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
81
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
82
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
83
+{"return": {}}
84
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
85
*** done
29
--
86
--
30
2.19.1
87
2.20.1
31
88
32
89
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Alberto Garcia <berto@igalia.com>
2
Reviewed-by: Alberto Garcia <berto@igalia.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
4
---
4
block/vpc.c | 2 ++
5
block.c | 4 +---
5
1 file changed, 2 insertions(+)
6
1 file changed, 1 insertion(+), 3 deletions(-)
6
7
7
diff --git a/block/vpc.c b/block/vpc.c
8
diff --git a/block.c b/block.c
8
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
9
--- a/block/vpc.c
10
--- a/block.c
10
+++ b/block/vpc.c
11
+++ b/block.c
11
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
12
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
12
}
13
{
13
14
int ret = -1;
14
qemu_co_mutex_init(&s->lock);
15
BlockReopenQueueEntry *bs_entry, *next;
15
+ qemu_opts_del(opts);
16
- Error *local_err = NULL;
16
17
17
return 0;
18
assert(bs_queue != NULL);
18
19
19
fail:
20
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
20
+ qemu_opts_del(opts);
21
assert(bs_entry->state.bs->quiesce_counter > 0);
21
qemu_vfree(s->pagetable);
22
- if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) {
22
#ifdef CACHE
23
- error_propagate(errp, local_err);
23
g_free(s->pageentry_u8);
24
+ if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, errp)) {
25
goto cleanup;
26
}
27
bs_entry->prepared = true;
24
--
28
--
25
2.19.1
29
2.20.1
26
30
27
31
diff view generated by jsdifflib
1
To fully change the read-only state of a node, we must not only change
1
The way that reopen interacts with permission changes has one big
2
bs->read_only, but also update bs->open_flags.
2
problem: Both operations are recursive, and the permissions are changes
3
for each node in the reopen queue.
4
5
For a simple graph that consists just of parent and child,
6
.bdrv_check_perm will be called twice for the child, once recursively
7
when adjusting the permissions of parent, and once again when the child
8
itself is reopened.
9
10
Even worse, the first .bdrv_check_perm call happens before
11
.bdrv_reopen_prepare was called for the child and the second one is
12
called afterwards.
13
14
Making sure that .bdrv_check_perm (and the other permission callbacks)
15
are called only once is hard. We can cope with multiple calls right now,
16
but as soon as file-posix gets a dynamic auto-read-only that may need to
17
open a new file descriptor, we get the additional requirement that all
18
of them are after the .bdrv_reopen_prepare call.
19
20
So reorder things in bdrv_reopen_multiple() to first call
21
.bdrv_reopen_prepare for all involved nodes and only then adjust
22
permissions.
3
23
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
---
25
---
8
block.c | 7 +++++++
26
block.c | 35 ++++++++++++++++++++++++-----------
9
1 file changed, 7 insertions(+)
27
1 file changed, 24 insertions(+), 11 deletions(-)
10
28
11
diff --git a/block.c b/block.c
29
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
31
--- a/block.c
14
+++ b/block.c
32
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
33
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
34
35
typedef struct BlockReopenQueueEntry {
36
bool prepared;
37
+ bool perms_checked;
38
BDRVReopenState state;
39
QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry;
40
} BlockReopenQueueEntry;
41
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
42
bs_entry->prepared = true;
16
}
43
}
17
44
18
bs->read_only = read_only;
45
+ QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
19
+
46
+ BDRVReopenState *state = &bs_entry->state;
20
+ if (read_only) {
47
+ ret = bdrv_check_perm(state->bs, bs_queue, state->perm,
21
+ bs->open_flags &= ~BDRV_O_RDWR;
48
+ state->shared_perm, NULL, errp);
22
+ } else {
49
+ if (ret < 0) {
23
+ bs->open_flags |= BDRV_O_RDWR;
50
+ goto cleanup_perm;
51
+ }
52
+ bs_entry->perms_checked = true;
24
+ }
53
+ }
25
+
54
+
26
return 0;
55
/* If we reach this point, we have success and just need to apply the
56
* changes
57
*/
58
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
59
}
60
61
ret = 0;
62
+cleanup_perm:
63
+ QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
64
+ BDRVReopenState *state = &bs_entry->state;
65
+
66
+ if (!bs_entry->perms_checked) {
67
+ continue;
68
+ }
69
70
+ if (ret == 0) {
71
+ bdrv_set_perm(state->bs, state->perm, state->shared_perm);
72
+ } else {
73
+ bdrv_abort_perm_update(state->bs);
74
+ }
75
+ }
76
cleanup:
77
QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
78
if (ret) {
79
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
80
} while ((entry = qdict_next(reopen_state->options, entry)));
81
}
82
83
- ret = bdrv_check_perm(reopen_state->bs, queue, reopen_state->perm,
84
- reopen_state->shared_perm, NULL, errp);
85
- if (ret < 0) {
86
- goto error;
87
- }
88
-
89
ret = 0;
90
91
/* Restore the original reopen_state->options QDict */
92
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
93
94
bdrv_refresh_limits(bs, NULL);
95
96
- bdrv_set_perm(reopen_state->bs, reopen_state->perm,
97
- reopen_state->shared_perm);
98
-
99
new_can_write =
100
!bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
101
if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) {
102
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
103
if (drv->bdrv_reopen_abort) {
104
drv->bdrv_reopen_abort(reopen_state);
105
}
106
-
107
- bdrv_abort_perm_update(reopen_state->bs);
27
}
108
}
28
109
110
29
--
111
--
30
2.19.1
112
2.20.1
31
113
32
114
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Using a different read-only setting for bs->open_flags than for the
2
flags to the driver's open function is just inconsistent and a bad idea.
3
After this patch, the temporary snapshot keeps being opened read-only if
4
read-only=on,snapshot=on is passed.
2
5
3
Following the example of qemu_opts_print_help(), indent all entries in
6
If we wanted to change this behaviour to make only the orginal image
4
the list of character devices.
7
file read-only, but the temporary overlay read-write (as the comment in
8
the removed code suggests), that change would have to be made in
9
bdrv_temp_snapshot_options() (where the comment suggests otherwise).
5
10
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Addressing this inconsistency before introducing dynamic auto-read-only
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
is important because otherwise we would immediately try to reopen the
13
temporary overlay even though the file is already unlinked.
14
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
16
---
10
chardev/char.c | 2 +-
17
block.c | 7 -------
11
1 file changed, 1 insertion(+), 1 deletion(-)
18
tests/qemu-iotests/051 | 7 +++++++
19
tests/qemu-iotests/051.out | 9 +++++++++
20
tests/qemu-iotests/051.pc.out | 9 +++++++++
21
4 files changed, 25 insertions(+), 7 deletions(-)
12
22
13
diff --git a/chardev/char.c b/chardev/char.c
23
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
15
--- a/chardev/char.c
25
--- a/block.c
16
+++ b/chardev/char.c
26
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ help_string_append(const char *name, void *opaque)
27
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
18
{
28
*/
19
GString *str = opaque;
29
open_flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_PROTOCOL);
20
30
21
- g_string_append_printf(str, "\n%s", name);
31
- /*
22
+ g_string_append_printf(str, "\n %s", name);
32
- * Snapshots should be writable.
33
- */
34
- if (flags & BDRV_O_TEMPORARY) {
35
- open_flags |= BDRV_O_RDWR;
36
- }
37
-
38
return open_flags;
23
}
39
}
24
40
25
static const char *chardev_alias_translate(const char *name)
41
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
42
index XXXXXXX..XXXXXXX 100755
43
--- a/tests/qemu-iotests/051
44
+++ b/tests/qemu-iotests/051
45
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io
46
# Using snapshot=on with a non-existent TMPDIR
47
TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
48
49
+# Using snapshot=on together with read-only=on
50
+echo "info block" |
51
+ run_qemu -drive file="$TEST_IMG",snapshot=on,read-only=on,if=none,id=$device_id |
52
+ _filter_qemu_io |
53
+ sed -e 's#"/[^"]*/vl\.[A-Za-z]\{6\}"#SNAPSHOT_PATH#g'
54
+
55
+
56
# success, all done
57
echo "*** done"
58
rm -f $seq.full
59
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
60
index XXXXXXX..XXXXXXX 100644
61
--- a/tests/qemu-iotests/051.out
62
+++ b/tests/qemu-iotests/051.out
63
@@ -XXX,XX +XXX,XX @@ read 4096/4096 bytes at offset 0
64
Testing: -drive driver=null-co,snapshot=on
65
QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
66
67
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
68
+QEMU X.Y.Z monitor - type 'help' for more information
69
+(qemu) info block
70
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}, "driver": "qcow2", "file": {"driver": "file", "filename": SNAPSHOT_PATH}} (qcow2, read-only)
71
+ Removable device: not locked, tray closed
72
+ Cache mode: writeback, ignore flushes
73
+ Backing file: TEST_DIR/t.qcow2 (chain depth: 1)
74
+(qemu) quit
75
+
76
*** done
77
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
78
index XXXXXXX..XXXXXXX 100644
79
--- a/tests/qemu-iotests/051.pc.out
80
+++ b/tests/qemu-iotests/051.pc.out
81
@@ -XXX,XX +XXX,XX @@ read 4096/4096 bytes at offset 0
82
Testing: -drive driver=null-co,snapshot=on
83
QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
84
85
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
86
+QEMU X.Y.Z monitor - type 'help' for more information
87
+(qemu) info block
88
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}, "driver": "qcow2", "file": {"driver": "file", "filename": SNAPSHOT_PATH}} (qcow2, read-only)
89
+ Removable device: not locked, tray closed
90
+ Cache mode: writeback, ignore flushes
91
+ Backing file: TEST_DIR/t.qcow2 (chain depth: 1)
92
+(qemu) quit
93
+
94
*** done
26
--
95
--
27
2.19.1
96
2.20.1
28
97
29
98
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
2
3
This adds some whitespace into the option help (including indentation)
4
and puts angle brackets around the type names. Furthermore, the list
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.
7
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.
16
17
Finally, this patch amends the reference output of iotest 082 to match
18
the changes (and thus makes it pass again).
19
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
2
---
24
include/qemu/option.h | 2 +-
3
block/file-posix.c | 107 ++++++++++++++++++++++++++-------------------
25
qemu-img.c | 4 +-
4
1 file changed, 62 insertions(+), 45 deletions(-)
26
util/qemu-option.c | 32 +-
27
tests/qemu-iotests/082.out | 956 ++++++++++++++++++-------------------
28
4 files changed, 507 insertions(+), 487 deletions(-)
29
5
30
diff --git a/include/qemu/option.h b/include/qemu/option.h
6
diff --git a/block/file-posix.c b/block/file-posix.c
31
index XXXXXXX..XXXXXXX 100644
7
index XXXXXXX..XXXXXXX 100644
32
--- a/include/qemu/option.h
8
--- a/block/file-posix.c
33
+++ b/include/qemu/option.h
9
+++ b/block/file-posix.c
34
@@ -XXX,XX +XXX,XX @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
10
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
35
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
11
return ret;
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
43
diff --git a/qemu-img.c b/qemu-img.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/qemu-img.c
46
+++ b/qemu-img.c
47
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
48
}
49
50
printf("Supported options:\n");
51
- qemu_opts_print_help(create_opts);
52
+ qemu_opts_print_help(create_opts, false);
53
qemu_opts_free(create_opts);
54
return 0;
55
}
12
}
56
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
13
57
assert(drv->create_opts);
14
+static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
58
15
+ int *open_flags, Error **errp)
59
printf("Creation options for '%s':\n", format);
16
+{
60
- qemu_opts_print_help(drv->create_opts);
17
+ BDRVRawState *s = bs->opaque;
61
+ qemu_opts_print_help(drv->create_opts, false);
18
+ int fd = -1;
62
printf("\nNote that not all of these options may be amendable.\n");
19
+ int ret;
63
return 0;
20
+ int fcntl_flags = O_APPEND | O_NONBLOCK;
64
}
21
+#ifdef O_NOATIME
65
diff --git a/util/qemu-option.c b/util/qemu-option.c
22
+ fcntl_flags |= O_NOATIME;
66
index XXXXXXX..XXXXXXX 100644
23
+#endif
67
--- a/util/qemu-option.c
24
+
68
+++ b/util/qemu-option.c
25
+ *open_flags = 0;
69
@@ -XXX,XX +XXX,XX @@ static const char *opt_type_to_string(enum QemuOptType type)
26
+ if (s->type == FTYPE_CD) {
70
g_assert_not_reached();
27
+ *open_flags |= O_NONBLOCK;
71
}
28
+ }
72
29
+
73
-void qemu_opts_print_help(QemuOptsList *list)
30
+ raw_parse_flags(flags, open_flags);
74
+/**
31
+
75
+ * Print the list of options available in the given list. If
32
+#ifdef O_ASYNC
76
+ * @print_caption is true, a caption (including the list name, if it
33
+ /* Not all operating systems have O_ASYNC, and those that don't
77
+ * exists) is printed. The options itself will be indented, so
34
+ * will not let us track the state into rs->open_flags (typically
78
+ * @print_caption should only be set to false if the caller prints its
35
+ * you achieve the same effect with an ioctl, for example I_SETSIG
79
+ * own custom caption (so that the indentation makes sense).
36
+ * on Solaris). But we do not use O_ASYNC, so that's fine.
80
+ */
37
+ */
81
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
38
+ assert((s->open_flags & O_ASYNC) == 0);
82
{
39
+#endif
83
QemuOptDesc *desc;
40
+
84
int i;
41
+ if ((*open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
85
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
42
+ /* dup the original fd */
86
desc = list->desc;
43
+ fd = qemu_dup(s->fd);
87
while (desc && desc->name) {
44
+ if (fd >= 0) {
88
GString *str = g_string_new(NULL);
45
+ ret = fcntl_setfl(fd, *open_flags);
89
- if (list->name) {
46
+ if (ret) {
90
- g_string_append_printf(str, "%s.", list->name);
47
+ qemu_close(fd);
91
- }
48
+ fd = -1;
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
+ }
49
+ }
99
g_string_append_printf(str, " - %s", desc->help);
100
}
101
g_ptr_array_add(array, g_string_free(str, false));
102
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
103
}
104
105
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
106
+ if (print_caption && array->len > 0) {
107
+ if (list->name) {
108
+ printf("%s options:\n", list->name);
109
+ } else {
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
+ }
50
+ }
118
+ }
51
+ }
119
for (i = 0; i < array->len; i++) {
52
+
120
printf("%s\n", (char *)array->pdata[i]);
53
+ /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */
54
+ if (fd == -1) {
55
+ const char *normalized_filename = bs->filename;
56
+ ret = raw_normalize_devicepath(&normalized_filename, errp);
57
+ if (ret >= 0) {
58
+ assert(!(*open_flags & O_CREAT));
59
+ fd = qemu_open(normalized_filename, *open_flags);
60
+ if (fd == -1) {
61
+ error_setg_errno(errp, errno, "Could not reopen file");
62
+ return -1;
63
+ }
64
+ }
65
+ }
66
+
67
+ return fd;
68
+}
69
+
70
static int raw_reopen_prepare(BDRVReopenState *state,
71
BlockReopenQueue *queue, Error **errp)
72
{
73
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
74
75
state->opaque = g_new0(BDRVRawReopenState, 1);
76
rs = state->opaque;
77
- rs->fd = -1;
78
79
/* Handle options changes */
80
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
81
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
82
* bdrv_reopen_prepare() will detect changes and complain. */
83
qemu_opts_to_qdict(opts, state->options);
84
85
- if (s->type == FTYPE_CD) {
86
- rs->open_flags |= O_NONBLOCK;
87
- }
88
-
89
- raw_parse_flags(state->flags, &rs->open_flags);
90
-
91
- int fcntl_flags = O_APPEND | O_NONBLOCK;
92
-#ifdef O_NOATIME
93
- fcntl_flags |= O_NOATIME;
94
-#endif
95
-
96
-#ifdef O_ASYNC
97
- /* Not all operating systems have O_ASYNC, and those that don't
98
- * will not let us track the state into rs->open_flags (typically
99
- * you achieve the same effect with an ioctl, for example I_SETSIG
100
- * on Solaris). But we do not use O_ASYNC, so that's fine.
101
- */
102
- assert((s->open_flags & O_ASYNC) == 0);
103
-#endif
104
-
105
- if ((rs->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
106
- /* dup the original fd */
107
- rs->fd = qemu_dup(s->fd);
108
- if (rs->fd >= 0) {
109
- ret = fcntl_setfl(rs->fd, rs->open_flags);
110
- if (ret) {
111
- qemu_close(rs->fd);
112
- rs->fd = -1;
113
- }
114
- }
115
- }
116
-
117
- /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */
118
- if (rs->fd == -1) {
119
- const char *normalized_filename = state->bs->filename;
120
- ret = raw_normalize_devicepath(&normalized_filename, errp);
121
- if (ret >= 0) {
122
- assert(!(rs->open_flags & O_CREAT));
123
- rs->fd = qemu_open(normalized_filename, rs->open_flags);
124
- if (rs->fd == -1) {
125
- error_setg_errno(errp, errno, "Could not reopen file");
126
- ret = -1;
127
- }
128
- }
129
+ rs->fd = raw_reconfigure_getfd(state->bs, state->flags, &rs->open_flags,
130
+ &local_err);
131
+ if (local_err) {
132
+ error_propagate(errp, local_err);
133
+ ret = -1;
134
+ goto out;
121
}
135
}
122
@@ -XXX,XX +XXX,XX @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
136
123
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
137
/* Fail already reopen_prepare() if we can't get a working O_DIRECT
124
if (err) {
125
if (invalidp && has_help_option(params)) {
126
- qemu_opts_print_help(list);
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
1221
--
138
--
1222
2.19.1
139
2.20.1
1223
140
1224
141
diff view generated by jsdifflib
1
From: Li Qiang <liq3ea@163.com>
1
We'll want to access the file descriptor in the reopen_state while
2
processing permission changes in the context of the repoen.
2
3
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
5
---
7
include/sysemu/block-backend.h | 6 +++---
6
block/file-posix.c | 10 ++++++++++
8
block/block-backend.c | 8 ++++----
7
1 file changed, 10 insertions(+)
9
2 files changed, 7 insertions(+), 7 deletions(-)
10
8
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
9
diff --git a/block/file-posix.c b/block/file-posix.c
12
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
13
--- a/include/sysemu/block-backend.h
11
--- a/block/file-posix.c
14
+++ b/include/sysemu/block-backend.h
12
+++ b/block/file-posix.c
15
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
13
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
16
int error);
14
uint64_t locked_perm;
17
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
15
uint64_t locked_shared_perm;
18
bool is_read, int error);
16
19
-int blk_is_read_only(BlockBackend *blk);
17
+ BDRVReopenState *reopen_state;
20
-int blk_is_sg(BlockBackend *blk);
18
+
21
-int blk_enable_write_cache(BlockBackend *blk);
19
#ifdef CONFIG_XFS
22
+bool blk_is_read_only(BlockBackend *blk);
20
bool is_xfs:1;
23
+bool blk_is_sg(BlockBackend *blk);
21
#endif
24
+bool blk_enable_write_cache(BlockBackend *blk);
22
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
25
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
23
}
26
void blk_invalidate_cache(BlockBackend *blk, Error **errp);
27
bool blk_is_inserted(BlockBackend *blk);
28
diff --git a/block/block-backend.c b/block/block-backend.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/block-backend.c
31
+++ b/block/block-backend.c
32
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
33
}
24
}
25
26
+ s->reopen_state = state;
27
out:
28
qemu_opts_del(opts);
29
return ret;
30
@@ -XXX,XX +XXX,XX @@ static void raw_reopen_commit(BDRVReopenState *state)
31
32
g_free(state->opaque);
33
state->opaque = NULL;
34
+
35
+ assert(s->reopen_state == state);
36
+ s->reopen_state = NULL;
34
}
37
}
35
38
36
-int blk_is_read_only(BlockBackend *blk)
39
37
+bool blk_is_read_only(BlockBackend *blk)
40
static void raw_reopen_abort(BDRVReopenState *state)
38
{
41
{
39
BlockDriverState *bs = blk_bs(blk);
42
BDRVRawReopenState *rs = state->opaque;
40
43
+ BDRVRawState *s = state->bs->opaque;
41
@@ -XXX,XX +XXX,XX @@ int blk_is_read_only(BlockBackend *blk)
44
45
/* nothing to do if NULL, we didn't get far enough */
46
if (rs == NULL) {
47
@@ -XXX,XX +XXX,XX @@ static void raw_reopen_abort(BDRVReopenState *state)
42
}
48
}
49
g_free(state->opaque);
50
state->opaque = NULL;
51
+
52
+ assert(s->reopen_state == state);
53
+ s->reopen_state = NULL;
43
}
54
}
44
55
45
-int blk_is_sg(BlockBackend *blk)
56
static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
46
+bool blk_is_sg(BlockBackend *blk)
47
{
48
BlockDriverState *bs = blk_bs(blk);
49
50
if (!bs) {
51
- return 0;
52
+ return false;
53
}
54
55
return bdrv_is_sg(bs);
56
}
57
58
-int blk_enable_write_cache(BlockBackend *blk)
59
+bool blk_enable_write_cache(BlockBackend *blk)
60
{
61
return blk->enable_write_cache;
62
}
63
--
57
--
64
2.19.1
58
2.20.1
65
59
66
60
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
There is no reason why we can take locks on the new file descriptor only
2
in raw_reopen_commit() where error handling isn't possible any more.
3
Instead, we can already do this in raw_reopen_prepare().
2
4
3
Taking the address of a field in a packed struct is a bad idea, because
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.
8
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
(and hand-editing to fold a few resulting overlength lines):
15
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>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
52
---
6
---
53
block/qcow2.c | 64 +++++++++++++++++++++++++++------------------------
7
block/file-posix.c | 27 ++++++++++++++++-----------
54
1 file changed, 34 insertions(+), 30 deletions(-)
8
1 file changed, 16 insertions(+), 11 deletions(-)
55
9
56
diff --git a/block/qcow2.c b/block/qcow2.c
10
diff --git a/block/file-posix.c b/block/file-posix.c
57
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
58
--- a/block/qcow2.c
12
--- a/block/file-posix.c
59
+++ b/block/qcow2.c
13
+++ b/block/file-posix.c
60
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
14
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
61
"pread fail from offset %" PRIu64, offset);
15
BDRVRawState *s;
62
return 1;
16
BDRVRawReopenState *rs;
63
}
17
QemuOpts *opts;
64
- be32_to_cpus(&ext.magic);
18
- int ret = 0;
65
- be32_to_cpus(&ext.len);
19
+ int ret;
66
+ ext.magic = be32_to_cpu(ext.magic);
20
Error *local_err = NULL;
67
+ ext.len = be32_to_cpu(ext.len);
21
68
offset += sizeof(ext);
22
assert(state != NULL);
69
#ifdef DEBUG_EXT
23
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
70
printf("ext.magic = 0x%x\n", ext.magic);
24
if (rs->fd != -1) {
71
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
25
raw_probe_alignment(state->bs, rs->fd, &local_err);
72
"Unable to read CRYPTO header extension");
26
if (local_err) {
73
return ret;
27
- qemu_close(rs->fd);
74
}
28
- rs->fd = -1;
75
- be64_to_cpus(&s->crypto_header.offset);
29
error_propagate(errp, local_err);
76
- be64_to_cpus(&s->crypto_header.length);
30
ret = -EINVAL;
77
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
31
+ goto out_fd;
78
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
32
+ }
79
33
+
80
if ((s->crypto_header.offset % s->cluster_size) != 0) {
34
+ /* Copy locks to the new fd */
81
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
35
+ ret = raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm,
82
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
36
+ s->locked_shared_perm, false, errp);
83
return -EINVAL;
37
+ if (ret < 0) {
84
}
38
+ ret = -EINVAL;
85
39
+ goto out_fd;
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;
100
}
101
- be32_to_cpus(&header.magic);
102
- be32_to_cpus(&header.version);
103
- be64_to_cpus(&header.backing_file_offset);
104
- be32_to_cpus(&header.backing_file_size);
105
- be64_to_cpus(&header.size);
106
- be32_to_cpus(&header.cluster_bits);
107
- be32_to_cpus(&header.crypt_method);
108
- be64_to_cpus(&header.l1_table_offset);
109
- be32_to_cpus(&header.l1_size);
110
- be64_to_cpus(&header.refcount_table_offset);
111
- be32_to_cpus(&header.refcount_table_clusters);
112
- be64_to_cpus(&header.snapshots_offset);
113
- be32_to_cpus(&header.nb_snapshots);
114
+ header.magic = be32_to_cpu(header.magic);
115
+ header.version = be32_to_cpu(header.version);
116
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
117
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
118
+ header.size = be64_to_cpu(header.size);
119
+ header.cluster_bits = be32_to_cpu(header.cluster_bits);
120
+ header.crypt_method = be32_to_cpu(header.crypt_method);
121
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
122
+ header.l1_size = be32_to_cpu(header.l1_size);
123
+ header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
124
+ header.refcount_table_clusters =
125
+ be32_to_cpu(header.refcount_table_clusters);
126
+ header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
127
+ header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
128
129
if (header.magic != QCOW_MAGIC) {
130
error_setg(errp, "Image is not in qcow2 format");
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
132
header.refcount_order = 4;
133
header.header_length = 72;
134
} else {
135
- be64_to_cpus(&header.incompatible_features);
136
- be64_to_cpus(&header.compatible_features);
137
- be64_to_cpus(&header.autoclear_features);
138
- be32_to_cpus(&header.refcount_order);
139
- be32_to_cpus(&header.header_length);
140
+ header.incompatible_features =
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
}
40
}
156
}
41
}
157
42
158
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
43
s->reopen_state = state;
159
44
+ ret = 0;
160
/* Full disk encryption header pointer extension */
45
+out_fd:
161
if (s->crypto_header.offset != 0) {
46
+ if (ret < 0) {
162
- cpu_to_be64s(&s->crypto_header.offset);
47
+ qemu_close(rs->fd);
163
- cpu_to_be64s(&s->crypto_header.length);
48
+ rs->fd = -1;
164
+ s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
49
+ }
165
+ s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
50
out:
166
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
51
qemu_opts_del(opts);
167
&s->crypto_header, sizeof(s->crypto_header),
52
return ret;
168
buflen);
53
@@ -XXX,XX +XXX,XX @@ static void raw_reopen_commit(BDRVReopenState *state)
169
- be64_to_cpus(&s->crypto_header.offset);
54
{
170
- be64_to_cpus(&s->crypto_header.length);
55
BDRVRawReopenState *rs = state->opaque;
171
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
56
BDRVRawState *s = state->bs->opaque;
172
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
57
- Error *local_err = NULL;
173
if (ret < 0) {
58
174
goto fail;
59
s->check_cache_dropped = rs->check_cache_dropped;
175
}
60
s->open_flags = rs->open_flags;
61
62
- /* Copy locks to the new fd before closing the old one. */
63
- raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm,
64
- s->locked_shared_perm, false, &local_err);
65
- if (local_err) {
66
- /* shouldn't fail in a sane host, but report it just in case. */
67
- error_report_err(local_err);
68
- }
69
qemu_close(s->fd);
70
s->fd = rs->fd;
71
176
--
72
--
177
2.19.1
73
2.20.1
178
74
179
75
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open the file
1
In order to be able to dynamically reopen the file read-only or
2
read-write if we have the permissions, but instead of erroring out for
2
read-write, depending on the users that are attached, we need to be able
3
read-only files, just degrade to read-only.
3
to switch to a different file descriptor during the permission change.
4
5
This interacts with reopen, which also creates a new file descriptor and
6
performs permission changes internally. In this case, the permission
7
change code must reuse the reopen file descriptor instead of creating a
8
third one.
9
10
In turn, reopen can drop its code to copy file locks to the new file
11
descriptor because that is now done when applying the new permissions.
4
12
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
14
---
8
block/file-posix.c | 19 ++++++++++++++++---
15
block/file-posix.c | 96 ++++++++++++++++++++++++++++++++++++++++------
9
1 file changed, 16 insertions(+), 3 deletions(-)
16
1 file changed, 85 insertions(+), 11 deletions(-)
10
17
11
diff --git a/block/file-posix.c b/block/file-posix.c
18
diff --git a/block/file-posix.c b/block/file-posix.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
20
--- a/block/file-posix.c
14
+++ b/block/file-posix.c
21
+++ b/block/file-posix.c
15
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
22
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
16
23
uint64_t locked_perm;
17
s->fd = -1;
24
uint64_t locked_shared_perm;
18
fd = qemu_open(filename, s->open_flags, 0644);
25
19
- if (fd < 0) {
26
+ int perm_change_fd;
20
- ret = -errno;
27
BDRVReopenState *reopen_state;
21
- error_setg_errno(errp, errno, "Could not open '%s'", filename);
28
22
+ ret = fd < 0 ? -errno : 0;
29
#ifdef CONFIG_XFS
30
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
31
}
32
33
static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
34
- int *open_flags, Error **errp)
35
+ int *open_flags, bool force_dup,
36
+ Error **errp)
37
{
38
BDRVRawState *s = bs->opaque;
39
int fd = -1;
40
@@ -XXX,XX +XXX,XX @@ static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
41
assert((s->open_flags & O_ASYNC) == 0);
42
#endif
43
44
+ if (!force_dup && *open_flags == s->open_flags) {
45
+ /* We're lucky, the existing fd is fine */
46
+ return s->fd;
47
+ }
23
+
48
+
24
+ if (ret == -EACCES || ret == -EROFS) {
49
if ((*open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
25
+ /* Try to degrade to read-only, but if it doesn't work, still use the
50
/* dup the original fd */
26
+ * normal error message. */
51
fd = qemu_dup(s->fd);
27
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
52
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
28
+ bdrv_flags &= ~BDRV_O_RDWR;
53
qemu_opts_to_qdict(opts, state->options);
29
+ raw_parse_flags(bdrv_flags, &s->open_flags);
54
30
+ assert(!(s->open_flags & O_CREAT));
55
rs->fd = raw_reconfigure_getfd(state->bs, state->flags, &rs->open_flags,
31
+ fd = qemu_open(filename, s->open_flags);
56
- &local_err);
32
+ ret = fd < 0 ? -errno : 0;
57
+ true, &local_err);
58
if (local_err) {
59
error_propagate(errp, local_err);
60
ret = -1;
61
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
62
ret = -EINVAL;
63
goto out_fd;
64
}
65
-
66
- /* Copy locks to the new fd */
67
- ret = raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm,
68
- s->locked_shared_perm, false, errp);
69
- if (ret < 0) {
70
- ret = -EINVAL;
71
- goto out_fd;
72
- }
73
}
74
75
s->reopen_state = state;
76
@@ -XXX,XX +XXX,XX @@ static QemuOptsList raw_create_opts = {
77
static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
78
Error **errp)
79
{
80
- return raw_handle_perm_lock(bs, RAW_PL_PREPARE, perm, shared, errp);
81
+ BDRVRawState *s = bs->opaque;
82
+ BDRVRawReopenState *rs = NULL;
83
+ int open_flags;
84
+ int ret;
85
+
86
+ if (s->perm_change_fd) {
87
+ /*
88
+ * In the context of reopen, this function may be called several times
89
+ * (directly and recursively while change permissions of the parent).
90
+ * This is even true for children that don't inherit from the original
91
+ * reopen node, so s->reopen_state is not set.
92
+ *
93
+ * Ignore all but the first call.
94
+ */
95
+ return 0;
96
+ }
97
+
98
+ if (s->reopen_state) {
99
+ /* We already have a new file descriptor to set permissions for */
100
+ assert(s->reopen_state->perm == perm);
101
+ assert(s->reopen_state->shared_perm == shared);
102
+ rs = s->reopen_state->opaque;
103
+ s->perm_change_fd = rs->fd;
104
+ } else {
105
+ /* We may need a new fd if auto-read-only switches the mode */
106
+ ret = raw_reconfigure_getfd(bs, bs->open_flags, &open_flags,
107
+ false, errp);
108
+ if (ret < 0) {
109
+ return ret;
110
+ } else if (ret != s->fd) {
111
+ s->perm_change_fd = ret;
33
+ }
112
+ }
34
+ }
113
+ }
35
+
114
+
115
+ /* Prepare permissions on old fd to avoid conflicts between old and new,
116
+ * but keep everything locked that new will need. */
117
+ ret = raw_handle_perm_lock(bs, RAW_PL_PREPARE, perm, shared, errp);
36
+ if (ret < 0) {
118
+ if (ret < 0) {
37
+ error_setg_errno(errp, -ret, "Could not open '%s'", filename);
119
+ goto fail;
38
if (ret == -EROFS) {
120
+ }
39
ret = -EACCES;
121
+
40
}
122
+ /* Copy locks to the new fd */
123
+ if (s->perm_change_fd) {
124
+ ret = raw_apply_lock_bytes(NULL, s->perm_change_fd, perm, ~shared,
125
+ false, errp);
126
+ if (ret < 0) {
127
+ raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
128
+ goto fail;
129
+ }
130
+ }
131
+ return 0;
132
+
133
+fail:
134
+ if (s->perm_change_fd && !s->reopen_state) {
135
+ qemu_close(s->perm_change_fd);
136
+ }
137
+ s->perm_change_fd = 0;
138
+ return ret;
139
}
140
141
static void raw_set_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared)
142
{
143
BDRVRawState *s = bs->opaque;
144
+
145
+ /* For reopen, we have already switched to the new fd (.bdrv_set_perm is
146
+ * called after .bdrv_reopen_commit) */
147
+ if (s->perm_change_fd && s->fd != s->perm_change_fd) {
148
+ qemu_close(s->fd);
149
+ s->fd = s->perm_change_fd;
150
+ }
151
+ s->perm_change_fd = 0;
152
+
153
raw_handle_perm_lock(bs, RAW_PL_COMMIT, perm, shared, NULL);
154
s->perm = perm;
155
s->shared_perm = shared;
156
@@ -XXX,XX +XXX,XX @@ static void raw_set_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared)
157
158
static void raw_abort_perm_update(BlockDriverState *bs)
159
{
160
+ BDRVRawState *s = bs->opaque;
161
+
162
+ /* For reopen, .bdrv_reopen_abort is called afterwards and will close
163
+ * the file descriptor. */
164
+ if (s->perm_change_fd && !s->reopen_state) {
165
+ qemu_close(s->perm_change_fd);
166
+ }
167
+ s->perm_change_fd = 0;
168
+
169
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
170
}
171
41
--
172
--
42
2.19.1
173
2.20.1
43
174
44
175
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
Until now, with auto-read-only=on we tried to open the file read-write
2
first and if that failed, read-only was tried. This is actually not good
3
enough for libvirt, which gives QEMU SELinux permissions for read-write
4
only as soon as it actually intends to write to the image. So we need to
5
be able to switch between read-only and read-write at runtime.
2
6
3
Taking the address of a field in a packed struct is a bad idea, because
7
This patch makes auto-read-only dynamic, i.e. the file is opened
4
it might not be actually aligned enough for that pointer type (and
8
read-only as long as no user of the node has requested write
5
thus cause a crash on dereference on some host architectures). Newer
9
permissions, but it is automatically reopened read-write as soon as the
6
versions of clang warn about this. Avoid the bug by not using the
10
first writer is attached. Conversely, if the last writer goes away, the
7
"modify in place" byte swapping functions.
11
file is reopened read-only again.
8
12
9
There are a few places where the in-place swap function is
13
bs->read_only is no longer set for auto-read-only=on files even if the
10
used on something other than a packed struct field; we convert
14
file descriptor is opened read-only because it will be transparently
11
those anyway, for consistency.
15
upgraded as soon as a writer is attached. This changes the output of
16
qemu-iotests 232.
12
17
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>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
19
---
52
block/qcow2-bitmap.c | 24 ++++++++++++------------
20
block/file-posix.c | 36 +++++++++++++++++-------------------
53
1 file changed, 12 insertions(+), 12 deletions(-)
21
tests/qemu-iotests/232.out | 12 ++++++------
22
2 files changed, 23 insertions(+), 25 deletions(-)
54
23
55
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
24
diff --git a/block/file-posix.c b/block/file-posix.c
56
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow2-bitmap.c
26
--- a/block/file-posix.c
58
+++ b/block/qcow2-bitmap.c
27
+++ b/block/file-posix.c
59
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
28
@@ -XXX,XX +XXX,XX @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
60
size_t i;
61
62
for (i = 0; i < size; ++i) {
63
- cpu_to_be64s(&bitmap_table[i]);
64
+ bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
65
}
29
}
66
}
30
}
67
31
68
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
32
-static void raw_parse_flags(int bdrv_flags, int *open_flags)
33
+static void raw_parse_flags(int bdrv_flags, int *open_flags, bool has_writers)
34
{
35
+ bool read_write = false;
36
assert(open_flags != NULL);
37
38
*open_flags |= O_BINARY;
39
*open_flags &= ~O_ACCMODE;
40
- if (bdrv_flags & BDRV_O_RDWR) {
41
+
42
+ if (bdrv_flags & BDRV_O_AUTO_RDONLY) {
43
+ read_write = has_writers;
44
+ } else if (bdrv_flags & BDRV_O_RDWR) {
45
+ read_write = true;
46
+ }
47
+
48
+ if (read_write) {
49
*open_flags |= O_RDWR;
50
} else {
51
*open_flags |= O_RDONLY;
52
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
53
false);
54
55
s->open_flags = open_flags;
56
- raw_parse_flags(bdrv_flags, &s->open_flags);
57
+ raw_parse_flags(bdrv_flags, &s->open_flags, false);
58
59
s->fd = -1;
60
fd = qemu_open(filename, s->open_flags, 0644);
61
ret = fd < 0 ? -errno : 0;
62
63
- if (ret == -EACCES || ret == -EROFS) {
64
- /* Try to degrade to read-only, but if it doesn't work, still use the
65
- * normal error message. */
66
- if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
67
- bdrv_flags &= ~BDRV_O_RDWR;
68
- raw_parse_flags(bdrv_flags, &s->open_flags);
69
- assert(!(s->open_flags & O_CREAT));
70
- fd = qemu_open(filename, s->open_flags);
71
- ret = fd < 0 ? -errno : 0;
72
- }
73
- }
74
-
75
if (ret < 0) {
76
error_setg_errno(errp, -ret, "Could not open '%s'", filename);
77
if (ret == -EROFS) {
78
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
79
}
80
81
static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
82
- int *open_flags, bool force_dup,
83
+ int *open_flags, uint64_t perm, bool force_dup,
84
Error **errp)
85
{
86
BDRVRawState *s = bs->opaque;
87
int fd = -1;
88
int ret;
89
+ bool has_writers = perm &
90
+ (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_RESIZE);
91
int fcntl_flags = O_APPEND | O_NONBLOCK;
92
#ifdef O_NOATIME
93
fcntl_flags |= O_NOATIME;
94
@@ -XXX,XX +XXX,XX @@ static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
95
*open_flags |= O_NONBLOCK;
69
}
96
}
70
97
71
for (i = 0; i < tb->size; ++i) {
98
- raw_parse_flags(flags, open_flags);
72
- be64_to_cpus(&table[i]);
99
+ raw_parse_flags(flags, open_flags, has_writers);
73
+ table[i] = be64_to_cpu(table[i]);
100
74
ret = check_table_entry(table[i], s->cluster_size);
101
#ifdef O_ASYNC
102
/* Not all operating systems have O_ASYNC, and those that don't
103
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
104
qemu_opts_to_qdict(opts, state->options);
105
106
rs->fd = raw_reconfigure_getfd(state->bs, state->flags, &rs->open_flags,
107
- true, &local_err);
108
+ state->perm, true, &local_err);
109
if (local_err) {
110
error_propagate(errp, local_err);
111
ret = -1;
112
@@ -XXX,XX +XXX,XX @@ static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
113
s->perm_change_fd = rs->fd;
114
} else {
115
/* We may need a new fd if auto-read-only switches the mode */
116
- ret = raw_reconfigure_getfd(bs, bs->open_flags, &open_flags,
117
+ ret = raw_reconfigure_getfd(bs, bs->open_flags, &open_flags, perm,
118
false, errp);
75
if (ret < 0) {
119
if (ret < 0) {
76
goto fail;
120
return ret;
77
@@ -XXX,XX +XXX,XX @@ fail:
121
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
78
122
index XXXXXXX..XXXXXXX 100644
79
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
123
--- a/tests/qemu-iotests/232.out
80
{
124
+++ b/tests/qemu-iotests/232.out
81
- be64_to_cpus(&entry->bitmap_table_offset);
125
@@ -XXX,XX +XXX,XX @@ NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
82
- be32_to_cpus(&entry->bitmap_table_size);
126
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
83
- be32_to_cpus(&entry->flags);
127
84
- be16_to_cpus(&entry->name_size);
128
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
85
- be32_to_cpus(&entry->extra_data_size);
129
-NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
86
+ entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
130
-NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
87
+ entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
131
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
88
+ entry->flags = be32_to_cpu(entry->flags);
132
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
89
+ entry->name_size = be16_to_cpu(entry->name_size);
133
90
+ entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
134
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
91
}
135
-NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
92
136
-NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
93
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
137
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
94
{
138
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
95
- cpu_to_be64s(&entry->bitmap_table_offset);
139
96
- cpu_to_be32s(&entry->bitmap_table_size);
140
=== -blockdev with read-write image: read-only/auto-read-only combinations ===
97
- cpu_to_be32s(&entry->flags);
141
98
- cpu_to_be16s(&entry->name_size);
142
@@ -XXX,XX +XXX,XX @@ node0: TEST_DIR/t.IMGFMT (file, read-only)
99
- cpu_to_be32s(&entry->extra_data_size);
143
node0: TEST_DIR/t.IMGFMT (file, read-only)
100
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
144
101
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
145
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
102
+ entry->flags = cpu_to_be32(entry->flags);
146
-node0: TEST_DIR/t.IMGFMT (file, read-only)
103
+ entry->name_size = cpu_to_be16(entry->name_size);
147
+node0: TEST_DIR/t.IMGFMT (file)
104
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
148
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
105
}
149
106
150
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
107
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
151
-node0: TEST_DIR/t.IMGFMT (file, read-only)
152
+node0: TEST_DIR/t.IMGFMT (file)
153
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
154
155
=== Try commit to backing file with auto-read-only ===
108
--
156
--
109
2.19.1
157
2.20.1
110
158
111
159
diff view generated by jsdifflib
1
From: Leonid Bloch <lbloch@janustech.com>
1
From: Keith Busch <keith.busch@intel.com>
2
2
3
The lookup table for power-of-two sizes was added in commit 540b8492618eb
3
The implementation used blocks units rather than the expected bytes.
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
4
11
Despite its convenience, this table introduced 55 lines of "dumb" code,
5
Fixes: c03e7ef12a9 ("nvme: Implement Write Zeroes")
12
the purpose and origin of which are obscure without reading the message
6
Reported-by: Ming Lei <ming.lei@redhat.com>
13
of the commit which introduced it. This patch fixes that by adding a
7
Signed-off-by: Keith Busch <keith.busch@intel.com>
14
comment to the code itself with a brief explanation for the reasoning
8
Reviewed-by: Christoph Hellwig <hch@lst.de>
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>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
10
---
23
include/qemu/units.h | 18 ++++++++++++++++++
11
hw/block/nvme.c | 6 +++---
24
1 file changed, 18 insertions(+)
12
1 file changed, 3 insertions(+), 3 deletions(-)
25
13
26
diff --git a/include/qemu/units.h b/include/qemu/units.h
14
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/include/qemu/units.h
16
--- a/hw/block/nvme.c
29
+++ b/include/qemu/units.h
17
+++ b/hw/block/nvme.c
30
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
31
#define PiB (INT64_C(1) << 50)
19
const uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds;
32
#define EiB (INT64_C(1) << 60)
20
uint64_t slba = le64_to_cpu(rw->slba);
33
21
uint32_t nlb = le16_to_cpu(rw->nlb) + 1;
34
+/*
22
- uint64_t aio_slba = slba << (data_shift - BDRV_SECTOR_BITS);
35
+ * The following lookup table is intended to be used when a literal string of
23
- uint32_t aio_nlb = nlb << (data_shift - BDRV_SECTOR_BITS);
36
+ * the number of bytes is required (for example if it needs to be stringified).
24
+ uint64_t offset = slba << data_shift;
37
+ * It can also be used for generic shortcuts of power-of-two sizes.
25
+ uint32_t count = nlb << data_shift;
38
+ * This table is generated using the AWK script below:
26
39
+ *
27
if (unlikely(slba + nlb > ns->id_ns.nsze)) {
40
+ * BEGIN {
28
trace_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze);
41
+ * suffix="KMGTPE";
29
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
42
+ * for(i=10; i<64; i++) {
30
req->has_sg = false;
43
+ * val=2**i;
31
block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0,
44
+ * s=substr(suffix, int(i/10), 1);
32
BLOCK_ACCT_WRITE);
45
+ * n=2**(i%10);
33
- req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, aio_slba, aio_nlb,
46
+ * pad=21-int(log(n)/log(10));
34
+ req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, offset, count,
47
+ * printf("#define S_%d%siB %*d\n", n, s, pad, val);
35
BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req);
48
+ * }
36
return NVME_NO_COMPLETE;
49
+ * }
37
}
50
+ */
51
+
52
#define S_1KiB 1024
53
#define S_2KiB 2048
54
#define S_4KiB 4096
55
--
38
--
56
2.19.1
39
2.20.1
57
40
58
41
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
Our permission system is useful to define what operations are allowed
4
it might not be actually aligned enough for that pointer type (and
4
on a certain block node and includes things like BLK_PERM_WRITE or
5
thus cause a crash on dereference on some host architectures). Newer
5
BLK_PERM_RESIZE among others.
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
6
9
There are a few places where the in-place swap function is
7
One of the permissions is BLK_PERM_GRAPH_MOD which allows "changing
10
used on something other than a packed struct field; we convert
8
the node that this BdrvChild points to". The exact meaning of this has
11
those anyway, for consistency.
9
never been very clear, but it can be understood as "change any of the
10
links connected to the node". This can be used to prevent changing a
11
backing link, but it's too coarse.
12
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
13
This patch adds a new 'frozen' attribute to BdrvChild, which forbids
14
detaching the link from the node it points to, and new API to freeze
15
and unfreeze a backing chain.
14
16
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
After this change a few functions can fail, so they need additional
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18
checks.
19
20
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
22
---
19
block/vhdx.h | 12 ++---
23
include/block/block.h | 5 +++
20
block/vhdx-endian.c | 118 ++++++++++++++++++++++----------------------
24
include/block/block_int.h | 6 ++++
21
block/vhdx-log.c | 4 +-
25
block.c | 76 +++++++++++++++++++++++++++++++++++++++
22
block/vhdx.c | 18 +++----
26
3 files changed, 87 insertions(+)
23
4 files changed, 76 insertions(+), 76 deletions(-)
24
27
25
diff --git a/block/vhdx.h b/block/vhdx.h
28
diff --git a/include/block/block.h b/include/block/block.h
26
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
27
--- a/block/vhdx.h
30
--- a/include/block/block.h
28
+++ b/block/vhdx.h
31
+++ b/include/block/block.h
29
@@ -XXX,XX +XXX,XX @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
32
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
30
33
BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
31
static inline void leguid_to_cpus(MSGUID *guid)
34
BlockDriverState *bs);
32
{
35
BlockDriverState *bdrv_find_base(BlockDriverState *bs);
33
- le32_to_cpus(&guid->data1);
36
+bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
34
- le16_to_cpus(&guid->data2);
37
+ Error **errp);
35
- le16_to_cpus(&guid->data3);
38
+int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
36
+ guid->data1 = le32_to_cpu(guid->data1);
39
+ Error **errp);
37
+ guid->data2 = le16_to_cpu(guid->data2);
40
+void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
38
+ guid->data3 = le16_to_cpu(guid->data3);
41
42
43
typedef struct BdrvCheckResult {
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
47
+++ b/include/block/block_int.h
48
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
49
uint64_t backup_perm;
50
uint64_t backup_shared_perm;
51
52
+ /*
53
+ * This link is frozen: the child can neither be replaced nor
54
+ * detached from the parent.
55
+ */
56
+ bool frozen;
57
+
58
QLIST_ENTRY(BdrvChild) next;
59
QLIST_ENTRY(BdrvChild) next_parent;
60
};
61
diff --git a/block.c b/block.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/block.c
64
+++ b/block.c
65
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
66
BlockDriverState *old_bs = child->bs;
67
int i;
68
69
+ assert(!child->frozen);
70
+
71
if (old_bs && new_bs) {
72
assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
73
}
74
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
75
bool update_inherits_from = bdrv_chain_contains(bs, backing_hd) &&
76
bdrv_inherits_from_recursive(backing_hd, bs);
77
78
+ if (bdrv_is_backing_chain_frozen(bs, backing_bs(bs), errp)) {
79
+ return;
80
+ }
81
+
82
if (backing_hd) {
83
bdrv_ref(backing_hd);
84
}
85
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
86
if (!should_update_child(c, to)) {
87
continue;
88
}
89
+ if (c->frozen) {
90
+ error_setg(errp, "Cannot change '%s' link to '%s'",
91
+ c->name, from->node_name);
92
+ goto out;
93
+ }
94
list = g_slist_prepend(list, c);
95
perm |= c->perm;
96
shared &= c->shared_perm;
97
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
98
return bdrv_find_overlay(bs, NULL);
39
}
99
}
40
100
41
static inline void cpu_to_leguids(MSGUID *guid)
101
+/*
42
{
102
+ * Return true if at least one of the backing links between @bs and
43
- cpu_to_le32s(&guid->data1);
103
+ * @base is frozen. @errp is set if that's the case.
44
- cpu_to_le16s(&guid->data2);
104
+ */
45
- cpu_to_le16s(&guid->data3);
105
+bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
46
+ guid->data1 = cpu_to_le32(guid->data1);
106
+ Error **errp)
47
+ guid->data2 = cpu_to_le16(guid->data2);
107
+{
48
+ guid->data3 = cpu_to_le16(guid->data3);
108
+ BlockDriverState *i;
49
}
109
+
50
110
+ for (i = bs; i != base && i->backing; i = backing_bs(i)) {
51
void vhdx_header_le_import(VHDXHeader *h);
111
+ if (i->backing->frozen) {
52
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
112
+ error_setg(errp, "Cannot change '%s' link from '%s' to '%s'",
53
index XXXXXXX..XXXXXXX 100644
113
+ i->backing->name, i->node_name,
54
--- a/block/vhdx-endian.c
114
+ backing_bs(i)->node_name);
55
+++ b/block/vhdx-endian.c
115
+ return true;
56
@@ -XXX,XX +XXX,XX @@ void vhdx_header_le_import(VHDXHeader *h)
116
+ }
57
{
117
+ }
58
assert(h != NULL);
118
+
59
119
+ return false;
60
- le32_to_cpus(&h->signature);
120
+}
61
- le32_to_cpus(&h->checksum);
121
+
62
- le64_to_cpus(&h->sequence_number);
122
+/*
63
+ h->signature = le32_to_cpu(h->signature);
123
+ * Freeze all backing links between @bs and @base.
64
+ h->checksum = le32_to_cpu(h->checksum);
124
+ * If any of the links is already frozen the operation is aborted and
65
+ h->sequence_number = le64_to_cpu(h->sequence_number);
125
+ * none of the links are modified.
66
126
+ * Returns 0 on success. On failure returns < 0 and sets @errp.
67
leguid_to_cpus(&h->file_write_guid);
127
+ */
68
leguid_to_cpus(&h->data_write_guid);
128
+int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
69
leguid_to_cpus(&h->log_guid);
129
+ Error **errp)
70
130
+{
71
- le16_to_cpus(&h->log_version);
131
+ BlockDriverState *i;
72
- le16_to_cpus(&h->version);
132
+
73
- le32_to_cpus(&h->log_length);
133
+ if (bdrv_is_backing_chain_frozen(bs, base, errp)) {
74
- le64_to_cpus(&h->log_offset);
134
+ return -EPERM;
75
+ h->log_version = le16_to_cpu(h->log_version);
135
+ }
76
+ h->version = le16_to_cpu(h->version);
136
+
77
+ h->log_length = le32_to_cpu(h->log_length);
137
+ for (i = bs; i != base && i->backing; i = backing_bs(i)) {
78
+ h->log_offset = le64_to_cpu(h->log_offset);
138
+ i->backing->frozen = true;
79
}
139
+ }
80
140
+
81
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
141
+ return 0;
82
@@ -XXX,XX +XXX,XX @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
142
+}
83
{
143
+
84
assert(d != NULL);
144
+/*
85
145
+ * Unfreeze all backing links between @bs and @base. The caller must
86
- le32_to_cpus(&d->signature);
146
+ * ensure that all links are frozen before using this function.
87
- le64_to_cpus(&d->file_offset);
147
+ */
88
- le64_to_cpus(&d->sequence_number);
148
+void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base)
89
+ d->signature = le32_to_cpu(d->signature);
149
+{
90
+ d->file_offset = le64_to_cpu(d->file_offset);
150
+ BlockDriverState *i;
91
+ d->sequence_number = le64_to_cpu(d->sequence_number);
151
+
92
}
152
+ for (i = bs; i != base && i->backing; i = backing_bs(i)) {
93
153
+ assert(i->backing->frozen);
94
void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
154
+ i->backing->frozen = false;
95
{
155
+ }
96
assert(d != NULL);
156
+}
97
157
+
98
- cpu_to_le32s(&d->signature);
158
/*
99
- cpu_to_le32s(&d->trailing_bytes);
159
* Drops images above 'base' up to and including 'top', and sets the image
100
- cpu_to_le64s(&d->leading_bytes);
160
* above 'top' to have base as its backing file.
101
- cpu_to_le64s(&d->file_offset);
161
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
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;
162
goto exit;
309
}
163
}
310
164
311
- le32_to_cpus(&s->params.block_size);
165
+ /* This function changes all links that point to top and makes
312
- le32_to_cpus(&s->params.data_bits);
166
+ * them point to base. Check that none of them is frozen. */
313
+ s->params.block_size = le32_to_cpu(s->params.block_size);
167
+ QLIST_FOREACH(c, &top->parents, next_parent) {
314
+ s->params.data_bits = le32_to_cpu(s->params.data_bits);
168
+ if (c->frozen) {
315
169
+ goto exit;
316
170
+ }
317
/* We now have the file parameters, so we can tell if this is a
171
+ }
318
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
172
+
319
goto exit;
173
/* If 'base' recursively inherits from 'top' then we should set
320
}
174
* base->inherits_from to top->inherits_from after 'top' and all
321
175
* other intermediate nodes have been dropped.
322
- le64_to_cpus(&s->virtual_disk_size);
323
- le32_to_cpus(&s->logical_sector_size);
324
- le32_to_cpus(&s->physical_sector_size);
325
+ s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
326
+ s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
327
+ s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
328
329
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
330
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
331
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
332
/* endian convert, and verify populated BAT field file offsets against
333
* region table and log entries */
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);
346
}
347
348
vhdx_guid_generate(&mt_page83->page_83_data);
349
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
350
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
351
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
352
block_state);
353
- cpu_to_le64s(&s->bat[sinfo.bat_idx]);
354
+ s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
355
sector_num += s->sectors_per_block;
356
}
357
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
358
--
176
--
359
2.19.1
177
2.20.1
360
178
361
179
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
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.
8
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>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
5
---
52
block/qcow.c | 18 +++++++++---------
6
block/commit.c | 16 ++++++++++++++++
53
1 file changed, 9 insertions(+), 9 deletions(-)
7
1 file changed, 16 insertions(+)
54
8
55
diff --git a/block/qcow.c b/block/qcow.c
9
diff --git a/block/commit.c b/block/commit.c
56
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow.c
11
--- a/block/commit.c
58
+++ b/block/qcow.c
12
+++ b/block/commit.c
59
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
13
@@ -XXX,XX +XXX,XX @@ typedef struct CommitBlockJob {
14
BlockDriverState *base_bs;
15
BlockdevOnError on_error;
16
bool base_read_only;
17
+ bool chain_frozen;
18
char *backing_file_str;
19
} CommitBlockJob;
20
21
@@ -XXX,XX +XXX,XX @@ static int commit_prepare(Job *job)
22
{
23
CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
24
25
+ bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
26
+ s->chain_frozen = false;
27
+
28
/* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before
29
* the normal backing chain can be restored. */
30
blk_unref(s->base);
31
@@ -XXX,XX +XXX,XX @@ static void commit_abort(Job *job)
32
CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
33
BlockDriverState *top_bs = blk_bs(s->top);
34
35
+ if (s->chain_frozen) {
36
+ bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
37
+ }
38
+
39
/* Make sure commit_top_bs and top stay around until bdrv_replace_node() */
40
bdrv_ref(top_bs);
41
bdrv_ref(s->commit_top_bs);
42
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
43
}
44
}
45
46
+ if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
47
+ goto fail;
48
+ }
49
+ s->chain_frozen = true;
50
+
51
ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
60
if (ret < 0) {
52
if (ret < 0) {
61
goto fail;
53
goto fail;
54
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
55
return;
56
57
fail:
58
+ if (s->chain_frozen) {
59
+ bdrv_unfreeze_backing_chain(commit_top_bs, base);
60
+ }
61
if (s->base) {
62
blk_unref(s->base);
62
}
63
}
63
- be32_to_cpus(&header.magic);
64
- be32_to_cpus(&header.version);
65
- be64_to_cpus(&header.backing_file_offset);
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,
83
}
84
85
for(i = 0;i < s->l1_size; i++) {
86
- be64_to_cpus(&s->l1_table[i]);
87
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
88
}
89
90
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
91
--
64
--
92
2.19.1
65
2.20.1
93
66
94
67
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
The blkverify mode of Quorum only works when the number of children is
4
exactly two, so any attempt to add a new one must return an error.
5
6
quorum_del_child() on the other hand doesn't need any additional check
7
because decreasing the number of children would make it go under the
8
vote threshold.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
5
---
14
block/quorum.c | 8 ++++++++
6
block/mirror.c | 8 ++++++++
15
1 file changed, 8 insertions(+)
7
1 file changed, 8 insertions(+)
16
8
17
diff --git a/block/quorum.c b/block/quorum.c
9
diff --git a/block/mirror.c b/block/mirror.c
18
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
11
--- a/block/mirror.c
20
+++ b/block/quorum.c
12
+++ b/block/mirror.c
21
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
13
@@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job)
22
char indexstr[32];
14
}
23
int ret;
15
s->prepared = true;
24
16
25
+ if (s->is_blkverify) {
17
+ if (bdrv_chain_contains(src, target_bs)) {
26
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
18
+ bdrv_unfreeze_backing_chain(mirror_top_bs, target_bs);
27
+ return;
28
+ }
19
+ }
29
+
20
+
30
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
21
bdrv_release_dirty_bitmap(src, s->dirty_bitmap);
31
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
22
32
s->next_child_index == UINT_MAX) {
23
/* Make sure that the source BDS doesn't go away during bdrv_replace_node,
33
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
24
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
34
return;
25
goto fail;
26
}
27
}
28
+
29
+ if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) {
30
+ goto fail;
31
+ }
35
}
32
}
36
33
37
+ /* We know now that num_children > threshold, so blkverify must be false */
34
QTAILQ_INIT(&s->ops_in_flight);
38
+ assert(!s->is_blkverify);
39
+
40
bdrv_drained_begin(bs);
41
42
/* We can safely remove this child now */
43
--
35
--
44
2.19.1
36
2.20.1
45
37
46
38
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Signed-off-by: Alberto Garcia <berto@igalia.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
tests/qemu-iotests/081 | 30 ++++++++++++++++++++++++++++++
6
block/stream.c | 21 +++++++++++++++++++++
7
tests/qemu-iotests/081.out | 16 ++++++++++++++++
7
1 file changed, 21 insertions(+)
8
2 files changed, 46 insertions(+)
9
8
10
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
9
diff --git a/block/stream.c b/block/stream.c
11
index XXXXXXX..XXXXXXX 100755
10
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/qemu-iotests/081
11
--- a/block/stream.c
13
+++ b/tests/qemu-iotests/081
12
+++ b/block/stream.c
14
@@ -XXX,XX +XXX,XX @@ echo "== checking that quorum is broken =="
13
@@ -XXX,XX +XXX,XX @@ typedef struct StreamBlockJob {
15
14
BlockdevOnError on_error;
16
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
15
char *backing_file_str;
17
16
bool bs_read_only;
18
+echo
17
+ bool chain_frozen;
19
+echo "== checking the blkverify mode with broken content =="
18
} StreamBlockJob;
19
20
static int coroutine_fn stream_populate(BlockBackend *blk,
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_populate(BlockBackend *blk,
22
return blk_co_preadv(blk, offset, qiov.size, &qiov, BDRV_REQ_COPY_ON_READ);
23
}
24
25
+static void stream_abort(Job *job)
26
+{
27
+ StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
20
+
28
+
21
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
29
+ if (s->chain_frozen) {
22
+quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
30
+ BlockJob *bjob = &s->common;
23
+quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
31
+ bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->base);
24
+quorum="$quorum,file.children.0.driver=raw"
32
+ }
25
+quorum="$quorum,file.children.1.driver=raw"
33
+}
26
+
34
+
27
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
35
static int stream_prepare(Job *job)
36
{
37
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
38
@@ -XXX,XX +XXX,XX @@ static int stream_prepare(Job *job)
39
Error *local_err = NULL;
40
int ret = 0;
41
42
+ bdrv_unfreeze_backing_chain(bs, base);
43
+ s->chain_frozen = false;
28
+
44
+
29
+echo
45
if (bs->backing) {
30
+echo "== writing the same data to both files =="
46
const char *base_id = NULL, *base_fmt = NULL;
47
if (base) {
48
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver stream_job_driver = {
49
.free = block_job_free,
50
.run = stream_run,
51
.prepare = stream_prepare,
52
+ .abort = stream_abort,
53
.clean = stream_clean,
54
.user_resume = block_job_user_resume,
55
.drain = block_job_drain,
56
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
57
&error_abort);
58
}
59
60
+ if (bdrv_freeze_backing_chain(bs, base, errp) < 0) {
61
+ job_early_fail(&s->common.job);
62
+ goto fail;
63
+ }
31
+
64
+
32
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
65
s->base = base;
33
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
66
s->backing_file_str = g_strdup(backing_file_str);
34
+
67
s->bs_read_only = bs_read_only;
35
+echo
68
+ s->chain_frozen = true;
36
+echo "== checking the blkverify mode with valid content =="
69
37
+
70
s->on_error = on_error;
38
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
71
trace_stream_start(bs, base, s);
39
+
40
+echo
41
+echo "== checking the blkverify mode with invalid settings =="
42
+
43
+quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
44
+quorum="$quorum,file.children.2.driver=raw"
45
+
46
+$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
47
+
48
# success, all done
49
echo "*** done"
50
rm -f $seq.full
51
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/081.out
54
+++ b/tests/qemu-iotests/081.out
55
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 0
56
57
== checking that quorum is broken ==
58
read failed: Input/output error
59
+
60
+== checking the blkverify mode with broken content ==
61
+quorum: offset=0 bytes=10485760 contents mismatch at offset 0
62
+
63
+== writing the same data to both files ==
64
+wrote 10485760/10485760 bytes at offset 0
65
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
66
+wrote 10485760/10485760 bytes at offset 0
67
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
68
+
69
+== checking the blkverify mode with valid content ==
70
+read 10485760/10485760 bytes at offset 0
71
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
72
+
73
+== checking the blkverify mode with invalid settings ==
74
+can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
75
*** done
76
--
72
--
77
2.19.1
73
2.20.1
78
74
79
75
diff view generated by jsdifflib
1
Some block drivers have traditionally changed their node to read-only
1
From: Alberto Garcia <berto@igalia.com>
2
mode without asking the user. This behaviour has been marked deprecated
3
since 2.11, expecting users to provide an explicit read-only=on option.
4
2
5
Now that we have auto-read-only=on, enable these drivers to make use of
3
The bdrv_reopen_queue() function is used to create a queue with
6
the option.
4
the BDSs that are going to be reopened and their new options. Once
5
the queue is ready bdrv_reopen_multiple() is called to perform the
6
operation.
7
7
8
This is the only use of bdrv_set_read_only(), so we can make it a bit
8
The original options from each one of the BDSs are kept, with the new
9
more specific and turn it into a bdrv_apply_auto_read_only() that is
9
options passed to bdrv_reopen_queue() applied on top of them.
10
more convenient for drivers to use.
11
10
11
For "x-blockdev-reopen" we want a function that behaves much like
12
"blockdev-add". We want to ignore the previous set of options so that
13
only the ones actually specified by the user are applied, with the
14
rest having their default values.
15
16
One of the things that we need is a way to tell bdrv_reopen_queue()
17
whether we want to keep the old set of options or not, and that's what
18
this patch does. All current callers are setting this new parameter to
19
true and x-blockdev-reopen will set it to false.
20
21
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
---
23
---
15
include/block/block.h | 3 ++-
24
include/block/block.h | 3 ++-
16
block.c | 42 +++++++++++++++++++++++++++---------------
25
block.c | 34 +++++++++++++++++++---------------
17
block/bochs.c | 17 ++++++-----------
26
block/replication.c | 4 ++--
18
block/cloop.c | 16 +++++-----------
27
qemu-io-cmds.c | 2 +-
19
block/dmg.c | 16 +++++-----------
28
4 files changed, 24 insertions(+), 19 deletions(-)
20
block/rbd.c | 15 ++++-----------
21
block/vvfat.c | 10 ++--------
22
7 files changed, 51 insertions(+), 68 deletions(-)
23
29
24
diff --git a/include/block/block.h b/include/block/block.h
30
diff --git a/include/block/block.h b/include/block/block.h
25
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
32
--- a/include/block/block.h
27
+++ b/include/block/block.h
33
+++ b/include/block/block.h
28
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
34
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
29
bool bdrv_is_read_only(BlockDriverState *bs);
35
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
36
int flags, Error **errp);
31
bool ignore_allow_rdw, Error **errp);
37
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
32
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
38
- BlockDriverState *bs, QDict *options);
33
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
39
+ BlockDriverState *bs, QDict *options,
34
+ Error **errp);
40
+ bool keep_old_opts);
35
bool bdrv_is_writable(BlockDriverState *bs);
41
int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp);
36
bool bdrv_is_sg(BlockDriverState *bs);
42
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
37
bool bdrv_is_inserted(BlockDriverState *bs);
43
Error **errp);
38
diff --git a/block.c b/block.c
44
diff --git a/block.c b/block.c
39
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
40
--- a/block.c
46
--- a/block.c
41
+++ b/block.c
47
+++ b/block.c
42
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
48
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
43
return 0;
49
QDict *options,
50
const BdrvChildRole *role,
51
QDict *parent_options,
52
- int parent_flags)
53
+ int parent_flags,
54
+ bool keep_old_opts)
55
{
56
assert(bs != NULL);
57
58
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
59
*/
60
61
/* Old explicitly set values (don't overwrite by inherited value) */
62
- if (bs_entry) {
63
- old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
64
- } else {
65
- old_options = qdict_clone_shallow(bs->explicit_options);
66
+ if (bs_entry || keep_old_opts) {
67
+ old_options = qdict_clone_shallow(bs_entry ?
68
+ bs_entry->state.explicit_options :
69
+ bs->explicit_options);
70
+ bdrv_join_options(bs, options, old_options);
71
+ qobject_unref(old_options);
72
}
73
- bdrv_join_options(bs, options, old_options);
74
- qobject_unref(old_options);
75
76
explicit_options = qdict_clone_shallow(options);
77
78
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
79
flags = bdrv_get_flags(bs);
80
}
81
82
- /* Old values are used for options that aren't set yet */
83
- old_options = qdict_clone_shallow(bs->options);
84
- bdrv_join_options(bs, options, old_options);
85
- qobject_unref(old_options);
86
+ if (keep_old_opts) {
87
+ /* Old values are used for options that aren't set yet */
88
+ old_options = qdict_clone_shallow(bs->options);
89
+ bdrv_join_options(bs, options, old_options);
90
+ qobject_unref(old_options);
91
+ }
92
93
/* We have the final set of options so let's update the flags */
94
options_copy = qdict_clone_shallow(options);
95
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
96
g_free(child_key_dot);
97
98
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
99
- child->role, options, flags);
100
+ child->role, options, flags, keep_old_opts);
101
}
102
103
return bs_queue;
104
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
105
106
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
107
BlockDriverState *bs,
108
- QDict *options)
109
+ QDict *options, bool keep_old_opts)
110
{
111
- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0);
112
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0,
113
+ keep_old_opts);
44
}
114
}
45
115
46
-/* TODO Remove (deprecated since 2.11)
116
/*
47
- * Block drivers are not supposed to automatically change bs->read_only.
117
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
48
- * Instead, they should just check whether they can provide what the user
118
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);
49
- * explicitly requested and error out if read-write is requested, but they can
119
50
- * only provide read-only access. */
120
bdrv_subtree_drained_begin(bs);
51
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
121
- queue = bdrv_reopen_queue(NULL, bs, opts);
52
+/*
122
+ queue = bdrv_reopen_queue(NULL, bs, opts, true);
53
+ * Called by a driver that can only provide a read-only image.
123
ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
54
+ *
124
bdrv_subtree_drained_end(bs);
55
+ * Returns 0 if the node is already read-only or it could switch the node to
125
56
+ * read-only because BDRV_O_AUTO_RDONLY is set.
126
diff --git a/block/replication.c b/block/replication.c
57
+ *
127
index XXXXXXX..XXXXXXX 100644
58
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
128
--- a/block/replication.c
59
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
129
+++ b/block/replication.c
60
+ * is not NULL, it is used as the error message for the Error object.
130
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
61
+ */
131
QDict *opts = qdict_new();
62
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
132
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
63
+ Error **errp)
133
reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs,
64
{
134
- opts);
65
int ret = 0;
135
+ opts, true);
66
67
- ret = bdrv_can_set_read_only(bs, read_only, false, errp);
68
- if (ret < 0) {
69
- return ret;
70
+ if (!(bs->open_flags & BDRV_O_RDWR)) {
71
+ return 0;
72
+ }
73
+ if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
74
+ goto fail;
75
}
136
}
76
137
77
- bs->read_only = read_only;
138
if (s->orig_secondary_read_only) {
78
-
139
QDict *opts = qdict_new();
79
- if (read_only) {
140
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
80
- bs->open_flags &= ~BDRV_O_RDWR;
141
reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
81
- } else {
142
- opts);
82
- bs->open_flags |= BDRV_O_RDWR;
143
+ opts, true);
83
+ ret = bdrv_can_set_read_only(bs, true, false, NULL);
84
+ if (ret < 0) {
85
+ goto fail;
86
}
144
}
87
145
88
+ bs->read_only = true;
146
if (reopen_queue) {
89
+ bs->open_flags &= ~BDRV_O_RDWR;
147
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
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
148
index XXXXXXX..XXXXXXX 100644
101
--- a/block/bochs.c
149
--- a/qemu-io-cmds.c
102
+++ b/block/bochs.c
150
+++ b/qemu-io-cmds.c
103
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
151
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
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
}
152
}
118
153
119
- if (!bdrv_is_read_only(bs)) {
154
bdrv_subtree_drained_begin(bs);
120
- error_report("Opening bochs images without an explicit read-only=on "
155
- brq = bdrv_reopen_queue(NULL, bs, opts);
121
- "option is deprecated. Future versions will refuse to "
156
+ brq = bdrv_reopen_queue(NULL, bs, opts, true);
122
- "open the image instead of automatically marking the "
157
bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
123
- "image read-only.");
158
bdrv_subtree_drained_end(bs);
124
- ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
159
125
- if (ret < 0) {
126
- return ret;
127
- }
128
- }
129
-
130
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
131
if (ret < 0) {
132
return ret;
133
diff --git a/block/cloop.c b/block/cloop.c
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;
222
}
223
}
224
225
diff --git a/block/vvfat.c b/block/vvfat.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/block/vvfat.c
228
+++ b/block/vvfat.c
229
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
230
"Unable to set VVFAT to 'rw' when drive is read-only");
231
goto fail;
232
}
233
- } else if (!bdrv_is_read_only(bs)) {
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
}
247
--
160
--
248
2.19.1
161
2.20.1
249
162
250
163
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
The blkverify mode of Quorum can only be enabled if the number of
3
Children in QMP are specified with BlockdevRef / BlockdevRefOrNull,
4
children is exactly two and the value of vote-threshold is also two.
4
which can contain a set of child options, a child reference, or
5
NULL. In optional attributes like "backing" it can also be missing.
5
6
6
If the user tries to enable it but the other settings are incorrect
7
Only the first case (set of child options) is being handled properly
7
then QEMU simply prints an error message to stderr and carries on
8
by bdrv_reopen_queue(). This patch deals with all the others.
8
disabling the blkverify setting.
9
9
10
This patch makes quorum_open() fail and return an error in this case.
10
Here's how these cases should be handled when bdrv_reopen_queue() is
11
deciding what to do with each child of a BlockDriverState:
12
13
1) Set of child options: if the child was implicitly created (i.e
14
inherits_from points to the parent) then the options are removed
15
from the parent's options QDict and are passed to the child with
16
a recursive bdrv_reopen_queue() call. This case was already
17
working fine.
18
19
2) Child reference: there's two possibilites here.
20
21
2a) Reference to the current child: if the child was implicitly
22
created then it is put in the reopen queue, keeping its
23
current set of options (since this was a child reference
24
there was no way to specify a different set of options).
25
If the child is not implicit then it keeps its current set
26
of options but it is not reopened (and therefore does not
27
inherit any new option from the parent).
28
29
2b) Reference to a different BDS: the current child is not put
30
in the reopen queue at all. Passing a reference to a
31
different BDS can be used to replace a child, although at
32
the moment no driver implements this, so it results in an
33
error. In any case, the current child is not going to be
34
reopened (and might in fact disappear if it's replaced)
35
36
3) NULL: This is similar to (2b). Although no driver allows this
37
yet it can be used to detach the current child so it should not
38
be put in the reopen queue.
39
40
4) Missing option: at the moment "backing" is the only case where
41
this can happen. With "blockdev-add", leaving "backing" out
42
means that the default backing file is opened. We don't want to
43
open a new image during reopen, so we require that "backing" is
44
always present. We'll relax this requirement a bit in the next
45
patch. If keep_old_opts is true and "backing" is missing then
46
this behaves like 2a (the current child is reopened).
11
47
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
48
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>
49
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
50
---
16
block/quorum.c | 13 ++++++-------
51
include/block/block.h | 1 +
17
1 file changed, 6 insertions(+), 7 deletions(-)
52
block.c | 52 +++++++++++++++++++++++++++++++++++++------
53
2 files changed, 46 insertions(+), 7 deletions(-)
18
54
19
diff --git a/block/quorum.c b/block/quorum.c
55
diff --git a/include/block/block.h b/include/block/block.h
20
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
21
--- a/block/quorum.c
57
--- a/include/block/block.h
22
+++ b/block/quorum.c
58
+++ b/include/block/block.h
23
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
59
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVReopenState {
24
s->read_pattern = ret;
60
BlockDriverState *bs;
25
61
int flags;
26
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
62
BlockdevDetectZeroesOptions detect_zeroes;
27
- /* is the driver in blkverify mode */
63
+ bool backing_missing;
28
- if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
64
uint64_t perm, shared_perm;
29
- s->num_children == 2 && s->threshold == 2) {
65
QDict *options;
30
- s->is_blkverify = true;
66
QDict *explicit_options;
31
- } else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
67
diff --git a/block.c b/block.c
32
- fprintf(stderr, "blkverify mode is set by setting blkverify=on "
68
index XXXXXXX..XXXXXXX 100644
33
- "and using two files with vote_threshold=2\n");
69
--- a/block.c
34
+ s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
70
+++ b/block.c
35
+ if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
71
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
36
+ error_setg(&local_err, "blkverify=on can only be set if there are "
72
bs_entry->state.perm = UINT64_MAX;
37
+ "exactly two files and vote-threshold is 2");
73
bs_entry->state.shared_perm = 0;
38
+ ret = -EINVAL;
74
39
+ goto exit;
75
+ /*
76
+ * If keep_old_opts is false then it means that unspecified
77
+ * options must be reset to their original value. We don't allow
78
+ * resetting 'backing' but we need to know if the option is
79
+ * missing in order to decide if we have to return an error.
80
+ */
81
+ if (!keep_old_opts) {
82
+ bs_entry->state.backing_missing =
83
+ !qdict_haskey(options, "backing") &&
84
+ !qdict_haskey(options, "backing.driver");
85
+ }
86
+
87
QLIST_FOREACH(child, &bs->children, next) {
88
- QDict *new_child_options;
89
- char *child_key_dot;
90
+ QDict *new_child_options = NULL;
91
+ bool child_keep_old = keep_old_opts;
92
93
/* reopen can only change the options of block devices that were
94
* implicitly created and inherited options. For other (referenced)
95
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
96
continue;
40
}
97
}
41
98
42
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
99
- child_key_dot = g_strdup_printf("%s.", child->name);
100
- qdict_extract_subqdict(explicit_options, NULL, child_key_dot);
101
- qdict_extract_subqdict(options, &new_child_options, child_key_dot);
102
- g_free(child_key_dot);
103
+ /* Check if the options contain a child reference */
104
+ if (qdict_haskey(options, child->name)) {
105
+ const char *childref = qdict_get_try_str(options, child->name);
106
+ /*
107
+ * The current child must not be reopened if the child
108
+ * reference is null or points to a different node.
109
+ */
110
+ if (g_strcmp0(childref, child->bs->node_name)) {
111
+ continue;
112
+ }
113
+ /*
114
+ * If the child reference points to the current child then
115
+ * reopen it with its existing set of options (note that
116
+ * it can still inherit new options from the parent).
117
+ */
118
+ child_keep_old = true;
119
+ } else {
120
+ /* Extract child options ("child-name.*") */
121
+ char *child_key_dot = g_strdup_printf("%s.", child->name);
122
+ qdict_extract_subqdict(explicit_options, NULL, child_key_dot);
123
+ qdict_extract_subqdict(options, &new_child_options, child_key_dot);
124
+ g_free(child_key_dot);
125
+ }
126
127
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
128
- child->role, options, flags, keep_old_opts);
129
+ child->role, options, flags, child_keep_old);
130
}
131
132
return bs_queue;
133
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
134
135
drv_prepared = true;
136
137
+ if (drv->supports_backing && reopen_state->backing_missing) {
138
+ error_setg(errp, "backing is missing for '%s'",
139
+ reopen_state->bs->node_name);
140
+ ret = -EINVAL;
141
+ goto error;
142
+ }
143
+
144
/* Options that are not handled are only okay if they are unchanged
145
* compared to the old state. It is expected that some options are only
146
* used for the initial open, but not reopen (e.g. filename) */
43
--
147
--
44
2.19.1
148
2.20.1
45
149
46
150
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
3
Of all options of type BlockdevRef used to specify children in
4
BlockdevOptions, 'backing' is the only one that is optional.
5
6
For "x-blockdev-reopen" we want that if an option is omitted then it
7
must be reset to its default value. The default value of 'backing'
8
means that QEMU opens the backing file specified in the image
9
metadata, but this is not something that we want to support for the
10
reopen operation.
11
12
Because of this the 'backing' option has to be specified during
13
reopen, pointing to the existing backing file if we want to keep it,
14
or pointing to a different one (or NULL) if we want to replace it (to
15
be implemented in a subsequent patch).
16
17
In order to simplify things a bit and not to require that the user
18
passes the 'backing' option to every single block device even when
19
it's clearly not necessary, this patch allows omitting this option if
20
the block device being reopened doesn't have a backing file attached
21
_and_ no default backing file is specified in the image metadata.
2
22
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
23
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
25
---
6
block.c | 6 +++---
26
block.c | 8 +++++++-
7
1 file changed, 3 insertions(+), 3 deletions(-)
27
1 file changed, 7 insertions(+), 1 deletion(-)
8
28
9
diff --git a/block.c b/block.c
29
diff --git a/block.c b/block.c
10
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
31
--- a/block.c
12
+++ b/block.c
32
+++ b/block.c
13
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
14
.help = "try to optimize zero writes (off, on, unmap)",
15
},
16
{
17
- .name = "discard",
18
+ .name = BDRV_OPT_DISCARD,
19
.type = QEMU_OPT_STRING,
20
.help = "discard operation (ignore/off, unmap/on)",
21
},
22
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
23
}
24
}
25
26
- discard = qemu_opt_get(opts, "discard");
27
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
28
if (discard != NULL) {
29
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
30
error_setg(errp, "Invalid discard option");
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
33
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
32
34
33
update_flags_from_options(&reopen_state->flags, opts);
35
drv_prepared = true;
34
36
35
- discard = qemu_opt_get_del(opts, "discard");
37
- if (drv->supports_backing && reopen_state->backing_missing) {
36
+ discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
38
+ /*
37
if (discard != NULL) {
39
+ * We must provide the 'backing' option if the BDS has a backing
38
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
40
+ * file or if the image file has a backing file name as part of
39
error_setg(errp, "Invalid discard option");
41
+ * its metadata. Otherwise the 'backing' option can be omitted.
42
+ */
43
+ if (drv->supports_backing && reopen_state->backing_missing &&
44
+ (backing_bs(reopen_state->bs) || reopen_state->bs->backing_file[0])) {
45
error_setg(errp, "backing is missing for '%s'",
46
reopen_state->bs->node_name);
47
ret = -EINVAL;
40
--
48
--
41
2.19.1
49
2.20.1
42
50
43
51
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Just like in qemu_opts_print_help(), print the device name as a caption
3
This patch allows the user to change the backing file of an image that
4
instead of on every single line, indent all options, add angle brackets
4
is being reopened. Here's what it does:
5
around types, and align the descriptions after 24 characters. Also,
5
6
separate the descriptions with " - " instead of putting them in
6
- In bdrv_reopen_prepare(): check that the value of 'backing' points
7
parentheses, because that is what we do everywhere else. This does look
7
to an existing node or is null. If it points to an existing node it
8
a bit funny here because basically all bits have the description
8
also needs to make sure that replacing the backing file will not
9
"on/off", but funny does not mean it is less readable.
9
create a cycle in the node graph (i.e. you cannot reach the parent
10
10
from the new backing file).
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
12
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
- In bdrv_reopen_commit(): perform the actual node replacement by
13
calling bdrv_set_backing_hd().
14
15
There may be temporary implicit nodes between a BDS and its backing
16
file (e.g. a commit filter node). In these cases bdrv_reopen_prepare()
17
looks for the real (non-implicit) backing file and requires that the
18
'backing' option points to it. Replacing or detaching a backing file
19
is forbidden if there are implicit nodes in the middle.
20
21
Although x-blockdev-reopen is meant to be used like blockdev-add,
22
there's an important thing that must be taken into account: the only
23
way to set a new backing file is by using a reference to an existing
24
node (previously added with e.g. blockdev-add). If 'backing' contains
25
a dictionary with a new set of options ({"driver": "qcow2", "file": {
26
... }}) then it is interpreted that the _existing_ backing file must
27
be reopened with those options.
28
29
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
31
---
15
qdev-monitor.c | 13 +++++++++++--
32
include/block/block.h | 2 +
16
1 file changed, 11 insertions(+), 2 deletions(-)
33
block.c | 166 ++++++++++++++++++++++++++++++++++++++++++
17
34
2 files changed, 168 insertions(+)
18
diff --git a/qdev-monitor.c b/qdev-monitor.c
35
36
diff --git a/include/block/block.h b/include/block/block.h
19
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
20
--- a/qdev-monitor.c
38
--- a/include/block/block.h
21
+++ b/qdev-monitor.c
39
+++ b/include/block/block.h
22
@@ -XXX,XX +XXX,XX @@ int qdev_device_help(QemuOpts *opts)
40
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVReopenState {
41
int flags;
42
BlockdevDetectZeroesOptions detect_zeroes;
43
bool backing_missing;
44
+ bool replace_backing_bs; /* new_backing_bs is ignored if this is false */
45
+ BlockDriverState *new_backing_bs; /* If NULL then detach the current bs */
46
uint64_t perm, shared_perm;
47
QDict *options;
48
QDict *explicit_options;
49
diff --git a/block.c b/block.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block.c
52
+++ b/block.c
53
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
54
NULL, errp);
55
}
56
57
+/*
58
+ * Returns true if @child can be reached recursively from @bs
59
+ */
60
+static bool bdrv_recurse_has_child(BlockDriverState *bs,
61
+ BlockDriverState *child)
62
+{
63
+ BdrvChild *c;
64
+
65
+ if (bs == child) {
66
+ return true;
67
+ }
68
+
69
+ QLIST_FOREACH(c, &bs->children, next) {
70
+ if (bdrv_recurse_has_child(c->bs, child)) {
71
+ return true;
72
+ }
73
+ }
74
+
75
+ return false;
76
+}
77
+
78
/*
79
* Adds a BlockDriverState to a simple queue for an atomic, transactional
80
* reopen of multiple devices.
81
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
82
if (ret < 0) {
83
goto cleanup_perm;
84
}
85
+ /* Check if new_backing_bs would accept the new permissions */
86
+ if (state->replace_backing_bs && state->new_backing_bs) {
87
+ uint64_t nperm, nshared;
88
+ bdrv_child_perm(state->bs, state->new_backing_bs,
89
+ NULL, &child_backing, bs_queue,
90
+ state->perm, state->shared_perm,
91
+ &nperm, &nshared);
92
+ ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
93
+ nperm, nshared, NULL, errp);
94
+ if (ret < 0) {
95
+ goto cleanup_perm;
96
+ }
97
+ }
98
bs_entry->perms_checked = true;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ cleanup_perm:
102
bdrv_set_perm(state->bs, state->perm, state->shared_perm);
103
} else {
104
bdrv_abort_perm_update(state->bs);
105
+ if (state->replace_backing_bs && state->new_backing_bs) {
106
+ bdrv_abort_perm_update(state->new_backing_bs);
107
+ }
108
}
109
}
110
cleanup:
111
@@ -XXX,XX +XXX,XX @@ cleanup:
112
qobject_unref(bs_entry->state.explicit_options);
113
qobject_unref(bs_entry->state.options);
114
}
115
+ if (bs_entry->state.new_backing_bs) {
116
+ bdrv_unref(bs_entry->state.new_backing_bs);
117
+ }
118
g_free(bs_entry);
119
}
120
g_free(bs_queue);
121
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
122
*shared = cumulative_shared_perms;
123
}
124
125
+/*
126
+ * Take a BDRVReopenState and check if the value of 'backing' in the
127
+ * reopen_state->options QDict is valid or not.
128
+ *
129
+ * If 'backing' is missing from the QDict then return 0.
130
+ *
131
+ * If 'backing' contains the node name of the backing file of
132
+ * reopen_state->bs then return 0.
133
+ *
134
+ * If 'backing' contains a different node name (or is null) then check
135
+ * whether the current backing file can be replaced with the new one.
136
+ * If that's the case then reopen_state->replace_backing_bs is set to
137
+ * true and reopen_state->new_backing_bs contains a pointer to the new
138
+ * backing BlockDriverState (or NULL).
139
+ *
140
+ * Return 0 on success, otherwise return < 0 and set @errp.
141
+ */
142
+static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
143
+ Error **errp)
144
+{
145
+ BlockDriverState *bs = reopen_state->bs;
146
+ BlockDriverState *overlay_bs, *new_backing_bs;
147
+ QObject *value;
148
+ const char *str;
149
+
150
+ value = qdict_get(reopen_state->options, "backing");
151
+ if (value == NULL) {
152
+ return 0;
153
+ }
154
+
155
+ switch (qobject_type(value)) {
156
+ case QTYPE_QNULL:
157
+ new_backing_bs = NULL;
158
+ break;
159
+ case QTYPE_QSTRING:
160
+ str = qobject_get_try_str(value);
161
+ new_backing_bs = bdrv_lookup_bs(NULL, str, errp);
162
+ if (new_backing_bs == NULL) {
163
+ return -EINVAL;
164
+ } else if (bdrv_recurse_has_child(new_backing_bs, bs)) {
165
+ error_setg(errp, "Making '%s' a backing file of '%s' "
166
+ "would create a cycle", str, bs->node_name);
167
+ return -EINVAL;
168
+ }
169
+ break;
170
+ default:
171
+ /* 'backing' does not allow any other data type */
172
+ g_assert_not_reached();
173
+ }
174
+
175
+ /*
176
+ * TODO: before removing the x- prefix from x-blockdev-reopen we
177
+ * should move the new backing file into the right AioContext
178
+ * instead of returning an error.
179
+ */
180
+ if (new_backing_bs) {
181
+ if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) {
182
+ error_setg(errp, "Cannot use a new backing file "
183
+ "with a different AioContext");
184
+ return -EINVAL;
185
+ }
186
+ }
187
+
188
+ /*
189
+ * Find the "actual" backing file by skipping all links that point
190
+ * to an implicit node, if any (e.g. a commit filter node).
191
+ */
192
+ overlay_bs = bs;
193
+ while (backing_bs(overlay_bs) && backing_bs(overlay_bs)->implicit) {
194
+ overlay_bs = backing_bs(overlay_bs);
195
+ }
196
+
197
+ /* If we want to replace the backing file we need some extra checks */
198
+ if (new_backing_bs != backing_bs(overlay_bs)) {
199
+ /* Check for implicit nodes between bs and its backing file */
200
+ if (bs != overlay_bs) {
201
+ error_setg(errp, "Cannot change backing link if '%s' has "
202
+ "an implicit backing file", bs->node_name);
203
+ return -EPERM;
204
+ }
205
+ /* Check if the backing link that we want to replace is frozen */
206
+ if (bdrv_is_backing_chain_frozen(overlay_bs, backing_bs(overlay_bs),
207
+ errp)) {
208
+ return -EPERM;
209
+ }
210
+ reopen_state->replace_backing_bs = true;
211
+ if (new_backing_bs) {
212
+ bdrv_ref(new_backing_bs);
213
+ reopen_state->new_backing_bs = new_backing_bs;
214
+ }
215
+ }
216
+
217
+ return 0;
218
+}
219
+
220
/*
221
* Prepares a BlockDriverState for reopen. All changes are staged in the
222
* 'opaque' field of the BDRVReopenState, which is used and allocated by
223
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
23
goto error;
224
goto error;
24
}
225
}
25
226
26
+ if (prop_list) {
227
+ /*
27
+ out_printf("%s options:\n", driver);
228
+ * Allow changing the 'backing' option. The new value can be
28
+ } else {
229
+ * either a reference to an existing node (using its node name)
29
+ out_printf("There are no options for %s.\n", driver);
230
+ * or NULL to simply detach the current backing file.
30
+ }
231
+ */
31
for (prop = prop_list; prop; prop = prop->next) {
232
+ ret = bdrv_reopen_parse_backing(reopen_state, errp);
32
- out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
233
+ if (ret < 0) {
33
+ int len;
234
+ goto error;
34
+ out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
235
+ }
35
if (prop->value->has_description) {
236
+ qdict_del(reopen_state->options, "backing");
36
- out_printf(" (%s)\n", prop->value->description);
237
+
37
+ if (len < 24) {
238
/* Options that are not handled are only okay if they are unchanged
38
+ out_printf("%*s", 24 - len, "");
239
* compared to the old state. It is expected that some options are only
39
+ }
240
* used for the initial open, but not reopen (e.g. filename) */
40
+ out_printf(" - %s\n", prop->value->description);
241
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
41
} else {
242
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
42
out_printf("\n");
243
bs->detect_zeroes = reopen_state->detect_zeroes;
43
}
244
245
+ if (reopen_state->replace_backing_bs) {
246
+ qdict_del(bs->explicit_options, "backing");
247
+ qdict_del(bs->options, "backing");
248
+ }
249
+
250
/* Remove child references from bs->options and bs->explicit_options.
251
* Child options were already removed in bdrv_reopen_queue_child() */
252
QLIST_FOREACH(child, &bs->children, next) {
253
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
254
qdict_del(bs->options, child->name);
255
}
256
257
+ /*
258
+ * Change the backing file if a new one was specified. We do this
259
+ * after updating bs->options, so bdrv_refresh_filename() (called
260
+ * from bdrv_set_backing_hd()) has the new values.
261
+ */
262
+ if (reopen_state->replace_backing_bs) {
263
+ BlockDriverState *old_backing_bs = backing_bs(bs);
264
+ assert(!old_backing_bs || !old_backing_bs->implicit);
265
+ /* Abort the permission update on the backing bs we're detaching */
266
+ if (old_backing_bs) {
267
+ bdrv_abort_perm_update(old_backing_bs);
268
+ }
269
+ bdrv_set_backing_hd(bs, reopen_state->new_backing_bs, &error_abort);
270
+ }
271
+
272
bdrv_refresh_limits(bs, NULL);
273
274
new_can_write =
44
--
275
--
45
2.19.1
276
2.20.1
46
277
47
278
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This doesn't have any practical effect at the moment because the
3
If we reopen a BlockDriverState and there is an option that is present
4
values of BDRV_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE and
4
in bs->options but missing from the new set of options then we have to
5
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE are all the same (512 bytes), but
5
return an error unless the driver is able to reset it to its default
6
future encryption methods could have different requirements.
6
value.
7
8
This patch adds a new 'mutable_opts' field to BlockDriver. This is
9
a list of runtime options that can be modified during reopen. If an
10
option in this list is unspecified on reopen then it must be reset (or
11
return an error).
7
12
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
15
---
12
block/qcow2.c | 2 +-
16
include/block/block_int.h | 8 ++++++++
13
1 file changed, 1 insertion(+), 1 deletion(-)
17
block/file-posix.c | 6 ++++++
18
block/qcow2.c | 25 +++++++++++++++++++++++++
19
block/raw-format.c | 3 +++
20
4 files changed, 42 insertions(+)
14
21
22
diff --git a/include/block/block_int.h b/include/block/block_int.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/block/block_int.h
25
+++ b/include/block/block_int.h
26
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
27
28
/* List of options for creating images, terminated by name == NULL */
29
QemuOptsList *create_opts;
30
+ /*
31
+ * If this driver supports reopening images this contains a
32
+ * NULL-terminated list of the runtime options that can be
33
+ * modified. If an option in this list is unspecified during
34
+ * reopen then it _must_ be reset to its default value or return
35
+ * an error.
36
+ */
37
+ const char *const *mutable_opts;
38
39
/*
40
* Returns 0 for completed check, -errno for internal errors.
41
diff --git a/block/file-posix.c b/block/file-posix.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block/file-posix.c
44
+++ b/block/file-posix.c
45
@@ -XXX,XX +XXX,XX @@ static QemuOptsList raw_runtime_opts = {
46
},
47
};
48
49
+static const char *const mutable_opts[] = { "x-check-cache-dropped", NULL };
50
+
51
static int raw_open_common(BlockDriverState *bs, QDict *options,
52
int bdrv_flags, int open_flags,
53
bool device, Error **errp)
54
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
55
.bdrv_set_perm = raw_set_perm,
56
.bdrv_abort_perm_update = raw_abort_perm_update,
57
.create_opts = &raw_create_opts,
58
+ .mutable_opts = mutable_opts,
59
};
60
61
/***********************************************/
62
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
63
.bdrv_reopen_abort = raw_reopen_abort,
64
.bdrv_co_create_opts = hdev_co_create_opts,
65
.create_opts = &raw_create_opts,
66
+ .mutable_opts = mutable_opts,
67
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
68
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
69
70
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
71
.bdrv_reopen_abort = raw_reopen_abort,
72
.bdrv_co_create_opts = hdev_co_create_opts,
73
.create_opts = &raw_create_opts,
74
+ .mutable_opts = mutable_opts,
75
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
76
77
78
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
79
.bdrv_reopen_abort = raw_reopen_abort,
80
.bdrv_co_create_opts = hdev_co_create_opts,
81
.create_opts = &raw_create_opts,
82
+ .mutable_opts = mutable_opts,
83
84
.bdrv_co_preadv = raw_co_preadv,
85
.bdrv_co_pwritev = raw_co_pwritev,
15
diff --git a/block/qcow2.c b/block/qcow2.c
86
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
88
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
89
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
90
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
20
91
return 0;
21
if (bs->encrypted) {
92
}
22
/* Encryption works on a sector granularity */
93
23
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
94
+static const char *const mutable_opts[] = {
24
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
95
+ QCOW2_OPT_LAZY_REFCOUNTS,
25
}
96
+ QCOW2_OPT_DISCARD_REQUEST,
26
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
97
+ QCOW2_OPT_DISCARD_SNAPSHOT,
27
bs->bl.pdiscard_alignment = s->cluster_size;
98
+ QCOW2_OPT_DISCARD_OTHER,
99
+ QCOW2_OPT_OVERLAP,
100
+ QCOW2_OPT_OVERLAP_TEMPLATE,
101
+ QCOW2_OPT_OVERLAP_MAIN_HEADER,
102
+ QCOW2_OPT_OVERLAP_ACTIVE_L1,
103
+ QCOW2_OPT_OVERLAP_ACTIVE_L2,
104
+ QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
105
+ QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
106
+ QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
107
+ QCOW2_OPT_OVERLAP_INACTIVE_L1,
108
+ QCOW2_OPT_OVERLAP_INACTIVE_L2,
109
+ QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY,
110
+ QCOW2_OPT_CACHE_SIZE,
111
+ QCOW2_OPT_L2_CACHE_SIZE,
112
+ QCOW2_OPT_L2_CACHE_ENTRY_SIZE,
113
+ QCOW2_OPT_REFCOUNT_CACHE_SIZE,
114
+ QCOW2_OPT_CACHE_CLEAN_INTERVAL,
115
+ NULL
116
+};
117
+
118
static QemuOptsList qcow2_runtime_opts = {
119
.name = "qcow2",
120
.head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head),
121
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
122
123
.create_opts = &qcow2_create_opts,
124
.strong_runtime_opts = qcow2_strong_runtime_opts,
125
+ .mutable_opts = mutable_opts,
126
.bdrv_co_check = qcow2_co_check,
127
.bdrv_amend_options = qcow2_amend_options,
128
129
diff --git a/block/raw-format.c b/block/raw-format.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/raw-format.c
132
+++ b/block/raw-format.c
133
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
134
bool has_size;
135
} BDRVRawState;
136
137
+static const char *const mutable_opts[] = { "offset", "size", NULL };
138
+
139
static QemuOptsList raw_runtime_opts = {
140
.name = "raw",
141
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
142
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
143
.create_opts = &raw_create_opts,
144
.bdrv_has_zero_init = &raw_has_zero_init,
145
.strong_runtime_opts = raw_strong_runtime_opts,
146
+ .mutable_opts = mutable_opts,
147
};
148
149
static void bdrv_raw_init(void)
28
--
150
--
29
2.19.1
151
2.20.1
30
152
31
153
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This patch tests that you can add and remove drives from a Quorum
3
bdrv_reopen_prepare() receives a BDRVReopenState with (among other
4
using the x-blockdev-change command.
4
things) a new set of options to be applied to that BlockDriverState.
5
6
If an option is missing then it means that we want to reset it to its
7
default value rather than keep the previous one. This way the state
8
of the block device after being reopened is comparable to that of a
9
device added with "blockdev-add" using the same set of options.
10
11
Not all options from all drivers can be changed this way, however.
12
If the user attempts to reset an immutable option to its default value
13
using this method then we must forbid it.
14
15
This new function takes a BlockDriverState and a new set of options
16
and checks if there's any option that was previously set but is
17
missing from the new set of options.
18
19
If the option is present in both sets we don't need to check that they
20
have the same value. The loop at the end of bdrv_reopen_prepare()
21
already takes care of that.
5
22
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
23
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
25
---
9
tests/qemu-iotests/081 | 86 ++++++++++++++++++++++++++++++++++++++
26
block.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/081.out | 54 ++++++++++++++++++++++++
27
1 file changed, 58 insertions(+)
11
2 files changed, 140 insertions(+)
12
28
13
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
29
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100755
30
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/081
31
--- a/block.c
16
+++ b/tests/qemu-iotests/081
32
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ quorum="$quorum,file.children.2.driver=raw"
33
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
18
34
NULL, errp);
19
$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
35
}
20
36
21
+echo
37
+/* Return true if the NULL-terminated @list contains @str */
22
+echo "== dynamically adding a child to a quorum =="
38
+static bool is_str_in_list(const char *str, const char *const *list)
23
+
39
+{
24
+for verify in false true; do
40
+ if (str && list) {
25
+ run_qemu <<EOF
41
+ int i;
26
+ { "execute": "qmp_capabilities" }
42
+ for (i = 0; list[i] != NULL; i++) {
27
+ { "execute": "blockdev-add",
43
+ if (!strcmp(str, list[i])) {
28
+ "arguments": {
44
+ return true;
29
+ "driver": "quorum",
30
+ "node-name": "drive0-quorum",
31
+ "vote-threshold": 2,
32
+ "blkverify": ${verify},
33
+ "children": [
34
+ {
35
+ "driver": "$IMGFMT",
36
+ "file": {
37
+ "driver": "file",
38
+ "filename": "$TEST_DIR/1.raw"
39
+ }
40
+ },
41
+ {
42
+ "driver": "$IMGFMT",
43
+ "file": {
44
+ "driver": "file",
45
+ "filename": "$TEST_DIR/2.raw"
46
+ }
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ { "execute": "blockdev-add",
52
+ "arguments": {
53
+ "node-name": "drive3",
54
+ "driver": "$IMGFMT",
55
+ "file": {
56
+ "driver": "file",
57
+ "filename": "$TEST_DIR/2.raw"
58
+ }
45
+ }
59
+ }
46
+ }
60
+ }
47
+ }
61
+ { "execute": "x-blockdev-change",
48
+ return false;
62
+ "arguments": { "parent": "drive0-quorum",
49
+}
63
+ "node": "drive3" } }
64
+ { "execute": "quit" }
65
+EOF
66
+done
67
+
50
+
68
+echo
51
+/*
69
+echo "== dynamically removing a child from a quorum =="
52
+ * Check that every option set in @bs->options is also set in
53
+ * @new_opts.
54
+ *
55
+ * Options listed in the common_options list and in
56
+ * @bs->drv->mutable_opts are skipped.
57
+ *
58
+ * Return 0 on success, otherwise return -EINVAL and set @errp.
59
+ */
60
+static int bdrv_reset_options_allowed(BlockDriverState *bs,
61
+ const QDict *new_opts, Error **errp)
62
+{
63
+ const QDictEntry *e;
64
+ /* These options are common to all block drivers and are handled
65
+ * in bdrv_reopen_prepare() so they can be left out of @new_opts */
66
+ const char *const common_options[] = {
67
+ "node-name", "discard", "cache.direct", "cache.no-flush",
68
+ "read-only", "auto-read-only", "detect-zeroes", NULL
69
+ };
70
+
70
+
71
+for verify in false true; do
71
+ for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) {
72
+ for vote_threshold in 1 2; do
72
+ if (!qdict_haskey(new_opts, e->key) &&
73
+ run_qemu <<EOF
73
+ !is_str_in_list(e->key, common_options) &&
74
+ { "execute": "qmp_capabilities" }
74
+ !is_str_in_list(e->key, bs->drv->mutable_opts)) {
75
+ { "execute": "blockdev-add",
75
+ error_setg(errp, "Option '%s' cannot be reset "
76
+ "arguments": {
76
+ "to its default value", e->key);
77
+ "driver": "quorum",
77
+ return -EINVAL;
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
+ ]
97
+ }
98
+ }
78
+ }
99
+ { "execute": "x-blockdev-change",
79
+ }
100
+ "arguments": { "parent": "drive0-quorum",
101
+ "child": "children.1" } }
102
+ { "execute": "quit" }
103
+EOF
104
+ done
105
+done
106
+
80
+
107
# success, all done
81
+ return 0;
108
echo "*** done"
82
+}
109
rm -f $seq.full
110
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/081.out
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
118
+
83
+
119
+== dynamically adding a child to a quorum ==
84
/*
120
+Testing:
85
* Returns true if @child can be reached recursively from @bs
121
+QMP_VERSION
86
*/
122
+{"return": {}}
87
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
123
+{"return": {}}
88
}
124
+{"return": {}}
89
125
+{"return": {}}
90
if (drv->bdrv_reopen_prepare) {
126
+{"return": {}}
91
+ /*
127
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
92
+ * If a driver-specific option is missing, it means that we
93
+ * should reset it to its default value.
94
+ * But not all options allow that, so we need to check it first.
95
+ */
96
+ ret = bdrv_reset_options_allowed(reopen_state->bs,
97
+ reopen_state->options, errp);
98
+ if (ret) {
99
+ goto error;
100
+ }
128
+
101
+
129
+Testing:
102
ret = drv->bdrv_reopen_prepare(reopen_state, queue, &local_err);
130
+QMP_VERSION
103
if (ret) {
131
+{"return": {}}
104
if (local_err != NULL) {
132
+{"return": {}}
133
+{"return": {}}
134
+{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
135
+{"return": {}}
136
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
137
+
138
+
139
+== dynamically removing a child from a quorum ==
140
+Testing:
141
+QMP_VERSION
142
+{"return": {}}
143
+{"return": {}}
144
+{"return": {}}
145
+{"return": {}}
146
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
147
+
148
+Testing:
149
+QMP_VERSION
150
+{"return": {}}
151
+{"return": {}}
152
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
153
+{"return": {}}
154
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
155
+
156
+Testing:
157
+QMP_VERSION
158
+{"return": {}}
159
+{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
160
+{"error": {"class": "GenericError", "desc": "Cannot find device=drive0-quorum nor node_name=drive0-quorum"}}
161
+{"return": {}}
162
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
163
+
164
+Testing:
165
+QMP_VERSION
166
+{"return": {}}
167
+{"return": {}}
168
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
169
+{"return": {}}
170
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
171
+
172
*** done
173
--
105
--
174
2.19.1
106
2.20.1
175
107
176
108
diff view generated by jsdifflib
1
From: Stefan Weil <sw@weilnetz.de>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Use %zu instead of %zd for unsigned numbers.
3
This parameter has been unused since 1a63a907507fbbcfaee3f622907ec244b
4
4
5
This fixes two error messages from the LSTM static code analyzer:
5
Signed-off-by: Alberto Garcia <berto@igalia.com>
6
7
This argument should be of type 'ssize_t' but is of type 'unsigned long'
8
9
Signed-off-by: Stefan Weil <sw@weilnetz.de>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
7
---
13
qemu-io-cmds.c | 4 ++--
8
include/block/block.h | 2 +-
14
1 file changed, 2 insertions(+), 2 deletions(-)
9
block.c | 4 ++--
10
block/replication.c | 3 +--
11
qemu-io-cmds.c | 2 +-
12
4 files changed, 5 insertions(+), 6 deletions(-)
15
13
14
diff --git a/include/block/block.h b/include/block/block.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block.h
17
+++ b/include/block/block.h
18
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
19
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
20
BlockDriverState *bs, QDict *options,
21
bool keep_old_opts);
22
-int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp);
23
+int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
24
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
25
Error **errp);
26
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
27
diff --git a/block.c b/block.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block.c
30
+++ b/block.c
31
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
32
* All affected nodes must be drained between bdrv_reopen_queue() and
33
* bdrv_reopen_multiple().
34
*/
35
-int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp)
36
+int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
37
{
38
int ret = -1;
39
BlockReopenQueueEntry *bs_entry, *next;
40
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
41
42
bdrv_subtree_drained_begin(bs);
43
queue = bdrv_reopen_queue(NULL, bs, opts, true);
44
- ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
45
+ ret = bdrv_reopen_multiple(queue, errp);
46
bdrv_subtree_drained_end(bs);
47
48
return ret;
49
diff --git a/block/replication.c b/block/replication.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/replication.c
52
+++ b/block/replication.c
53
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
54
}
55
56
if (reopen_queue) {
57
- bdrv_reopen_multiple(bdrv_get_aio_context(bs),
58
- reopen_queue, &local_err);
59
+ bdrv_reopen_multiple(reopen_queue, &local_err);
60
error_propagate(errp, local_err);
61
}
62
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
63
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
17
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
18
--- a/qemu-io-cmds.c
65
--- a/qemu-io-cmds.c
19
+++ b/qemu-io-cmds.c
66
+++ b/qemu-io-cmds.c
20
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
67
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
21
memset(cmp_buf, pattern, qiov.size);
68
22
if (memcmp(buf, cmp_buf, qiov.size)) {
69
bdrv_subtree_drained_begin(bs);
23
printf("Pattern verification failed at offset %"
70
brq = bdrv_reopen_queue(NULL, bs, opts, true);
24
- PRId64 ", %zd bytes\n", offset, qiov.size);
71
- bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
25
+ PRId64 ", %zu bytes\n", offset, qiov.size);
72
+ bdrv_reopen_multiple(brq, &local_err);
26
ret = -EINVAL;
73
bdrv_subtree_drained_end(bs);
27
}
74
28
g_free(cmp_buf);
75
if (local_err) {
29
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
30
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
31
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
32
printf("Pattern verification failed at offset %"
33
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
34
+ PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
35
}
36
g_free(cmp_buf);
37
}
38
--
76
--
39
2.19.1
77
2.20.1
40
78
41
79
diff view generated by jsdifflib
Deleted patch
1
From: Daniel P. Berrangé <berrange@redhat.com>
2
1
3
The qcow2 block driver expects to see a valid sector size even when it
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>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
crypto/block-qcow.c | 2 ++
11
1 file changed, 2 insertions(+)
12
13
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/crypto/block-qcow.c
16
+++ b/crypto/block-qcow.c
17
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
18
Error **errp)
19
{
20
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
21
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
22
+ block->payload_offset = 0;
23
return 0;
24
} else {
25
if (!options->u.qcow.key_secret) {
26
--
27
2.19.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
3
Taking the address of a field in a packed struct is a bad idea, because
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.
8
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
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>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
block/vdi.c | 64 ++++++++++++++++++++++++++---------------------------
24
1 file changed, 32 insertions(+), 32 deletions(-)
25
26
diff --git a/block/vdi.c b/block/vdi.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/vdi.c
29
+++ b/block/vdi.c
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
32
static void vdi_header_to_cpu(VdiHeader *header)
33
{
34
- le32_to_cpus(&header->signature);
35
- le32_to_cpus(&header->version);
36
- le32_to_cpus(&header->header_size);
37
- le32_to_cpus(&header->image_type);
38
- le32_to_cpus(&header->image_flags);
39
- le32_to_cpus(&header->offset_bmap);
40
- le32_to_cpus(&header->offset_data);
41
- le32_to_cpus(&header->cylinders);
42
- le32_to_cpus(&header->heads);
43
- le32_to_cpus(&header->sectors);
44
- le32_to_cpus(&header->sector_size);
45
- le64_to_cpus(&header->disk_size);
46
- le32_to_cpus(&header->block_size);
47
- le32_to_cpus(&header->block_extra);
48
- le32_to_cpus(&header->blocks_in_image);
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);
108
--
109
2.19.1
110
111
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This is a static function with only one caller, so there's no need to
3
This command allows reopening an arbitrary BlockDriverState with a
4
keep it. Inlining the code in quorum_compare() makes it much simpler.
4
new set of options. Some options (e.g node-name) cannot be changed
5
and some block drivers don't allow reopening, but otherwise this
6
command is modelled after 'blockdev-add' and the state of the reopened
7
BlockDriverState should generally be the same as if it had just been
8
added by 'blockdev-add' with the same set of options.
9
10
One notable exception is the 'backing' option: 'x-blockdev-reopen'
11
requires that it is always present unless the BlockDriverState in
12
question doesn't have a current or default backing file.
13
14
This command allows reconfiguring the graph by using the appropriate
15
options to change the children of a node. At the moment it's possible
16
to change a backing file by setting the 'backing' option to the name
17
of the new node, but it should also be possible to add a similar
18
functionality to other block drivers (e.g. Quorum, blkverify).
19
20
Although the API is unlikely to change, this command is marked
21
experimental for the time being so there's room to see if the
22
semantics need changes.
5
23
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
24
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reported-by: Markus Armbruster <armbru@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
26
---
10
block/quorum.c | 24 +++++-------------------
27
qapi/block-core.json | 42 +++++++++++++++++++++++++++++++++++++++
11
1 file changed, 5 insertions(+), 19 deletions(-)
28
blockdev.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
29
2 files changed, 89 insertions(+)
12
30
13
diff --git a/block/quorum.c b/block/quorum.c
31
diff --git a/qapi/block-core.json b/qapi/block-core.json
14
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
15
--- a/block/quorum.c
33
--- a/qapi/block-core.json
16
+++ b/block/quorum.c
34
+++ b/qapi/block-core.json
17
@@ -XXX,XX +XXX,XX @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
35
@@ -XXX,XX +XXX,XX @@
18
return true;
36
##
37
{ 'command': 'blockdev-add', 'data': 'BlockdevOptions', 'boxed': true }
38
39
+##
40
+# @x-blockdev-reopen:
41
+#
42
+# Reopens a block device using the given set of options. Any option
43
+# not specified will be reset to its default value regardless of its
44
+# previous status. If an option cannot be changed or a particular
45
+# driver does not support reopening then the command will return an
46
+# error.
47
+#
48
+# The top-level @node-name option (from BlockdevOptions) must be
49
+# specified and is used to select the block device to be reopened.
50
+# Other @node-name options must be either omitted or set to the
51
+# current name of the appropriate node. This command won't change any
52
+# node name and any attempt to do it will result in an error.
53
+#
54
+# In the case of options that refer to child nodes, the behavior of
55
+# this command depends on the value:
56
+#
57
+# 1) A set of options (BlockdevOptions): the child is reopened with
58
+# the specified set of options.
59
+#
60
+# 2) A reference to the current child: the child is reopened using
61
+# its existing set of options.
62
+#
63
+# 3) A reference to a different node: the current child is replaced
64
+# with the specified one.
65
+#
66
+# 4) NULL: the current child (if any) is detached.
67
+#
68
+# Options (1) and (2) are supported in all cases, but at the moment
69
+# only @backing allows replacing or detaching an existing child.
70
+#
71
+# Unlike with blockdev-add, the @backing option must always be present
72
+# unless the node being reopened does not have a backing file and its
73
+# image does not have a default backing file name as part of its
74
+# metadata.
75
+#
76
+# Since: 4.0
77
+##
78
+{ 'command': 'x-blockdev-reopen',
79
+ 'data': 'BlockdevOptions', 'boxed': true }
80
+
81
##
82
# @blockdev-del:
83
#
84
diff --git a/blockdev.c b/blockdev.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/blockdev.c
87
+++ b/blockdev.c
88
@@ -XXX,XX +XXX,XX @@ fail:
89
visit_free(v);
19
}
90
}
20
91
21
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
92
+void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
22
- const char *fmt, ...)
93
+{
23
-{
94
+ BlockDriverState *bs;
24
- va_list ap;
95
+ AioContext *ctx;
25
-
96
+ QObject *obj;
26
- va_start(ap, fmt);
97
+ Visitor *v = qobject_output_visitor_new(&obj);
27
- fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
98
+ Error *local_err = NULL;
28
- acb->offset, acb->bytes);
99
+ BlockReopenQueue *queue;
29
- vfprintf(stderr, fmt, ap);
100
+ QDict *qdict;
30
- fprintf(stderr, "\n");
101
+
31
- va_end(ap);
102
+ /* Check for the selected node name */
32
- exit(1);
103
+ if (!options->has_node_name) {
33
-}
104
+ error_setg(errp, "Node name not specified");
34
-
105
+ goto fail;
35
-static bool quorum_compare(QuorumAIOCB *acb,
106
+ }
36
- QEMUIOVector *a,
107
+
37
- QEMUIOVector *b)
108
+ bs = bdrv_find_node(options->node_name);
38
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
109
+ if (!bs) {
110
+ error_setg(errp, "Cannot find node named '%s'", options->node_name);
111
+ goto fail;
112
+ }
113
+
114
+ /* Put all options in a QDict and flatten it */
115
+ visit_type_BlockdevOptions(v, NULL, &options, &local_err);
116
+ if (local_err) {
117
+ error_propagate(errp, local_err);
118
+ goto fail;
119
+ }
120
+
121
+ visit_complete(v, &obj);
122
+ qdict = qobject_to(QDict, obj);
123
+
124
+ qdict_flatten(qdict);
125
+
126
+ /* Perform the reopen operation */
127
+ ctx = bdrv_get_aio_context(bs);
128
+ aio_context_acquire(ctx);
129
+ bdrv_subtree_drained_begin(bs);
130
+ queue = bdrv_reopen_queue(NULL, bs, qdict, false);
131
+ bdrv_reopen_multiple(queue, errp);
132
+ bdrv_subtree_drained_end(bs);
133
+ aio_context_release(ctx);
134
+
135
+fail:
136
+ visit_free(v);
137
+}
138
+
139
void qmp_blockdev_del(const char *node_name, Error **errp)
39
{
140
{
40
BDRVQuorumState *s = acb->bs->opaque;
141
AioContext *aio_context;
41
ssize_t offset;
42
@@ -XXX,XX +XXX,XX @@ static bool quorum_compare(QuorumAIOCB *acb,
43
if (s->is_blkverify) {
44
offset = qemu_iovec_compare(a, b);
45
if (offset != -1) {
46
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
47
- acb->offset + offset);
48
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
49
+ " contents mismatch at offset %" PRIu64 "\n",
50
+ acb->offset, acb->bytes, acb->offset + offset);
51
+ exit(1);
52
}
53
return true;
54
}
55
--
142
--
56
2.19.1
143
2.20.1
57
144
58
145
diff view generated by jsdifflib
Deleted patch
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.
5
1
6
This adds the missing rbd_close() call.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
---
11
block/rbd.c | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/block/rbd.c b/block/rbd.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
17
+++ b/block/rbd.c
18
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
19
"automatically marking the image read-only.");
20
r = bdrv_set_read_only(bs, true, &local_err);
21
if (r < 0) {
22
+ rbd_close(s->image);
23
error_propagate(errp, local_err);
24
goto failed_open;
25
}
26
--
27
2.19.1
28
29
diff view generated by jsdifflib
Deleted patch
1
If read-only=off, but auto-read-only=on is given, open a read-write NBD
2
connection if the server provides a read-write export, but instead of
3
erroring out for read-only exports, just degrade to read-only.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
block/nbd-client.c | 10 +++++-----
9
1 file changed, 5 insertions(+), 5 deletions(-)
10
11
diff --git a/block/nbd-client.c b/block/nbd-client.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/nbd-client.c
14
+++ b/block/nbd-client.c
15
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
16
logout("Failed to negotiate with the NBD server\n");
17
return ret;
18
}
19
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
20
- !bdrv_is_read_only(bs)) {
21
- error_setg(errp,
22
- "request for write access conflicts with read-only export");
23
- return -EACCES;
24
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
25
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
26
+ if (ret < 0) {
27
+ return ret;
28
+ }
29
}
30
if (client->info.flags & NBD_FLAG_SEND_FUA) {
31
bs->supported_write_flags = BDRV_REQ_FUA;
32
--
33
2.19.1
34
35
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
2
3
This patch adds several tests for the x-blockdev-reopen QMP command.
4
5
Signed-off-by: Alberto Garcia <berto@igalia.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
7
---
4
tests/qemu-iotests/232 | 147 +++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/245 | 991 +++++++++++++++++++++++++++++++++++++
5
tests/qemu-iotests/232.out | 59 +++++++++++++++
9
tests/qemu-iotests/245.out | 5 +
6
tests/qemu-iotests/group | 1 +
10
tests/qemu-iotests/group | 1 +
7
3 files changed, 207 insertions(+)
11
3 files changed, 997 insertions(+)
8
create mode 100755 tests/qemu-iotests/232
12
create mode 100644 tests/qemu-iotests/245
9
create mode 100644 tests/qemu-iotests/232.out
13
create mode 100644 tests/qemu-iotests/245.out
10
14
11
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
15
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
12
new file mode 100755
16
new file mode 100644
13
index XXXXXXX..XXXXXXX
17
index XXXXXXX..XXXXXXX
14
--- /dev/null
18
--- /dev/null
15
+++ b/tests/qemu-iotests/232
19
+++ b/tests/qemu-iotests/245
16
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
17
+#!/bin/bash
21
+#!/usr/bin/env python
18
+#
22
+#
19
+# Test for auto-read-only
23
+# Test cases for the QMP 'x-blockdev-reopen' command
20
+#
24
+#
21
+# Copyright (C) 2018 Red Hat, Inc.
25
+# Copyright (C) 2018-2019 Igalia, S.L.
26
+# Author: Alberto Garcia <berto@igalia.com>
22
+#
27
+#
23
+# This program is free software; you can redistribute it and/or modify
28
+# This program is free software; you can redistribute it and/or modify
24
+# it under the terms of the GNU General Public License as published by
29
+# it under the terms of the GNU General Public License as published by
25
+# the Free Software Foundation; either version 2 of the License, or
30
+# the Free Software Foundation; either version 2 of the License, or
26
+# (at your option) any later version.
31
+# (at your option) any later version.
...
...
32
+#
37
+#
33
+# You should have received a copy of the GNU General Public License
38
+# You should have received a copy of the GNU General Public License
34
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+#
40
+#
36
+
41
+
37
+# creator
42
+import os
38
+owner=kwolf@redhat.com
43
+import re
39
+
44
+import iotests
40
+seq=`basename $0`
45
+import copy
41
+echo "QA output created by $seq"
46
+import json
42
+
47
+from iotests import qemu_img, qemu_io
43
+here=`pwd`
48
+
44
+status=1    # failure is the default!
49
+hd_path = [
45
+
50
+ os.path.join(iotests.test_dir, 'hd0.img'),
46
+_cleanup()
51
+ os.path.join(iotests.test_dir, 'hd1.img'),
47
+{
52
+ os.path.join(iotests.test_dir, 'hd2.img')
48
+ _cleanup_test_img
53
+]
49
+ rm -f $TEST_IMG.snap
54
+
50
+}
55
+def hd_opts(idx):
51
+trap "_cleanup; exit \$status" 0 1 2 3 15
56
+ return {'driver': iotests.imgfmt,
52
+
57
+ 'node-name': 'hd%d' % idx,
53
+# get standard environment, filters and checks
58
+ 'file': {'driver': 'file',
54
+. ./common.rc
59
+ 'node-name': 'hd%d-file' % idx,
55
+. ./common.filter
60
+ 'filename': hd_path[idx] } }
56
+
61
+
57
+_supported_fmt generic
62
+class TestBlockdevReopen(iotests.QMPTestCase):
58
+_supported_proto file
63
+ total_io_cmds = 0
59
+_supported_os Linux
64
+
60
+
65
+ def setUp(self):
61
+function do_run_qemu()
66
+ qemu_img('create', '-f', iotests.imgfmt, hd_path[0], '3M')
62
+{
67
+ qemu_img('create', '-f', iotests.imgfmt, '-b', hd_path[0], hd_path[1])
63
+ echo Testing: "$@"
68
+ qemu_img('create', '-f', iotests.imgfmt, hd_path[2], '3M')
64
+ (
69
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xa0 0 1M', hd_path[0])
65
+ if ! test -t 0; then
70
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xa1 1M 1M', hd_path[1])
66
+ while read cmd; do
71
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xa2 2M 1M', hd_path[2])
67
+ echo $cmd
72
+ self.vm = iotests.VM()
68
+ done
73
+ self.vm.launch()
69
+ fi
74
+
70
+ echo quit
75
+ def tearDown(self):
71
+ ) | $QEMU -nographic -monitor stdio -nodefaults "$@"
76
+ self.vm.shutdown()
72
+ echo
77
+ self.check_qemu_io_errors()
73
+}
78
+ os.remove(hd_path[0])
74
+
79
+ os.remove(hd_path[1])
75
+function run_qemu()
80
+ os.remove(hd_path[2])
76
+{
81
+
77
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
82
+ # The output of qemu-io is not returned by vm.hmp_qemu_io() but
78
+ _filter_generated_node_ids | _filter_imgfmt
83
+ # it's stored in the log and can only be read when the VM has been
79
+}
84
+ # shut down. This function runs qemu-io and keeps track of the
80
+
85
+ # number of times it's been called.
81
+function run_qemu_info_block()
86
+ def run_qemu_io(self, img, cmd):
82
+{
87
+ result = self.vm.hmp_qemu_io(img, cmd)
83
+ echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
88
+ self.assert_qmp(result, 'return', '')
84
+}
89
+ self.total_io_cmds += 1
85
+
90
+
86
+size=128M
91
+ # Once the VM is shut down we can parse the log and see if qemu-io
87
+
92
+ # ran without errors.
88
+_make_test_img $size
93
+ def check_qemu_io_errors(self):
89
+
94
+ self.assertFalse(self.vm.is_running())
90
+echo
95
+ found = 0
91
+echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
96
+ log = self.vm.get_log()
92
+echo
97
+ for line in log.split("\n"):
93
+
98
+ if line.startswith("Pattern verification failed"):
94
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
99
+ raise Exception("%s (command #%d)" % (line, found))
95
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
100
+ if re.match("read .*/.* bytes at offset", line):
96
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
101
+ found += 1
97
+echo
102
+ self.assertEqual(found, self.total_io_cmds,
98
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
103
+ "Expected output of %d qemu-io commands, found %d" %
99
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
104
+ (found, self.total_io_cmds))
100
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
105
+
101
+echo
106
+ # Run x-blockdev-reopen with 'opts' but applying 'newopts'
102
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
107
+ # on top of it. The original 'opts' dict is unmodified
103
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
108
+ def reopen(self, opts, newopts = {}, errmsg = None):
104
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
109
+ opts = copy.deepcopy(opts)
105
+
110
+
106
+echo
111
+ # Apply the changes from 'newopts' on top of 'opts'
107
+echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
112
+ for key in newopts:
108
+echo
113
+ value = newopts[key]
109
+
114
+ # If key has the form "foo.bar" then we need to do
110
+chmod a-w $TEST_IMG
115
+ # opts["foo"]["bar"] = value, not opts["foo.bar"] = value
111
+
116
+ subdict = opts
112
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
117
+ while key.find('.') != -1:
113
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
118
+ [prefix, key] = key.split('.', 1)
114
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
119
+ subdict = opts[prefix]
115
+echo
120
+ subdict[key] = value
116
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
121
+
117
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
122
+ result = self.vm.qmp('x-blockdev-reopen', conv_keys = False, **opts)
118
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
123
+ if errmsg:
119
+echo
124
+ self.assert_qmp(result, 'error/class', 'GenericError')
120
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
125
+ self.assert_qmp(result, 'error/desc', errmsg)
121
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
126
+ else:
122
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
127
+ self.assert_qmp(result, 'return', {})
123
+
128
+
124
+echo
129
+
125
+echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
130
+ # Run query-named-block-nodes and return the specified entry
126
+echo
131
+ def get_node(self, node_name):
127
+
132
+ result = self.vm.qmp('query-named-block-nodes')
128
+chmod a+w $TEST_IMG
133
+ for node in result['return']:
129
+
134
+ if node['node-name'] == node_name:
130
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
135
+ return node
131
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
136
+ return None
132
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
137
+
133
+echo
138
+ # Run 'query-named-block-nodes' and compare its output with the
134
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
139
+ # value passed by the user in 'graph'
135
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
140
+ def check_node_graph(self, graph):
136
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
141
+ result = self.vm.qmp('query-named-block-nodes')
137
+echo
142
+ self.assertEqual(json.dumps(graph, sort_keys=True),
138
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
143
+ json.dumps(result, sort_keys=True))
139
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
144
+
140
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
145
+ # This test opens one single disk image (without backing files)
141
+
146
+ # and tries to reopen it with illegal / incorrect parameters.
142
+echo
147
+ def test_incorrect_parameters_single_file(self):
143
+echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
148
+ # Open 'hd0' only (no backing files)
144
+echo
149
+ opts = hd_opts(0)
145
+
150
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
146
+chmod a-w $TEST_IMG
151
+ self.assert_qmp(result, 'return', {})
147
+
152
+ original_graph = self.vm.qmp('query-named-block-nodes')
148
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
153
+
149
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
154
+ # We can reopen the image passing the same options
150
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
155
+ self.reopen(opts)
151
+echo
156
+
152
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
157
+ # We can also reopen passing a child reference in 'file'
153
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
158
+ self.reopen(opts, {'file': 'hd0-file'})
154
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
159
+
155
+echo
160
+ # We cannot change any of these
156
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
161
+ self.reopen(opts, {'node-name': 'not-found'}, "Cannot find node named 'not-found'")
157
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
162
+ self.reopen(opts, {'node-name': ''}, "Cannot find node named ''")
158
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
163
+ self.reopen(opts, {'node-name': None}, "Invalid parameter type for 'node-name', expected: string")
159
+
164
+ self.reopen(opts, {'driver': 'raw'}, "Cannot change the option 'driver'")
160
+# success, all done
165
+ self.reopen(opts, {'driver': ''}, "Invalid parameter ''")
161
+echo "*** done"
166
+ self.reopen(opts, {'driver': None}, "Invalid parameter type for 'driver', expected: string")
162
+rm -f $seq.full
167
+ self.reopen(opts, {'file': 'not-found'}, "Cannot change the option 'file'")
163
+status=0
168
+ self.reopen(opts, {'file': ''}, "Cannot change the option 'file'")
164
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
169
+ self.reopen(opts, {'file': None}, "Invalid parameter type for 'file', expected: BlockdevRef")
170
+ self.reopen(opts, {'file.node-name': 'newname'}, "Cannot change the option 'node-name'")
171
+ self.reopen(opts, {'file.driver': 'host_device'}, "Cannot change the option 'driver'")
172
+ self.reopen(opts, {'file.filename': hd_path[1]}, "Cannot change the option 'filename'")
173
+ self.reopen(opts, {'file.aio': 'native'}, "Cannot change the option 'aio'")
174
+ self.reopen(opts, {'file.locking': 'off'}, "Cannot change the option 'locking'")
175
+ self.reopen(opts, {'file.filename': None}, "Invalid parameter type for 'file.filename', expected: string")
176
+
177
+ # node-name is optional in BlockdevOptions, but x-blockdev-reopen needs it
178
+ del opts['node-name']
179
+ self.reopen(opts, {}, "Node name not specified")
180
+
181
+ # Check that nothing has changed
182
+ self.check_node_graph(original_graph)
183
+
184
+ # Remove the node
185
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
186
+ self.assert_qmp(result, 'return', {})
187
+
188
+ # This test opens an image with a backing file and tries to reopen
189
+ # it with illegal / incorrect parameters.
190
+ def test_incorrect_parameters_backing_file(self):
191
+ # Open hd1 omitting the backing options (hd0 will be opened
192
+ # with the default options)
193
+ opts = hd_opts(1)
194
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
195
+ self.assert_qmp(result, 'return', {})
196
+ original_graph = self.vm.qmp('query-named-block-nodes')
197
+
198
+ # We can't reopen the image passing the same options, 'backing' is mandatory
199
+ self.reopen(opts, {}, "backing is missing for 'hd1'")
200
+
201
+ # Everything works if we pass 'backing' using the existing node name
202
+ for node in original_graph['return']:
203
+ if node['drv'] == iotests.imgfmt and node['file'] == hd_path[0]:
204
+ backing_node_name = node['node-name']
205
+ self.reopen(opts, {'backing': backing_node_name})
206
+
207
+ # We can't use a non-existing or empty (non-NULL) node as the backing image
208
+ self.reopen(opts, {'backing': 'not-found'}, "Cannot find device= nor node_name=not-found")
209
+ self.reopen(opts, {'backing': ''}, "Cannot find device= nor node_name=")
210
+
211
+ # We can reopen the image just fine if we specify the backing options
212
+ opts['backing'] = {'driver': iotests.imgfmt,
213
+ 'file': {'driver': 'file',
214
+ 'filename': hd_path[0]}}
215
+ self.reopen(opts)
216
+
217
+ # We cannot change any of these options
218
+ self.reopen(opts, {'backing.node-name': 'newname'}, "Cannot change the option 'node-name'")
219
+ self.reopen(opts, {'backing.driver': 'raw'}, "Cannot change the option 'driver'")
220
+ self.reopen(opts, {'backing.file.node-name': 'newname'}, "Cannot change the option 'node-name'")
221
+ self.reopen(opts, {'backing.file.driver': 'host_device'}, "Cannot change the option 'driver'")
222
+
223
+ # Check that nothing has changed since the beginning
224
+ self.check_node_graph(original_graph)
225
+
226
+ # Remove the node
227
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd1')
228
+ self.assert_qmp(result, 'return', {})
229
+
230
+ # Reopen an image several times changing some of its options
231
+ def test_reopen(self):
232
+ # Open the hd1 image passing all backing options
233
+ opts = hd_opts(1)
234
+ opts['backing'] = hd_opts(0)
235
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
236
+ self.assert_qmp(result, 'return', {})
237
+ original_graph = self.vm.qmp('query-named-block-nodes')
238
+
239
+ # We can reopen the image passing the same options
240
+ self.reopen(opts)
241
+
242
+ # Reopen in read-only mode
243
+ self.assert_qmp(self.get_node('hd1'), 'ro', False)
244
+
245
+ self.reopen(opts, {'read-only': True})
246
+ self.assert_qmp(self.get_node('hd1'), 'ro', True)
247
+ self.reopen(opts)
248
+ self.assert_qmp(self.get_node('hd1'), 'ro', False)
249
+
250
+ # Change the cache options
251
+ self.assert_qmp(self.get_node('hd1'), 'cache/writeback', True)
252
+ self.assert_qmp(self.get_node('hd1'), 'cache/direct', False)
253
+ self.assert_qmp(self.get_node('hd1'), 'cache/no-flush', False)
254
+ self.reopen(opts, {'cache': { 'direct': True, 'no-flush': True }})
255
+ self.assert_qmp(self.get_node('hd1'), 'cache/writeback', True)
256
+ self.assert_qmp(self.get_node('hd1'), 'cache/direct', True)
257
+ self.assert_qmp(self.get_node('hd1'), 'cache/no-flush', True)
258
+
259
+ # Reopen again with the original options
260
+ self.reopen(opts)
261
+ self.assert_qmp(self.get_node('hd1'), 'cache/writeback', True)
262
+ self.assert_qmp(self.get_node('hd1'), 'cache/direct', False)
263
+ self.assert_qmp(self.get_node('hd1'), 'cache/no-flush', False)
264
+
265
+ # Change 'detect-zeroes' and 'discard'
266
+ self.assert_qmp(self.get_node('hd1'), 'detect_zeroes', 'off')
267
+ self.reopen(opts, {'detect-zeroes': 'on'})
268
+ self.assert_qmp(self.get_node('hd1'), 'detect_zeroes', 'on')
269
+ self.reopen(opts, {'detect-zeroes': 'unmap'},
270
+ "setting detect-zeroes to unmap is not allowed " +
271
+ "without setting discard operation to unmap")
272
+ self.assert_qmp(self.get_node('hd1'), 'detect_zeroes', 'on')
273
+ self.reopen(opts, {'detect-zeroes': 'unmap', 'discard': 'unmap'})
274
+ self.assert_qmp(self.get_node('hd1'), 'detect_zeroes', 'unmap')
275
+ self.reopen(opts)
276
+ self.assert_qmp(self.get_node('hd1'), 'detect_zeroes', 'off')
277
+
278
+ # Changing 'force-share' is currently not supported
279
+ self.reopen(opts, {'force-share': True}, "Cannot change the option 'force-share'")
280
+
281
+ # Change some qcow2-specific options
282
+ # No way to test for success other than checking the return message
283
+ if iotests.imgfmt == 'qcow2':
284
+ self.reopen(opts, {'l2-cache-entry-size': 128 * 1024},
285
+ "L2 cache entry size must be a power of two "+
286
+ "between 512 and the cluster size (65536)")
287
+ self.reopen(opts, {'l2-cache-size': 1024 * 1024,
288
+ 'cache-size': 512 * 1024},
289
+ "l2-cache-size may not exceed cache-size")
290
+ self.reopen(opts, {'l2-cache-size': 4 * 1024 * 1024,
291
+ 'refcount-cache-size': 4 * 1024 * 1024,
292
+ 'l2-cache-entry-size': 32 * 1024})
293
+ self.reopen(opts, {'pass-discard-request': True})
294
+
295
+ # Check that nothing has changed since the beginning
296
+ # (from the parameters that we can check)
297
+ self.check_node_graph(original_graph)
298
+
299
+ # Check that the node names (other than the top-level one) are optional
300
+ del opts['file']['node-name']
301
+ del opts['backing']['node-name']
302
+ del opts['backing']['file']['node-name']
303
+ self.reopen(opts)
304
+ self.check_node_graph(original_graph)
305
+
306
+ # Reopen setting backing = null, this removes the backing image from the chain
307
+ self.reopen(opts, {'backing': None})
308
+ self.assert_qmp_absent(self.get_node('hd1'), 'image/backing-image')
309
+
310
+ # Open the 'hd0' image
311
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **hd_opts(0))
312
+ self.assert_qmp(result, 'return', {})
313
+
314
+ # Reopen the hd1 image setting 'hd0' as its backing image
315
+ self.reopen(opts, {'backing': 'hd0'})
316
+ self.assert_qmp(self.get_node('hd1'), 'image/backing-image/filename', hd_path[0])
317
+
318
+ # Check that nothing has changed since the beginning
319
+ self.reopen(hd_opts(0), {'read-only': True})
320
+ self.check_node_graph(original_graph)
321
+
322
+ # The backing file (hd0) is now a reference, we cannot change backing.* anymore
323
+ self.reopen(opts, {}, "Cannot change the option 'backing.driver'")
324
+
325
+ # We can't remove 'hd0' while it's a backing image of 'hd1'
326
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
327
+ self.assert_qmp(result, 'error/class', 'GenericError')
328
+ self.assert_qmp(result, 'error/desc', "Node 'hd0' is busy: node is used as backing hd of 'hd1'")
329
+
330
+ # But we can remove both nodes if done in the proper order
331
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd1')
332
+ self.assert_qmp(result, 'return', {})
333
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
334
+ self.assert_qmp(result, 'return', {})
335
+
336
+ # Reopen a raw image and see the effect of changing the 'offset' option
337
+ def test_reopen_raw(self):
338
+ opts = {'driver': 'raw', 'node-name': 'hd0',
339
+ 'file': { 'driver': 'file',
340
+ 'filename': hd_path[0],
341
+ 'node-name': 'hd0-file' } }
342
+
343
+ # First we create a 2MB raw file, and fill each half with a
344
+ # different value
345
+ qemu_img('create', '-f', 'raw', hd_path[0], '2M')
346
+ qemu_io('-f', 'raw', '-c', 'write -P 0xa0 0 1M', hd_path[0])
347
+ qemu_io('-f', 'raw', '-c', 'write -P 0xa1 1M 1M', hd_path[0])
348
+
349
+ # Open the raw file with QEMU
350
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
351
+ self.assert_qmp(result, 'return', {})
352
+
353
+ # Read 1MB from offset 0
354
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
355
+
356
+ # Reopen the image with a 1MB offset.
357
+ # Now the results are different
358
+ self.reopen(opts, {'offset': 1024*1024})
359
+ self.run_qemu_io("hd0", "read -P 0xa1 0 1M")
360
+
361
+ # Reopen again with the original options.
362
+ # We get the original results again
363
+ self.reopen(opts)
364
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
365
+
366
+ # Remove the block device
367
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
368
+ self.assert_qmp(result, 'return', {})
369
+
370
+ # Omitting an option should reset it to the default value, but if
371
+ # an option cannot be changed it shouldn't be possible to reset it
372
+ # to its default value either
373
+ def test_reset_default_values(self):
374
+ opts = {'driver': 'qcow2', 'node-name': 'hd0',
375
+ 'file': { 'driver': 'file',
376
+ 'filename': hd_path[0],
377
+ 'x-check-cache-dropped': True, # This one can be changed
378
+ 'locking': 'off', # This one can NOT be changed
379
+ 'node-name': 'hd0-file' } }
380
+
381
+ # Open the file with QEMU
382
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
383
+ self.assert_qmp(result, 'return', {})
384
+
385
+ # file.x-check-cache-dropped can be changed...
386
+ self.reopen(opts, { 'file.x-check-cache-dropped': False })
387
+ # ...and dropped completely (resetting to the default value)
388
+ del opts['file']['x-check-cache-dropped']
389
+ self.reopen(opts)
390
+
391
+ # file.locking cannot be changed nor reset to the default value
392
+ self.reopen(opts, { 'file.locking': 'on' }, "Cannot change the option 'locking'")
393
+ del opts['file']['locking']
394
+ self.reopen(opts, {}, "Option 'locking' cannot be reset to its default value")
395
+ # But we can reopen it if we maintain its previous value
396
+ self.reopen(opts, { 'file.locking': 'off' })
397
+
398
+ # Remove the block device
399
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
400
+ self.assert_qmp(result, 'return', {})
401
+
402
+ # This test modifies the node graph a few times by changing the
403
+ # 'backing' option on reopen and verifies that the guest data that
404
+ # is read afterwards is consistent with the graph changes.
405
+ def test_io_with_graph_changes(self):
406
+ opts = []
407
+
408
+ # Open hd0, hd1 and hd2 without any backing image
409
+ for i in range(3):
410
+ opts.append(hd_opts(i))
411
+ opts[i]['backing'] = None
412
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts[i])
413
+ self.assert_qmp(result, 'return', {})
414
+
415
+ # hd0
416
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
417
+ self.run_qemu_io("hd0", "read -P 0 1M 1M")
418
+ self.run_qemu_io("hd0", "read -P 0 2M 1M")
419
+
420
+ # hd1 <- hd0
421
+ self.reopen(opts[0], {'backing': 'hd1'})
422
+
423
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
424
+ self.run_qemu_io("hd0", "read -P 0xa1 1M 1M")
425
+ self.run_qemu_io("hd0", "read -P 0 2M 1M")
426
+
427
+ # hd1 <- hd0 , hd1 <- hd2
428
+ self.reopen(opts[2], {'backing': 'hd1'})
429
+
430
+ self.run_qemu_io("hd2", "read -P 0 0 1M")
431
+ self.run_qemu_io("hd2", "read -P 0xa1 1M 1M")
432
+ self.run_qemu_io("hd2", "read -P 0xa2 2M 1M")
433
+
434
+ # hd1 <- hd2 <- hd0
435
+ self.reopen(opts[0], {'backing': 'hd2'})
436
+
437
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
438
+ self.run_qemu_io("hd0", "read -P 0xa1 1M 1M")
439
+ self.run_qemu_io("hd0", "read -P 0xa2 2M 1M")
440
+
441
+ # hd2 <- hd0
442
+ self.reopen(opts[2], {'backing': None})
443
+
444
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
445
+ self.run_qemu_io("hd0", "read -P 0 1M 1M")
446
+ self.run_qemu_io("hd0", "read -P 0xa2 2M 1M")
447
+
448
+ # hd2 <- hd1 <- hd0
449
+ self.reopen(opts[1], {'backing': 'hd2'})
450
+ self.reopen(opts[0], {'backing': 'hd1'})
451
+
452
+ self.run_qemu_io("hd0", "read -P 0xa0 0 1M")
453
+ self.run_qemu_io("hd0", "read -P 0xa1 1M 1M")
454
+ self.run_qemu_io("hd0", "read -P 0xa2 2M 1M")
455
+
456
+ # Illegal operation: hd2 is a child of hd1
457
+ self.reopen(opts[2], {'backing': 'hd1'},
458
+ "Making 'hd1' a backing file of 'hd2' would create a cycle")
459
+
460
+ # hd2 <- hd0, hd2 <- hd1
461
+ self.reopen(opts[0], {'backing': 'hd2'})
462
+
463
+ self.run_qemu_io("hd1", "read -P 0 0 1M")
464
+ self.run_qemu_io("hd1", "read -P 0xa1 1M 1M")
465
+ self.run_qemu_io("hd1", "read -P 0xa2 2M 1M")
466
+
467
+ # More illegal operations
468
+ self.reopen(opts[2], {'backing': 'hd1'},
469
+ "Making 'hd1' a backing file of 'hd2' would create a cycle")
470
+ self.reopen(opts[2], {'file': 'hd0-file'}, "Cannot change the option 'file'")
471
+
472
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd2')
473
+ self.assert_qmp(result, 'error/class', 'GenericError')
474
+ self.assert_qmp(result, 'error/desc', "Node 'hd2' is busy: node is used as backing hd of 'hd0'")
475
+
476
+ # hd1 doesn't have a backing file now
477
+ self.reopen(opts[1], {'backing': None})
478
+
479
+ self.run_qemu_io("hd1", "read -P 0 0 1M")
480
+ self.run_qemu_io("hd1", "read -P 0xa1 1M 1M")
481
+ self.run_qemu_io("hd1", "read -P 0 2M 1M")
482
+
483
+ # We can't remove the 'backing' option if the image has a
484
+ # default backing file
485
+ del opts[1]['backing']
486
+ self.reopen(opts[1], {}, "backing is missing for 'hd1'")
487
+
488
+ self.run_qemu_io("hd1", "read -P 0 0 1M")
489
+ self.run_qemu_io("hd1", "read -P 0xa1 1M 1M")
490
+ self.run_qemu_io("hd1", "read -P 0 2M 1M")
491
+
492
+ # This test verifies that we can't change the children of a block
493
+ # device during a reopen operation in a way that would create
494
+ # cycles in the node graph
495
+ def test_graph_cycles(self):
496
+ opts = []
497
+
498
+ # Open all three images without backing file
499
+ for i in range(3):
500
+ opts.append(hd_opts(i))
501
+ opts[i]['backing'] = None
502
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts[i])
503
+ self.assert_qmp(result, 'return', {})
504
+
505
+ # hd1 <- hd0, hd1 <- hd2
506
+ self.reopen(opts[0], {'backing': 'hd1'})
507
+ self.reopen(opts[2], {'backing': 'hd1'})
508
+
509
+ # Illegal: hd2 is backed by hd1
510
+ self.reopen(opts[1], {'backing': 'hd2'},
511
+ "Making 'hd2' a backing file of 'hd1' would create a cycle")
512
+
513
+ # hd1 <- hd0 <- hd2
514
+ self.reopen(opts[2], {'backing': 'hd0'})
515
+
516
+ # Illegal: hd2 is backed by hd0, which is backed by hd1
517
+ self.reopen(opts[1], {'backing': 'hd2'},
518
+ "Making 'hd2' a backing file of 'hd1' would create a cycle")
519
+
520
+ # Illegal: hd1 cannot point to itself
521
+ self.reopen(opts[1], {'backing': 'hd1'},
522
+ "Making 'hd1' a backing file of 'hd1' would create a cycle")
523
+
524
+ # Remove all backing files
525
+ self.reopen(opts[0])
526
+ self.reopen(opts[2])
527
+
528
+ ##########################################
529
+ # Add a blkverify node using hd0 and hd1 #
530
+ ##########################################
531
+ bvopts = {'driver': 'blkverify',
532
+ 'node-name': 'bv',
533
+ 'test': 'hd0',
534
+ 'raw': 'hd1'}
535
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **bvopts)
536
+ self.assert_qmp(result, 'return', {})
537
+
538
+ # blkverify doesn't currently allow reopening. TODO: implement this
539
+ self.reopen(bvopts, {}, "Block format 'blkverify' used by node 'bv'" +
540
+ " does not support reopening files")
541
+
542
+ # Illegal: hd0 is a child of the blkverify node
543
+ self.reopen(opts[0], {'backing': 'bv'},
544
+ "Making 'bv' a backing file of 'hd0' would create a cycle")
545
+
546
+ # Delete the blkverify node
547
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'bv')
548
+ self.assert_qmp(result, 'return', {})
549
+
550
+ # Misc reopen tests with different block drivers
551
+ def test_misc_drivers(self):
552
+ ####################
553
+ ###### quorum ######
554
+ ####################
555
+ for i in range(3):
556
+ opts = hd_opts(i)
557
+ # Open all three images without backing file
558
+ opts['backing'] = None
559
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
560
+ self.assert_qmp(result, 'return', {})
561
+
562
+ opts = {'driver': 'quorum',
563
+ 'node-name': 'quorum0',
564
+ 'children': ['hd0', 'hd1', 'hd2'],
565
+ 'vote-threshold': 2}
566
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
567
+ self.assert_qmp(result, 'return', {})
568
+
569
+ # Quorum doesn't currently allow reopening. TODO: implement this
570
+ self.reopen(opts, {}, "Block format 'quorum' used by node 'quorum0'" +
571
+ " does not support reopening files")
572
+
573
+ # You can't make quorum0 a backing file of hd0:
574
+ # hd0 is already a child of quorum0.
575
+ self.reopen(hd_opts(0), {'backing': 'quorum0'},
576
+ "Making 'quorum0' a backing file of 'hd0' would create a cycle")
577
+
578
+ # Delete quorum0
579
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'quorum0')
580
+ self.assert_qmp(result, 'return', {})
581
+
582
+ # Delete hd0, hd1 and hd2
583
+ for i in range(3):
584
+ result = self.vm.qmp('blockdev-del', conv_keys = True,
585
+ node_name = 'hd%d' % i)
586
+ self.assert_qmp(result, 'return', {})
587
+
588
+ ######################
589
+ ###### blkdebug ######
590
+ ######################
591
+ opts = {'driver': 'blkdebug',
592
+ 'node-name': 'bd',
593
+ 'config': '/dev/null',
594
+ 'image': hd_opts(0)}
595
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
596
+ self.assert_qmp(result, 'return', {})
597
+
598
+ # blkdebug allows reopening if we keep the same options
599
+ self.reopen(opts)
600
+
601
+ # but it currently does not allow changes
602
+ self.reopen(opts, {'image': 'hd1'}, "Cannot change the option 'image'")
603
+ self.reopen(opts, {'align': 33554432}, "Cannot change the option 'align'")
604
+ self.reopen(opts, {'config': '/non/existent'}, "Cannot change the option 'config'")
605
+ del opts['config']
606
+ self.reopen(opts, {}, "Option 'config' cannot be reset to its default value")
607
+
608
+ # Delete the blkdebug node
609
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'bd')
610
+ self.assert_qmp(result, 'return', {})
611
+
612
+ ##################
613
+ ###### null ######
614
+ ##################
615
+ opts = {'driver': 'null-aio', 'node-name': 'root', 'size': 1024}
616
+
617
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
618
+ self.assert_qmp(result, 'return', {})
619
+
620
+ # 1 << 30 is the default value, but we cannot change it explicitly
621
+ self.reopen(opts, {'size': (1 << 30)}, "Cannot change the option 'size'")
622
+
623
+ # We cannot change 'size' back to its default value either
624
+ del opts['size']
625
+ self.reopen(opts, {}, "Option 'size' cannot be reset to its default value")
626
+
627
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'root')
628
+ self.assert_qmp(result, 'return', {})
629
+
630
+ ##################
631
+ ###### file ######
632
+ ##################
633
+ opts = hd_opts(0)
634
+ opts['file']['locking'] = 'on'
635
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
636
+ self.assert_qmp(result, 'return', {})
637
+
638
+ # 'locking' cannot be changed
639
+ del opts['file']['locking']
640
+ self.reopen(opts, {'file.locking': 'on'})
641
+ self.reopen(opts, {'file.locking': 'off'}, "Cannot change the option 'locking'")
642
+ self.reopen(opts, {}, "Option 'locking' cannot be reset to its default value")
643
+
644
+ # Trying to reopen the 'file' node directly does not make a difference
645
+ opts = opts['file']
646
+ self.reopen(opts, {'locking': 'on'})
647
+ self.reopen(opts, {'locking': 'off'}, "Cannot change the option 'locking'")
648
+ self.reopen(opts, {}, "Option 'locking' cannot be reset to its default value")
649
+
650
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
651
+ self.assert_qmp(result, 'return', {})
652
+
653
+ ######################
654
+ ###### throttle ######
655
+ ######################
656
+ opts = { 'qom-type': 'throttle-group', 'id': 'group0',
657
+ 'props': { 'limits': { 'iops-total': 1000 } } }
658
+ result = self.vm.qmp('object-add', conv_keys = False, **opts)
659
+ self.assert_qmp(result, 'return', {})
660
+
661
+ opts = { 'qom-type': 'throttle-group', 'id': 'group1',
662
+ 'props': { 'limits': { 'iops-total': 2000 } } }
663
+ result = self.vm.qmp('object-add', conv_keys = False, **opts)
664
+ self.assert_qmp(result, 'return', {})
665
+
666
+ # Add a throttle filter with group = group0
667
+ opts = { 'driver': 'throttle', 'node-name': 'throttle0',
668
+ 'throttle-group': 'group0', 'file': hd_opts(0) }
669
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
670
+ self.assert_qmp(result, 'return', {})
671
+
672
+ # We can reopen it if we keep the same options
673
+ self.reopen(opts)
674
+
675
+ # We can also reopen if 'file' is a reference to the child
676
+ self.reopen(opts, {'file': 'hd0'})
677
+
678
+ # This is illegal
679
+ self.reopen(opts, {'throttle-group': 'notfound'}, "Throttle group 'notfound' does not exist")
680
+
681
+ # But it's possible to change the group to group1
682
+ self.reopen(opts, {'throttle-group': 'group1'})
683
+
684
+ # Now group1 is in use, it cannot be deleted
685
+ result = self.vm.qmp('object-del', id = 'group1')
686
+ self.assert_qmp(result, 'error/class', 'GenericError')
687
+ self.assert_qmp(result, 'error/desc', "object 'group1' is in use, can not be deleted")
688
+
689
+ # Default options, this switches the group back to group0
690
+ self.reopen(opts)
691
+
692
+ # So now we cannot delete group0
693
+ result = self.vm.qmp('object-del', id = 'group0')
694
+ self.assert_qmp(result, 'error/class', 'GenericError')
695
+ self.assert_qmp(result, 'error/desc', "object 'group0' is in use, can not be deleted")
696
+
697
+ # But group1 is free this time, and it can be deleted
698
+ result = self.vm.qmp('object-del', id = 'group1')
699
+ self.assert_qmp(result, 'return', {})
700
+
701
+ # Let's delete the filter node
702
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'throttle0')
703
+ self.assert_qmp(result, 'return', {})
704
+
705
+ # And we can finally get rid of group0
706
+ result = self.vm.qmp('object-del', id = 'group0')
707
+ self.assert_qmp(result, 'return', {})
708
+
709
+ # If an image has a backing file then the 'backing' option must be
710
+ # passed on reopen. We don't allow leaving the option out in this
711
+ # case because it's unclear what the correct semantics would be.
712
+ def test_missing_backing_options_1(self):
713
+ # hd2
714
+ opts = hd_opts(2)
715
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
716
+ self.assert_qmp(result, 'return', {})
717
+
718
+ # hd0
719
+ opts = hd_opts(0)
720
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
721
+ self.assert_qmp(result, 'return', {})
722
+
723
+ # hd0 has no backing file: we can omit the 'backing' option
724
+ self.reopen(opts)
725
+
726
+ # hd2 <- hd0
727
+ self.reopen(opts, {'backing': 'hd2'})
728
+
729
+ # hd0 has a backing file: we must set the 'backing' option
730
+ self.reopen(opts, {}, "backing is missing for 'hd0'")
731
+
732
+ # hd2 can't be removed because it's the backing file of hd0
733
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd2')
734
+ self.assert_qmp(result, 'error/class', 'GenericError')
735
+ self.assert_qmp(result, 'error/desc', "Node 'hd2' is busy: node is used as backing hd of 'hd0'")
736
+
737
+ # Detach hd2 from hd0.
738
+ self.reopen(opts, {'backing': None})
739
+ self.reopen(opts, {}, "backing is missing for 'hd0'")
740
+
741
+ # Remove both hd0 and hd2
742
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
743
+ self.assert_qmp(result, 'return', {})
744
+
745
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd2')
746
+ self.assert_qmp(result, 'return', {})
747
+
748
+ # If an image has default backing file (as part of its metadata)
749
+ # then the 'backing' option must be passed on reopen. We don't
750
+ # allow leaving the option out in this case because it's unclear
751
+ # what the correct semantics would be.
752
+ def test_missing_backing_options_2(self):
753
+ # hd0 <- hd1
754
+ # (hd0 is hd1's default backing file)
755
+ opts = hd_opts(1)
756
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
757
+ self.assert_qmp(result, 'return', {})
758
+
759
+ # hd1 has a backing file: we can't omit the 'backing' option
760
+ self.reopen(opts, {}, "backing is missing for 'hd1'")
761
+
762
+ # Let's detach the backing file
763
+ self.reopen(opts, {'backing': None})
764
+
765
+ # No backing file attached to hd1 now, but we still can't omit the 'backing' option
766
+ self.reopen(opts, {}, "backing is missing for 'hd1'")
767
+
768
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd1')
769
+ self.assert_qmp(result, 'return', {})
770
+
771
+ # Test that making 'backing' a reference to an existing child
772
+ # keeps its current options
773
+ def test_backing_reference(self):
774
+ # hd2 <- hd1 <- hd0
775
+ opts = hd_opts(0)
776
+ opts['backing'] = hd_opts(1)
777
+ opts['backing']['backing'] = hd_opts(2)
778
+ # Enable 'detect-zeroes' on all three nodes
779
+ opts['detect-zeroes'] = 'on'
780
+ opts['backing']['detect-zeroes'] = 'on'
781
+ opts['backing']['backing']['detect-zeroes'] = 'on'
782
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
783
+ self.assert_qmp(result, 'return', {})
784
+
785
+ # Reopen the chain passing the minimum amount of required options.
786
+ # By making 'backing' a reference to hd1 (instead of a sub-dict)
787
+ # we tell QEMU to keep its current set of options.
788
+ opts = {'driver': iotests.imgfmt,
789
+ 'node-name': 'hd0',
790
+ 'file': 'hd0-file',
791
+ 'backing': 'hd1' }
792
+ self.reopen(opts)
793
+
794
+ # This has reset 'detect-zeroes' on hd0, but not on hd1 and hd2.
795
+ self.assert_qmp(self.get_node('hd0'), 'detect_zeroes', 'off')
796
+ self.assert_qmp(self.get_node('hd1'), 'detect_zeroes', 'on')
797
+ self.assert_qmp(self.get_node('hd2'), 'detect_zeroes', 'on')
798
+
799
+ # Test what happens if the graph changes due to other operations
800
+ # such as block-stream
801
+ def test_block_stream_1(self):
802
+ # hd1 <- hd0
803
+ opts = hd_opts(0)
804
+ opts['backing'] = hd_opts(1)
805
+ opts['backing']['backing'] = None
806
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
807
+ self.assert_qmp(result, 'return', {})
808
+
809
+ # Stream hd1 into hd0 and wait until it's done
810
+ result = self.vm.qmp('block-stream', conv_keys = True, job_id = 'stream0', device = 'hd0')
811
+ self.assert_qmp(result, 'return', {})
812
+ self.wait_until_completed(drive = 'stream0')
813
+
814
+ # Now we have only hd0
815
+ self.assertEqual(self.get_node('hd1'), None)
816
+
817
+ # We have backing.* options but there's no backing file anymore
818
+ self.reopen(opts, {}, "Cannot change the option 'backing.driver'")
819
+
820
+ # If we remove the 'backing' option then we can reopen hd0 just fine
821
+ del opts['backing']
822
+ self.reopen(opts)
823
+
824
+ # We can also reopen hd0 if we set 'backing' to null
825
+ self.reopen(opts, {'backing': None})
826
+
827
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
828
+ self.assert_qmp(result, 'return', {})
829
+
830
+ # Another block_stream test
831
+ def test_block_stream_2(self):
832
+ # hd2 <- hd1 <- hd0
833
+ opts = hd_opts(0)
834
+ opts['backing'] = hd_opts(1)
835
+ opts['backing']['backing'] = hd_opts(2)
836
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
837
+ self.assert_qmp(result, 'return', {})
838
+
839
+ # Stream hd1 into hd0 and wait until it's done
840
+ result = self.vm.qmp('block-stream', conv_keys = True, job_id = 'stream0',
841
+ device = 'hd0', base_node = 'hd2')
842
+ self.assert_qmp(result, 'return', {})
843
+ self.wait_until_completed(drive = 'stream0')
844
+
845
+ # The chain is hd2 <- hd0 now. hd1 is missing
846
+ self.assertEqual(self.get_node('hd1'), None)
847
+
848
+ # The backing options in the dict were meant for hd1, but we cannot
849
+ # use them with hd2 because hd1 had a backing file while hd2 does not.
850
+ self.reopen(opts, {}, "Cannot change the option 'backing.driver'")
851
+
852
+ # If we remove hd1's options from the dict then things work fine
853
+ opts['backing'] = opts['backing']['backing']
854
+ self.reopen(opts)
855
+
856
+ # We can also reopen hd0 if we use a reference to the backing file
857
+ self.reopen(opts, {'backing': 'hd2'})
858
+
859
+ # But we cannot leave the option out
860
+ del opts['backing']
861
+ self.reopen(opts, {}, "backing is missing for 'hd0'")
862
+
863
+ # Now we can delete hd0 (and hd2)
864
+ result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
865
+ self.assert_qmp(result, 'return', {})
866
+ self.assertEqual(self.get_node('hd2'), None)
867
+
868
+ # Reopen the chain during a block-stream job (from hd1 to hd0)
869
+ def test_block_stream_3(self):
870
+ # hd2 <- hd1 <- hd0
871
+ opts = hd_opts(0)
872
+ opts['backing'] = hd_opts(1)
873
+ opts['backing']['backing'] = hd_opts(2)
874
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
875
+ self.assert_qmp(result, 'return', {})
876
+
877
+ # hd2 <- hd0
878
+ result = self.vm.qmp('block-stream', conv_keys = True, job_id = 'stream0',
879
+ device = 'hd0', base_node = 'hd2', speed = 512 * 1024)
880
+ self.assert_qmp(result, 'return', {})
881
+
882
+ # We can't remove hd2 while the stream job is ongoing
883
+ opts['backing']['backing'] = None
884
+ self.reopen(opts, {}, "Cannot change 'backing' link from 'hd1' to 'hd2'")
885
+
886
+ # We can't remove hd1 while the stream job is ongoing
887
+ opts['backing'] = None
888
+ self.reopen(opts, {}, "Cannot change 'backing' link from 'hd0' to 'hd1'")
889
+
890
+ self.wait_until_completed(drive = 'stream0')
891
+
892
+ # Reopen the chain during a block-stream job (from hd2 to hd1)
893
+ def test_block_stream_4(self):
894
+ # hd2 <- hd1 <- hd0
895
+ opts = hd_opts(0)
896
+ opts['backing'] = hd_opts(1)
897
+ opts['backing']['backing'] = hd_opts(2)
898
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
899
+ self.assert_qmp(result, 'return', {})
900
+
901
+ # hd1 <- hd0
902
+ result = self.vm.qmp('block-stream', conv_keys = True, job_id = 'stream0',
903
+ device = 'hd1', speed = 512 * 1024)
904
+ self.assert_qmp(result, 'return', {})
905
+
906
+ # We can't reopen with the original options because that would
907
+ # make hd1 read-only and block-stream requires it to be read-write
908
+ self.reopen(opts, {}, "Can't set node 'hd1' to r/o with copy-on-read enabled")
909
+
910
+ # We can't remove hd2 while the stream job is ongoing
911
+ opts['backing']['backing'] = None
912
+ self.reopen(opts, {'backing.read-only': False}, "Cannot change 'backing' link from 'hd1' to 'hd2'")
913
+
914
+ # We can detach hd1 from hd0 because it doesn't affect the stream job
915
+ opts['backing'] = None
916
+ self.reopen(opts)
917
+
918
+ self.wait_until_completed(drive = 'stream0')
919
+
920
+ # Reopen the chain during a block-commit job (from hd0 to hd2)
921
+ def test_block_commit_1(self):
922
+ # hd2 <- hd1 <- hd0
923
+ opts = hd_opts(0)
924
+ opts['backing'] = hd_opts(1)
925
+ opts['backing']['backing'] = hd_opts(2)
926
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
927
+ self.assert_qmp(result, 'return', {})
928
+
929
+ result = self.vm.qmp('block-commit', conv_keys = True, job_id = 'commit0',
930
+ device = 'hd0', speed = 1024 * 1024)
931
+ self.assert_qmp(result, 'return', {})
932
+
933
+ # We can't remove hd2 while the commit job is ongoing
934
+ opts['backing']['backing'] = None
935
+ self.reopen(opts, {}, "Cannot change 'backing' link from 'hd1' to 'hd2'")
936
+
937
+ # We can't remove hd1 while the commit job is ongoing
938
+ opts['backing'] = None
939
+ self.reopen(opts, {}, "Cannot change 'backing' link from 'hd0' to 'hd1'")
940
+
941
+ event = self.vm.event_wait(name='BLOCK_JOB_READY')
942
+ self.assert_qmp(event, 'data/device', 'commit0')
943
+ self.assert_qmp(event, 'data/type', 'commit')
944
+ self.assert_qmp_absent(event, 'data/error')
945
+
946
+ result = self.vm.qmp('block-job-complete', device='commit0')
947
+ self.assert_qmp(result, 'return', {})
948
+
949
+ self.wait_until_completed(drive = 'commit0')
950
+
951
+ # Reopen the chain during a block-commit job (from hd1 to hd2)
952
+ def test_block_commit_2(self):
953
+ # hd2 <- hd1 <- hd0
954
+ opts = hd_opts(0)
955
+ opts['backing'] = hd_opts(1)
956
+ opts['backing']['backing'] = hd_opts(2)
957
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
958
+ self.assert_qmp(result, 'return', {})
959
+
960
+ result = self.vm.qmp('block-commit', conv_keys = True, job_id = 'commit0',
961
+ device = 'hd0', top_node = 'hd1', speed = 1024 * 1024)
962
+ self.assert_qmp(result, 'return', {})
963
+
964
+ # We can't remove hd2 while the commit job is ongoing
965
+ opts['backing']['backing'] = None
966
+ self.reopen(opts, {}, "Cannot change the option 'backing.driver'")
967
+
968
+ # We can't remove hd1 while the commit job is ongoing
969
+ opts['backing'] = None
970
+ self.reopen(opts, {}, "Cannot change backing link if 'hd0' has an implicit backing file")
971
+
972
+ # hd2 <- hd0
973
+ self.wait_until_completed(drive = 'commit0')
974
+
975
+ self.assert_qmp(self.get_node('hd0'), 'ro', False)
976
+ self.assertEqual(self.get_node('hd1'), None)
977
+ self.assert_qmp(self.get_node('hd2'), 'ro', True)
978
+
979
+ # We don't allow setting a backing file that uses a different AioContext
980
+ def test_iothreads(self):
981
+ opts = hd_opts(0)
982
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
983
+ self.assert_qmp(result, 'return', {})
984
+
985
+ opts2 = hd_opts(2)
986
+ result = self.vm.qmp('blockdev-add', conv_keys = False, **opts2)
987
+ self.assert_qmp(result, 'return', {})
988
+
989
+ result = self.vm.qmp('object-add', qom_type='iothread', id='iothread0')
990
+ self.assert_qmp(result, 'return', {})
991
+
992
+ result = self.vm.qmp('object-add', qom_type='iothread', id='iothread1')
993
+ self.assert_qmp(result, 'return', {})
994
+
995
+ result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd0', iothread='iothread0')
996
+ self.assert_qmp(result, 'return', {})
997
+
998
+ self.reopen(opts, {'backing': 'hd2'}, "Cannot use a new backing file with a different AioContext")
999
+
1000
+ result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd2', iothread='iothread1')
1001
+ self.assert_qmp(result, 'return', {})
1002
+
1003
+ self.reopen(opts, {'backing': 'hd2'}, "Cannot use a new backing file with a different AioContext")
1004
+
1005
+ result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd2', iothread='iothread0')
1006
+ self.assert_qmp(result, 'return', {})
1007
+
1008
+ self.reopen(opts, {'backing': 'hd2'})
1009
+
1010
+if __name__ == '__main__':
1011
+ iotests.main(supported_fmts=["qcow2"])
1012
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
165
new file mode 100644
1013
new file mode 100644
166
index XXXXXXX..XXXXXXX
1014
index XXXXXXX..XXXXXXX
167
--- /dev/null
1015
--- /dev/null
168
+++ b/tests/qemu-iotests/232.out
1016
+++ b/tests/qemu-iotests/245.out
169
@@ -XXX,XX +XXX,XX @@
1017
@@ -XXX,XX +XXX,XX @@
170
+QA output created by 232
1018
+..................
171
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
1019
+----------------------------------------------------------------------
172
+
1020
+Ran 18 tests
173
+=== -drive with read-write image: read-only/auto-read-only combinations ===
1021
+
174
+
1022
+OK
175
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
176
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
177
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
178
+
179
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
180
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
181
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
182
+
183
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
184
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
185
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
186
+
187
+=== -drive with read-only image: read-only/auto-read-only combinations ===
188
+
189
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
190
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
191
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
192
+
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
194
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
195
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
196
+
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
198
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
199
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
200
+
201
+=== -blockdev with read-write image: read-only/auto-read-only combinations ===
202
+
203
+node0: TEST_DIR/t.IMGFMT (file, read-only)
204
+node0: TEST_DIR/t.IMGFMT (file, read-only)
205
+node0: TEST_DIR/t.IMGFMT (file, read-only)
206
+
207
+node0: TEST_DIR/t.IMGFMT (file)
208
+node0: TEST_DIR/t.IMGFMT (file)
209
+node0: TEST_DIR/t.IMGFMT (file)
210
+
211
+node0: TEST_DIR/t.IMGFMT (file)
212
+node0: TEST_DIR/t.IMGFMT (file)
213
+node0: TEST_DIR/t.IMGFMT (file)
214
+
215
+=== -blockdev with read-only image: read-only/auto-read-only combinations ===
216
+
217
+node0: TEST_DIR/t.IMGFMT (file, read-only)
218
+node0: TEST_DIR/t.IMGFMT (file, read-only)
219
+node0: TEST_DIR/t.IMGFMT (file, read-only)
220
+
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
222
+node0: TEST_DIR/t.IMGFMT (file, read-only)
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
224
+
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
226
+node0: TEST_DIR/t.IMGFMT (file, read-only)
227
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
228
+*** done
229
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
1023
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
230
index XXXXXXX..XXXXXXX 100644
1024
index XXXXXXX..XXXXXXX 100644
231
--- a/tests/qemu-iotests/group
1025
--- a/tests/qemu-iotests/group
232
+++ b/tests/qemu-iotests/group
1026
+++ b/tests/qemu-iotests/group
233
@@ -XXX,XX +XXX,XX @@
1027
@@ -XXX,XX +XXX,XX @@
234
227 auto quick
1028
242 rw auto quick
235
229 auto quick
1029
243 rw auto quick
236
231 auto quick
1030
244 rw auto quick
237
+232 auto quick
1031
+245 rw auto
238
--
1032
--
239
2.19.1
1033
2.20.1
240
1034
241
1035
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Just like in qemu_opts_print_help(), print the object 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.
6
7
Also, indent every object name in the list of available objects.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
vl.c | 13 ++++++++++---
14
1 file changed, 10 insertions(+), 3 deletions(-)
15
16
diff --git a/vl.c b/vl.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/vl.c
19
+++ b/vl.c
20
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
21
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
22
for (l = list; l != NULL; l = l->next) {
23
ObjectClass *oc = OBJECT_CLASS(l->data);
24
- printf("%s\n", object_class_get_name(oc));
25
+ printf(" %s\n", object_class_get_name(oc));
26
}
27
g_slist_free(list);
28
exit(0);
29
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
30
}
31
32
str = g_string_new(NULL);
33
- g_string_append_printf(str, "%s.%s=%s", type,
34
- prop->name, prop->type);
35
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
36
if (prop->description) {
37
+ if (str->len < 24) {
38
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
39
+ }
40
g_string_append_printf(str, " - %s", prop->description);
41
}
42
g_ptr_array_add(array, g_string_free(str, false));
43
}
44
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
45
+ if (array->len > 0) {
46
+ printf("%s options:\n", type);
47
+ } else {
48
+ printf("There are no options for %s.\n", type);
49
+ }
50
for (i = 0; i < array->len; i++) {
51
printf("%s\n", (char *)array->pdata[i]);
52
}
53
--
54
2.19.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
There is no good reason why there should be a newline in this
4
description, so remove it.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
vl.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/vl.c b/vl.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/vl.c
17
+++ b/vl.c
18
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_fw_cfg_opts = {
19
}, {
20
.name = "file",
21
.type = QEMU_OPT_STRING,
22
- .help = "Sets the name of the file from which\n"
23
+ .help = "Sets the name of the file from which "
24
"the fw_cfg blob will be loaded",
25
}, {
26
.name = "string",
27
--
28
2.19.1
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Leonid Bloch <lbloch@janustech.com>
2
1
3
If an expression is used to define DEFAULT_CLUSTER_SIZE, when compiled,
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.
7
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
9
Reviewed-by: Stefan Weil <sw@weilnetz.de>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/vdi.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/block/vdi.c b/block/vdi.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/vdi.c
18
+++ b/block/vdi.c
19
@@ -XXX,XX +XXX,XX @@
20
#define BLOCK_OPT_STATIC "static"
21
22
#define SECTOR_SIZE 512
23
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
24
+#define DEFAULT_CLUSTER_SIZE S_1MiB
25
26
#if defined(CONFIG_VDI_DEBUG)
27
#define VDI_DEBUG 1
28
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
29
goto fail;
30
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
31
error_setg(errp, "unsupported VDI image (block size %" PRIu32
32
- " is not %" PRIu64 ")",
33
+ " is not %" PRIu32 ")",
34
header.block_size, DEFAULT_CLUSTER_SIZE);
35
ret = -ENOTSUP;
36
goto fail;
37
--
38
2.19.1
39
40
diff view generated by jsdifflib