1 | The following changes since commit 1e3ee834083227f552179f6e43902cba5a866e6b: | 1 | The following changes since commit 86f4c7e05b1c44dbe1b329a51f311f10aef6ff34: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging (2017-09-25 20:31:24 +0100) | 3 | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180302' into staging (2018-03-02 14:37:10 +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 b156d51b62e6970753e1f9f36f7c4d5fdbf4c619: | 9 | for you to fetch changes up to bfe1a14c180ec44c033be12b9151252ffda69292: |
10 | 10 | ||
11 | Merge remote-tracking branch 'mreitz/tags/pull-block-2017-09-26' into queue-block (2017-09-26 15:03:02 +0200) | 11 | block: Fix NULL dereference on empty drive error (2018-03-05 18:45:32 +0100) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block layer patches | 14 | Block layer patches |
15 | 15 | ||
16 | ---------------------------------------------------------------- | 16 | ---------------------------------------------------------------- |
17 | Alberto Garcia (1): | 17 | Alberto Garcia (3): |
18 | throttle: Assert that bkt->max is valid in throttle_compute_wait() | 18 | specs/qcow2: Fix documentation of the compressed cluster descriptor |
19 | docs: document how to use the l2-cache-entry-size parameter | ||
20 | qcow2: Replace align_offset() with ROUND_UP() | ||
19 | 21 | ||
20 | Cornelia Huck (3): | 22 | Anton Nefedov (2): |
21 | iotests: use -ccw on s390x for 040, 139, and 182 | 23 | block: fix write with zero flag set and iovector provided |
22 | iotests: use -ccw on s390x for 051 | 24 | iotest 033: add misaligned write-zeroes test via truncate |
23 | iotests: use virtio aliases for 067 | ||
24 | 25 | ||
25 | Fam Zheng (3): | 26 | Eric Blake (21): |
26 | qemu-img: Clarify about relative backing file options | 27 | block: Add .bdrv_co_block_status() callback |
27 | file-posix: Clear out first sector in hdev_create | 28 | nvme: Drop pointless .bdrv_co_get_block_status() |
28 | iotests: Print full path of bad output if mismatch | 29 | block: Switch passthrough drivers to .bdrv_co_block_status() |
30 | file-posix: Switch to .bdrv_co_block_status() | ||
31 | gluster: Switch to .bdrv_co_block_status() | ||
32 | iscsi: Switch cluster_sectors to byte-based | ||
33 | iscsi: Switch iscsi_allocmap_update() to byte-based | ||
34 | iscsi: Switch to .bdrv_co_block_status() | ||
35 | null: Switch to .bdrv_co_block_status() | ||
36 | parallels: Switch to .bdrv_co_block_status() | ||
37 | qcow: Switch to .bdrv_co_block_status() | ||
38 | qcow2: Switch to .bdrv_co_block_status() | ||
39 | qed: Switch to .bdrv_co_block_status() | ||
40 | raw: Switch to .bdrv_co_block_status() | ||
41 | sheepdog: Switch to .bdrv_co_block_status() | ||
42 | vdi: Avoid bitrot of debugging code | ||
43 | vdi: Switch to .bdrv_co_block_status() | ||
44 | vmdk: Switch to .bdrv_co_block_status() | ||
45 | vpc: Switch to .bdrv_co_block_status() | ||
46 | vvfat: Switch to .bdrv_co_block_status() | ||
47 | block: Drop unused .bdrv_co_get_block_status() | ||
29 | 48 | ||
30 | Kevin Wolf (9): | 49 | Kevin Wolf (3): |
31 | qemu-iotests: Add missing -machine accel=qtest | 50 | block: test blk_aio_flush() with blk->root == NULL |
32 | qemu-io: Drop write permissions before read-only reopen | 51 | Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-02' into queue-block |
33 | block: Add reopen_queue to bdrv_child_perm() | 52 | block: Fix NULL dereference on empty drive error |
34 | block: Add reopen queue to bdrv_check_perm() | ||
35 | block: Base permissions on rw state after reopen | ||
36 | block: reopen: Queue children after their parents | ||
37 | block: Fix permissions after bdrv_reopen() | ||
38 | qemu-iotests: Test change-backing-file command | ||
39 | Merge remote-tracking branch 'mreitz/tags/pull-block-2017-09-26' into queue-block | ||
40 | 53 | ||
41 | Manos Pitsidianakis (1): | 54 | Max Reitz (4): |
42 | block/throttle-groups.c: allocate RestartData on the heap | 55 | qemu-img: Make resize error message more general |
56 | block/ssh: Pull ssh_grow_file() from ssh_create() | ||
57 | block/ssh: Make ssh_grow_file() blocking | ||
58 | block/ssh: Add basic .bdrv_truncate() | ||
43 | 59 | ||
44 | Pavel Butsykin (4): | 60 | Stefan Hajnoczi (6): |
45 | qemu-img: add --shrink flag for resize | 61 | aio: rename aio_context_in_iothread() to in_aio_context_home_thread() |
46 | qcow2: add qcow2_cache_discard | 62 | block: extract AIO_WAIT_WHILE() from BlockDriverState |
47 | qcow2: add shrink image support | 63 | block: add BlockBackend->in_flight counter |
48 | qemu-iotests: add shrinking image test | 64 | Revert "IDE: Do not flush empty CDROM drives" |
65 | block: rename .bdrv_create() to .bdrv_co_create_opts() | ||
66 | qcow2: make qcow2_co_create2() a coroutine_fn | ||
49 | 67 | ||
50 | Stefan Hajnoczi (1): | 68 | qapi/block-core.json | 6 +- |
51 | docs: add qemu-block-drivers(7) man page | 69 | docs/interop/qcow2.txt | 16 ++++- |
70 | docs/qcow2-cache.txt | 46 ++++++++++++- | ||
71 | block/qcow2.h | 6 -- | ||
72 | include/block/aio-wait.h | 116 ++++++++++++++++++++++++++++++++ | ||
73 | include/block/aio.h | 7 +- | ||
74 | include/block/block.h | 54 ++++----------- | ||
75 | include/block/block_int.h | 61 ++++++++++------- | ||
76 | block.c | 11 ++- | ||
77 | block/blkdebug.c | 20 +++--- | ||
78 | block/block-backend.c | 65 +++++++++++++++--- | ||
79 | block/commit.c | 2 +- | ||
80 | block/crypto.c | 8 +-- | ||
81 | block/file-posix.c | 79 +++++++++++----------- | ||
82 | block/file-win32.c | 5 +- | ||
83 | block/gluster.c | 83 ++++++++++++----------- | ||
84 | block/io.c | 98 +++++++++++---------------- | ||
85 | block/iscsi.c | 164 ++++++++++++++++++++++++--------------------- | ||
86 | block/mirror.c | 2 +- | ||
87 | block/nfs.c | 5 +- | ||
88 | block/null.c | 23 ++++--- | ||
89 | block/nvme.c | 14 ---- | ||
90 | block/parallels.c | 28 +++++--- | ||
91 | block/qcow.c | 32 +++++---- | ||
92 | block/qcow2-bitmap.c | 4 +- | ||
93 | block/qcow2-cluster.c | 4 +- | ||
94 | block/qcow2-refcount.c | 4 +- | ||
95 | block/qcow2-snapshot.c | 10 +-- | ||
96 | block/qcow2.c | 60 +++++++++-------- | ||
97 | block/qed.c | 82 ++++++++--------------- | ||
98 | block/raw-format.c | 21 +++--- | ||
99 | block/rbd.c | 6 +- | ||
100 | block/sheepdog.c | 36 +++++----- | ||
101 | block/ssh.c | 66 +++++++++++++++--- | ||
102 | block/throttle.c | 2 +- | ||
103 | block/vdi.c | 50 +++++++------- | ||
104 | block/vhdx.c | 5 +- | ||
105 | block/vmdk.c | 43 +++++------- | ||
106 | block/vpc.c | 50 +++++++------- | ||
107 | block/vvfat.c | 16 ++--- | ||
108 | hw/ide/core.c | 10 +-- | ||
109 | qemu-img.c | 2 +- | ||
110 | tests/test-block-backend.c | 82 +++++++++++++++++++++++ | ||
111 | util/aio-wait.c | 40 +++++++++++ | ||
112 | tests/Makefile.include | 2 + | ||
113 | tests/qemu-iotests/033 | 29 ++++++++ | ||
114 | tests/qemu-iotests/033.out | 13 ++++ | ||
115 | util/Makefile.objs | 2 +- | ||
116 | 48 files changed, 980 insertions(+), 610 deletions(-) | ||
117 | create mode 100644 include/block/aio-wait.h | ||
118 | create mode 100644 tests/test-block-backend.c | ||
119 | create mode 100644 util/aio-wait.c | ||
52 | 120 | ||
53 | Thomas Huth (1): | ||
54 | block: Clean up some bad code in the vvfat driver | ||
55 | |||
56 | Vladimir Sementsov-Ogievskiy (2): | ||
57 | iotests: fix 181: enable postcopy-ram capability on target | ||
58 | block/qcow2-bitmap: fix use of uninitialized pointer | ||
59 | |||
60 | qapi/block-core.json | 8 +- | ||
61 | block/qcow2.h | 17 + | ||
62 | include/block/block.h | 2 +- | ||
63 | include/block/block_int.h | 7 + | ||
64 | block.c | 191 +++++++--- | ||
65 | block/commit.c | 1 + | ||
66 | block/file-posix.c | 10 + | ||
67 | block/mirror.c | 1 + | ||
68 | block/qcow2-bitmap.c | 2 +- | ||
69 | block/qcow2-cache.c | 26 ++ | ||
70 | block/qcow2-cluster.c | 50 +++ | ||
71 | block/qcow2-refcount.c | 140 +++++++- | ||
72 | block/qcow2.c | 43 ++- | ||
73 | block/replication.c | 1 + | ||
74 | block/throttle-groups.c | 12 +- | ||
75 | block/vvfat.c | 27 +- | ||
76 | qemu-img.c | 23 ++ | ||
77 | qemu-io-cmds.c | 12 + | ||
78 | util/throttle.c | 1 + | ||
79 | Makefile | 6 +- | ||
80 | docs/qemu-block-drivers.texi | 804 ++++++++++++++++++++++++++++++++++++++++++ | ||
81 | qemu-doc.texi | 781 +--------------------------------------- | ||
82 | qemu-img-cmds.hx | 4 +- | ||
83 | qemu-img.texi | 15 +- | ||
84 | tests/qemu-iotests/040 | 6 +- | ||
85 | tests/qemu-iotests/051 | 12 +- | ||
86 | tests/qemu-iotests/051.out | 2 +- | ||
87 | tests/qemu-iotests/051.pc.out | 2 +- | ||
88 | tests/qemu-iotests/067 | 2 +- | ||
89 | tests/qemu-iotests/067.out | 2 +- | ||
90 | tests/qemu-iotests/102 | 4 +- | ||
91 | tests/qemu-iotests/106 | 2 +- | ||
92 | tests/qemu-iotests/139 | 12 +- | ||
93 | tests/qemu-iotests/163 | 170 +++++++++ | ||
94 | tests/qemu-iotests/163.out | 5 + | ||
95 | tests/qemu-iotests/172 | 2 +- | ||
96 | tests/qemu-iotests/181 | 2 + | ||
97 | tests/qemu-iotests/181.out | 1 - | ||
98 | tests/qemu-iotests/182 | 13 +- | ||
99 | tests/qemu-iotests/186 | 6 +- | ||
100 | tests/qemu-iotests/187.out | 2 +- | ||
101 | tests/qemu-iotests/195 | 92 +++++ | ||
102 | tests/qemu-iotests/195.out | 78 ++++ | ||
103 | tests/qemu-iotests/check | 2 +- | ||
104 | tests/qemu-iotests/group | 2 + | ||
105 | 45 files changed, 1708 insertions(+), 895 deletions(-) | ||
106 | create mode 100644 docs/qemu-block-drivers.texi | ||
107 | create mode 100644 tests/qemu-iotests/163 | ||
108 | create mode 100644 tests/qemu-iotests/163.out | ||
109 | create mode 100755 tests/qemu-iotests/195 | ||
110 | create mode 100644 tests/qemu-iotests/195.out | ||
111 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | A basic set of qemu options is initialised in ./common: | ||
2 | 1 | ||
3 | export QEMU_OPTIONS="-nodefaults -machine accel=qtest" | ||
4 | |||
5 | However, two test cases (172 and 186) overwrite QEMU_OPTIONS and neglect | ||
6 | to manually set '-machine accel=qtest'. Add the missing option for 172. | ||
7 | 186 probably only copied the code from 172, it doesn't actually need to | ||
8 | overwrite QEMU_OPTIONS, so remove that in 186. | ||
9 | |||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | Tested-by: Cornelia Huck <cohuck@redhat.com> | ||
12 | Reviewed-by: Cornelia Huck <cohuck@redhat.com> | ||
13 | --- | ||
14 | tests/qemu-iotests/172 | 2 +- | ||
15 | tests/qemu-iotests/186 | 6 +++--- | ||
16 | 2 files changed, 4 insertions(+), 4 deletions(-) | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172 | ||
19 | index XXXXXXX..XXXXXXX 100755 | ||
20 | --- a/tests/qemu-iotests/172 | ||
21 | +++ b/tests/qemu-iotests/172 | ||
22 | @@ -XXX,XX +XXX,XX @@ function do_run_qemu() | ||
23 | done | ||
24 | fi | ||
25 | echo quit | ||
26 | - ) | $QEMU -nographic -monitor stdio -serial none "$@" | ||
27 | + ) | $QEMU -machine accel=qtest -nographic -monitor stdio -serial none "$@" | ||
28 | echo | ||
29 | } | ||
30 | |||
31 | diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186 | ||
32 | index XXXXXXX..XXXXXXX 100755 | ||
33 | --- a/tests/qemu-iotests/186 | ||
34 | +++ b/tests/qemu-iotests/186 | ||
35 | @@ -XXX,XX +XXX,XX @@ function do_run_qemu() | ||
36 | done | ||
37 | fi | ||
38 | echo quit | ||
39 | - ) | $QEMU -S -nodefaults -display none -device virtio-scsi-pci -monitor stdio "$@" 2>&1 | ||
40 | + ) | $QEMU -S -display none -device virtio-scsi-pci -monitor stdio "$@" 2>&1 | ||
41 | echo | ||
42 | } | ||
43 | |||
44 | function check_info_block() | ||
45 | { | ||
46 | echo "info block" | | ||
47 | - QEMU_OPTIONS="" do_run_qemu "$@" | _filter_win32 | _filter_hmp | | ||
48 | - _filter_qemu | _filter_generated_node_ids | ||
49 | + do_run_qemu "$@" | _filter_win32 | _filter_hmp | _filter_qemu | | ||
50 | + _filter_generated_node_ids | ||
51 | } | ||
52 | |||
53 | |||
54 | -- | ||
55 | 2.13.5 | ||
56 | |||
57 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Fam Zheng <famz@redhat.com> | ||
2 | 1 | ||
3 | It's not too surprising when a user specifies the backing file relative | ||
4 | to the current working directory instead of the top layer image. This | ||
5 | causes error when they differ. Though the error message has enough | ||
6 | information to infer the fact about the misunderstanding, it is better | ||
7 | if we document this explicitly, so that users don't have to learn from | ||
8 | mistakes. | ||
9 | |||
10 | Signed-off-by: Fam Zheng <famz@redhat.com> | ||
11 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
12 | Reviewed-by: Jeff Cody <jcody@redhat.com> | ||
13 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | --- | ||
16 | qemu-img.texi | 9 +++++++++ | ||
17 | 1 file changed, 9 insertions(+) | ||
18 | |||
19 | diff --git a/qemu-img.texi b/qemu-img.texi | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/qemu-img.texi | ||
22 | +++ b/qemu-img.texi | ||
23 | @@ -XXX,XX +XXX,XX @@ only the differences from @var{backing_file}. No size needs to be specified in | ||
24 | this case. @var{backing_file} will never be modified unless you use the | ||
25 | @code{commit} monitor command (or qemu-img commit). | ||
26 | |||
27 | +If a relative path name is given, the backing file is looked up relative to | ||
28 | +the directory containing @var{filename}. | ||
29 | + | ||
30 | Note that a given backing file will be opened to check that it is valid. Use | ||
31 | the @code{-u} option to enable unsafe backing file mode, which means that the | ||
32 | image will be created even if the associated backing file cannot be opened. A | ||
33 | @@ -XXX,XX +XXX,XX @@ created as a copy on write image of the specified base image; the | ||
34 | @var{backing_file} should have the same content as the input's base image, | ||
35 | however the path, image format, etc may differ. | ||
36 | |||
37 | +If a relative path name is given, the backing file is looked up relative to | ||
38 | +the directory containing @var{output_filename}. | ||
39 | + | ||
40 | If the @code{-n} option is specified, the target volume creation will be | ||
41 | skipped. This is useful for formats such as @code{rbd} if the target | ||
42 | volume has already been created with site specific options that cannot | ||
43 | @@ -XXX,XX +XXX,XX @@ The backing file is changed to @var{backing_file} and (if the image format of | ||
44 | string), then the image is rebased onto no backing file (i.e. it will exist | ||
45 | independently of any backing file). | ||
46 | |||
47 | +If a relative path name is given, the backing file is looked up relative to | ||
48 | +the directory containing @var{filename}. | ||
49 | + | ||
50 | @var{cache} specifies the cache mode to be used for @var{filename}, whereas | ||
51 | @var{src_cache} specifies the cache mode for reading backing files. | ||
52 | |||
53 | -- | ||
54 | 2.13.5 | ||
55 | |||
56 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Fam Zheng <famz@redhat.com> | ||
2 | 1 | ||
3 | People get surprised when, after "qemu-img create -f raw /dev/sdX", they | ||
4 | still see qcow2 with "qemu-img info", if previously the bdev had a qcow2 | ||
5 | header. While this is natural because raw doesn't need to write any | ||
6 | magic bytes during creation, hdev_create is free to clear out the first | ||
7 | sector to make sure the stale qcow2 header doesn't cause such confusion. | ||
8 | |||
9 | Signed-off-by: Fam Zheng <famz@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | --- | ||
12 | block/file-posix.c | 10 ++++++++++ | ||
13 | 1 file changed, 10 insertions(+) | ||
14 | |||
15 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/block/file-posix.c | ||
18 | +++ b/block/file-posix.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static int hdev_create(const char *filename, QemuOpts *opts, | ||
20 | ret = -ENOSPC; | ||
21 | } | ||
22 | |||
23 | + if (!ret && total_size) { | ||
24 | + uint8_t buf[BDRV_SECTOR_SIZE] = { 0 }; | ||
25 | + int64_t zero_size = MIN(BDRV_SECTOR_SIZE, total_size); | ||
26 | + if (lseek(fd, 0, SEEK_SET) == -1) { | ||
27 | + ret = -errno; | ||
28 | + } else { | ||
29 | + ret = qemu_write_full(fd, buf, zero_size); | ||
30 | + ret = ret == zero_size ? 0 : -errno; | ||
31 | + } | ||
32 | + } | ||
33 | qemu_close(fd); | ||
34 | return ret; | ||
35 | } | ||
36 | -- | ||
37 | 2.13.5 | ||
38 | |||
39 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Stefan Hajnoczi <stefanha@redhat.com> | ||
2 | 1 | ||
3 | Block driver documentation is available in qemu-doc.html. It would be | ||
4 | convenient to have documentation for formats, protocols, and filter | ||
5 | drivers in a man page. | ||
6 | |||
7 | Extract the relevant part of qemu-doc.html into a new file called | ||
8 | docs/qemu-block-drivers.texi. This file can also be built as a | ||
9 | stand-alone document (man, html, etc). | ||
10 | |||
11 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | Makefile | 6 +- | ||
15 | docs/qemu-block-drivers.texi | 804 +++++++++++++++++++++++++++++++++++++++++++ | ||
16 | qemu-doc.texi | 781 +---------------------------------------- | ||
17 | 3 files changed, 810 insertions(+), 781 deletions(-) | ||
18 | create mode 100644 docs/qemu-block-drivers.texi | ||
19 | |||
20 | diff --git a/Makefile b/Makefile | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/Makefile | ||
23 | +++ b/Makefile | ||
24 | @@ -XXX,XX +XXX,XX @@ ifdef BUILD_DOCS | ||
25 | DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8 | ||
26 | DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7 | ||
27 | DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7 | ||
28 | +DOCS+=docs/qemu-block-drivers.7 | ||
29 | ifdef CONFIG_VIRTFS | ||
30 | DOCS+=fsdev/virtfs-proxy-helper.1 | ||
31 | endif | ||
32 | @@ -XXX,XX +XXX,XX @@ distclean: clean | ||
33 | rm -f docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt | ||
34 | rm -f docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf | ||
35 | rm -f docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html | ||
36 | + rm -f docs/qemu-block-drivers.7 | ||
37 | for d in $(TARGET_DIRS); do \ | ||
38 | rm -rf $$d || exit 1 ; \ | ||
39 | done | ||
40 | @@ -XXX,XX +XXX,XX @@ ifdef CONFIG_POSIX | ||
41 | $(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1" | ||
42 | $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man7" | ||
43 | $(INSTALL_DATA) docs/interop/qemu-qmp-ref.7 "$(DESTDIR)$(mandir)/man7" | ||
44 | + $(INSTALL_DATA) docs/qemu-block-drivers.7 "$(DESTDIR)$(mandir)/man7" | ||
45 | ifneq ($(TOOLS),) | ||
46 | $(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1" | ||
47 | $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8" | ||
48 | @@ -XXX,XX +XXX,XX @@ qemu-img.1: qemu-img.texi qemu-option-trace.texi qemu-img-cmds.texi | ||
49 | fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi | ||
50 | qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi | ||
51 | qemu-ga.8: qemu-ga.texi | ||
52 | +docs/qemu-block-drivers.7: docs/qemu-block-drivers.texi | ||
53 | |||
54 | html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html | ||
55 | info: qemu-doc.info docs/interop/qemu-qmp-ref.info docs/interop/qemu-ga-ref.info | ||
56 | @@ -XXX,XX +XXX,XX @@ txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt | ||
57 | qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \ | ||
58 | qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \ | ||
59 | qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \ | ||
60 | - qemu-monitor-info.texi | ||
61 | + qemu-monitor-info.texi docs/qemu-block-drivers.texi | ||
62 | |||
63 | docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \ | ||
64 | docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \ | ||
65 | diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi | ||
66 | new file mode 100644 | ||
67 | index XXXXXXX..XXXXXXX | ||
68 | --- /dev/null | ||
69 | +++ b/docs/qemu-block-drivers.texi | ||
70 | @@ -XXX,XX +XXX,XX @@ | ||
71 | +@c man begin SYNOPSIS | ||
72 | +QEMU block driver reference manual | ||
73 | +@c man end | ||
74 | + | ||
75 | +@c man begin DESCRIPTION | ||
76 | + | ||
77 | +@node disk_images_formats | ||
78 | +@subsection Disk image file formats | ||
79 | + | ||
80 | +QEMU supports many image file formats that can be used with VMs as well as with | ||
81 | +any of the tools (like @code{qemu-img}). This includes the preferred formats | ||
82 | +raw and qcow2 as well as formats that are supported for compatibility with | ||
83 | +older QEMU versions or other hypervisors. | ||
84 | + | ||
85 | +Depending on the image format, different options can be passed to | ||
86 | +@code{qemu-img create} and @code{qemu-img convert} using the @code{-o} option. | ||
87 | +This section describes each format and the options that are supported for it. | ||
88 | + | ||
89 | +@table @option | ||
90 | +@item raw | ||
91 | + | ||
92 | +Raw disk image format. This format has the advantage of | ||
93 | +being simple and easily exportable to all other emulators. If your | ||
94 | +file system supports @emph{holes} (for example in ext2 or ext3 on | ||
95 | +Linux or NTFS on Windows), then only the written sectors will reserve | ||
96 | +space. Use @code{qemu-img info} to know the real size used by the | ||
97 | +image or @code{ls -ls} on Unix/Linux. | ||
98 | + | ||
99 | +Supported options: | ||
100 | +@table @code | ||
101 | +@item preallocation | ||
102 | +Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}). | ||
103 | +@code{falloc} mode preallocates space for image by calling posix_fallocate(). | ||
104 | +@code{full} mode preallocates space for image by writing zeros to underlying | ||
105 | +storage. | ||
106 | +@end table | ||
107 | + | ||
108 | +@item qcow2 | ||
109 | +QEMU image format, the most versatile format. Use it to have smaller | ||
110 | +images (useful if your filesystem does not supports holes, for example | ||
111 | +on Windows), zlib based compression and support of multiple VM | ||
112 | +snapshots. | ||
113 | + | ||
114 | +Supported options: | ||
115 | +@table @code | ||
116 | +@item compat | ||
117 | +Determines the qcow2 version to use. @code{compat=0.10} uses the | ||
118 | +traditional image format that can be read by any QEMU since 0.10. | ||
119 | +@code{compat=1.1} enables image format extensions that only QEMU 1.1 and | ||
120 | +newer understand (this is the default). Amongst others, this includes | ||
121 | +zero clusters, which allow efficient copy-on-read for sparse images. | ||
122 | + | ||
123 | +@item backing_file | ||
124 | +File name of a base image (see @option{create} subcommand) | ||
125 | +@item backing_fmt | ||
126 | +Image format of the base image | ||
127 | +@item encryption | ||
128 | +This option is deprecated and equivalent to @code{encrypt.format=aes} | ||
129 | + | ||
130 | +@item encrypt.format | ||
131 | + | ||
132 | +If this is set to @code{luks}, it requests that the qcow2 payload (not | ||
133 | +qcow2 header) be encrypted using the LUKS format. The passphrase to | ||
134 | +use to unlock the LUKS key slot is given by the @code{encrypt.key-secret} | ||
135 | +parameter. LUKS encryption parameters can be tuned with the other | ||
136 | +@code{encrypt.*} parameters. | ||
137 | + | ||
138 | +If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC. | ||
139 | +The encryption key is given by the @code{encrypt.key-secret} parameter. | ||
140 | +This encryption format is considered to be flawed by modern cryptography | ||
141 | +standards, suffering from a number of design problems: | ||
142 | + | ||
143 | +@itemize @minus | ||
144 | +@item The AES-CBC cipher is used with predictable initialization vectors based | ||
145 | +on the sector number. This makes it vulnerable to chosen plaintext attacks | ||
146 | +which can reveal the existence of encrypted data. | ||
147 | +@item The user passphrase is directly used as the encryption key. A poorly | ||
148 | +chosen or short passphrase will compromise the security of the encryption. | ||
149 | +@item In the event of the passphrase being compromised there is no way to | ||
150 | +change the passphrase to protect data in any qcow images. The files must | ||
151 | +be cloned, using a different encryption passphrase in the new file. The | ||
152 | +original file must then be securely erased using a program like shred, | ||
153 | +though even this is ineffective with many modern storage technologies. | ||
154 | +@end itemize | ||
155 | + | ||
156 | +The use of this is no longer supported in system emulators. Support only | ||
157 | +remains in the command line utilities, for the purposes of data liberation | ||
158 | +and interoperability with old versions of QEMU. The @code{luks} format | ||
159 | +should be used instead. | ||
160 | + | ||
161 | +@item encrypt.key-secret | ||
162 | + | ||
163 | +Provides the ID of a @code{secret} object that contains the passphrase | ||
164 | +(@code{encrypt.format=luks}) or encryption key (@code{encrypt.format=aes}). | ||
165 | + | ||
166 | +@item encrypt.cipher-alg | ||
167 | + | ||
168 | +Name of the cipher algorithm and key length. Currently defaults | ||
169 | +to @code{aes-256}. Only used when @code{encrypt.format=luks}. | ||
170 | + | ||
171 | +@item encrypt.cipher-mode | ||
172 | + | ||
173 | +Name of the encryption mode to use. Currently defaults to @code{xts}. | ||
174 | +Only used when @code{encrypt.format=luks}. | ||
175 | + | ||
176 | +@item encrypt.ivgen-alg | ||
177 | + | ||
178 | +Name of the initialization vector generator algorithm. Currently defaults | ||
179 | +to @code{plain64}. Only used when @code{encrypt.format=luks}. | ||
180 | + | ||
181 | +@item encrypt.ivgen-hash-alg | ||
182 | + | ||
183 | +Name of the hash algorithm to use with the initialization vector generator | ||
184 | +(if required). Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}. | ||
185 | + | ||
186 | +@item encrypt.hash-alg | ||
187 | + | ||
188 | +Name of the hash algorithm to use for PBKDF algorithm | ||
189 | +Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}. | ||
190 | + | ||
191 | +@item encrypt.iter-time | ||
192 | + | ||
193 | +Amount of time, in milliseconds, to use for PBKDF algorithm per key slot. | ||
194 | +Defaults to @code{2000}. Only used when @code{encrypt.format=luks}. | ||
195 | + | ||
196 | +@item cluster_size | ||
197 | +Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster | ||
198 | +sizes can improve the image file size whereas larger cluster sizes generally | ||
199 | +provide better performance. | ||
200 | + | ||
201 | +@item preallocation | ||
202 | +Preallocation mode (allowed values: @code{off}, @code{metadata}, @code{falloc}, | ||
203 | +@code{full}). An image with preallocated metadata is initially larger but can | ||
204 | +improve performance when the image needs to grow. @code{falloc} and @code{full} | ||
205 | +preallocations are like the same options of @code{raw} format, but sets up | ||
206 | +metadata also. | ||
207 | + | ||
208 | +@item lazy_refcounts | ||
209 | +If this option is set to @code{on}, reference count updates are postponed with | ||
210 | +the goal of avoiding metadata I/O and improving performance. This is | ||
211 | +particularly interesting with @option{cache=writethrough} which doesn't batch | ||
212 | +metadata updates. The tradeoff is that after a host crash, the reference count | ||
213 | +tables must be rebuilt, i.e. on the next open an (automatic) @code{qemu-img | ||
214 | +check -r all} is required, which may take some time. | ||
215 | + | ||
216 | +This option can only be enabled if @code{compat=1.1} is specified. | ||
217 | + | ||
218 | +@item nocow | ||
219 | +If this option is set to @code{on}, it will turn off COW of the file. It's only | ||
220 | +valid on btrfs, no effect on other file systems. | ||
221 | + | ||
222 | +Btrfs has low performance when hosting a VM image file, even more when the guest | ||
223 | +on the VM also using btrfs as file system. Turning off COW is a way to mitigate | ||
224 | +this bad performance. Generally there are two ways to turn off COW on btrfs: | ||
225 | +a) Disable it by mounting with nodatacow, then all newly created files will be | ||
226 | +NOCOW. b) For an empty file, add the NOCOW file attribute. That's what this option | ||
227 | +does. | ||
228 | + | ||
229 | +Note: this option is only valid to new or empty files. If there is an existing | ||
230 | +file which is COW and has data blocks already, it couldn't be changed to NOCOW | ||
231 | +by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if | ||
232 | +the NOCOW flag is set or not (Capital 'C' is NOCOW flag). | ||
233 | + | ||
234 | +@end table | ||
235 | + | ||
236 | +@item qed | ||
237 | +Old QEMU image format with support for backing files and compact image files | ||
238 | +(when your filesystem or transport medium does not support holes). | ||
239 | + | ||
240 | +When converting QED images to qcow2, you might want to consider using the | ||
241 | +@code{lazy_refcounts=on} option to get a more QED-like behaviour. | ||
242 | + | ||
243 | +Supported options: | ||
244 | +@table @code | ||
245 | +@item backing_file | ||
246 | +File name of a base image (see @option{create} subcommand). | ||
247 | +@item backing_fmt | ||
248 | +Image file format of backing file (optional). Useful if the format cannot be | ||
249 | +autodetected because it has no header, like some vhd/vpc files. | ||
250 | +@item cluster_size | ||
251 | +Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller | ||
252 | +cluster sizes can improve the image file size whereas larger cluster sizes | ||
253 | +generally provide better performance. | ||
254 | +@item table_size | ||
255 | +Changes the number of clusters per L1/L2 table (must be power-of-2 between 1 | ||
256 | +and 16). There is normally no need to change this value but this option can be | ||
257 | +used for performance benchmarking. | ||
258 | +@end table | ||
259 | + | ||
260 | +@item qcow | ||
261 | +Old QEMU image format with support for backing files, compact image files, | ||
262 | +encryption and compression. | ||
263 | + | ||
264 | +Supported options: | ||
265 | +@table @code | ||
266 | +@item backing_file | ||
267 | +File name of a base image (see @option{create} subcommand) | ||
268 | +@item encryption | ||
269 | +This option is deprecated and equivalent to @code{encrypt.format=aes} | ||
270 | + | ||
271 | +@item encrypt.format | ||
272 | +If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC. | ||
273 | +The encryption key is given by the @code{encrypt.key-secret} parameter. | ||
274 | +This encryption format is considered to be flawed by modern cryptography | ||
275 | +standards, suffering from a number of design problems enumerated previously | ||
276 | +against the @code{qcow2} image format. | ||
277 | + | ||
278 | +The use of this is no longer supported in system emulators. Support only | ||
279 | +remains in the command line utilities, for the purposes of data liberation | ||
280 | +and interoperability with old versions of QEMU. | ||
281 | + | ||
282 | +Users requiring native encryption should use the @code{qcow2} format | ||
283 | +instead with @code{encrypt.format=luks}. | ||
284 | + | ||
285 | +@item encrypt.key-secret | ||
286 | + | ||
287 | +Provides the ID of a @code{secret} object that contains the encryption | ||
288 | +key (@code{encrypt.format=aes}). | ||
289 | + | ||
290 | +@end table | ||
291 | + | ||
292 | +@item luks | ||
293 | + | ||
294 | +LUKS v1 encryption format, compatible with Linux dm-crypt/cryptsetup | ||
295 | + | ||
296 | +Supported options: | ||
297 | +@table @code | ||
298 | + | ||
299 | +@item key-secret | ||
300 | + | ||
301 | +Provides the ID of a @code{secret} object that contains the passphrase. | ||
302 | + | ||
303 | +@item cipher-alg | ||
304 | + | ||
305 | +Name of the cipher algorithm and key length. Currently defaults | ||
306 | +to @code{aes-256}. | ||
307 | + | ||
308 | +@item cipher-mode | ||
309 | + | ||
310 | +Name of the encryption mode to use. Currently defaults to @code{xts}. | ||
311 | + | ||
312 | +@item ivgen-alg | ||
313 | + | ||
314 | +Name of the initialization vector generator algorithm. Currently defaults | ||
315 | +to @code{plain64}. | ||
316 | + | ||
317 | +@item ivgen-hash-alg | ||
318 | + | ||
319 | +Name of the hash algorithm to use with the initialization vector generator | ||
320 | +(if required). Defaults to @code{sha256}. | ||
321 | + | ||
322 | +@item hash-alg | ||
323 | + | ||
324 | +Name of the hash algorithm to use for PBKDF algorithm | ||
325 | +Defaults to @code{sha256}. | ||
326 | + | ||
327 | +@item iter-time | ||
328 | + | ||
329 | +Amount of time, in milliseconds, to use for PBKDF algorithm per key slot. | ||
330 | +Defaults to @code{2000}. | ||
331 | + | ||
332 | +@end table | ||
333 | + | ||
334 | +@item vdi | ||
335 | +VirtualBox 1.1 compatible image format. | ||
336 | +Supported options: | ||
337 | +@table @code | ||
338 | +@item static | ||
339 | +If this option is set to @code{on}, the image is created with metadata | ||
340 | +preallocation. | ||
341 | +@end table | ||
342 | + | ||
343 | +@item vmdk | ||
344 | +VMware 3 and 4 compatible image format. | ||
345 | + | ||
346 | +Supported options: | ||
347 | +@table @code | ||
348 | +@item backing_file | ||
349 | +File name of a base image (see @option{create} subcommand). | ||
350 | +@item compat6 | ||
351 | +Create a VMDK version 6 image (instead of version 4) | ||
352 | +@item hwversion | ||
353 | +Specify vmdk virtual hardware version. Compat6 flag cannot be enabled | ||
354 | +if hwversion is specified. | ||
355 | +@item subformat | ||
356 | +Specifies which VMDK subformat to use. Valid options are | ||
357 | +@code{monolithicSparse} (default), | ||
358 | +@code{monolithicFlat}, | ||
359 | +@code{twoGbMaxExtentSparse}, | ||
360 | +@code{twoGbMaxExtentFlat} and | ||
361 | +@code{streamOptimized}. | ||
362 | +@end table | ||
363 | + | ||
364 | +@item vpc | ||
365 | +VirtualPC compatible image format (VHD). | ||
366 | +Supported options: | ||
367 | +@table @code | ||
368 | +@item subformat | ||
369 | +Specifies which VHD subformat to use. Valid options are | ||
370 | +@code{dynamic} (default) and @code{fixed}. | ||
371 | +@end table | ||
372 | + | ||
373 | +@item VHDX | ||
374 | +Hyper-V compatible image format (VHDX). | ||
375 | +Supported options: | ||
376 | +@table @code | ||
377 | +@item subformat | ||
378 | +Specifies which VHDX subformat to use. Valid options are | ||
379 | +@code{dynamic} (default) and @code{fixed}. | ||
380 | +@item block_state_zero | ||
381 | +Force use of payload blocks of type 'ZERO'. Can be set to @code{on} (default) | ||
382 | +or @code{off}. When set to @code{off}, new blocks will be created as | ||
383 | +@code{PAYLOAD_BLOCK_NOT_PRESENT}, which means parsers are free to return | ||
384 | +arbitrary data for those blocks. Do not set to @code{off} when using | ||
385 | +@code{qemu-img convert} with @code{subformat=dynamic}. | ||
386 | +@item block_size | ||
387 | +Block size; min 1 MB, max 256 MB. 0 means auto-calculate based on image size. | ||
388 | +@item log_size | ||
389 | +Log size; min 1 MB. | ||
390 | +@end table | ||
391 | +@end table | ||
392 | + | ||
393 | +@subsubsection Read-only formats | ||
394 | +More disk image file formats are supported in a read-only mode. | ||
395 | +@table @option | ||
396 | +@item bochs | ||
397 | +Bochs images of @code{growing} type. | ||
398 | +@item cloop | ||
399 | +Linux Compressed Loop image, useful only to reuse directly compressed | ||
400 | +CD-ROM images present for example in the Knoppix CD-ROMs. | ||
401 | +@item dmg | ||
402 | +Apple disk image. | ||
403 | +@item parallels | ||
404 | +Parallels disk image format. | ||
405 | +@end table | ||
406 | + | ||
407 | + | ||
408 | +@node host_drives | ||
409 | +@subsection Using host drives | ||
410 | + | ||
411 | +In addition to disk image files, QEMU can directly access host | ||
412 | +devices. We describe here the usage for QEMU version >= 0.8.3. | ||
413 | + | ||
414 | +@subsubsection Linux | ||
415 | + | ||
416 | +On Linux, you can directly use the host device filename instead of a | ||
417 | +disk image filename provided you have enough privileges to access | ||
418 | +it. For example, use @file{/dev/cdrom} to access to the CDROM. | ||
419 | + | ||
420 | +@table @code | ||
421 | +@item CD | ||
422 | +You can specify a CDROM device even if no CDROM is loaded. QEMU has | ||
423 | +specific code to detect CDROM insertion or removal. CDROM ejection by | ||
424 | +the guest OS is supported. Currently only data CDs are supported. | ||
425 | +@item Floppy | ||
426 | +You can specify a floppy device even if no floppy is loaded. Floppy | ||
427 | +removal is currently not detected accurately (if you change floppy | ||
428 | +without doing floppy access while the floppy is not loaded, the guest | ||
429 | +OS will think that the same floppy is loaded). | ||
430 | +Use of the host's floppy device is deprecated, and support for it will | ||
431 | +be removed in a future release. | ||
432 | +@item Hard disks | ||
433 | +Hard disks can be used. Normally you must specify the whole disk | ||
434 | +(@file{/dev/hdb} instead of @file{/dev/hdb1}) so that the guest OS can | ||
435 | +see it as a partitioned disk. WARNING: unless you know what you do, it | ||
436 | +is better to only make READ-ONLY accesses to the hard disk otherwise | ||
437 | +you may corrupt your host data (use the @option{-snapshot} command | ||
438 | +line option or modify the device permissions accordingly). | ||
439 | +@end table | ||
440 | + | ||
441 | +@subsubsection Windows | ||
442 | + | ||
443 | +@table @code | ||
444 | +@item CD | ||
445 | +The preferred syntax is the drive letter (e.g. @file{d:}). The | ||
446 | +alternate syntax @file{\\.\d:} is supported. @file{/dev/cdrom} is | ||
447 | +supported as an alias to the first CDROM drive. | ||
448 | + | ||
449 | +Currently there is no specific code to handle removable media, so it | ||
450 | +is better to use the @code{change} or @code{eject} monitor commands to | ||
451 | +change or eject media. | ||
452 | +@item Hard disks | ||
453 | +Hard disks can be used with the syntax: @file{\\.\PhysicalDrive@var{N}} | ||
454 | +where @var{N} is the drive number (0 is the first hard disk). | ||
455 | + | ||
456 | +WARNING: unless you know what you do, it is better to only make | ||
457 | +READ-ONLY accesses to the hard disk otherwise you may corrupt your | ||
458 | +host data (use the @option{-snapshot} command line so that the | ||
459 | +modifications are written in a temporary file). | ||
460 | +@end table | ||
461 | + | ||
462 | + | ||
463 | +@subsubsection Mac OS X | ||
464 | + | ||
465 | +@file{/dev/cdrom} is an alias to the first CDROM. | ||
466 | + | ||
467 | +Currently there is no specific code to handle removable media, so it | ||
468 | +is better to use the @code{change} or @code{eject} monitor commands to | ||
469 | +change or eject media. | ||
470 | + | ||
471 | +@node disk_images_fat_images | ||
472 | +@subsection Virtual FAT disk images | ||
473 | + | ||
474 | +QEMU can automatically create a virtual FAT disk image from a | ||
475 | +directory tree. In order to use it, just type: | ||
476 | + | ||
477 | +@example | ||
478 | +qemu-system-i386 linux.img -hdb fat:/my_directory | ||
479 | +@end example | ||
480 | + | ||
481 | +Then you access access to all the files in the @file{/my_directory} | ||
482 | +directory without having to copy them in a disk image or to export | ||
483 | +them via SAMBA or NFS. The default access is @emph{read-only}. | ||
484 | + | ||
485 | +Floppies can be emulated with the @code{:floppy:} option: | ||
486 | + | ||
487 | +@example | ||
488 | +qemu-system-i386 linux.img -fda fat:floppy:/my_directory | ||
489 | +@end example | ||
490 | + | ||
491 | +A read/write support is available for testing (beta stage) with the | ||
492 | +@code{:rw:} option: | ||
493 | + | ||
494 | +@example | ||
495 | +qemu-system-i386 linux.img -fda fat:floppy:rw:/my_directory | ||
496 | +@end example | ||
497 | + | ||
498 | +What you should @emph{never} do: | ||
499 | +@itemize | ||
500 | +@item use non-ASCII filenames ; | ||
501 | +@item use "-snapshot" together with ":rw:" ; | ||
502 | +@item expect it to work when loadvm'ing ; | ||
503 | +@item write to the FAT directory on the host system while accessing it with the guest system. | ||
504 | +@end itemize | ||
505 | + | ||
506 | +@node disk_images_nbd | ||
507 | +@subsection NBD access | ||
508 | + | ||
509 | +QEMU can access directly to block device exported using the Network Block Device | ||
510 | +protocol. | ||
511 | + | ||
512 | +@example | ||
513 | +qemu-system-i386 linux.img -hdb nbd://my_nbd_server.mydomain.org:1024/ | ||
514 | +@end example | ||
515 | + | ||
516 | +If the NBD server is located on the same host, you can use an unix socket instead | ||
517 | +of an inet socket: | ||
518 | + | ||
519 | +@example | ||
520 | +qemu-system-i386 linux.img -hdb nbd+unix://?socket=/tmp/my_socket | ||
521 | +@end example | ||
522 | + | ||
523 | +In this case, the block device must be exported using qemu-nbd: | ||
524 | + | ||
525 | +@example | ||
526 | +qemu-nbd --socket=/tmp/my_socket my_disk.qcow2 | ||
527 | +@end example | ||
528 | + | ||
529 | +The use of qemu-nbd allows sharing of a disk between several guests: | ||
530 | +@example | ||
531 | +qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2 | ||
532 | +@end example | ||
533 | + | ||
534 | +@noindent | ||
535 | +and then you can use it with two guests: | ||
536 | +@example | ||
537 | +qemu-system-i386 linux1.img -hdb nbd+unix://?socket=/tmp/my_socket | ||
538 | +qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket | ||
539 | +@end example | ||
540 | + | ||
541 | +If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's | ||
542 | +own embedded NBD server), you must specify an export name in the URI: | ||
543 | +@example | ||
544 | +qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst | ||
545 | +qemu-system-i386 -cdrom nbd://localhost/openSUSE-11.1-ppc-netinst | ||
546 | +@end example | ||
547 | + | ||
548 | +The URI syntax for NBD is supported since QEMU 1.3. An alternative syntax is | ||
549 | +also available. Here are some example of the older syntax: | ||
550 | +@example | ||
551 | +qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024 | ||
552 | +qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket | ||
553 | +qemu-system-i386 -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst | ||
554 | +@end example | ||
555 | + | ||
556 | +@node disk_images_sheepdog | ||
557 | +@subsection Sheepdog disk images | ||
558 | + | ||
559 | +Sheepdog is a distributed storage system for QEMU. It provides highly | ||
560 | +available block level storage volumes that can be attached to | ||
561 | +QEMU-based virtual machines. | ||
562 | + | ||
563 | +You can create a Sheepdog disk image with the command: | ||
564 | +@example | ||
565 | +qemu-img create sheepdog:///@var{image} @var{size} | ||
566 | +@end example | ||
567 | +where @var{image} is the Sheepdog image name and @var{size} is its | ||
568 | +size. | ||
569 | + | ||
570 | +To import the existing @var{filename} to Sheepdog, you can use a | ||
571 | +convert command. | ||
572 | +@example | ||
573 | +qemu-img convert @var{filename} sheepdog:///@var{image} | ||
574 | +@end example | ||
575 | + | ||
576 | +You can boot from the Sheepdog disk image with the command: | ||
577 | +@example | ||
578 | +qemu-system-i386 sheepdog:///@var{image} | ||
579 | +@end example | ||
580 | + | ||
581 | +You can also create a snapshot of the Sheepdog image like qcow2. | ||
582 | +@example | ||
583 | +qemu-img snapshot -c @var{tag} sheepdog:///@var{image} | ||
584 | +@end example | ||
585 | +where @var{tag} is a tag name of the newly created snapshot. | ||
586 | + | ||
587 | +To boot from the Sheepdog snapshot, specify the tag name of the | ||
588 | +snapshot. | ||
589 | +@example | ||
590 | +qemu-system-i386 sheepdog:///@var{image}#@var{tag} | ||
591 | +@end example | ||
592 | + | ||
593 | +You can create a cloned image from the existing snapshot. | ||
594 | +@example | ||
595 | +qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image} | ||
596 | +@end example | ||
597 | +where @var{base} is a image name of the source snapshot and @var{tag} | ||
598 | +is its tag name. | ||
599 | + | ||
600 | +You can use an unix socket instead of an inet socket: | ||
601 | + | ||
602 | +@example | ||
603 | +qemu-system-i386 sheepdog+unix:///@var{image}?socket=@var{path} | ||
604 | +@end example | ||
605 | + | ||
606 | +If the Sheepdog daemon doesn't run on the local host, you need to | ||
607 | +specify one of the Sheepdog servers to connect to. | ||
608 | +@example | ||
609 | +qemu-img create sheepdog://@var{hostname}:@var{port}/@var{image} @var{size} | ||
610 | +qemu-system-i386 sheepdog://@var{hostname}:@var{port}/@var{image} | ||
611 | +@end example | ||
612 | + | ||
613 | +@node disk_images_iscsi | ||
614 | +@subsection iSCSI LUNs | ||
615 | + | ||
616 | +iSCSI is a popular protocol used to access SCSI devices across a computer | ||
617 | +network. | ||
618 | + | ||
619 | +There are two different ways iSCSI devices can be used by QEMU. | ||
620 | + | ||
621 | +The first method is to mount the iSCSI LUN on the host, and make it appear as | ||
622 | +any other ordinary SCSI device on the host and then to access this device as a | ||
623 | +/dev/sd device from QEMU. How to do this differs between host OSes. | ||
624 | + | ||
625 | +The second method involves using the iSCSI initiator that is built into | ||
626 | +QEMU. This provides a mechanism that works the same way regardless of which | ||
627 | +host OS you are running QEMU on. This section will describe this second method | ||
628 | +of using iSCSI together with QEMU. | ||
629 | + | ||
630 | +In QEMU, iSCSI devices are described using special iSCSI URLs | ||
631 | + | ||
632 | +@example | ||
633 | +URL syntax: | ||
634 | +iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun> | ||
635 | +@end example | ||
636 | + | ||
637 | +Username and password are optional and only used if your target is set up | ||
638 | +using CHAP authentication for access control. | ||
639 | +Alternatively the username and password can also be set via environment | ||
640 | +variables to have these not show up in the process list | ||
641 | + | ||
642 | +@example | ||
643 | +export LIBISCSI_CHAP_USERNAME=<username> | ||
644 | +export LIBISCSI_CHAP_PASSWORD=<password> | ||
645 | +iscsi://<host>/<target-iqn-name>/<lun> | ||
646 | +@end example | ||
647 | + | ||
648 | +Various session related parameters can be set via special options, either | ||
649 | +in a configuration file provided via '-readconfig' or directly on the | ||
650 | +command line. | ||
651 | + | ||
652 | +If the initiator-name is not specified qemu will use a default name | ||
653 | +of 'iqn.2008-11.org.linux-kvm[:<uuid>'] where <uuid> is the UUID of the | ||
654 | +virtual machine. If the UUID is not specified qemu will use | ||
655 | +'iqn.2008-11.org.linux-kvm[:<name>'] where <name> is the name of the | ||
656 | +virtual machine. | ||
657 | + | ||
658 | +@example | ||
659 | +Setting a specific initiator name to use when logging in to the target | ||
660 | +-iscsi initiator-name=iqn.qemu.test:my-initiator | ||
661 | +@end example | ||
662 | + | ||
663 | +@example | ||
664 | +Controlling which type of header digest to negotiate with the target | ||
665 | +-iscsi header-digest=CRC32C|CRC32C-NONE|NONE-CRC32C|NONE | ||
666 | +@end example | ||
667 | + | ||
668 | +These can also be set via a configuration file | ||
669 | +@example | ||
670 | +[iscsi] | ||
671 | + user = "CHAP username" | ||
672 | + password = "CHAP password" | ||
673 | + initiator-name = "iqn.qemu.test:my-initiator" | ||
674 | + # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE | ||
675 | + header-digest = "CRC32C" | ||
676 | +@end example | ||
677 | + | ||
678 | + | ||
679 | +Setting the target name allows different options for different targets | ||
680 | +@example | ||
681 | +[iscsi "iqn.target.name"] | ||
682 | + user = "CHAP username" | ||
683 | + password = "CHAP password" | ||
684 | + initiator-name = "iqn.qemu.test:my-initiator" | ||
685 | + # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE | ||
686 | + header-digest = "CRC32C" | ||
687 | +@end example | ||
688 | + | ||
689 | + | ||
690 | +Howto use a configuration file to set iSCSI configuration options: | ||
691 | +@example | ||
692 | +cat >iscsi.conf <<EOF | ||
693 | +[iscsi] | ||
694 | + user = "me" | ||
695 | + password = "my password" | ||
696 | + initiator-name = "iqn.qemu.test:my-initiator" | ||
697 | + header-digest = "CRC32C" | ||
698 | +EOF | ||
699 | + | ||
700 | +qemu-system-i386 -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \ | ||
701 | + -readconfig iscsi.conf | ||
702 | +@end example | ||
703 | + | ||
704 | + | ||
705 | +Howto set up a simple iSCSI target on loopback and accessing it via QEMU: | ||
706 | +@example | ||
707 | +This example shows how to set up an iSCSI target with one CDROM and one DISK | ||
708 | +using the Linux STGT software target. This target is available on Red Hat based | ||
709 | +systems as the package 'scsi-target-utils'. | ||
710 | + | ||
711 | +tgtd --iscsi portal=127.0.0.1:3260 | ||
712 | +tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test | ||
713 | +tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \ | ||
714 | + -b /IMAGES/disk.img --device-type=disk | ||
715 | +tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \ | ||
716 | + -b /IMAGES/cd.iso --device-type=cd | ||
717 | +tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL | ||
718 | + | ||
719 | +qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \ | ||
720 | + -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \ | ||
721 | + -cdrom iscsi://127.0.0.1/iqn.qemu.test/2 | ||
722 | +@end example | ||
723 | + | ||
724 | +@node disk_images_gluster | ||
725 | +@subsection GlusterFS disk images | ||
726 | + | ||
727 | +GlusterFS is a user space distributed file system. | ||
728 | + | ||
729 | +You can boot from the GlusterFS disk image with the command: | ||
730 | +@example | ||
731 | +URI: | ||
732 | +qemu-system-x86_64 -drive file=gluster[+@var{type}]://[@var{host}[:@var{port}]]/@var{volume}/@var{path} | ||
733 | + [?socket=...][,file.debug=9][,file.logfile=...] | ||
734 | + | ||
735 | +JSON: | ||
736 | +qemu-system-x86_64 'json:@{"driver":"qcow2", | ||
737 | + "file":@{"driver":"gluster", | ||
738 | + "volume":"testvol","path":"a.img","debug":9,"logfile":"...", | ||
739 | + "server":[@{"type":"tcp","host":"...","port":"..."@}, | ||
740 | + @{"type":"unix","socket":"..."@}]@}@}' | ||
741 | +@end example | ||
742 | + | ||
743 | +@var{gluster} is the protocol. | ||
744 | + | ||
745 | +@var{type} specifies the transport type used to connect to gluster | ||
746 | +management daemon (glusterd). Valid transport types are | ||
747 | +tcp and unix. In the URI form, if a transport type isn't specified, | ||
748 | +then tcp type is assumed. | ||
749 | + | ||
750 | +@var{host} specifies the server where the volume file specification for | ||
751 | +the given volume resides. This can be either a hostname or an ipv4 address. | ||
752 | +If transport type is unix, then @var{host} field should not be specified. | ||
753 | +Instead @var{socket} field needs to be populated with the path to unix domain | ||
754 | +socket. | ||
755 | + | ||
756 | +@var{port} is the port number on which glusterd is listening. This is optional | ||
757 | +and if not specified, it defaults to port 24007. If the transport type is unix, | ||
758 | +then @var{port} should not be specified. | ||
759 | + | ||
760 | +@var{volume} is the name of the gluster volume which contains the disk image. | ||
761 | + | ||
762 | +@var{path} is the path to the actual disk image that resides on gluster volume. | ||
763 | + | ||
764 | +@var{debug} is the logging level of the gluster protocol driver. Debug levels | ||
765 | +are 0-9, with 9 being the most verbose, and 0 representing no debugging output. | ||
766 | +The default level is 4. The current logging levels defined in the gluster source | ||
767 | +are 0 - None, 1 - Emergency, 2 - Alert, 3 - Critical, 4 - Error, 5 - Warning, | ||
768 | +6 - Notice, 7 - Info, 8 - Debug, 9 - Trace | ||
769 | + | ||
770 | +@var{logfile} is a commandline option to mention log file path which helps in | ||
771 | +logging to the specified file and also help in persisting the gfapi logs. The | ||
772 | +default is stderr. | ||
773 | + | ||
774 | + | ||
775 | + | ||
776 | + | ||
777 | +You can create a GlusterFS disk image with the command: | ||
778 | +@example | ||
779 | +qemu-img create gluster://@var{host}/@var{volume}/@var{path} @var{size} | ||
780 | +@end example | ||
781 | + | ||
782 | +Examples | ||
783 | +@example | ||
784 | +qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img | ||
785 | +qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4/testvol/a.img | ||
786 | +qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img | ||
787 | +qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img | ||
788 | +qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img | ||
789 | +qemu-system-x86_64 -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img | ||
790 | +qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket | ||
791 | +qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img | ||
792 | +qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img,file.debug=9,file.logfile=/var/log/qemu-gluster.log | ||
793 | +qemu-system-x86_64 'json:@{"driver":"qcow2", | ||
794 | + "file":@{"driver":"gluster", | ||
795 | + "volume":"testvol","path":"a.img", | ||
796 | + "debug":9,"logfile":"/var/log/qemu-gluster.log", | ||
797 | + "server":[@{"type":"tcp","host":"1.2.3.4","port":24007@}, | ||
798 | + @{"type":"unix","socket":"/var/run/glusterd.socket"@}]@}@}' | ||
799 | +qemu-system-x86_64 -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img, | ||
800 | + file.debug=9,file.logfile=/var/log/qemu-gluster.log, | ||
801 | + file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007, | ||
802 | + file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket | ||
803 | +@end example | ||
804 | + | ||
805 | +@node disk_images_ssh | ||
806 | +@subsection Secure Shell (ssh) disk images | ||
807 | + | ||
808 | +You can access disk images located on a remote ssh server | ||
809 | +by using the ssh protocol: | ||
810 | + | ||
811 | +@example | ||
812 | +qemu-system-x86_64 -drive file=ssh://[@var{user}@@]@var{server}[:@var{port}]/@var{path}[?host_key_check=@var{host_key_check}] | ||
813 | +@end example | ||
814 | + | ||
815 | +Alternative syntax using properties: | ||
816 | + | ||
817 | +@example | ||
818 | +qemu-system-x86_64 -drive file.driver=ssh[,file.user=@var{user}],file.host=@var{server}[,file.port=@var{port}],file.path=@var{path}[,file.host_key_check=@var{host_key_check}] | ||
819 | +@end example | ||
820 | + | ||
821 | +@var{ssh} is the protocol. | ||
822 | + | ||
823 | +@var{user} is the remote user. If not specified, then the local | ||
824 | +username is tried. | ||
825 | + | ||
826 | +@var{server} specifies the remote ssh server. Any ssh server can be | ||
827 | +used, but it must implement the sftp-server protocol. Most Unix/Linux | ||
828 | +systems should work without requiring any extra configuration. | ||
829 | + | ||
830 | +@var{port} is the port number on which sshd is listening. By default | ||
831 | +the standard ssh port (22) is used. | ||
832 | + | ||
833 | +@var{path} is the path to the disk image. | ||
834 | + | ||
835 | +The optional @var{host_key_check} parameter controls how the remote | ||
836 | +host's key is checked. The default is @code{yes} which means to use | ||
837 | +the local @file{.ssh/known_hosts} file. Setting this to @code{no} | ||
838 | +turns off known-hosts checking. Or you can check that the host key | ||
839 | +matches a specific fingerprint: | ||
840 | +@code{host_key_check=md5:78:45:8e:14:57:4f:d5:45:83:0a:0e:f3:49:82:c9:c8} | ||
841 | +(@code{sha1:} can also be used as a prefix, but note that OpenSSH | ||
842 | +tools only use MD5 to print fingerprints). | ||
843 | + | ||
844 | +Currently authentication must be done using ssh-agent. Other | ||
845 | +authentication methods may be supported in future. | ||
846 | + | ||
847 | +Note: Many ssh servers do not support an @code{fsync}-style operation. | ||
848 | +The ssh driver cannot guarantee that disk flush requests are | ||
849 | +obeyed, and this causes a risk of disk corruption if the remote | ||
850 | +server or network goes down during writes. The driver will | ||
851 | +print a warning when @code{fsync} is not supported: | ||
852 | + | ||
853 | +warning: ssh server @code{ssh.example.com:22} does not support fsync | ||
854 | + | ||
855 | +With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is | ||
856 | +supported. | ||
857 | + | ||
858 | +@c man end | ||
859 | + | ||
860 | +@ignore | ||
861 | + | ||
862 | +@setfilename qemu-block-drivers | ||
863 | +@settitle QEMU block drivers reference | ||
864 | + | ||
865 | +@c man begin SEEALSO | ||
866 | +The HTML documentation of QEMU for more precise information and Linux | ||
867 | +user mode emulator invocation. | ||
868 | +@c man end | ||
869 | + | ||
870 | +@c man begin AUTHOR | ||
871 | +Fabrice Bellard and the QEMU Project developers | ||
872 | +@c man end | ||
873 | + | ||
874 | +@end ignore | ||
875 | diff --git a/qemu-doc.texi b/qemu-doc.texi | ||
876 | index XXXXXXX..XXXXXXX 100644 | ||
877 | --- a/qemu-doc.texi | ||
878 | +++ b/qemu-doc.texi | ||
879 | @@ -XXX,XX +XXX,XX @@ state is not saved or restored properly (in particular USB). | ||
880 | |||
881 | @include qemu-nbd.texi | ||
882 | |||
883 | -@node disk_images_formats | ||
884 | -@subsection Disk image file formats | ||
885 | - | ||
886 | -QEMU supports many image file formats that can be used with VMs as well as with | ||
887 | -any of the tools (like @code{qemu-img}). This includes the preferred formats | ||
888 | -raw and qcow2 as well as formats that are supported for compatibility with | ||
889 | -older QEMU versions or other hypervisors. | ||
890 | - | ||
891 | -Depending on the image format, different options can be passed to | ||
892 | -@code{qemu-img create} and @code{qemu-img convert} using the @code{-o} option. | ||
893 | -This section describes each format and the options that are supported for it. | ||
894 | - | ||
895 | -@table @option | ||
896 | -@item raw | ||
897 | - | ||
898 | -Raw disk image format. This format has the advantage of | ||
899 | -being simple and easily exportable to all other emulators. If your | ||
900 | -file system supports @emph{holes} (for example in ext2 or ext3 on | ||
901 | -Linux or NTFS on Windows), then only the written sectors will reserve | ||
902 | -space. Use @code{qemu-img info} to know the real size used by the | ||
903 | -image or @code{ls -ls} on Unix/Linux. | ||
904 | - | ||
905 | -Supported options: | ||
906 | -@table @code | ||
907 | -@item preallocation | ||
908 | -Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}). | ||
909 | -@code{falloc} mode preallocates space for image by calling posix_fallocate(). | ||
910 | -@code{full} mode preallocates space for image by writing zeros to underlying | ||
911 | -storage. | ||
912 | -@end table | ||
913 | - | ||
914 | -@item qcow2 | ||
915 | -QEMU image format, the most versatile format. Use it to have smaller | ||
916 | -images (useful if your filesystem does not supports holes, for example | ||
917 | -on Windows), zlib based compression and support of multiple VM | ||
918 | -snapshots. | ||
919 | - | ||
920 | -Supported options: | ||
921 | -@table @code | ||
922 | -@item compat | ||
923 | -Determines the qcow2 version to use. @code{compat=0.10} uses the | ||
924 | -traditional image format that can be read by any QEMU since 0.10. | ||
925 | -@code{compat=1.1} enables image format extensions that only QEMU 1.1 and | ||
926 | -newer understand (this is the default). Amongst others, this includes | ||
927 | -zero clusters, which allow efficient copy-on-read for sparse images. | ||
928 | - | ||
929 | -@item backing_file | ||
930 | -File name of a base image (see @option{create} subcommand) | ||
931 | -@item backing_fmt | ||
932 | -Image format of the base image | ||
933 | -@item encryption | ||
934 | -This option is deprecated and equivalent to @code{encrypt.format=aes} | ||
935 | - | ||
936 | -@item encrypt.format | ||
937 | - | ||
938 | -If this is set to @code{luks}, it requests that the qcow2 payload (not | ||
939 | -qcow2 header) be encrypted using the LUKS format. The passphrase to | ||
940 | -use to unlock the LUKS key slot is given by the @code{encrypt.key-secret} | ||
941 | -parameter. LUKS encryption parameters can be tuned with the other | ||
942 | -@code{encrypt.*} parameters. | ||
943 | - | ||
944 | -If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC. | ||
945 | -The encryption key is given by the @code{encrypt.key-secret} parameter. | ||
946 | -This encryption format is considered to be flawed by modern cryptography | ||
947 | -standards, suffering from a number of design problems: | ||
948 | - | ||
949 | -@itemize @minus | ||
950 | -@item The AES-CBC cipher is used with predictable initialization vectors based | ||
951 | -on the sector number. This makes it vulnerable to chosen plaintext attacks | ||
952 | -which can reveal the existence of encrypted data. | ||
953 | -@item The user passphrase is directly used as the encryption key. A poorly | ||
954 | -chosen or short passphrase will compromise the security of the encryption. | ||
955 | -@item In the event of the passphrase being compromised there is no way to | ||
956 | -change the passphrase to protect data in any qcow images. The files must | ||
957 | -be cloned, using a different encryption passphrase in the new file. The | ||
958 | -original file must then be securely erased using a program like shred, | ||
959 | -though even this is ineffective with many modern storage technologies. | ||
960 | -@end itemize | ||
961 | - | ||
962 | -The use of this is no longer supported in system emulators. Support only | ||
963 | -remains in the command line utilities, for the purposes of data liberation | ||
964 | -and interoperability with old versions of QEMU. The @code{luks} format | ||
965 | -should be used instead. | ||
966 | - | ||
967 | -@item encrypt.key-secret | ||
968 | - | ||
969 | -Provides the ID of a @code{secret} object that contains the passphrase | ||
970 | -(@code{encrypt.format=luks}) or encryption key (@code{encrypt.format=aes}). | ||
971 | - | ||
972 | -@item encrypt.cipher-alg | ||
973 | - | ||
974 | -Name of the cipher algorithm and key length. Currently defaults | ||
975 | -to @code{aes-256}. Only used when @code{encrypt.format=luks}. | ||
976 | - | ||
977 | -@item encrypt.cipher-mode | ||
978 | - | ||
979 | -Name of the encryption mode to use. Currently defaults to @code{xts}. | ||
980 | -Only used when @code{encrypt.format=luks}. | ||
981 | - | ||
982 | -@item encrypt.ivgen-alg | ||
983 | - | ||
984 | -Name of the initialization vector generator algorithm. Currently defaults | ||
985 | -to @code{plain64}. Only used when @code{encrypt.format=luks}. | ||
986 | - | ||
987 | -@item encrypt.ivgen-hash-alg | ||
988 | - | ||
989 | -Name of the hash algorithm to use with the initialization vector generator | ||
990 | -(if required). Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}. | ||
991 | - | ||
992 | -@item encrypt.hash-alg | ||
993 | - | ||
994 | -Name of the hash algorithm to use for PBKDF algorithm | ||
995 | -Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}. | ||
996 | - | ||
997 | -@item encrypt.iter-time | ||
998 | - | ||
999 | -Amount of time, in milliseconds, to use for PBKDF algorithm per key slot. | ||
1000 | -Defaults to @code{2000}. Only used when @code{encrypt.format=luks}. | ||
1001 | - | ||
1002 | -@item cluster_size | ||
1003 | -Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster | ||
1004 | -sizes can improve the image file size whereas larger cluster sizes generally | ||
1005 | -provide better performance. | ||
1006 | - | ||
1007 | -@item preallocation | ||
1008 | -Preallocation mode (allowed values: @code{off}, @code{metadata}, @code{falloc}, | ||
1009 | -@code{full}). An image with preallocated metadata is initially larger but can | ||
1010 | -improve performance when the image needs to grow. @code{falloc} and @code{full} | ||
1011 | -preallocations are like the same options of @code{raw} format, but sets up | ||
1012 | -metadata also. | ||
1013 | - | ||
1014 | -@item lazy_refcounts | ||
1015 | -If this option is set to @code{on}, reference count updates are postponed with | ||
1016 | -the goal of avoiding metadata I/O and improving performance. This is | ||
1017 | -particularly interesting with @option{cache=writethrough} which doesn't batch | ||
1018 | -metadata updates. The tradeoff is that after a host crash, the reference count | ||
1019 | -tables must be rebuilt, i.e. on the next open an (automatic) @code{qemu-img | ||
1020 | -check -r all} is required, which may take some time. | ||
1021 | - | ||
1022 | -This option can only be enabled if @code{compat=1.1} is specified. | ||
1023 | - | ||
1024 | -@item nocow | ||
1025 | -If this option is set to @code{on}, it will turn off COW of the file. It's only | ||
1026 | -valid on btrfs, no effect on other file systems. | ||
1027 | - | ||
1028 | -Btrfs has low performance when hosting a VM image file, even more when the guest | ||
1029 | -on the VM also using btrfs as file system. Turning off COW is a way to mitigate | ||
1030 | -this bad performance. Generally there are two ways to turn off COW on btrfs: | ||
1031 | -a) Disable it by mounting with nodatacow, then all newly created files will be | ||
1032 | -NOCOW. b) For an empty file, add the NOCOW file attribute. That's what this option | ||
1033 | -does. | ||
1034 | - | ||
1035 | -Note: this option is only valid to new or empty files. If there is an existing | ||
1036 | -file which is COW and has data blocks already, it couldn't be changed to NOCOW | ||
1037 | -by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if | ||
1038 | -the NOCOW flag is set or not (Capital 'C' is NOCOW flag). | ||
1039 | - | ||
1040 | -@end table | ||
1041 | - | ||
1042 | -@item qed | ||
1043 | -Old QEMU image format with support for backing files and compact image files | ||
1044 | -(when your filesystem or transport medium does not support holes). | ||
1045 | - | ||
1046 | -When converting QED images to qcow2, you might want to consider using the | ||
1047 | -@code{lazy_refcounts=on} option to get a more QED-like behaviour. | ||
1048 | - | ||
1049 | -Supported options: | ||
1050 | -@table @code | ||
1051 | -@item backing_file | ||
1052 | -File name of a base image (see @option{create} subcommand). | ||
1053 | -@item backing_fmt | ||
1054 | -Image file format of backing file (optional). Useful if the format cannot be | ||
1055 | -autodetected because it has no header, like some vhd/vpc files. | ||
1056 | -@item cluster_size | ||
1057 | -Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller | ||
1058 | -cluster sizes can improve the image file size whereas larger cluster sizes | ||
1059 | -generally provide better performance. | ||
1060 | -@item table_size | ||
1061 | -Changes the number of clusters per L1/L2 table (must be power-of-2 between 1 | ||
1062 | -and 16). There is normally no need to change this value but this option can be | ||
1063 | -used for performance benchmarking. | ||
1064 | -@end table | ||
1065 | - | ||
1066 | -@item qcow | ||
1067 | -Old QEMU image format with support for backing files, compact image files, | ||
1068 | -encryption and compression. | ||
1069 | - | ||
1070 | -Supported options: | ||
1071 | -@table @code | ||
1072 | -@item backing_file | ||
1073 | -File name of a base image (see @option{create} subcommand) | ||
1074 | -@item encryption | ||
1075 | -This option is deprecated and equivalent to @code{encrypt.format=aes} | ||
1076 | - | ||
1077 | -@item encrypt.format | ||
1078 | -If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC. | ||
1079 | -The encryption key is given by the @code{encrypt.key-secret} parameter. | ||
1080 | -This encryption format is considered to be flawed by modern cryptography | ||
1081 | -standards, suffering from a number of design problems enumerated previously | ||
1082 | -against the @code{qcow2} image format. | ||
1083 | - | ||
1084 | -The use of this is no longer supported in system emulators. Support only | ||
1085 | -remains in the command line utilities, for the purposes of data liberation | ||
1086 | -and interoperability with old versions of QEMU. | ||
1087 | - | ||
1088 | -Users requiring native encryption should use the @code{qcow2} format | ||
1089 | -instead with @code{encrypt.format=luks}. | ||
1090 | - | ||
1091 | -@item encrypt.key-secret | ||
1092 | - | ||
1093 | -Provides the ID of a @code{secret} object that contains the encryption | ||
1094 | -key (@code{encrypt.format=aes}). | ||
1095 | - | ||
1096 | -@end table | ||
1097 | - | ||
1098 | -@item luks | ||
1099 | - | ||
1100 | -LUKS v1 encryption format, compatible with Linux dm-crypt/cryptsetup | ||
1101 | - | ||
1102 | -Supported options: | ||
1103 | -@table @code | ||
1104 | - | ||
1105 | -@item key-secret | ||
1106 | - | ||
1107 | -Provides the ID of a @code{secret} object that contains the passphrase. | ||
1108 | - | ||
1109 | -@item cipher-alg | ||
1110 | - | ||
1111 | -Name of the cipher algorithm and key length. Currently defaults | ||
1112 | -to @code{aes-256}. | ||
1113 | - | ||
1114 | -@item cipher-mode | ||
1115 | - | ||
1116 | -Name of the encryption mode to use. Currently defaults to @code{xts}. | ||
1117 | - | ||
1118 | -@item ivgen-alg | ||
1119 | - | ||
1120 | -Name of the initialization vector generator algorithm. Currently defaults | ||
1121 | -to @code{plain64}. | ||
1122 | - | ||
1123 | -@item ivgen-hash-alg | ||
1124 | - | ||
1125 | -Name of the hash algorithm to use with the initialization vector generator | ||
1126 | -(if required). Defaults to @code{sha256}. | ||
1127 | - | ||
1128 | -@item hash-alg | ||
1129 | - | ||
1130 | -Name of the hash algorithm to use for PBKDF algorithm | ||
1131 | -Defaults to @code{sha256}. | ||
1132 | - | ||
1133 | -@item iter-time | ||
1134 | - | ||
1135 | -Amount of time, in milliseconds, to use for PBKDF algorithm per key slot. | ||
1136 | -Defaults to @code{2000}. | ||
1137 | - | ||
1138 | -@end table | ||
1139 | - | ||
1140 | -@item vdi | ||
1141 | -VirtualBox 1.1 compatible image format. | ||
1142 | -Supported options: | ||
1143 | -@table @code | ||
1144 | -@item static | ||
1145 | -If this option is set to @code{on}, the image is created with metadata | ||
1146 | -preallocation. | ||
1147 | -@end table | ||
1148 | - | ||
1149 | -@item vmdk | ||
1150 | -VMware 3 and 4 compatible image format. | ||
1151 | - | ||
1152 | -Supported options: | ||
1153 | -@table @code | ||
1154 | -@item backing_file | ||
1155 | -File name of a base image (see @option{create} subcommand). | ||
1156 | -@item compat6 | ||
1157 | -Create a VMDK version 6 image (instead of version 4) | ||
1158 | -@item hwversion | ||
1159 | -Specify vmdk virtual hardware version. Compat6 flag cannot be enabled | ||
1160 | -if hwversion is specified. | ||
1161 | -@item subformat | ||
1162 | -Specifies which VMDK subformat to use. Valid options are | ||
1163 | -@code{monolithicSparse} (default), | ||
1164 | -@code{monolithicFlat}, | ||
1165 | -@code{twoGbMaxExtentSparse}, | ||
1166 | -@code{twoGbMaxExtentFlat} and | ||
1167 | -@code{streamOptimized}. | ||
1168 | -@end table | ||
1169 | - | ||
1170 | -@item vpc | ||
1171 | -VirtualPC compatible image format (VHD). | ||
1172 | -Supported options: | ||
1173 | -@table @code | ||
1174 | -@item subformat | ||
1175 | -Specifies which VHD subformat to use. Valid options are | ||
1176 | -@code{dynamic} (default) and @code{fixed}. | ||
1177 | -@end table | ||
1178 | - | ||
1179 | -@item VHDX | ||
1180 | -Hyper-V compatible image format (VHDX). | ||
1181 | -Supported options: | ||
1182 | -@table @code | ||
1183 | -@item subformat | ||
1184 | -Specifies which VHDX subformat to use. Valid options are | ||
1185 | -@code{dynamic} (default) and @code{fixed}. | ||
1186 | -@item block_state_zero | ||
1187 | -Force use of payload blocks of type 'ZERO'. Can be set to @code{on} (default) | ||
1188 | -or @code{off}. When set to @code{off}, new blocks will be created as | ||
1189 | -@code{PAYLOAD_BLOCK_NOT_PRESENT}, which means parsers are free to return | ||
1190 | -arbitrary data for those blocks. Do not set to @code{off} when using | ||
1191 | -@code{qemu-img convert} with @code{subformat=dynamic}. | ||
1192 | -@item block_size | ||
1193 | -Block size; min 1 MB, max 256 MB. 0 means auto-calculate based on image size. | ||
1194 | -@item log_size | ||
1195 | -Log size; min 1 MB. | ||
1196 | -@end table | ||
1197 | -@end table | ||
1198 | - | ||
1199 | -@subsubsection Read-only formats | ||
1200 | -More disk image file formats are supported in a read-only mode. | ||
1201 | -@table @option | ||
1202 | -@item bochs | ||
1203 | -Bochs images of @code{growing} type. | ||
1204 | -@item cloop | ||
1205 | -Linux Compressed Loop image, useful only to reuse directly compressed | ||
1206 | -CD-ROM images present for example in the Knoppix CD-ROMs. | ||
1207 | -@item dmg | ||
1208 | -Apple disk image. | ||
1209 | -@item parallels | ||
1210 | -Parallels disk image format. | ||
1211 | -@end table | ||
1212 | - | ||
1213 | - | ||
1214 | -@node host_drives | ||
1215 | -@subsection Using host drives | ||
1216 | - | ||
1217 | -In addition to disk image files, QEMU can directly access host | ||
1218 | -devices. We describe here the usage for QEMU version >= 0.8.3. | ||
1219 | - | ||
1220 | -@subsubsection Linux | ||
1221 | - | ||
1222 | -On Linux, you can directly use the host device filename instead of a | ||
1223 | -disk image filename provided you have enough privileges to access | ||
1224 | -it. For example, use @file{/dev/cdrom} to access to the CDROM. | ||
1225 | - | ||
1226 | -@table @code | ||
1227 | -@item CD | ||
1228 | -You can specify a CDROM device even if no CDROM is loaded. QEMU has | ||
1229 | -specific code to detect CDROM insertion or removal. CDROM ejection by | ||
1230 | -the guest OS is supported. Currently only data CDs are supported. | ||
1231 | -@item Floppy | ||
1232 | -You can specify a floppy device even if no floppy is loaded. Floppy | ||
1233 | -removal is currently not detected accurately (if you change floppy | ||
1234 | -without doing floppy access while the floppy is not loaded, the guest | ||
1235 | -OS will think that the same floppy is loaded). | ||
1236 | -Use of the host's floppy device is deprecated, and support for it will | ||
1237 | -be removed in a future release. | ||
1238 | -@item Hard disks | ||
1239 | -Hard disks can be used. Normally you must specify the whole disk | ||
1240 | -(@file{/dev/hdb} instead of @file{/dev/hdb1}) so that the guest OS can | ||
1241 | -see it as a partitioned disk. WARNING: unless you know what you do, it | ||
1242 | -is better to only make READ-ONLY accesses to the hard disk otherwise | ||
1243 | -you may corrupt your host data (use the @option{-snapshot} command | ||
1244 | -line option or modify the device permissions accordingly). | ||
1245 | -@end table | ||
1246 | - | ||
1247 | -@subsubsection Windows | ||
1248 | - | ||
1249 | -@table @code | ||
1250 | -@item CD | ||
1251 | -The preferred syntax is the drive letter (e.g. @file{d:}). The | ||
1252 | -alternate syntax @file{\\.\d:} is supported. @file{/dev/cdrom} is | ||
1253 | -supported as an alias to the first CDROM drive. | ||
1254 | - | ||
1255 | -Currently there is no specific code to handle removable media, so it | ||
1256 | -is better to use the @code{change} or @code{eject} monitor commands to | ||
1257 | -change or eject media. | ||
1258 | -@item Hard disks | ||
1259 | -Hard disks can be used with the syntax: @file{\\.\PhysicalDrive@var{N}} | ||
1260 | -where @var{N} is the drive number (0 is the first hard disk). | ||
1261 | - | ||
1262 | -WARNING: unless you know what you do, it is better to only make | ||
1263 | -READ-ONLY accesses to the hard disk otherwise you may corrupt your | ||
1264 | -host data (use the @option{-snapshot} command line so that the | ||
1265 | -modifications are written in a temporary file). | ||
1266 | -@end table | ||
1267 | - | ||
1268 | - | ||
1269 | -@subsubsection Mac OS X | ||
1270 | - | ||
1271 | -@file{/dev/cdrom} is an alias to the first CDROM. | ||
1272 | - | ||
1273 | -Currently there is no specific code to handle removable media, so it | ||
1274 | -is better to use the @code{change} or @code{eject} monitor commands to | ||
1275 | -change or eject media. | ||
1276 | - | ||
1277 | -@node disk_images_fat_images | ||
1278 | -@subsection Virtual FAT disk images | ||
1279 | - | ||
1280 | -QEMU can automatically create a virtual FAT disk image from a | ||
1281 | -directory tree. In order to use it, just type: | ||
1282 | - | ||
1283 | -@example | ||
1284 | -qemu-system-i386 linux.img -hdb fat:/my_directory | ||
1285 | -@end example | ||
1286 | - | ||
1287 | -Then you access access to all the files in the @file{/my_directory} | ||
1288 | -directory without having to copy them in a disk image or to export | ||
1289 | -them via SAMBA or NFS. The default access is @emph{read-only}. | ||
1290 | - | ||
1291 | -Floppies can be emulated with the @code{:floppy:} option: | ||
1292 | - | ||
1293 | -@example | ||
1294 | -qemu-system-i386 linux.img -fda fat:floppy:/my_directory | ||
1295 | -@end example | ||
1296 | - | ||
1297 | -A read/write support is available for testing (beta stage) with the | ||
1298 | -@code{:rw:} option: | ||
1299 | - | ||
1300 | -@example | ||
1301 | -qemu-system-i386 linux.img -fda fat:floppy:rw:/my_directory | ||
1302 | -@end example | ||
1303 | - | ||
1304 | -What you should @emph{never} do: | ||
1305 | -@itemize | ||
1306 | -@item use non-ASCII filenames ; | ||
1307 | -@item use "-snapshot" together with ":rw:" ; | ||
1308 | -@item expect it to work when loadvm'ing ; | ||
1309 | -@item write to the FAT directory on the host system while accessing it with the guest system. | ||
1310 | -@end itemize | ||
1311 | - | ||
1312 | -@node disk_images_nbd | ||
1313 | -@subsection NBD access | ||
1314 | - | ||
1315 | -QEMU can access directly to block device exported using the Network Block Device | ||
1316 | -protocol. | ||
1317 | - | ||
1318 | -@example | ||
1319 | -qemu-system-i386 linux.img -hdb nbd://my_nbd_server.mydomain.org:1024/ | ||
1320 | -@end example | ||
1321 | - | ||
1322 | -If the NBD server is located on the same host, you can use an unix socket instead | ||
1323 | -of an inet socket: | ||
1324 | - | ||
1325 | -@example | ||
1326 | -qemu-system-i386 linux.img -hdb nbd+unix://?socket=/tmp/my_socket | ||
1327 | -@end example | ||
1328 | - | ||
1329 | -In this case, the block device must be exported using qemu-nbd: | ||
1330 | - | ||
1331 | -@example | ||
1332 | -qemu-nbd --socket=/tmp/my_socket my_disk.qcow2 | ||
1333 | -@end example | ||
1334 | - | ||
1335 | -The use of qemu-nbd allows sharing of a disk between several guests: | ||
1336 | -@example | ||
1337 | -qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2 | ||
1338 | -@end example | ||
1339 | - | ||
1340 | -@noindent | ||
1341 | -and then you can use it with two guests: | ||
1342 | -@example | ||
1343 | -qemu-system-i386 linux1.img -hdb nbd+unix://?socket=/tmp/my_socket | ||
1344 | -qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket | ||
1345 | -@end example | ||
1346 | - | ||
1347 | -If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's | ||
1348 | -own embedded NBD server), you must specify an export name in the URI: | ||
1349 | -@example | ||
1350 | -qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst | ||
1351 | -qemu-system-i386 -cdrom nbd://localhost/openSUSE-11.1-ppc-netinst | ||
1352 | -@end example | ||
1353 | - | ||
1354 | -The URI syntax for NBD is supported since QEMU 1.3. An alternative syntax is | ||
1355 | -also available. Here are some example of the older syntax: | ||
1356 | -@example | ||
1357 | -qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024 | ||
1358 | -qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket | ||
1359 | -qemu-system-i386 -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst | ||
1360 | -@end example | ||
1361 | - | ||
1362 | -@node disk_images_sheepdog | ||
1363 | -@subsection Sheepdog disk images | ||
1364 | - | ||
1365 | -Sheepdog is a distributed storage system for QEMU. It provides highly | ||
1366 | -available block level storage volumes that can be attached to | ||
1367 | -QEMU-based virtual machines. | ||
1368 | - | ||
1369 | -You can create a Sheepdog disk image with the command: | ||
1370 | -@example | ||
1371 | -qemu-img create sheepdog:///@var{image} @var{size} | ||
1372 | -@end example | ||
1373 | -where @var{image} is the Sheepdog image name and @var{size} is its | ||
1374 | -size. | ||
1375 | - | ||
1376 | -To import the existing @var{filename} to Sheepdog, you can use a | ||
1377 | -convert command. | ||
1378 | -@example | ||
1379 | -qemu-img convert @var{filename} sheepdog:///@var{image} | ||
1380 | -@end example | ||
1381 | - | ||
1382 | -You can boot from the Sheepdog disk image with the command: | ||
1383 | -@example | ||
1384 | -qemu-system-i386 sheepdog:///@var{image} | ||
1385 | -@end example | ||
1386 | - | ||
1387 | -You can also create a snapshot of the Sheepdog image like qcow2. | ||
1388 | -@example | ||
1389 | -qemu-img snapshot -c @var{tag} sheepdog:///@var{image} | ||
1390 | -@end example | ||
1391 | -where @var{tag} is a tag name of the newly created snapshot. | ||
1392 | - | ||
1393 | -To boot from the Sheepdog snapshot, specify the tag name of the | ||
1394 | -snapshot. | ||
1395 | -@example | ||
1396 | -qemu-system-i386 sheepdog:///@var{image}#@var{tag} | ||
1397 | -@end example | ||
1398 | - | ||
1399 | -You can create a cloned image from the existing snapshot. | ||
1400 | -@example | ||
1401 | -qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image} | ||
1402 | -@end example | ||
1403 | -where @var{base} is a image name of the source snapshot and @var{tag} | ||
1404 | -is its tag name. | ||
1405 | - | ||
1406 | -You can use an unix socket instead of an inet socket: | ||
1407 | - | ||
1408 | -@example | ||
1409 | -qemu-system-i386 sheepdog+unix:///@var{image}?socket=@var{path} | ||
1410 | -@end example | ||
1411 | - | ||
1412 | -If the Sheepdog daemon doesn't run on the local host, you need to | ||
1413 | -specify one of the Sheepdog servers to connect to. | ||
1414 | -@example | ||
1415 | -qemu-img create sheepdog://@var{hostname}:@var{port}/@var{image} @var{size} | ||
1416 | -qemu-system-i386 sheepdog://@var{hostname}:@var{port}/@var{image} | ||
1417 | -@end example | ||
1418 | - | ||
1419 | -@node disk_images_iscsi | ||
1420 | -@subsection iSCSI LUNs | ||
1421 | - | ||
1422 | -iSCSI is a popular protocol used to access SCSI devices across a computer | ||
1423 | -network. | ||
1424 | - | ||
1425 | -There are two different ways iSCSI devices can be used by QEMU. | ||
1426 | - | ||
1427 | -The first method is to mount the iSCSI LUN on the host, and make it appear as | ||
1428 | -any other ordinary SCSI device on the host and then to access this device as a | ||
1429 | -/dev/sd device from QEMU. How to do this differs between host OSes. | ||
1430 | - | ||
1431 | -The second method involves using the iSCSI initiator that is built into | ||
1432 | -QEMU. This provides a mechanism that works the same way regardless of which | ||
1433 | -host OS you are running QEMU on. This section will describe this second method | ||
1434 | -of using iSCSI together with QEMU. | ||
1435 | - | ||
1436 | -In QEMU, iSCSI devices are described using special iSCSI URLs | ||
1437 | - | ||
1438 | -@example | ||
1439 | -URL syntax: | ||
1440 | -iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun> | ||
1441 | -@end example | ||
1442 | - | ||
1443 | -Username and password are optional and only used if your target is set up | ||
1444 | -using CHAP authentication for access control. | ||
1445 | -Alternatively the username and password can also be set via environment | ||
1446 | -variables to have these not show up in the process list | ||
1447 | - | ||
1448 | -@example | ||
1449 | -export LIBISCSI_CHAP_USERNAME=<username> | ||
1450 | -export LIBISCSI_CHAP_PASSWORD=<password> | ||
1451 | -iscsi://<host>/<target-iqn-name>/<lun> | ||
1452 | -@end example | ||
1453 | - | ||
1454 | -Various session related parameters can be set via special options, either | ||
1455 | -in a configuration file provided via '-readconfig' or directly on the | ||
1456 | -command line. | ||
1457 | - | ||
1458 | -If the initiator-name is not specified qemu will use a default name | ||
1459 | -of 'iqn.2008-11.org.linux-kvm[:<uuid>'] where <uuid> is the UUID of the | ||
1460 | -virtual machine. If the UUID is not specified qemu will use | ||
1461 | -'iqn.2008-11.org.linux-kvm[:<name>'] where <name> is the name of the | ||
1462 | -virtual machine. | ||
1463 | - | ||
1464 | -@example | ||
1465 | -Setting a specific initiator name to use when logging in to the target | ||
1466 | --iscsi initiator-name=iqn.qemu.test:my-initiator | ||
1467 | -@end example | ||
1468 | - | ||
1469 | -@example | ||
1470 | -Controlling which type of header digest to negotiate with the target | ||
1471 | --iscsi header-digest=CRC32C|CRC32C-NONE|NONE-CRC32C|NONE | ||
1472 | -@end example | ||
1473 | - | ||
1474 | -These can also be set via a configuration file | ||
1475 | -@example | ||
1476 | -[iscsi] | ||
1477 | - user = "CHAP username" | ||
1478 | - password = "CHAP password" | ||
1479 | - initiator-name = "iqn.qemu.test:my-initiator" | ||
1480 | - # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE | ||
1481 | - header-digest = "CRC32C" | ||
1482 | -@end example | ||
1483 | - | ||
1484 | - | ||
1485 | -Setting the target name allows different options for different targets | ||
1486 | -@example | ||
1487 | -[iscsi "iqn.target.name"] | ||
1488 | - user = "CHAP username" | ||
1489 | - password = "CHAP password" | ||
1490 | - initiator-name = "iqn.qemu.test:my-initiator" | ||
1491 | - # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE | ||
1492 | - header-digest = "CRC32C" | ||
1493 | -@end example | ||
1494 | - | ||
1495 | - | ||
1496 | -Howto use a configuration file to set iSCSI configuration options: | ||
1497 | -@example | ||
1498 | -cat >iscsi.conf <<EOF | ||
1499 | -[iscsi] | ||
1500 | - user = "me" | ||
1501 | - password = "my password" | ||
1502 | - initiator-name = "iqn.qemu.test:my-initiator" | ||
1503 | - header-digest = "CRC32C" | ||
1504 | -EOF | ||
1505 | - | ||
1506 | -qemu-system-i386 -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \ | ||
1507 | - -readconfig iscsi.conf | ||
1508 | -@end example | ||
1509 | - | ||
1510 | - | ||
1511 | -Howto set up a simple iSCSI target on loopback and accessing it via QEMU: | ||
1512 | -@example | ||
1513 | -This example shows how to set up an iSCSI target with one CDROM and one DISK | ||
1514 | -using the Linux STGT software target. This target is available on Red Hat based | ||
1515 | -systems as the package 'scsi-target-utils'. | ||
1516 | - | ||
1517 | -tgtd --iscsi portal=127.0.0.1:3260 | ||
1518 | -tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test | ||
1519 | -tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \ | ||
1520 | - -b /IMAGES/disk.img --device-type=disk | ||
1521 | -tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \ | ||
1522 | - -b /IMAGES/cd.iso --device-type=cd | ||
1523 | -tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL | ||
1524 | - | ||
1525 | -qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \ | ||
1526 | - -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \ | ||
1527 | - -cdrom iscsi://127.0.0.1/iqn.qemu.test/2 | ||
1528 | -@end example | ||
1529 | - | ||
1530 | -@node disk_images_gluster | ||
1531 | -@subsection GlusterFS disk images | ||
1532 | - | ||
1533 | -GlusterFS is a user space distributed file system. | ||
1534 | - | ||
1535 | -You can boot from the GlusterFS disk image with the command: | ||
1536 | -@example | ||
1537 | -URI: | ||
1538 | -qemu-system-x86_64 -drive file=gluster[+@var{type}]://[@var{host}[:@var{port}]]/@var{volume}/@var{path} | ||
1539 | - [?socket=...][,file.debug=9][,file.logfile=...] | ||
1540 | - | ||
1541 | -JSON: | ||
1542 | -qemu-system-x86_64 'json:@{"driver":"qcow2", | ||
1543 | - "file":@{"driver":"gluster", | ||
1544 | - "volume":"testvol","path":"a.img","debug":9,"logfile":"...", | ||
1545 | - "server":[@{"type":"tcp","host":"...","port":"..."@}, | ||
1546 | - @{"type":"unix","socket":"..."@}]@}@}' | ||
1547 | -@end example | ||
1548 | - | ||
1549 | -@var{gluster} is the protocol. | ||
1550 | - | ||
1551 | -@var{type} specifies the transport type used to connect to gluster | ||
1552 | -management daemon (glusterd). Valid transport types are | ||
1553 | -tcp and unix. In the URI form, if a transport type isn't specified, | ||
1554 | -then tcp type is assumed. | ||
1555 | - | ||
1556 | -@var{host} specifies the server where the volume file specification for | ||
1557 | -the given volume resides. This can be either a hostname or an ipv4 address. | ||
1558 | -If transport type is unix, then @var{host} field should not be specified. | ||
1559 | -Instead @var{socket} field needs to be populated with the path to unix domain | ||
1560 | -socket. | ||
1561 | - | ||
1562 | -@var{port} is the port number on which glusterd is listening. This is optional | ||
1563 | -and if not specified, it defaults to port 24007. If the transport type is unix, | ||
1564 | -then @var{port} should not be specified. | ||
1565 | - | ||
1566 | -@var{volume} is the name of the gluster volume which contains the disk image. | ||
1567 | - | ||
1568 | -@var{path} is the path to the actual disk image that resides on gluster volume. | ||
1569 | - | ||
1570 | -@var{debug} is the logging level of the gluster protocol driver. Debug levels | ||
1571 | -are 0-9, with 9 being the most verbose, and 0 representing no debugging output. | ||
1572 | -The default level is 4. The current logging levels defined in the gluster source | ||
1573 | -are 0 - None, 1 - Emergency, 2 - Alert, 3 - Critical, 4 - Error, 5 - Warning, | ||
1574 | -6 - Notice, 7 - Info, 8 - Debug, 9 - Trace | ||
1575 | - | ||
1576 | -@var{logfile} is a commandline option to mention log file path which helps in | ||
1577 | -logging to the specified file and also help in persisting the gfapi logs. The | ||
1578 | -default is stderr. | ||
1579 | - | ||
1580 | - | ||
1581 | - | ||
1582 | - | ||
1583 | -You can create a GlusterFS disk image with the command: | ||
1584 | -@example | ||
1585 | -qemu-img create gluster://@var{host}/@var{volume}/@var{path} @var{size} | ||
1586 | -@end example | ||
1587 | - | ||
1588 | -Examples | ||
1589 | -@example | ||
1590 | -qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img | ||
1591 | -qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4/testvol/a.img | ||
1592 | -qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img | ||
1593 | -qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img | ||
1594 | -qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img | ||
1595 | -qemu-system-x86_64 -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img | ||
1596 | -qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket | ||
1597 | -qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img | ||
1598 | -qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img,file.debug=9,file.logfile=/var/log/qemu-gluster.log | ||
1599 | -qemu-system-x86_64 'json:@{"driver":"qcow2", | ||
1600 | - "file":@{"driver":"gluster", | ||
1601 | - "volume":"testvol","path":"a.img", | ||
1602 | - "debug":9,"logfile":"/var/log/qemu-gluster.log", | ||
1603 | - "server":[@{"type":"tcp","host":"1.2.3.4","port":24007@}, | ||
1604 | - @{"type":"unix","socket":"/var/run/glusterd.socket"@}]@}@}' | ||
1605 | -qemu-system-x86_64 -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img, | ||
1606 | - file.debug=9,file.logfile=/var/log/qemu-gluster.log, | ||
1607 | - file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007, | ||
1608 | - file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket | ||
1609 | -@end example | ||
1610 | - | ||
1611 | -@node disk_images_ssh | ||
1612 | -@subsection Secure Shell (ssh) disk images | ||
1613 | - | ||
1614 | -You can access disk images located on a remote ssh server | ||
1615 | -by using the ssh protocol: | ||
1616 | - | ||
1617 | -@example | ||
1618 | -qemu-system-x86_64 -drive file=ssh://[@var{user}@@]@var{server}[:@var{port}]/@var{path}[?host_key_check=@var{host_key_check}] | ||
1619 | -@end example | ||
1620 | - | ||
1621 | -Alternative syntax using properties: | ||
1622 | - | ||
1623 | -@example | ||
1624 | -qemu-system-x86_64 -drive file.driver=ssh[,file.user=@var{user}],file.host=@var{server}[,file.port=@var{port}],file.path=@var{path}[,file.host_key_check=@var{host_key_check}] | ||
1625 | -@end example | ||
1626 | - | ||
1627 | -@var{ssh} is the protocol. | ||
1628 | - | ||
1629 | -@var{user} is the remote user. If not specified, then the local | ||
1630 | -username is tried. | ||
1631 | - | ||
1632 | -@var{server} specifies the remote ssh server. Any ssh server can be | ||
1633 | -used, but it must implement the sftp-server protocol. Most Unix/Linux | ||
1634 | -systems should work without requiring any extra configuration. | ||
1635 | - | ||
1636 | -@var{port} is the port number on which sshd is listening. By default | ||
1637 | -the standard ssh port (22) is used. | ||
1638 | - | ||
1639 | -@var{path} is the path to the disk image. | ||
1640 | - | ||
1641 | -The optional @var{host_key_check} parameter controls how the remote | ||
1642 | -host's key is checked. The default is @code{yes} which means to use | ||
1643 | -the local @file{.ssh/known_hosts} file. Setting this to @code{no} | ||
1644 | -turns off known-hosts checking. Or you can check that the host key | ||
1645 | -matches a specific fingerprint: | ||
1646 | -@code{host_key_check=md5:78:45:8e:14:57:4f:d5:45:83:0a:0e:f3:49:82:c9:c8} | ||
1647 | -(@code{sha1:} can also be used as a prefix, but note that OpenSSH | ||
1648 | -tools only use MD5 to print fingerprints). | ||
1649 | - | ||
1650 | -Currently authentication must be done using ssh-agent. Other | ||
1651 | -authentication methods may be supported in future. | ||
1652 | - | ||
1653 | -Note: Many ssh servers do not support an @code{fsync}-style operation. | ||
1654 | -The ssh driver cannot guarantee that disk flush requests are | ||
1655 | -obeyed, and this causes a risk of disk corruption if the remote | ||
1656 | -server or network goes down during writes. The driver will | ||
1657 | -print a warning when @code{fsync} is not supported: | ||
1658 | - | ||
1659 | -warning: ssh server @code{ssh.example.com:22} does not support fsync | ||
1660 | - | ||
1661 | -With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is | ||
1662 | -supported. | ||
1663 | +@include docs/qemu-block-drivers.texi | ||
1664 | |||
1665 | @node pcsys_network | ||
1666 | @section Network emulation | ||
1667 | -- | ||
1668 | 2.13.5 | ||
1669 | |||
1670 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Cornelia Huck <cohuck@redhat.com> | ||
2 | 1 | ||
3 | The default cpu model on s390x does not provide zPCI, which is | ||
4 | not yet wired up on tcg. Moreover, virtio-ccw is the standard | ||
5 | on s390x, so use the -ccw instead of the -pci versions of virtio | ||
6 | devices on s390x. | ||
7 | |||
8 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Signed-off-by: Cornelia Huck <cohuck@redhat.com> | ||
10 | Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com> | ||
11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | --- | ||
13 | tests/qemu-iotests/040 | 6 +++++- | ||
14 | tests/qemu-iotests/139 | 12 ++++++++++-- | ||
15 | tests/qemu-iotests/182 | 13 +++++++++++-- | ||
16 | 3 files changed, 26 insertions(+), 5 deletions(-) | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 | ||
19 | index XXXXXXX..XXXXXXX 100755 | ||
20 | --- a/tests/qemu-iotests/040 | ||
21 | +++ b/tests/qemu-iotests/040 | ||
22 | @@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase): | ||
23 | qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img) | ||
24 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) | ||
25 | self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none") | ||
26 | - self.vm.add_device("virtio-scsi-pci") | ||
27 | + if iotests.qemu_default_machine == 's390-ccw-virtio': | ||
28 | + self.vm.add_device("virtio-scsi-ccw") | ||
29 | + else: | ||
30 | + self.vm.add_device("virtio-scsi-pci") | ||
31 | + | ||
32 | self.vm.add_device("scsi-hd,id=scsi0,drive=drive0") | ||
33 | self.vm.launch() | ||
34 | |||
35 | diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139 | ||
36 | index XXXXXXX..XXXXXXX 100644 | ||
37 | --- a/tests/qemu-iotests/139 | ||
38 | +++ b/tests/qemu-iotests/139 | ||
39 | @@ -XXX,XX +XXX,XX @@ import time | ||
40 | |||
41 | base_img = os.path.join(iotests.test_dir, 'base.img') | ||
42 | new_img = os.path.join(iotests.test_dir, 'new.img') | ||
43 | +if iotests.qemu_default_machine == 's390-ccw-virtio': | ||
44 | + default_virtio_blk = 'virtio-blk-ccw' | ||
45 | +else: | ||
46 | + default_virtio_blk = 'virtio-blk-pci' | ||
47 | |||
48 | class TestBlockdevDel(iotests.QMPTestCase): | ||
49 | |||
50 | def setUp(self): | ||
51 | iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M') | ||
52 | self.vm = iotests.VM() | ||
53 | - self.vm.add_device("virtio-scsi-pci,id=virtio-scsi") | ||
54 | + if iotests.qemu_default_machine == 's390-ccw-virtio': | ||
55 | + self.vm.add_device("virtio-scsi-ccw,id=virtio-scsi") | ||
56 | + else: | ||
57 | + self.vm.add_device("virtio-scsi-pci,id=virtio-scsi") | ||
58 | + | ||
59 | self.vm.launch() | ||
60 | |||
61 | def tearDown(self): | ||
62 | @@ -XXX,XX +XXX,XX @@ class TestBlockdevDel(iotests.QMPTestCase): | ||
63 | self.checkBlockDriverState(node, expect_error) | ||
64 | |||
65 | # Add a device model | ||
66 | - def addDeviceModel(self, device, backend, driver = 'virtio-blk-pci'): | ||
67 | + def addDeviceModel(self, device, backend, driver = default_virtio_blk): | ||
68 | result = self.vm.qmp('device_add', id = device, | ||
69 | driver = driver, drive = backend) | ||
70 | self.assert_qmp(result, 'return', {}) | ||
71 | diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182 | ||
72 | index XXXXXXX..XXXXXXX 100755 | ||
73 | --- a/tests/qemu-iotests/182 | ||
74 | +++ b/tests/qemu-iotests/182 | ||
75 | @@ -XXX,XX +XXX,XX @@ _supported_os Linux | ||
76 | |||
77 | size=32M | ||
78 | |||
79 | +case "$QEMU_DEFAULT_MACHINE" in | ||
80 | + s390-ccw-virtio) | ||
81 | + virtioblk=virtio-blk-ccw | ||
82 | + ;; | ||
83 | + *) | ||
84 | + virtioblk=virtio-blk-pci | ||
85 | + ;; | ||
86 | +esac | ||
87 | + | ||
88 | _make_test_img $size | ||
89 | |||
90 | echo "Starting QEMU" | ||
91 | _launch_qemu -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \ | ||
92 | - -device virtio-blk-pci,drive=drive0 | ||
93 | + -device $virtioblk,drive=drive0 | ||
94 | |||
95 | echo | ||
96 | echo "Starting a second QEMU using the same image should fail" | ||
97 | echo 'quit' | $QEMU -monitor stdio \ | ||
98 | -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \ | ||
99 | - -device virtio-blk-pci,drive=drive0 2>&1 | _filter_testdir 2>&1 | | ||
100 | + -device $virtioblk,drive=drive0 2>&1 | _filter_testdir 2>&1 | | ||
101 | _filter_qemu | | ||
102 | sed -e '/falling back to POSIX file/d' \ | ||
103 | -e '/locks can be lost unexpectedly/d' | ||
104 | -- | ||
105 | 2.13.5 | ||
106 | |||
107 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Cornelia Huck <cohuck@redhat.com> | ||
2 | 1 | ||
3 | The default cpu model on s390x does not provide zPCI, which is | ||
4 | not yet wired up on tcg. Moreover, virtio-ccw is the standard | ||
5 | on s390x, so use the -ccw instead of the -pci versions of virtio | ||
6 | devices on s390x. | ||
7 | |||
8 | Signed-off-by: Cornelia Huck <cohuck@redhat.com> | ||
9 | Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com> | ||
10 | Reviewed-by: David Hildenbrand <david@redhat.com> | ||
11 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | tests/qemu-iotests/051 | 12 +++++++++++- | ||
15 | tests/qemu-iotests/051.out | 2 +- | ||
16 | tests/qemu-iotests/051.pc.out | 2 +- | ||
17 | 3 files changed, 13 insertions(+), 3 deletions(-) | ||
18 | |||
19 | diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 | ||
20 | index XXXXXXX..XXXXXXX 100755 | ||
21 | --- a/tests/qemu-iotests/051 | ||
22 | +++ b/tests/qemu-iotests/051 | ||
23 | @@ -XXX,XX +XXX,XX @@ echo | ||
24 | echo === Device without drive === | ||
25 | echo | ||
26 | |||
27 | -run_qemu -device virtio-scsi-pci -device scsi-hd | ||
28 | +case "$QEMU_DEFAULT_MACHINE" in | ||
29 | + s390-ccw-virtio) | ||
30 | + virtio_scsi=virtio-scsi-ccw | ||
31 | + ;; | ||
32 | + *) | ||
33 | + virtio_scsi=virtio-scsi-pci | ||
34 | + ;; | ||
35 | +esac | ||
36 | + | ||
37 | +run_qemu -device $virtio_scsi -device scsi-hd | | ||
38 | + sed -e "s/$virtio_scsi/VIRTIO_SCSI/" | ||
39 | |||
40 | echo | ||
41 | echo === Overriding backing file === | ||
42 | diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out | ||
43 | index XXXXXXX..XXXXXXX 100644 | ||
44 | --- a/tests/qemu-iotests/051.out | ||
45 | +++ b/tests/qemu-iotests/051.out | ||
46 | @@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specif | ||
47 | |||
48 | === Device without drive === | ||
49 | |||
50 | -Testing: -device virtio-scsi-pci -device scsi-hd | ||
51 | +Testing: -device VIRTIO_SCSI -device scsi-hd | ||
52 | QEMU X.Y.Z monitor - type 'help' for more information | ||
53 | (qemu) QEMU_PROG: -device scsi-hd: drive property not set | ||
54 | |||
55 | diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/tests/qemu-iotests/051.pc.out | ||
58 | +++ b/tests/qemu-iotests/051.pc.out | ||
59 | @@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specif | ||
60 | |||
61 | === Device without drive === | ||
62 | |||
63 | -Testing: -device virtio-scsi-pci -device scsi-hd | ||
64 | +Testing: -device VIRTIO_SCSI -device scsi-hd | ||
65 | QEMU X.Y.Z monitor - type 'help' for more information | ||
66 | (qemu) QEMU_PROG: -device scsi-hd: drive property not set | ||
67 | |||
68 | -- | ||
69 | 2.13.5 | ||
70 | |||
71 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Cornelia Huck <cohuck@redhat.com> | ||
2 | 1 | ||
3 | The default cpu model on s390x does not provide zPCI, which is | ||
4 | not yet wired up on tcg. Moreover, virtio-ccw is the standard | ||
5 | on s390x. | ||
6 | |||
7 | Using virtio-scsi will implicitly pick the right device, so just | ||
8 | switch to that for simplicity. | ||
9 | |||
10 | Signed-off-by: Cornelia Huck <cohuck@redhat.com> | ||
11 | Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com> | ||
12 | Reviewed-by: David Hildenbrand <david@redhat.com> | ||
13 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | --- | ||
16 | tests/qemu-iotests/067 | 2 +- | ||
17 | tests/qemu-iotests/067.out | 2 +- | ||
18 | 2 files changed, 2 insertions(+), 2 deletions(-) | ||
19 | |||
20 | diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 | ||
21 | index XXXXXXX..XXXXXXX 100755 | ||
22 | --- a/tests/qemu-iotests/067 | ||
23 | +++ b/tests/qemu-iotests/067 | ||
24 | @@ -XXX,XX +XXX,XX @@ echo | ||
25 | echo === Empty drive with -device and device_del === | ||
26 | echo | ||
27 | |||
28 | -run_qemu -device virtio-scsi-pci -device scsi-cd,id=cd0 <<EOF | ||
29 | +run_qemu -device virtio-scsi -device scsi-cd,id=cd0 <<EOF | ||
30 | { "execute": "qmp_capabilities" } | ||
31 | { "execute": "query-block" } | ||
32 | { "execute": "device_del", "arguments": { "id": "cd0" } } | ||
33 | diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/tests/qemu-iotests/067.out | ||
36 | +++ b/tests/qemu-iotests/067.out | ||
37 | @@ -XXX,XX +XXX,XX @@ Testing: | ||
38 | |||
39 | === Empty drive with -device and device_del === | ||
40 | |||
41 | -Testing: -device virtio-scsi-pci -device scsi-cd,id=cd0 | ||
42 | +Testing: -device virtio-scsi -device scsi-cd,id=cd0 | ||
43 | { | ||
44 | QMP_VERSION | ||
45 | } | ||
46 | -- | ||
47 | 2.13.5 | ||
48 | |||
49 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Fam Zheng <famz@redhat.com> | ||
2 | 1 | ||
3 | So it is easier to copy paste the path. | ||
4 | |||
5 | Signed-off-by: Fam Zheng <famz@redhat.com> | ||
6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
7 | --- | ||
8 | tests/qemu-iotests/check | 2 +- | ||
9 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
10 | |||
11 | diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check | ||
12 | index XXXXXXX..XXXXXXX 100755 | ||
13 | --- a/tests/qemu-iotests/check | ||
14 | +++ b/tests/qemu-iotests/check | ||
15 | @@ -XXX,XX +XXX,XX @@ do | ||
16 | else | ||
17 | echo " - output mismatch (see $seq.out.bad)" | ||
18 | mv $tmp.out $seq.out.bad | ||
19 | - $diff -w "$reference" $seq.out.bad | ||
20 | + $diff -w "$reference" $(realpath $seq.out.bad) | ||
21 | err=true | ||
22 | fi | ||
23 | fi | ||
24 | -- | ||
25 | 2.13.5 | ||
26 | |||
27 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | If bkt->max == 0 and bkt->burst_length > 1 then we could have a | ||
4 | division by 0 in throttle_do_compute_wait(). That configuration is | ||
5 | however not permitted and is already detected by throttle_is_valid(), | ||
6 | but let's assert it in throttle_compute_wait() to make it explicit. | ||
7 | |||
8 | Found by Coverity (CID: 1381016). | ||
9 | |||
10 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
11 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | util/throttle.c | 1 + | ||
15 | 1 file changed, 1 insertion(+) | ||
16 | |||
17 | diff --git a/util/throttle.c b/util/throttle.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/util/throttle.c | ||
20 | +++ b/util/throttle.c | ||
21 | @@ -XXX,XX +XXX,XX @@ int64_t throttle_compute_wait(LeakyBucket *bkt) | ||
22 | /* If the main bucket is not full yet we still have to check the | ||
23 | * burst bucket in order to enforce the burst limit */ | ||
24 | if (bkt->burst_length > 1) { | ||
25 | + assert(bkt->max > 0); /* see throttle_is_valid() */ | ||
26 | extra = bkt->burst_level - burst_bucket_size; | ||
27 | if (extra > 0) { | ||
28 | return throttle_do_compute_wait(bkt->max, extra); | ||
29 | -- | ||
30 | 2.13.5 | ||
31 | |||
32 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Manos Pitsidianakis <el13635@mail.ntua.gr> | ||
2 | 1 | ||
3 | RestartData is the opaque data of the throttle_group_restart_queue_entry | ||
4 | coroutine. By being stack allocated, it isn't available anymore if | ||
5 | aio_co_enter schedules the coroutine with a bottom half and runs after | ||
6 | throttle_group_restart_queue returns. | ||
7 | |||
8 | Cc: qemu-stable@nongnu.org | ||
9 | Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr> | ||
10 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
11 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | block/throttle-groups.c | 12 +++++++----- | ||
15 | 1 file changed, 7 insertions(+), 5 deletions(-) | ||
16 | |||
17 | diff --git a/block/throttle-groups.c b/block/throttle-groups.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/block/throttle-groups.c | ||
20 | +++ b/block/throttle-groups.c | ||
21 | @@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_group_restart_queue_entry(void *opaque) | ||
22 | schedule_next_request(tgm, is_write); | ||
23 | qemu_mutex_unlock(&tg->lock); | ||
24 | } | ||
25 | + | ||
26 | + g_free(data); | ||
27 | } | ||
28 | |||
29 | static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write) | ||
30 | { | ||
31 | Coroutine *co; | ||
32 | - RestartData rd = { | ||
33 | - .tgm = tgm, | ||
34 | - .is_write = is_write | ||
35 | - }; | ||
36 | + RestartData *rd = g_new0(RestartData, 1); | ||
37 | + | ||
38 | + rd->tgm = tgm; | ||
39 | + rd->is_write = is_write; | ||
40 | |||
41 | - co = qemu_coroutine_create(throttle_group_restart_queue_entry, &rd); | ||
42 | + co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd); | ||
43 | aio_co_enter(tgm->aio_context, co); | ||
44 | } | ||
45 | |||
46 | -- | ||
47 | 2.13.5 | ||
48 | |||
49 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
2 | 1 | ||
3 | Remove the unnecessary home-grown redefinition of the assert() macro here, | ||
4 | and remove the unusable debug code at the end of the checkpoint() function. | ||
5 | The code there uses assert() with side-effects (assignment to the "mapping" | ||
6 | variable), which should be avoided. Looking more closely, it seems as it is | ||
7 | apparently also only usable for one certain directory layout (with a file | ||
8 | named USB.H in it) and thus is of no use for the rest of the world. | ||
9 | |||
10 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
11 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | --- | ||
15 | block/vvfat.c | 26 ++------------------------ | ||
16 | 1 file changed, 2 insertions(+), 24 deletions(-) | ||
17 | |||
18 | diff --git a/block/vvfat.c b/block/vvfat.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/vvfat.c | ||
21 | +++ b/block/vvfat.c | ||
22 | @@ -XXX,XX +XXX,XX @@ | ||
23 | |||
24 | static void checkpoint(void); | ||
25 | |||
26 | -#ifdef __MINGW32__ | ||
27 | -void nonono(const char* file, int line, const char* msg) { | ||
28 | - fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg); | ||
29 | - exit(-5); | ||
30 | -} | ||
31 | -#undef assert | ||
32 | -#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0) | ||
33 | -#endif | ||
34 | - | ||
35 | #else | ||
36 | |||
37 | #define DLOG(a) | ||
38 | @@ -XXX,XX +XXX,XX @@ static void bdrv_vvfat_init(void) | ||
39 | block_init(bdrv_vvfat_init); | ||
40 | |||
41 | #ifdef DEBUG | ||
42 | -static void checkpoint(void) { | ||
43 | +static void checkpoint(void) | ||
44 | +{ | ||
45 | assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2); | ||
46 | check1(vvv); | ||
47 | check2(vvv); | ||
48 | assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY)); | ||
49 | -#if 0 | ||
50 | - if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf) | ||
51 | - fprintf(stderr, "Nonono!\n"); | ||
52 | - mapping_t* mapping; | ||
53 | - direntry_t* direntry; | ||
54 | - assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next); | ||
55 | - assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next); | ||
56 | - if (vvv->mapping.next<47) | ||
57 | - return; | ||
58 | - assert((mapping = array_get(&(vvv->mapping), 47))); | ||
59 | - assert(mapping->dir_index < vvv->directory.next); | ||
60 | - direntry = array_get(&(vvv->directory), mapping->dir_index); | ||
61 | - assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0); | ||
62 | -#endif | ||
63 | } | ||
64 | #endif | ||
65 | -- | ||
66 | 2.13.5 | ||
67 | |||
68 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | qemu-io provides a 'reopen' command that allows switching from writable | ||
2 | to read-only access. We need to make sure that we don't try to keep | ||
3 | write permissions to a BlockBackend that becomes read-only, otherwise | ||
4 | things are going to fail. | ||
5 | 1 | ||
6 | This requires a bdrv_drain() call because otherwise in-flight AIO | ||
7 | write requests could issue new internal requests while the permission | ||
8 | has already gone away, which would cause assertion failures. Draining | ||
9 | the queue doesn't break AIO requests in any new way, bdrv_reopen() would | ||
10 | drain it anyway only a few lines later. | ||
11 | |||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | Reviewed-by: Fam Zheng <famz@redhat.com> | ||
14 | --- | ||
15 | qemu-io-cmds.c | 12 ++++++++++++ | ||
16 | tests/qemu-iotests/187.out | 2 +- | ||
17 | 2 files changed, 13 insertions(+), 1 deletion(-) | ||
18 | |||
19 | diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/qemu-io-cmds.c | ||
22 | +++ b/qemu-io-cmds.c | ||
23 | @@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv) | ||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | + if (!(flags & BDRV_O_RDWR)) { | ||
28 | + uint64_t orig_perm, orig_shared_perm; | ||
29 | + | ||
30 | + bdrv_drain(bs); | ||
31 | + | ||
32 | + blk_get_perm(blk, &orig_perm, &orig_shared_perm); | ||
33 | + blk_set_perm(blk, | ||
34 | + orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED), | ||
35 | + orig_shared_perm, | ||
36 | + &error_abort); | ||
37 | + } | ||
38 | + | ||
39 | qopts = qemu_opts_find(&reopen_opts, NULL); | ||
40 | opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL; | ||
41 | qemu_opts_reset(&reopen_opts); | ||
42 | diff --git a/tests/qemu-iotests/187.out b/tests/qemu-iotests/187.out | ||
43 | index XXXXXXX..XXXXXXX 100644 | ||
44 | --- a/tests/qemu-iotests/187.out | ||
45 | +++ b/tests/qemu-iotests/187.out | ||
46 | @@ -XXX,XX +XXX,XX @@ Start from read-write | ||
47 | |||
48 | wrote 65536/65536 bytes at offset 0 | ||
49 | 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
50 | -write failed: Operation not permitted | ||
51 | +Block node is read-only | ||
52 | wrote 65536/65536 bytes at offset 0 | ||
53 | 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
54 | *** done | ||
55 | -- | ||
56 | 2.13.5 | ||
57 | |||
58 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | In the context of bdrv_reopen(), we'll have to look at the state of the | ||
2 | graph as it will be after the reopen. This interface addition is in | ||
3 | preparation for the change. | ||
4 | 1 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
6 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
7 | --- | ||
8 | include/block/block_int.h | 7 +++++++ | ||
9 | block.c | 19 ++++++++++++------- | ||
10 | block/commit.c | 1 + | ||
11 | block/mirror.c | 1 + | ||
12 | block/replication.c | 1 + | ||
13 | block/vvfat.c | 1 + | ||
14 | 6 files changed, 23 insertions(+), 7 deletions(-) | ||
15 | |||
16 | diff --git a/include/block/block_int.h b/include/block/block_int.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/include/block/block_int.h | ||
19 | +++ b/include/block/block_int.h | ||
20 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
21 | * | ||
22 | * If @c is NULL, return the permissions for attaching a new child for the | ||
23 | * given @role. | ||
24 | + * | ||
25 | + * If @reopen_queue is non-NULL, don't return the currently needed | ||
26 | + * permissions, but those that will be needed after applying the | ||
27 | + * @reopen_queue. | ||
28 | */ | ||
29 | void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c, | ||
30 | const BdrvChildRole *role, | ||
31 | + BlockReopenQueue *reopen_queue, | ||
32 | uint64_t parent_perm, uint64_t parent_shared, | ||
33 | uint64_t *nperm, uint64_t *nshared); | ||
34 | |||
35 | @@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, | ||
36 | * all children */ | ||
37 | void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
38 | const BdrvChildRole *role, | ||
39 | + BlockReopenQueue *reopen_queue, | ||
40 | uint64_t perm, uint64_t shared, | ||
41 | uint64_t *nperm, uint64_t *nshared); | ||
42 | |||
43 | @@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
44 | * CONSISTENT_READ and doesn't share WRITE. */ | ||
45 | void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
46 | const BdrvChildRole *role, | ||
47 | + BlockReopenQueue *reopen_queue, | ||
48 | uint64_t perm, uint64_t shared, | ||
49 | uint64_t *nperm, uint64_t *nshared); | ||
50 | |||
51 | diff --git a/block.c b/block.c | ||
52 | index XXXXXXX..XXXXXXX 100644 | ||
53 | --- a/block.c | ||
54 | +++ b/block.c | ||
55 | @@ -XXX,XX +XXX,XX @@ static void bdrv_child_abort_perm_update(BdrvChild *c); | ||
56 | static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared); | ||
57 | |||
58 | static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs, | ||
59 | - BdrvChild *c, | ||
60 | - const BdrvChildRole *role, | ||
61 | + BdrvChild *c, const BdrvChildRole *role, | ||
62 | + BlockReopenQueue *reopen_queue, | ||
63 | uint64_t parent_perm, uint64_t parent_shared, | ||
64 | uint64_t *nperm, uint64_t *nshared) | ||
65 | { | ||
66 | if (bs->drv && bs->drv->bdrv_child_perm) { | ||
67 | - bs->drv->bdrv_child_perm(bs, c, role, | ||
68 | + bs->drv->bdrv_child_perm(bs, c, role, reopen_queue, | ||
69 | parent_perm, parent_shared, | ||
70 | nperm, nshared); | ||
71 | } | ||
72 | + /* TODO Take force_share from reopen_queue */ | ||
73 | if (child_bs && child_bs->force_share) { | ||
74 | *nshared = BLK_PERM_ALL; | ||
75 | } | ||
76 | @@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms, | ||
77 | /* Check all children */ | ||
78 | QLIST_FOREACH(c, &bs->children, next) { | ||
79 | uint64_t cur_perm, cur_shared; | ||
80 | - bdrv_child_perm(bs, c->bs, c, c->role, | ||
81 | + bdrv_child_perm(bs, c->bs, c, c->role, NULL, | ||
82 | cumulative_perms, cumulative_shared_perms, | ||
83 | &cur_perm, &cur_shared); | ||
84 | ret = bdrv_child_check_perm(c, cur_perm, cur_shared, ignore_children, | ||
85 | @@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms, | ||
86 | /* Update all children */ | ||
87 | QLIST_FOREACH(c, &bs->children, next) { | ||
88 | uint64_t cur_perm, cur_shared; | ||
89 | - bdrv_child_perm(bs, c->bs, c, c->role, | ||
90 | + bdrv_child_perm(bs, c->bs, c, c->role, NULL, | ||
91 | cumulative_perms, cumulative_shared_perms, | ||
92 | &cur_perm, &cur_shared); | ||
93 | bdrv_child_set_perm(c, cur_perm, cur_shared); | ||
94 | @@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, | ||
95 | |||
96 | void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
97 | const BdrvChildRole *role, | ||
98 | + BlockReopenQueue *reopen_queue, | ||
99 | uint64_t perm, uint64_t shared, | ||
100 | uint64_t *nperm, uint64_t *nshared) | ||
101 | { | ||
102 | @@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
103 | |||
104 | void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
105 | const BdrvChildRole *role, | ||
106 | + BlockReopenQueue *reopen_queue, | ||
107 | uint64_t perm, uint64_t shared, | ||
108 | uint64_t *nperm, uint64_t *nshared) | ||
109 | { | ||
110 | @@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
111 | if (!backing) { | ||
112 | /* Apart from the modifications below, the same permissions are | ||
113 | * forwarded and left alone as for filters */ | ||
114 | - bdrv_filter_default_perms(bs, c, role, perm, shared, &perm, &shared); | ||
115 | + bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared, | ||
116 | + &perm, &shared); | ||
117 | |||
118 | /* Format drivers may touch metadata even if the guest doesn't write */ | ||
119 | + /* TODO Take flags from reopen_queue */ | ||
120 | if (bdrv_is_writable(bs)) { | ||
121 | perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE; | ||
122 | } | ||
123 | @@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, | ||
124 | |||
125 | assert(parent_bs->drv); | ||
126 | assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs)); | ||
127 | - bdrv_child_perm(parent_bs, child_bs, NULL, child_role, | ||
128 | + bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL, | ||
129 | perm, shared_perm, &perm, &shared_perm); | ||
130 | |||
131 | child = bdrv_root_attach_child(child_bs, child_name, child_role, | ||
132 | diff --git a/block/commit.c b/block/commit.c | ||
133 | index XXXXXXX..XXXXXXX 100644 | ||
134 | --- a/block/commit.c | ||
135 | +++ b/block/commit.c | ||
136 | @@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_close(BlockDriverState *bs) | ||
137 | |||
138 | static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c, | ||
139 | const BdrvChildRole *role, | ||
140 | + BlockReopenQueue *reopen_queue, | ||
141 | uint64_t perm, uint64_t shared, | ||
142 | uint64_t *nperm, uint64_t *nshared) | ||
143 | { | ||
144 | diff --git a/block/mirror.c b/block/mirror.c | ||
145 | index XXXXXXX..XXXXXXX 100644 | ||
146 | --- a/block/mirror.c | ||
147 | +++ b/block/mirror.c | ||
148 | @@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_close(BlockDriverState *bs) | ||
149 | |||
150 | static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c, | ||
151 | const BdrvChildRole *role, | ||
152 | + BlockReopenQueue *reopen_queue, | ||
153 | uint64_t perm, uint64_t shared, | ||
154 | uint64_t *nperm, uint64_t *nshared) | ||
155 | { | ||
156 | diff --git a/block/replication.c b/block/replication.c | ||
157 | index XXXXXXX..XXXXXXX 100644 | ||
158 | --- a/block/replication.c | ||
159 | +++ b/block/replication.c | ||
160 | @@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs) | ||
161 | |||
162 | static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, | ||
163 | const BdrvChildRole *role, | ||
164 | + BlockReopenQueue *reopen_queue, | ||
165 | uint64_t perm, uint64_t shared, | ||
166 | uint64_t *nperm, uint64_t *nshared) | ||
167 | { | ||
168 | diff --git a/block/vvfat.c b/block/vvfat.c | ||
169 | index XXXXXXX..XXXXXXX 100644 | ||
170 | --- a/block/vvfat.c | ||
171 | +++ b/block/vvfat.c | ||
172 | @@ -XXX,XX +XXX,XX @@ err: | ||
173 | |||
174 | static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c, | ||
175 | const BdrvChildRole *role, | ||
176 | + BlockReopenQueue *reopen_queue, | ||
177 | uint64_t perm, uint64_t shared, | ||
178 | uint64_t *nperm, uint64_t *nshared) | ||
179 | { | ||
180 | -- | ||
181 | 2.13.5 | ||
182 | |||
183 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | In the context of bdrv_reopen(), we'll have to look at the state of the | ||
2 | graph as it will be after the reopen. This interface addition is in | ||
3 | preparation for the change. | ||
4 | 1 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
6 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
7 | --- | ||
8 | block.c | 34 +++++++++++++++++++--------------- | ||
9 | 1 file changed, 19 insertions(+), 15 deletions(-) | ||
10 | |||
11 | diff --git a/block.c b/block.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/block.c | ||
14 | +++ b/block.c | ||
15 | @@ -XXX,XX +XXX,XX @@ static int bdrv_fill_options(QDict **options, const char *filename, | ||
16 | return 0; | ||
17 | } | ||
18 | |||
19 | -static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, | ||
20 | +static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q, | ||
21 | + uint64_t perm, uint64_t shared, | ||
22 | GSList *ignore_children, Error **errp); | ||
23 | static void bdrv_child_abort_perm_update(BdrvChild *c); | ||
24 | static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared); | ||
25 | @@ -XXX,XX +XXX,XX @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs, | ||
26 | * A call to this function must always be followed by a call to bdrv_set_perm() | ||
27 | * or bdrv_abort_perm_update(). | ||
28 | */ | ||
29 | -static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms, | ||
30 | +static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, | ||
31 | + uint64_t cumulative_perms, | ||
32 | uint64_t cumulative_shared_perms, | ||
33 | GSList *ignore_children, Error **errp) | ||
34 | { | ||
35 | @@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms, | ||
36 | /* Check all children */ | ||
37 | QLIST_FOREACH(c, &bs->children, next) { | ||
38 | uint64_t cur_perm, cur_shared; | ||
39 | - bdrv_child_perm(bs, c->bs, c, c->role, NULL, | ||
40 | + bdrv_child_perm(bs, c->bs, c, c->role, q, | ||
41 | cumulative_perms, cumulative_shared_perms, | ||
42 | &cur_perm, &cur_shared); | ||
43 | - ret = bdrv_child_check_perm(c, cur_perm, cur_shared, ignore_children, | ||
44 | - errp); | ||
45 | + ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, | ||
46 | + ignore_children, errp); | ||
47 | if (ret < 0) { | ||
48 | return ret; | ||
49 | } | ||
50 | @@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm) | ||
51 | * | ||
52 | * Needs to be followed by a call to either bdrv_set_perm() or | ||
53 | * bdrv_abort_perm_update(). */ | ||
54 | -static int bdrv_check_update_perm(BlockDriverState *bs, uint64_t new_used_perm, | ||
55 | +static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q, | ||
56 | + uint64_t new_used_perm, | ||
57 | uint64_t new_shared_perm, | ||
58 | GSList *ignore_children, Error **errp) | ||
59 | { | ||
60 | @@ -XXX,XX +XXX,XX @@ static int bdrv_check_update_perm(BlockDriverState *bs, uint64_t new_used_perm, | ||
61 | cumulative_shared_perms &= c->shared_perm; | ||
62 | } | ||
63 | |||
64 | - return bdrv_check_perm(bs, cumulative_perms, cumulative_shared_perms, | ||
65 | + return bdrv_check_perm(bs, q, cumulative_perms, cumulative_shared_perms, | ||
66 | ignore_children, errp); | ||
67 | } | ||
68 | |||
69 | /* Needs to be followed by a call to either bdrv_child_set_perm() or | ||
70 | * bdrv_child_abort_perm_update(). */ | ||
71 | -static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, | ||
72 | +static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q, | ||
73 | + uint64_t perm, uint64_t shared, | ||
74 | GSList *ignore_children, Error **errp) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | ignore_children = g_slist_prepend(g_slist_copy(ignore_children), c); | ||
79 | - ret = bdrv_check_update_perm(c->bs, perm, shared, ignore_children, errp); | ||
80 | + ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp); | ||
81 | g_slist_free(ignore_children); | ||
82 | |||
83 | return ret; | ||
84 | @@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, | ||
85 | { | ||
86 | int ret; | ||
87 | |||
88 | - ret = bdrv_child_check_perm(c, perm, shared, NULL, errp); | ||
89 | + ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL, errp); | ||
90 | if (ret < 0) { | ||
91 | bdrv_child_abort_perm_update(c); | ||
92 | return ret; | ||
93 | @@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) | ||
94 | * because we're just taking a parent away, so we're loosening | ||
95 | * restrictions. */ | ||
96 | bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm); | ||
97 | - bdrv_check_perm(old_bs, perm, shared_perm, NULL, &error_abort); | ||
98 | + bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL, &error_abort); | ||
99 | bdrv_set_perm(old_bs, perm, shared_perm); | ||
100 | } | ||
101 | |||
102 | @@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, | ||
103 | BdrvChild *child; | ||
104 | int ret; | ||
105 | |||
106 | - ret = bdrv_check_update_perm(child_bs, perm, shared_perm, NULL, errp); | ||
107 | + ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp); | ||
108 | if (ret < 0) { | ||
109 | bdrv_abort_perm_update(child_bs); | ||
110 | return NULL; | ||
111 | @@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, | ||
112 | |||
113 | /* Check whether the required permissions can be granted on @to, ignoring | ||
114 | * all BdrvChild in @list so that they can't block themselves. */ | ||
115 | - ret = bdrv_check_update_perm(to, perm, shared, list, errp); | ||
116 | + ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp); | ||
117 | if (ret < 0) { | ||
118 | bdrv_abort_perm_update(to); | ||
119 | goto out; | ||
120 | @@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) | ||
121 | |||
122 | /* Update permissions, they may differ for inactive nodes */ | ||
123 | bdrv_get_cumulative_perm(bs, &perm, &shared_perm); | ||
124 | - ret = bdrv_check_perm(bs, perm, shared_perm, NULL, &local_err); | ||
125 | + ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &local_err); | ||
126 | if (ret < 0) { | ||
127 | bs->open_flags |= BDRV_O_INACTIVE; | ||
128 | error_propagate(errp, local_err); | ||
129 | @@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs, | ||
130 | |||
131 | /* Update permissions, they may differ for inactive nodes */ | ||
132 | bdrv_get_cumulative_perm(bs, &perm, &shared_perm); | ||
133 | - bdrv_check_perm(bs, perm, shared_perm, NULL, &error_abort); | ||
134 | + bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort); | ||
135 | bdrv_set_perm(bs, perm, shared_perm); | ||
136 | } | ||
137 | |||
138 | -- | ||
139 | 2.13.5 | ||
140 | |||
141 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | When new permissions are calculated during bdrv_reopen(), they need to | ||
2 | be based on the state of the graph as it will be after the reopen has | ||
3 | completed, not on the current state of the involved nodes. | ||
4 | 1 | ||
5 | This patch makes bdrv_is_writable() optionally accept a BlockReopenQueue | ||
6 | from which the new flags are taken. This is then used for determining | ||
7 | the new bs->file permissions of format drivers as soon as we add the | ||
8 | code to actually pass a non-NULL reopen queue to the .bdrv_child_perm | ||
9 | callbacks. | ||
10 | |||
11 | While moving bdrv_is_writable(), make it static. It isn't used outside | ||
12 | block.c. | ||
13 | |||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
16 | --- | ||
17 | include/block/block.h | 1 - | ||
18 | block.c | 52 ++++++++++++++++++++++++++++++++++++--------------- | ||
19 | 2 files changed, 37 insertions(+), 16 deletions(-) | ||
20 | |||
21 | diff --git a/include/block/block.h b/include/block/block.h | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/include/block/block.h | ||
24 | +++ b/include/block/block.h | ||
25 | @@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, | ||
26 | int64_t offset, int64_t bytes, int64_t *pnum); | ||
27 | |||
28 | bool bdrv_is_read_only(BlockDriverState *bs); | ||
29 | -bool bdrv_is_writable(BlockDriverState *bs); | ||
30 | int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, | ||
31 | bool ignore_allow_rdw, Error **errp); | ||
32 | int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp); | ||
33 | diff --git a/block.c b/block.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/block.c | ||
36 | +++ b/block.c | ||
37 | @@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs) | ||
38 | return bs->read_only; | ||
39 | } | ||
40 | |||
41 | -/* Returns whether the image file can be written to right now */ | ||
42 | -bool bdrv_is_writable(BlockDriverState *bs) | ||
43 | -{ | ||
44 | - return !bdrv_is_read_only(bs) && !(bs->open_flags & BDRV_O_INACTIVE); | ||
45 | -} | ||
46 | - | ||
47 | int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, | ||
48 | bool ignore_allow_rdw, Error **errp) | ||
49 | { | ||
50 | @@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q, | ||
51 | static void bdrv_child_abort_perm_update(BdrvChild *c); | ||
52 | static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared); | ||
53 | |||
54 | +typedef struct BlockReopenQueueEntry { | ||
55 | + bool prepared; | ||
56 | + BDRVReopenState state; | ||
57 | + QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry; | ||
58 | +} BlockReopenQueueEntry; | ||
59 | + | ||
60 | +/* | ||
61 | + * Return the flags that @bs will have after the reopens in @q have | ||
62 | + * successfully completed. If @q is NULL (or @bs is not contained in @q), | ||
63 | + * return the current flags. | ||
64 | + */ | ||
65 | +static int bdrv_reopen_get_flags(BlockReopenQueue *q, BlockDriverState *bs) | ||
66 | +{ | ||
67 | + BlockReopenQueueEntry *entry; | ||
68 | + | ||
69 | + if (q != NULL) { | ||
70 | + QSIMPLEQ_FOREACH(entry, q, entry) { | ||
71 | + if (entry->state.bs == bs) { | ||
72 | + return entry->state.flags; | ||
73 | + } | ||
74 | + } | ||
75 | + } | ||
76 | + | ||
77 | + return bs->open_flags; | ||
78 | +} | ||
79 | + | ||
80 | +/* Returns whether the image file can be written to after the reopen queue @q | ||
81 | + * has been successfully applied, or right now if @q is NULL. */ | ||
82 | +static bool bdrv_is_writable(BlockDriverState *bs, BlockReopenQueue *q) | ||
83 | +{ | ||
84 | + int flags = bdrv_reopen_get_flags(q, bs); | ||
85 | + | ||
86 | + return (flags & (BDRV_O_RDWR | BDRV_O_INACTIVE)) == BDRV_O_RDWR; | ||
87 | +} | ||
88 | + | ||
89 | static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs, | ||
90 | BdrvChild *c, const BdrvChildRole *role, | ||
91 | BlockReopenQueue *reopen_queue, | ||
92 | @@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, | ||
93 | |||
94 | /* Write permissions never work with read-only images */ | ||
95 | if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) && | ||
96 | - !bdrv_is_writable(bs)) | ||
97 | + !bdrv_is_writable(bs, q)) | ||
98 | { | ||
99 | error_setg(errp, "Block node is read-only"); | ||
100 | return -EPERM; | ||
101 | @@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, | ||
102 | &perm, &shared); | ||
103 | |||
104 | /* Format drivers may touch metadata even if the guest doesn't write */ | ||
105 | - /* TODO Take flags from reopen_queue */ | ||
106 | - if (bdrv_is_writable(bs)) { | ||
107 | + if (bdrv_is_writable(bs, reopen_queue)) { | ||
108 | perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE; | ||
109 | } | ||
110 | |||
111 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, | ||
112 | NULL, errp); | ||
113 | } | ||
114 | |||
115 | -typedef struct BlockReopenQueueEntry { | ||
116 | - bool prepared; | ||
117 | - BDRVReopenState state; | ||
118 | - QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry; | ||
119 | -} BlockReopenQueueEntry; | ||
120 | - | ||
121 | /* | ||
122 | * Adds a BlockDriverState to a simple queue for an atomic, transactional | ||
123 | * reopen of multiple devices. | ||
124 | -- | ||
125 | 2.13.5 | ||
126 | |||
127 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | We will calculate the required new permissions in the prepare stage of a | ||
2 | reopen. Required permissions of children can be influenced by the | ||
3 | changes made to their parents, but parents are independent from their | ||
4 | children. This means that permissions need to be calculated top-down. In | ||
5 | order to achieve this, queue parents before their children rather than | ||
6 | queuing the children first. | ||
7 | 1 | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
10 | --- | ||
11 | block.c | 26 +++++++++++++------------- | ||
12 | 1 file changed, 13 insertions(+), 13 deletions(-) | ||
13 | |||
14 | diff --git a/block.c b/block.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/block.c | ||
17 | +++ b/block.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, | ||
19 | flags |= BDRV_O_ALLOW_RDWR; | ||
20 | } | ||
21 | |||
22 | + if (!bs_entry) { | ||
23 | + bs_entry = g_new0(BlockReopenQueueEntry, 1); | ||
24 | + QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry); | ||
25 | + } else { | ||
26 | + QDECREF(bs_entry->state.options); | ||
27 | + QDECREF(bs_entry->state.explicit_options); | ||
28 | + } | ||
29 | + | ||
30 | + bs_entry->state.bs = bs; | ||
31 | + bs_entry->state.options = options; | ||
32 | + bs_entry->state.explicit_options = explicit_options; | ||
33 | + bs_entry->state.flags = flags; | ||
34 | + | ||
35 | QLIST_FOREACH(child, &bs->children, next) { | ||
36 | QDict *new_child_options; | ||
37 | char *child_key_dot; | ||
38 | @@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, | ||
39 | child->role, options, flags); | ||
40 | } | ||
41 | |||
42 | - if (!bs_entry) { | ||
43 | - bs_entry = g_new0(BlockReopenQueueEntry, 1); | ||
44 | - QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry); | ||
45 | - } else { | ||
46 | - QDECREF(bs_entry->state.options); | ||
47 | - QDECREF(bs_entry->state.explicit_options); | ||
48 | - } | ||
49 | - | ||
50 | - bs_entry->state.bs = bs; | ||
51 | - bs_entry->state.options = options; | ||
52 | - bs_entry->state.explicit_options = explicit_options; | ||
53 | - bs_entry->state.flags = flags; | ||
54 | - | ||
55 | return bs_queue; | ||
56 | } | ||
57 | |||
58 | -- | ||
59 | 2.13.5 | ||
60 | |||
61 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | If we switch between read-only and read-write, the permissions that | ||
2 | image format drivers need on bs->file change, too. Make sure to update | ||
3 | the permissions during bdrv_reopen(). | ||
4 | 1 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
6 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
7 | --- | ||
8 | include/block/block.h | 1 + | ||
9 | block.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
10 | 2 files changed, 65 insertions(+) | ||
11 | |||
12 | diff --git a/include/block/block.h b/include/block/block.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/include/block/block.h | ||
15 | +++ b/include/block/block.h | ||
16 | @@ -XXX,XX +XXX,XX @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; | ||
17 | typedef struct BDRVReopenState { | ||
18 | BlockDriverState *bs; | ||
19 | int flags; | ||
20 | + uint64_t perm, shared_perm; | ||
21 | QDict *options; | ||
22 | QDict *explicit_options; | ||
23 | void *opaque; | ||
24 | diff --git a/block.c b/block.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/block.c | ||
27 | +++ b/block.c | ||
28 | @@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, | ||
29 | bs_entry->state.explicit_options = explicit_options; | ||
30 | bs_entry->state.flags = flags; | ||
31 | |||
32 | + /* This needs to be overwritten in bdrv_reopen_prepare() */ | ||
33 | + bs_entry->state.perm = UINT64_MAX; | ||
34 | + bs_entry->state.shared_perm = 0; | ||
35 | + | ||
36 | QLIST_FOREACH(child, &bs->children, next) { | ||
37 | QDict *new_child_options; | ||
38 | char *child_key_dot; | ||
39 | @@ -XXX,XX +XXX,XX @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp) | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | +static BlockReopenQueueEntry *find_parent_in_reopen_queue(BlockReopenQueue *q, | ||
44 | + BdrvChild *c) | ||
45 | +{ | ||
46 | + BlockReopenQueueEntry *entry; | ||
47 | + | ||
48 | + QSIMPLEQ_FOREACH(entry, q, entry) { | ||
49 | + BlockDriverState *bs = entry->state.bs; | ||
50 | + BdrvChild *child; | ||
51 | + | ||
52 | + QLIST_FOREACH(child, &bs->children, next) { | ||
53 | + if (child == c) { | ||
54 | + return entry; | ||
55 | + } | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + return NULL; | ||
60 | +} | ||
61 | + | ||
62 | +static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs, | ||
63 | + uint64_t *perm, uint64_t *shared) | ||
64 | +{ | ||
65 | + BdrvChild *c; | ||
66 | + BlockReopenQueueEntry *parent; | ||
67 | + uint64_t cumulative_perms = 0; | ||
68 | + uint64_t cumulative_shared_perms = BLK_PERM_ALL; | ||
69 | + | ||
70 | + QLIST_FOREACH(c, &bs->parents, next_parent) { | ||
71 | + parent = find_parent_in_reopen_queue(q, c); | ||
72 | + if (!parent) { | ||
73 | + cumulative_perms |= c->perm; | ||
74 | + cumulative_shared_perms &= c->shared_perm; | ||
75 | + } else { | ||
76 | + uint64_t nperm, nshared; | ||
77 | + | ||
78 | + bdrv_child_perm(parent->state.bs, bs, c, c->role, q, | ||
79 | + parent->state.perm, parent->state.shared_perm, | ||
80 | + &nperm, &nshared); | ||
81 | + | ||
82 | + cumulative_perms |= nperm; | ||
83 | + cumulative_shared_perms &= nshared; | ||
84 | + } | ||
85 | + } | ||
86 | + *perm = cumulative_perms; | ||
87 | + *shared = cumulative_shared_perms; | ||
88 | +} | ||
89 | |||
90 | /* | ||
91 | * Prepares a BlockDriverState for reopen. All changes are staged in the | ||
92 | @@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, | ||
93 | goto error; | ||
94 | } | ||
95 | |||
96 | + /* Calculate required permissions after reopening */ | ||
97 | + bdrv_reopen_perm(queue, reopen_state->bs, | ||
98 | + &reopen_state->perm, &reopen_state->shared_perm); | ||
99 | |||
100 | ret = bdrv_flush(reopen_state->bs); | ||
101 | if (ret) { | ||
102 | @@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, | ||
103 | } while ((entry = qdict_next(reopen_state->options, entry))); | ||
104 | } | ||
105 | |||
106 | + ret = bdrv_check_perm(reopen_state->bs, queue, reopen_state->perm, | ||
107 | + reopen_state->shared_perm, NULL, errp); | ||
108 | + if (ret < 0) { | ||
109 | + goto error; | ||
110 | + } | ||
111 | + | ||
112 | ret = 0; | ||
113 | |||
114 | error: | ||
115 | @@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state) | ||
116 | |||
117 | bdrv_refresh_limits(bs, NULL); | ||
118 | |||
119 | + bdrv_set_perm(reopen_state->bs, reopen_state->perm, | ||
120 | + reopen_state->shared_perm); | ||
121 | + | ||
122 | new_can_write = | ||
123 | !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE); | ||
124 | if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) { | ||
125 | @@ -XXX,XX +XXX,XX @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state) | ||
126 | } | ||
127 | |||
128 | QDECREF(reopen_state->explicit_options); | ||
129 | + | ||
130 | + bdrv_abort_perm_update(reopen_state->bs); | ||
131 | } | ||
132 | |||
133 | |||
134 | -- | ||
135 | 2.13.5 | ||
136 | |||
137 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | This involves a temporary read-write reopen if the backing file link in | ||
2 | the middle of a backing file chain should be changed and is therefore a | ||
3 | good test for the latest bdrv_reopen() vs. op blockers fixes. | ||
4 | 1 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
6 | --- | ||
7 | tests/qemu-iotests/195 | 92 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
8 | tests/qemu-iotests/195.out | 78 +++++++++++++++++++++++++++++++++++++++ | ||
9 | tests/qemu-iotests/group | 1 + | ||
10 | 3 files changed, 171 insertions(+) | ||
11 | create mode 100755 tests/qemu-iotests/195 | ||
12 | create mode 100644 tests/qemu-iotests/195.out | ||
13 | |||
14 | diff --git a/tests/qemu-iotests/195 b/tests/qemu-iotests/195 | ||
15 | new file mode 100755 | ||
16 | index XXXXXXX..XXXXXXX | ||
17 | --- /dev/null | ||
18 | +++ b/tests/qemu-iotests/195 | ||
19 | @@ -XXX,XX +XXX,XX @@ | ||
20 | +#!/bin/bash | ||
21 | +# | ||
22 | +# Test change-backing-file command | ||
23 | +# | ||
24 | +# Copyright (C) 2017 Red Hat, Inc. | ||
25 | +# | ||
26 | +# This program is free software; you can redistribute it and/or modify | ||
27 | +# it under the terms of the GNU General Public License as published by | ||
28 | +# the Free Software Foundation; either version 2 of the License, or | ||
29 | +# (at your option) any later version. | ||
30 | +# | ||
31 | +# This program is distributed in the hope that it will be useful, | ||
32 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
33 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
34 | +# GNU General Public License for more details. | ||
35 | +# | ||
36 | +# You should have received a copy of the GNU General Public License | ||
37 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
38 | +# | ||
39 | + | ||
40 | +# creator | ||
41 | +owner=kwolf@redhat.com | ||
42 | + | ||
43 | +seq=`basename $0` | ||
44 | +echo "QA output created by $seq" | ||
45 | + | ||
46 | +here=`pwd` | ||
47 | +status=1 # failure is the default! | ||
48 | + | ||
49 | +_cleanup() | ||
50 | +{ | ||
51 | + _cleanup_test_img | ||
52 | + rm -f "$TEST_IMG.mid" | ||
53 | +} | ||
54 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
55 | + | ||
56 | +# get standard environment, filters and checks | ||
57 | +. ./common.rc | ||
58 | +. ./common.filter | ||
59 | + | ||
60 | +_supported_fmt qcow2 | ||
61 | +_supported_proto file | ||
62 | +_supported_os Linux | ||
63 | + | ||
64 | +function do_run_qemu() | ||
65 | +{ | ||
66 | + echo Testing: "$@" | _filter_imgfmt | ||
67 | + $QEMU -nographic -qmp-pretty stdio -serial none "$@" | ||
68 | + echo | ||
69 | +} | ||
70 | + | ||
71 | +function run_qemu() | ||
72 | +{ | ||
73 | + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp \ | ||
74 | + | _filter_qemu_io | _filter_generated_node_ids | ||
75 | +} | ||
76 | + | ||
77 | +size=64M | ||
78 | +TEST_IMG="$TEST_IMG.base" _make_test_img $size | ||
79 | +TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" | ||
80 | +_make_test_img -b "$TEST_IMG.mid" | ||
81 | + | ||
82 | +echo | ||
83 | +echo "Change backing file of mid (opened read-only)" | ||
84 | +echo | ||
85 | + | ||
86 | +run_qemu -drive if=none,file="$TEST_IMG",backing.node-name=mid <<EOF | ||
87 | +{"execute":"qmp_capabilities"} | ||
88 | +{"execute":"change-backing-file", "arguments":{"device":"none0","image-node-name":"mid","backing-file":"/dev/null"}} | ||
89 | +{"execute":"quit"} | ||
90 | +EOF | ||
91 | + | ||
92 | +TEST_IMG="$TEST_IMG.mid" _img_info | ||
93 | + | ||
94 | +echo | ||
95 | +echo "Change backing file of top (opened writable)" | ||
96 | +echo | ||
97 | + | ||
98 | +TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" | ||
99 | + | ||
100 | +run_qemu -drive if=none,file="$TEST_IMG",node-name=top <<EOF | ||
101 | +{"execute":"qmp_capabilities"} | ||
102 | +{"execute":"change-backing-file", "arguments":{"device":"none0","image-node-name":"top","backing-file":"/dev/null"}} | ||
103 | +{"execute":"quit"} | ||
104 | +EOF | ||
105 | + | ||
106 | +_img_info | ||
107 | + | ||
108 | +# success, all done | ||
109 | +echo "*** done" | ||
110 | +rm -f $seq.full | ||
111 | +status=0 | ||
112 | diff --git a/tests/qemu-iotests/195.out b/tests/qemu-iotests/195.out | ||
113 | new file mode 100644 | ||
114 | index XXXXXXX..XXXXXXX | ||
115 | --- /dev/null | ||
116 | +++ b/tests/qemu-iotests/195.out | ||
117 | @@ -XXX,XX +XXX,XX @@ | ||
118 | +QA output created by 195 | ||
119 | +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 | ||
120 | +Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base | ||
121 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid | ||
122 | + | ||
123 | +Change backing file of mid (opened read-only) | ||
124 | + | ||
125 | +Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid | ||
126 | +{ | ||
127 | + QMP_VERSION | ||
128 | +} | ||
129 | +{ | ||
130 | + "return": { | ||
131 | + } | ||
132 | +} | ||
133 | +{ | ||
134 | + "return": { | ||
135 | + } | ||
136 | +} | ||
137 | +{ | ||
138 | + "return": { | ||
139 | + } | ||
140 | +} | ||
141 | +{ | ||
142 | + "timestamp": { | ||
143 | + "seconds": TIMESTAMP, | ||
144 | + "microseconds": TIMESTAMP | ||
145 | + }, | ||
146 | + "event": "SHUTDOWN", | ||
147 | + "data": { | ||
148 | + "guest": false | ||
149 | + } | ||
150 | +} | ||
151 | + | ||
152 | +image: TEST_DIR/t.IMGFMT.mid | ||
153 | +file format: IMGFMT | ||
154 | +virtual size: 64M (67108864 bytes) | ||
155 | +cluster_size: 65536 | ||
156 | +backing file: /dev/null | ||
157 | +backing file format: IMGFMT | ||
158 | + | ||
159 | +Change backing file of top (opened writable) | ||
160 | + | ||
161 | +Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base | ||
162 | +Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top | ||
163 | +{ | ||
164 | + QMP_VERSION | ||
165 | +} | ||
166 | +{ | ||
167 | + "return": { | ||
168 | + } | ||
169 | +} | ||
170 | +{ | ||
171 | + "return": { | ||
172 | + } | ||
173 | +} | ||
174 | +{ | ||
175 | + "return": { | ||
176 | + } | ||
177 | +} | ||
178 | +{ | ||
179 | + "timestamp": { | ||
180 | + "seconds": TIMESTAMP, | ||
181 | + "microseconds": TIMESTAMP | ||
182 | + }, | ||
183 | + "event": "SHUTDOWN", | ||
184 | + "data": { | ||
185 | + "guest": false | ||
186 | + } | ||
187 | +} | ||
188 | + | ||
189 | +image: TEST_DIR/t.IMGFMT | ||
190 | +file format: IMGFMT | ||
191 | +virtual size: 64M (67108864 bytes) | ||
192 | +cluster_size: 65536 | ||
193 | +backing file: /dev/null | ||
194 | +backing file format: IMGFMT | ||
195 | +*** done | ||
196 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
197 | index XXXXXXX..XXXXXXX 100644 | ||
198 | --- a/tests/qemu-iotests/group | ||
199 | +++ b/tests/qemu-iotests/group | ||
200 | @@ -XXX,XX +XXX,XX @@ | ||
201 | 190 rw auto quick | ||
202 | 192 rw auto quick | ||
203 | 194 rw auto migration quick | ||
204 | +195 rw auto quick | ||
205 | -- | ||
206 | 2.13.5 | ||
207 | |||
208 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
2 | 1 | ||
3 | Migration capabilities should be enabled on both source and | ||
4 | destination qemu processes. | ||
5 | |||
6 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
8 | --- | ||
9 | tests/qemu-iotests/181 | 2 ++ | ||
10 | tests/qemu-iotests/181.out | 1 - | ||
11 | 2 files changed, 2 insertions(+), 1 deletion(-) | ||
12 | |||
13 | diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181 | ||
14 | index XXXXXXX..XXXXXXX 100755 | ||
15 | --- a/tests/qemu-iotests/181 | ||
16 | +++ b/tests/qemu-iotests/181 | ||
17 | @@ -XXX,XX +XXX,XX @@ echo | ||
18 | |||
19 | # Slow down migration so much that it definitely won't finish before we can | ||
20 | # switch to postcopy | ||
21 | +# Enable postcopy-ram capability both on source and destination | ||
22 | silent=yes | ||
23 | +_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)" | ||
24 | _send_qemu_cmd $src 'migrate_set_speed 4k' "(qemu)" | ||
25 | _send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)" | ||
26 | _send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)" | ||
27 | diff --git a/tests/qemu-iotests/181.out b/tests/qemu-iotests/181.out | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/tests/qemu-iotests/181.out | ||
30 | +++ b/tests/qemu-iotests/181.out | ||
31 | @@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0 | ||
32 | |||
33 | === Do some I/O on the destination === | ||
34 | |||
35 | -QEMU X.Y.Z monitor - type 'help' for more information | ||
36 | (qemu) qemu-io disk "read -P 0x55 0 64k" | ||
37 | read 65536/65536 bytes at offset 0 | ||
38 | 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
39 | -- | ||
40 | 2.13.5 | ||
41 | |||
42 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
2 | 1 | ||
3 | The flag is additional precaution against data loss. Perhaps in the future the | ||
4 | operation shrink without this flag will be blocked for all formats, but for now | ||
5 | we need to maintain compatibility with raw. | ||
6 | |||
7 | Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
8 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
10 | Message-id: 20170918124230.8152-2-pbutsykin@virtuozzo.com | ||
11 | [mreitz: Added a missing space to a warning] | ||
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
13 | --- | ||
14 | qemu-img.c | 23 +++++++++++++++++++++++ | ||
15 | qemu-img-cmds.hx | 4 ++-- | ||
16 | qemu-img.texi | 6 +++++- | ||
17 | tests/qemu-iotests/102 | 4 ++-- | ||
18 | tests/qemu-iotests/106 | 2 +- | ||
19 | 5 files changed, 33 insertions(+), 6 deletions(-) | ||
20 | |||
21 | diff --git a/qemu-img.c b/qemu-img.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/qemu-img.c | ||
24 | +++ b/qemu-img.c | ||
25 | @@ -XXX,XX +XXX,XX @@ enum { | ||
26 | OPTION_TARGET_IMAGE_OPTS = 263, | ||
27 | OPTION_SIZE = 264, | ||
28 | OPTION_PREALLOCATION = 265, | ||
29 | + OPTION_SHRINK = 266, | ||
30 | }; | ||
31 | |||
32 | typedef enum OutputFormat { | ||
33 | @@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv) | ||
34 | }, | ||
35 | }; | ||
36 | bool image_opts = false; | ||
37 | + bool shrink = false; | ||
38 | |||
39 | /* Remove size from argv manually so that negative numbers are not treated | ||
40 | * as options by getopt. */ | ||
41 | @@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv) | ||
42 | {"object", required_argument, 0, OPTION_OBJECT}, | ||
43 | {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, | ||
44 | {"preallocation", required_argument, 0, OPTION_PREALLOCATION}, | ||
45 | + {"shrink", no_argument, 0, OPTION_SHRINK}, | ||
46 | {0, 0, 0, 0} | ||
47 | }; | ||
48 | c = getopt_long(argc, argv, ":f:hq", | ||
49 | @@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv) | ||
50 | return 1; | ||
51 | } | ||
52 | break; | ||
53 | + case OPTION_SHRINK: | ||
54 | + shrink = true; | ||
55 | + break; | ||
56 | } | ||
57 | } | ||
58 | if (optind != argc - 1) { | ||
59 | @@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv) | ||
60 | goto out; | ||
61 | } | ||
62 | |||
63 | + if (total_size < current_size && !shrink) { | ||
64 | + warn_report("Shrinking an image will delete all data beyond the " | ||
65 | + "shrunken image's end. Before performing such an " | ||
66 | + "operation, make sure there is no important data there."); | ||
67 | + | ||
68 | + if (g_strcmp0(bdrv_get_format_name(blk_bs(blk)), "raw") != 0) { | ||
69 | + error_report( | ||
70 | + "Use the --shrink option to perform a shrink operation."); | ||
71 | + ret = -1; | ||
72 | + goto out; | ||
73 | + } else { | ||
74 | + warn_report("Using the --shrink option will suppress this message. " | ||
75 | + "Note that future versions of qemu-img may refuse to " | ||
76 | + "shrink images without this option."); | ||
77 | + } | ||
78 | + } | ||
79 | + | ||
80 | ret = blk_truncate(blk, total_size, prealloc, &err); | ||
81 | if (!ret) { | ||
82 | qprintf(quiet, "Image resized.\n"); | ||
83 | diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx | ||
84 | index XXXXXXX..XXXXXXX 100644 | ||
85 | --- a/qemu-img-cmds.hx | ||
86 | +++ b/qemu-img-cmds.hx | ||
87 | @@ -XXX,XX +XXX,XX @@ STEXI | ||
88 | ETEXI | ||
89 | |||
90 | DEF("resize", img_resize, | ||
91 | - "resize [--object objectdef] [--image-opts] [-q] filename [+ | -]size") | ||
92 | + "resize [--object objectdef] [--image-opts] [-q] [--shrink] filename [+ | -]size") | ||
93 | STEXI | ||
94 | -@item resize [--object @var{objectdef}] [--image-opts] [-q] @var{filename} [+ | -]@var{size} | ||
95 | +@item resize [--object @var{objectdef}] [--image-opts] [-q] [--shrink] @var{filename} [+ | -]@var{size} | ||
96 | ETEXI | ||
97 | |||
98 | STEXI | ||
99 | diff --git a/qemu-img.texi b/qemu-img.texi | ||
100 | index XXXXXXX..XXXXXXX 100644 | ||
101 | --- a/qemu-img.texi | ||
102 | +++ b/qemu-img.texi | ||
103 | @@ -XXX,XX +XXX,XX @@ qemu-img rebase -b base.img diff.qcow2 | ||
104 | At this point, @code{modified.img} can be discarded, since | ||
105 | @code{base.img + diff.qcow2} contains the same information. | ||
106 | |||
107 | -@item resize [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size} | ||
108 | +@item resize [--shrink] [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size} | ||
109 | |||
110 | Change the disk image as if it had been created with @var{size}. | ||
111 | |||
112 | @@ -XXX,XX +XXX,XX @@ Before using this command to shrink a disk image, you MUST use file system and | ||
113 | partitioning tools inside the VM to reduce allocated file systems and partition | ||
114 | sizes accordingly. Failure to do so will result in data loss! | ||
115 | |||
116 | +When shrinking images, the @code{--shrink} option must be given. This informs | ||
117 | +qemu-img that the user acknowledges all loss of data beyond the truncated | ||
118 | +image's end. | ||
119 | + | ||
120 | After using this command to grow a disk image, you must use file system and | ||
121 | partitioning tools inside the VM to actually begin using the new space on the | ||
122 | device. | ||
123 | diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 | ||
124 | index XXXXXXX..XXXXXXX 100755 | ||
125 | --- a/tests/qemu-iotests/102 | ||
126 | +++ b/tests/qemu-iotests/102 | ||
127 | @@ -XXX,XX +XXX,XX @@ _make_test_img $IMG_SIZE | ||
128 | $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io | ||
129 | # Remove data cluster from image (first cluster: image header, second: reftable, | ||
130 | # third: refblock, fourth: L1 table, fifth: L2 table) | ||
131 | -$QEMU_IMG resize -f raw "$TEST_IMG" $((5 * 64 * 1024)) | ||
132 | +$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024)) | ||
133 | |||
134 | $QEMU_IO -c map "$TEST_IMG" | ||
135 | $QEMU_IMG map "$TEST_IMG" | ||
136 | @@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io | ||
137 | |||
138 | qemu_comm_method=monitor _launch_qemu -drive if=none,file="$TEST_IMG",id=drv0 | ||
139 | |||
140 | -$QEMU_IMG resize -f raw "$TEST_IMG" $((5 * 64 * 1024)) | ||
141 | +$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024)) | ||
142 | |||
143 | _send_qemu_cmd $QEMU_HANDLE 'qemu-io drv0 map' 'allocated' \ | ||
144 | | sed -e 's/^(qemu).*qemu-io drv0 map...$/(qemu) qemu-io drv0 map/' | ||
145 | diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106 | ||
146 | index XXXXXXX..XXXXXXX 100755 | ||
147 | --- a/tests/qemu-iotests/106 | ||
148 | +++ b/tests/qemu-iotests/106 | ||
149 | @@ -XXX,XX +XXX,XX @@ echo '=== Testing image shrinking ===' | ||
150 | for growth_mode in falloc full off; do | ||
151 | echo | ||
152 | echo "--- growth_mode=$growth_mode ---" | ||
153 | - $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K | ||
154 | + $QEMU_IMG resize -f "$IMGFMT" --shrink --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K | ||
155 | done | ||
156 | |||
157 | # success, all done | ||
158 | -- | ||
159 | 2.13.5 | ||
160 | |||
161 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
2 | 1 | ||
3 | Whenever l2/refcount table clusters are discarded from the file we can | ||
4 | automatically drop unnecessary content of the cache tables. This reduces | ||
5 | the chance of eviction useful cache data and eliminates inconsistent data | ||
6 | in the cache with the data in the file. | ||
7 | |||
8 | Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
9 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
10 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
11 | Message-id: 20170918124230.8152-3-pbutsykin@virtuozzo.com | ||
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
13 | --- | ||
14 | block/qcow2.h | 3 +++ | ||
15 | block/qcow2-cache.c | 26 ++++++++++++++++++++++++++ | ||
16 | block/qcow2-refcount.c | 20 ++++++++++++++++++-- | ||
17 | 3 files changed, 47 insertions(+), 2 deletions(-) | ||
18 | |||
19 | diff --git a/block/qcow2.h b/block/qcow2.h | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/block/qcow2.h | ||
22 | +++ b/block/qcow2.h | ||
23 | @@ -XXX,XX +XXX,XX @@ int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, | ||
24 | int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, | ||
25 | void **table); | ||
26 | void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); | ||
27 | +void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c, | ||
28 | + uint64_t offset); | ||
29 | +void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table); | ||
30 | |||
31 | /* qcow2-bitmap.c functions */ | ||
32 | int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||
33 | diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/block/qcow2-cache.c | ||
36 | +++ b/block/qcow2-cache.c | ||
37 | @@ -XXX,XX +XXX,XX @@ void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c, | ||
38 | assert(c->entries[i].offset != 0); | ||
39 | c->entries[i].dirty = true; | ||
40 | } | ||
41 | + | ||
42 | +void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c, | ||
43 | + uint64_t offset) | ||
44 | +{ | ||
45 | + int i; | ||
46 | + | ||
47 | + for (i = 0; i < c->size; i++) { | ||
48 | + if (c->entries[i].offset == offset) { | ||
49 | + return qcow2_cache_get_table_addr(bs, c, i); | ||
50 | + } | ||
51 | + } | ||
52 | + return NULL; | ||
53 | +} | ||
54 | + | ||
55 | +void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table) | ||
56 | +{ | ||
57 | + int i = qcow2_cache_get_table_idx(bs, c, table); | ||
58 | + | ||
59 | + assert(c->entries[i].ref == 0); | ||
60 | + | ||
61 | + c->entries[i].offset = 0; | ||
62 | + c->entries[i].lru_counter = 0; | ||
63 | + c->entries[i].dirty = false; | ||
64 | + | ||
65 | + qcow2_cache_table_release(bs, c, i, 1); | ||
66 | +} | ||
67 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/block/qcow2-refcount.c | ||
70 | +++ b/block/qcow2-refcount.c | ||
71 | @@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, | ||
72 | } | ||
73 | s->set_refcount(refcount_block, block_index, refcount); | ||
74 | |||
75 | - if (refcount == 0 && s->discard_passthrough[type]) { | ||
76 | - update_refcount_discard(bs, cluster_offset, s->cluster_size); | ||
77 | + if (refcount == 0) { | ||
78 | + void *table; | ||
79 | + | ||
80 | + table = qcow2_cache_is_table_offset(bs, s->refcount_block_cache, | ||
81 | + offset); | ||
82 | + if (table != NULL) { | ||
83 | + qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block); | ||
84 | + qcow2_cache_discard(bs, s->refcount_block_cache, table); | ||
85 | + } | ||
86 | + | ||
87 | + table = qcow2_cache_is_table_offset(bs, s->l2_table_cache, offset); | ||
88 | + if (table != NULL) { | ||
89 | + qcow2_cache_discard(bs, s->l2_table_cache, table); | ||
90 | + } | ||
91 | + | ||
92 | + if (s->discard_passthrough[type]) { | ||
93 | + update_refcount_discard(bs, cluster_offset, s->cluster_size); | ||
94 | + } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | -- | ||
99 | 2.13.5 | ||
100 | |||
101 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
2 | 1 | ||
3 | This patch add shrinking of the image file for qcow2. As a result, this allows | ||
4 | us to reduce the virtual image size and free up space on the disk without | ||
5 | copying the image. Image can be fragmented and shrink is done by punching holes | ||
6 | in the image file. | ||
7 | |||
8 | Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
9 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
10 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
11 | Message-id: 20170918124230.8152-4-pbutsykin@virtuozzo.com | ||
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
13 | --- | ||
14 | qapi/block-core.json | 8 +++- | ||
15 | block/qcow2.h | 14 ++++++ | ||
16 | block/qcow2-cluster.c | 50 +++++++++++++++++++++ | ||
17 | block/qcow2-refcount.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++ | ||
18 | block/qcow2.c | 43 ++++++++++++++---- | ||
19 | 5 files changed, 225 insertions(+), 10 deletions(-) | ||
20 | |||
21 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/qapi/block-core.json | ||
24 | +++ b/qapi/block-core.json | ||
25 | @@ -XXX,XX +XXX,XX @@ | ||
26 | # | ||
27 | # Trigger events supported by blkdebug. | ||
28 | # | ||
29 | +# @l1_shrink_write_table: write zeros to the l1 table to shrink image. | ||
30 | +# (since 2.11) | ||
31 | +# | ||
32 | +# @l1_shrink_free_l2_clusters: discard the l2 tables. (since 2.11) | ||
33 | +# | ||
34 | # Since: 2.9 | ||
35 | ## | ||
36 | { 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG', | ||
37 | @@ -XXX,XX +XXX,XX @@ | ||
38 | 'cluster_alloc_bytes', 'cluster_free', 'flush_to_os', | ||
39 | 'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head', | ||
40 | 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev', | ||
41 | - 'pwritev_zero', 'pwritev_done', 'empty_image_prepare' ] } | ||
42 | + 'pwritev_zero', 'pwritev_done', 'empty_image_prepare', | ||
43 | + 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters' ] } | ||
44 | |||
45 | ## | ||
46 | # @BlkdebugInjectErrorOptions: | ||
47 | diff --git a/block/qcow2.h b/block/qcow2.h | ||
48 | index XXXXXXX..XXXXXXX 100644 | ||
49 | --- a/block/qcow2.h | ||
50 | +++ b/block/qcow2.h | ||
51 | @@ -XXX,XX +XXX,XX @@ static inline uint64_t refcount_diff(uint64_t r1, uint64_t r2) | ||
52 | return r1 > r2 ? r1 - r2 : r2 - r1; | ||
53 | } | ||
54 | |||
55 | +static inline | ||
56 | +uint32_t offset_to_reftable_index(BDRVQcow2State *s, uint64_t offset) | ||
57 | +{ | ||
58 | + return offset >> (s->refcount_block_bits + s->cluster_bits); | ||
59 | +} | ||
60 | + | ||
61 | +static inline uint64_t get_refblock_offset(BDRVQcow2State *s, uint64_t offset) | ||
62 | +{ | ||
63 | + uint32_t index = offset_to_reftable_index(s, offset); | ||
64 | + return s->refcount_table[index] & REFT_OFFSET_MASK; | ||
65 | +} | ||
66 | + | ||
67 | /* qcow2.c functions */ | ||
68 | int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, | ||
69 | int64_t sector_num, int nb_sectors); | ||
70 | @@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, | ||
71 | int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, | ||
72 | BlockDriverAmendStatusCB *status_cb, | ||
73 | void *cb_opaque, Error **errp); | ||
74 | +int qcow2_shrink_reftable(BlockDriverState *bs); | ||
75 | |||
76 | /* qcow2-cluster.c functions */ | ||
77 | int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
78 | bool exact_size); | ||
79 | +int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size); | ||
80 | int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); | ||
81 | int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); | ||
82 | int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, | ||
83 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
84 | index XXXXXXX..XXXXXXX 100644 | ||
85 | --- a/block/qcow2-cluster.c | ||
86 | +++ b/block/qcow2-cluster.c | ||
87 | @@ -XXX,XX +XXX,XX @@ | ||
88 | #include "qemu/bswap.h" | ||
89 | #include "trace.h" | ||
90 | |||
91 | +int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size) | ||
92 | +{ | ||
93 | + BDRVQcow2State *s = bs->opaque; | ||
94 | + int new_l1_size, i, ret; | ||
95 | + | ||
96 | + if (exact_size >= s->l1_size) { | ||
97 | + return 0; | ||
98 | + } | ||
99 | + | ||
100 | + new_l1_size = exact_size; | ||
101 | + | ||
102 | +#ifdef DEBUG_ALLOC2 | ||
103 | + fprintf(stderr, "shrink l1_table from %d to %d\n", s->l1_size, new_l1_size); | ||
104 | +#endif | ||
105 | + | ||
106 | + BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE); | ||
107 | + ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset + | ||
108 | + new_l1_size * sizeof(uint64_t), | ||
109 | + (s->l1_size - new_l1_size) * sizeof(uint64_t), 0); | ||
110 | + if (ret < 0) { | ||
111 | + goto fail; | ||
112 | + } | ||
113 | + | ||
114 | + ret = bdrv_flush(bs->file->bs); | ||
115 | + if (ret < 0) { | ||
116 | + goto fail; | ||
117 | + } | ||
118 | + | ||
119 | + BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_FREE_L2_CLUSTERS); | ||
120 | + for (i = s->l1_size - 1; i > new_l1_size - 1; i--) { | ||
121 | + if ((s->l1_table[i] & L1E_OFFSET_MASK) == 0) { | ||
122 | + continue; | ||
123 | + } | ||
124 | + qcow2_free_clusters(bs, s->l1_table[i] & L1E_OFFSET_MASK, | ||
125 | + s->cluster_size, QCOW2_DISCARD_ALWAYS); | ||
126 | + s->l1_table[i] = 0; | ||
127 | + } | ||
128 | + return 0; | ||
129 | + | ||
130 | +fail: | ||
131 | + /* | ||
132 | + * If the write in the l1_table failed the image may contain a partially | ||
133 | + * overwritten l1_table. In this case it would be better to clear the | ||
134 | + * l1_table in memory to avoid possible image corruption. | ||
135 | + */ | ||
136 | + memset(s->l1_table + new_l1_size, 0, | ||
137 | + (s->l1_size - new_l1_size) * sizeof(uint64_t)); | ||
138 | + return ret; | ||
139 | +} | ||
140 | + | ||
141 | int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
142 | bool exact_size) | ||
143 | { | ||
144 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
145 | index XXXXXXX..XXXXXXX 100644 | ||
146 | --- a/block/qcow2-refcount.c | ||
147 | +++ b/block/qcow2-refcount.c | ||
148 | @@ -XXX,XX +XXX,XX @@ | ||
149 | #include "block/qcow2.h" | ||
150 | #include "qemu/range.h" | ||
151 | #include "qemu/bswap.h" | ||
152 | +#include "qemu/cutils.h" | ||
153 | |||
154 | static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size); | ||
155 | static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, | ||
156 | @@ -XXX,XX +XXX,XX @@ done: | ||
157 | qemu_vfree(new_refblock); | ||
158 | return ret; | ||
159 | } | ||
160 | + | ||
161 | +static int qcow2_discard_refcount_block(BlockDriverState *bs, | ||
162 | + uint64_t discard_block_offs) | ||
163 | +{ | ||
164 | + BDRVQcow2State *s = bs->opaque; | ||
165 | + uint64_t refblock_offs = get_refblock_offset(s, discard_block_offs); | ||
166 | + uint64_t cluster_index = discard_block_offs >> s->cluster_bits; | ||
167 | + uint32_t block_index = cluster_index & (s->refcount_block_size - 1); | ||
168 | + void *refblock; | ||
169 | + int ret; | ||
170 | + | ||
171 | + assert(discard_block_offs != 0); | ||
172 | + | ||
173 | + ret = qcow2_cache_get(bs, s->refcount_block_cache, refblock_offs, | ||
174 | + &refblock); | ||
175 | + if (ret < 0) { | ||
176 | + return ret; | ||
177 | + } | ||
178 | + | ||
179 | + if (s->get_refcount(refblock, block_index) != 1) { | ||
180 | + qcow2_signal_corruption(bs, true, -1, -1, "Invalid refcount:" | ||
181 | + " refblock offset %#" PRIx64 | ||
182 | + ", reftable index %u" | ||
183 | + ", block offset %#" PRIx64 | ||
184 | + ", refcount %#" PRIx64, | ||
185 | + refblock_offs, | ||
186 | + offset_to_reftable_index(s, discard_block_offs), | ||
187 | + discard_block_offs, | ||
188 | + s->get_refcount(refblock, block_index)); | ||
189 | + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); | ||
190 | + return -EINVAL; | ||
191 | + } | ||
192 | + s->set_refcount(refblock, block_index, 0); | ||
193 | + | ||
194 | + qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, refblock); | ||
195 | + | ||
196 | + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); | ||
197 | + | ||
198 | + if (cluster_index < s->free_cluster_index) { | ||
199 | + s->free_cluster_index = cluster_index; | ||
200 | + } | ||
201 | + | ||
202 | + refblock = qcow2_cache_is_table_offset(bs, s->refcount_block_cache, | ||
203 | + discard_block_offs); | ||
204 | + if (refblock) { | ||
205 | + /* discard refblock from the cache if refblock is cached */ | ||
206 | + qcow2_cache_discard(bs, s->refcount_block_cache, refblock); | ||
207 | + } | ||
208 | + update_refcount_discard(bs, discard_block_offs, s->cluster_size); | ||
209 | + | ||
210 | + return 0; | ||
211 | +} | ||
212 | + | ||
213 | +int qcow2_shrink_reftable(BlockDriverState *bs) | ||
214 | +{ | ||
215 | + BDRVQcow2State *s = bs->opaque; | ||
216 | + uint64_t *reftable_tmp = | ||
217 | + g_malloc(s->refcount_table_size * sizeof(uint64_t)); | ||
218 | + int i, ret; | ||
219 | + | ||
220 | + for (i = 0; i < s->refcount_table_size; i++) { | ||
221 | + int64_t refblock_offs = s->refcount_table[i] & REFT_OFFSET_MASK; | ||
222 | + void *refblock; | ||
223 | + bool unused_block; | ||
224 | + | ||
225 | + if (refblock_offs == 0) { | ||
226 | + reftable_tmp[i] = 0; | ||
227 | + continue; | ||
228 | + } | ||
229 | + ret = qcow2_cache_get(bs, s->refcount_block_cache, refblock_offs, | ||
230 | + &refblock); | ||
231 | + if (ret < 0) { | ||
232 | + goto out; | ||
233 | + } | ||
234 | + | ||
235 | + /* the refblock has own reference */ | ||
236 | + if (i == offset_to_reftable_index(s, refblock_offs)) { | ||
237 | + uint64_t block_index = (refblock_offs >> s->cluster_bits) & | ||
238 | + (s->refcount_block_size - 1); | ||
239 | + uint64_t refcount = s->get_refcount(refblock, block_index); | ||
240 | + | ||
241 | + s->set_refcount(refblock, block_index, 0); | ||
242 | + | ||
243 | + unused_block = buffer_is_zero(refblock, s->cluster_size); | ||
244 | + | ||
245 | + s->set_refcount(refblock, block_index, refcount); | ||
246 | + } else { | ||
247 | + unused_block = buffer_is_zero(refblock, s->cluster_size); | ||
248 | + } | ||
249 | + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); | ||
250 | + | ||
251 | + reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]); | ||
252 | + } | ||
253 | + | ||
254 | + ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_tmp, | ||
255 | + s->refcount_table_size * sizeof(uint64_t)); | ||
256 | + /* | ||
257 | + * If the write in the reftable failed the image may contain a partially | ||
258 | + * overwritten reftable. In this case it would be better to clear the | ||
259 | + * reftable in memory to avoid possible image corruption. | ||
260 | + */ | ||
261 | + for (i = 0; i < s->refcount_table_size; i++) { | ||
262 | + if (s->refcount_table[i] && !reftable_tmp[i]) { | ||
263 | + if (ret == 0) { | ||
264 | + ret = qcow2_discard_refcount_block(bs, s->refcount_table[i] & | ||
265 | + REFT_OFFSET_MASK); | ||
266 | + } | ||
267 | + s->refcount_table[i] = 0; | ||
268 | + } | ||
269 | + } | ||
270 | + | ||
271 | + if (!s->cache_discards) { | ||
272 | + qcow2_process_discards(bs, ret); | ||
273 | + } | ||
274 | + | ||
275 | +out: | ||
276 | + g_free(reftable_tmp); | ||
277 | + return ret; | ||
278 | +} | ||
279 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
280 | index XXXXXXX..XXXXXXX 100644 | ||
281 | --- a/block/qcow2.c | ||
282 | +++ b/block/qcow2.c | ||
283 | @@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset, | ||
284 | } | ||
285 | |||
286 | old_length = bs->total_sectors * 512; | ||
287 | + new_l1_size = size_to_l1(s, offset); | ||
288 | |||
289 | - /* shrinking is currently not supported */ | ||
290 | if (offset < old_length) { | ||
291 | - error_setg(errp, "qcow2 doesn't support shrinking images yet"); | ||
292 | - return -ENOTSUP; | ||
293 | - } | ||
294 | + if (prealloc != PREALLOC_MODE_OFF) { | ||
295 | + error_setg(errp, | ||
296 | + "Preallocation can't be used for shrinking an image"); | ||
297 | + return -EINVAL; | ||
298 | + } | ||
299 | |||
300 | - new_l1_size = size_to_l1(s, offset); | ||
301 | - ret = qcow2_grow_l1_table(bs, new_l1_size, true); | ||
302 | - if (ret < 0) { | ||
303 | - error_setg_errno(errp, -ret, "Failed to grow the L1 table"); | ||
304 | - return ret; | ||
305 | + ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size), | ||
306 | + old_length - ROUND_UP(offset, | ||
307 | + s->cluster_size), | ||
308 | + QCOW2_DISCARD_ALWAYS, true); | ||
309 | + if (ret < 0) { | ||
310 | + error_setg_errno(errp, -ret, "Failed to discard cropped clusters"); | ||
311 | + return ret; | ||
312 | + } | ||
313 | + | ||
314 | + ret = qcow2_shrink_l1_table(bs, new_l1_size); | ||
315 | + if (ret < 0) { | ||
316 | + error_setg_errno(errp, -ret, | ||
317 | + "Failed to reduce the number of L2 tables"); | ||
318 | + return ret; | ||
319 | + } | ||
320 | + | ||
321 | + ret = qcow2_shrink_reftable(bs); | ||
322 | + if (ret < 0) { | ||
323 | + error_setg_errno(errp, -ret, | ||
324 | + "Failed to discard unused refblocks"); | ||
325 | + return ret; | ||
326 | + } | ||
327 | + } else { | ||
328 | + ret = qcow2_grow_l1_table(bs, new_l1_size, true); | ||
329 | + if (ret < 0) { | ||
330 | + error_setg_errno(errp, -ret, "Failed to grow the L1 table"); | ||
331 | + return ret; | ||
332 | + } | ||
333 | } | ||
334 | |||
335 | switch (prealloc) { | ||
336 | -- | ||
337 | 2.13.5 | ||
338 | |||
339 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
2 | 1 | ||
3 | Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com> | ||
4 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
5 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
6 | Message-id: 20170918124230.8152-5-pbutsykin@virtuozzo.com | ||
7 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
8 | --- | ||
9 | tests/qemu-iotests/163 | 170 +++++++++++++++++++++++++++++++++++++++++++++ | ||
10 | tests/qemu-iotests/163.out | 5 ++ | ||
11 | tests/qemu-iotests/group | 1 + | ||
12 | 3 files changed, 176 insertions(+) | ||
13 | create mode 100644 tests/qemu-iotests/163 | ||
14 | create mode 100644 tests/qemu-iotests/163.out | ||
15 | |||
16 | diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163 | ||
17 | new file mode 100644 | ||
18 | index XXXXXXX..XXXXXXX | ||
19 | --- /dev/null | ||
20 | +++ b/tests/qemu-iotests/163 | ||
21 | @@ -XXX,XX +XXX,XX @@ | ||
22 | +#!/usr/bin/env python | ||
23 | +# | ||
24 | +# Tests for shrinking images | ||
25 | +# | ||
26 | +# Copyright (c) 2016-2017 Parallels International GmbH | ||
27 | +# | ||
28 | +# This program is free software; you can redistribute it and/or modify | ||
29 | +# it under the terms of the GNU General Public License as published by | ||
30 | +# the Free Software Foundation; either version 2 of the License, or | ||
31 | +# (at your option) any later version. | ||
32 | +# | ||
33 | +# This program is distributed in the hope that it will be useful, | ||
34 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
35 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
36 | +# GNU General Public License for more details. | ||
37 | +# | ||
38 | +# You should have received a copy of the GNU General Public License | ||
39 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
40 | +# | ||
41 | + | ||
42 | +import os, random, iotests, struct, qcow2 | ||
43 | +from iotests import qemu_img, qemu_io, image_size | ||
44 | + | ||
45 | +test_img = os.path.join(iotests.test_dir, 'test.img') | ||
46 | +check_img = os.path.join(iotests.test_dir, 'check.img') | ||
47 | + | ||
48 | +def size_to_int(str): | ||
49 | + suff = ['B', 'K', 'M', 'G', 'T'] | ||
50 | + return int(str[:-1]) * 1024**suff.index(str[-1:]) | ||
51 | + | ||
52 | +class ShrinkBaseClass(iotests.QMPTestCase): | ||
53 | + image_len = '128M' | ||
54 | + shrink_size = '10M' | ||
55 | + chunk_size = '16M' | ||
56 | + refcount_bits = '16' | ||
57 | + | ||
58 | + def __qcow2_check(self, filename): | ||
59 | + entry_bits = 3 | ||
60 | + entry_size = 1 << entry_bits | ||
61 | + l1_mask = 0x00fffffffffffe00 | ||
62 | + div_roundup = lambda n, d: (n + d - 1) / d | ||
63 | + | ||
64 | + def split_by_n(data, n): | ||
65 | + for x in xrange(0, len(data), n): | ||
66 | + yield struct.unpack('>Q', data[x:x + n])[0] & l1_mask | ||
67 | + | ||
68 | + def check_l1_table(h, l1_data): | ||
69 | + l1_list = list(split_by_n(l1_data, entry_size)) | ||
70 | + real_l1_size = div_roundup(h.size, | ||
71 | + 1 << (h.cluster_bits*2 - entry_size)) | ||
72 | + used, unused = l1_list[:real_l1_size], l1_list[real_l1_size:] | ||
73 | + | ||
74 | + self.assertTrue(len(used) != 0, "Verifying l1 table content") | ||
75 | + self.assertFalse(any(unused), "Verifying l1 table content") | ||
76 | + | ||
77 | + def check_reftable(fd, h, reftable): | ||
78 | + for offset in split_by_n(reftable, entry_size): | ||
79 | + if offset != 0: | ||
80 | + fd.seek(offset) | ||
81 | + cluster = fd.read(1 << h.cluster_bits) | ||
82 | + self.assertTrue(any(cluster), "Verifying reftable content") | ||
83 | + | ||
84 | + with open(filename, "rb") as fd: | ||
85 | + h = qcow2.QcowHeader(fd) | ||
86 | + | ||
87 | + fd.seek(h.l1_table_offset) | ||
88 | + l1_table = fd.read(h.l1_size << entry_bits) | ||
89 | + | ||
90 | + fd.seek(h.refcount_table_offset) | ||
91 | + reftable = fd.read(h.refcount_table_clusters << h.cluster_bits) | ||
92 | + | ||
93 | + check_l1_table(h, l1_table) | ||
94 | + check_reftable(fd, h, reftable) | ||
95 | + | ||
96 | + def __raw_check(self, filename): | ||
97 | + pass | ||
98 | + | ||
99 | + image_check = { | ||
100 | + 'qcow2' : __qcow2_check, | ||
101 | + 'raw' : __raw_check | ||
102 | + } | ||
103 | + | ||
104 | + def setUp(self): | ||
105 | + if iotests.imgfmt == 'raw': | ||
106 | + qemu_img('create', '-f', iotests.imgfmt, test_img, self.image_len) | ||
107 | + qemu_img('create', '-f', iotests.imgfmt, check_img, | ||
108 | + self.shrink_size) | ||
109 | + else: | ||
110 | + qemu_img('create', '-f', iotests.imgfmt, | ||
111 | + '-o', 'cluster_size=' + self.cluster_size + | ||
112 | + ',refcount_bits=' + self.refcount_bits, | ||
113 | + test_img, self.image_len) | ||
114 | + qemu_img('create', '-f', iotests.imgfmt, | ||
115 | + '-o', 'cluster_size=%s'% self.cluster_size, | ||
116 | + check_img, self.shrink_size) | ||
117 | + qemu_io('-c', 'write -P 0xff 0 ' + self.shrink_size, check_img) | ||
118 | + | ||
119 | + def tearDown(self): | ||
120 | + os.remove(test_img) | ||
121 | + os.remove(check_img) | ||
122 | + | ||
123 | + def image_verify(self): | ||
124 | + self.assertEqual(image_size(test_img), image_size(check_img), | ||
125 | + "Verifying image size") | ||
126 | + self.image_check[iotests.imgfmt](self, test_img) | ||
127 | + | ||
128 | + if iotests.imgfmt == 'raw': | ||
129 | + return | ||
130 | + self.assertEqual(qemu_img('check', test_img), 0, | ||
131 | + "Verifying image corruption") | ||
132 | + | ||
133 | + def test_empty_image(self): | ||
134 | + qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img, | ||
135 | + self.shrink_size) | ||
136 | + | ||
137 | + self.assertEqual( | ||
138 | + qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, test_img), | ||
139 | + qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, check_img), | ||
140 | + "Verifying image content") | ||
141 | + | ||
142 | + self.image_verify() | ||
143 | + | ||
144 | + def test_sequential_write(self): | ||
145 | + for offs in range(0, size_to_int(self.image_len), | ||
146 | + size_to_int(self.chunk_size)): | ||
147 | + qemu_io('-c', 'write -P 0xff %d %s' % (offs, self.chunk_size), | ||
148 | + test_img) | ||
149 | + | ||
150 | + qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img, | ||
151 | + self.shrink_size) | ||
152 | + | ||
153 | + self.assertEqual(qemu_img("compare", test_img, check_img), 0, | ||
154 | + "Verifying image content") | ||
155 | + | ||
156 | + self.image_verify() | ||
157 | + | ||
158 | + def test_random_write(self): | ||
159 | + offs_list = range(0, size_to_int(self.image_len), | ||
160 | + size_to_int(self.chunk_size)) | ||
161 | + random.shuffle(offs_list) | ||
162 | + for offs in offs_list: | ||
163 | + qemu_io('-c', 'write -P 0xff %d %s' % (offs, self.chunk_size), | ||
164 | + test_img) | ||
165 | + | ||
166 | + qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img, | ||
167 | + self.shrink_size) | ||
168 | + | ||
169 | + self.assertEqual(qemu_img("compare", test_img, check_img), 0, | ||
170 | + "Verifying image content") | ||
171 | + | ||
172 | + self.image_verify() | ||
173 | + | ||
174 | +class TestShrink512(ShrinkBaseClass): | ||
175 | + image_len = '3M' | ||
176 | + shrink_size = '1M' | ||
177 | + chunk_size = '256K' | ||
178 | + cluster_size = '512' | ||
179 | + refcount_bits = '64' | ||
180 | + | ||
181 | +class TestShrink64K(ShrinkBaseClass): | ||
182 | + cluster_size = '64K' | ||
183 | + | ||
184 | +class TestShrink1M(ShrinkBaseClass): | ||
185 | + cluster_size = '1M' | ||
186 | + refcount_bits = '1' | ||
187 | + | ||
188 | +ShrinkBaseClass = None | ||
189 | + | ||
190 | +if __name__ == '__main__': | ||
191 | + iotests.main(supported_fmts=['raw', 'qcow2']) | ||
192 | diff --git a/tests/qemu-iotests/163.out b/tests/qemu-iotests/163.out | ||
193 | new file mode 100644 | ||
194 | index XXXXXXX..XXXXXXX | ||
195 | --- /dev/null | ||
196 | +++ b/tests/qemu-iotests/163.out | ||
197 | @@ -XXX,XX +XXX,XX @@ | ||
198 | +......... | ||
199 | +---------------------------------------------------------------------- | ||
200 | +Ran 9 tests | ||
201 | + | ||
202 | +OK | ||
203 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
204 | index XXXXXXX..XXXXXXX 100644 | ||
205 | --- a/tests/qemu-iotests/group | ||
206 | +++ b/tests/qemu-iotests/group | ||
207 | @@ -XXX,XX +XXX,XX @@ | ||
208 | 159 rw auto quick | ||
209 | 160 rw auto quick | ||
210 | 162 auto quick | ||
211 | +163 rw auto quick | ||
212 | 165 rw auto quick | ||
213 | 170 rw auto quick | ||
214 | 171 rw auto quick | ||
215 | -- | ||
216 | 2.13.5 | ||
217 | |||
218 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
2 | 1 | ||
3 | Without initialization to zero dirty_bitmap field may be not zero | ||
4 | for a bitmap which should not be stored and | ||
5 | qcow2_store_persistent_dirty_bitmaps will erroneously call | ||
6 | store_bitmap for it which leads to SIGSEGV on bdrv_dirty_bitmap_name. | ||
7 | |||
8 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
9 | Message-id: 20170922144353.4220-1-vsementsov@virtuozzo.com | ||
10 | Cc: qemu-stable@nongnu.org | ||
11 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
12 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block/qcow2-bitmap.c | 2 +- | ||
16 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
17 | |||
18 | diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/qcow2-bitmap.c | ||
21 | +++ b/block/qcow2-bitmap.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset, | ||
23 | goto fail; | ||
24 | } | ||
25 | |||
26 | - bm = g_new(Qcow2Bitmap, 1); | ||
27 | + bm = g_new0(Qcow2Bitmap, 1); | ||
28 | bm->table.offset = e->bitmap_table_offset; | ||
29 | bm->table.size = e->bitmap_table_size; | ||
30 | bm->flags = e->flags; | ||
31 | -- | ||
32 | 2.13.5 | ||
33 | |||
34 | diff view generated by jsdifflib |