1 | The following changes since commit 527266f324def9f7f392fe3b0dd940cb8dc699d9: | 1 | The following changes since commit 7bc8f9734213b76e76631a483be13d6737c2adbc: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/armbru/tags/pull-pflash-2019-03-26' into staging (2019-03-26 09:57:07 +0000) | 3 | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191025' into staging (2019-10-25 13:12:16 +0100) |
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 c6e3f520c802c5cb2de80576aba7f9f1fe985d8b: | 9 | for you to fetch changes up to 5e9785505210e2477e590e61b1ab100d0ec22b01: |
10 | 10 | ||
11 | qemu-io: Add write -n for BDRV_REQ_NO_FALLBACK (2019-03-26 11:37:51 +0100) | 11 | qcow2: Fix corruption bug in qcow2_detect_metadata_preallocation() (2019-10-25 15:18:55 +0200) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block layer patches: | 14 | Block layer patches: |
15 | 15 | ||
16 | - Fix slow pre-zeroing in qemu-img convert | 16 | - qcow2: Fix data corruption bug that is triggered in partial cluster |
17 | - Test case for block job pausing on I/O errors | 17 | allocation with default options |
18 | - qapi: add support for blkreplay driver | ||
19 | - doc: Describe missing generic -blockdev options | ||
20 | - iotests: Fix 118 when run as root | ||
21 | - Minor code cleanups | ||
18 | 22 | ||
19 | ---------------------------------------------------------------- | 23 | ---------------------------------------------------------------- |
20 | Kevin Wolf (6): | 24 | Kevin Wolf (5): |
21 | block: Remove error messages in bdrv_make_zero() | 25 | iotests: Skip read-only cases in 118 when run as root |
22 | block: Add BDRV_REQ_NO_FALLBACK | 26 | blockdev: Use error_report() in hmp_commit() |
23 | block: Advertise BDRV_REQ_NO_FALLBACK in filter drivers | 27 | doc: Describe missing generic -blockdev options |
24 | file-posix: Support BDRV_REQ_NO_FALLBACK for zero writes | 28 | coroutine: Add qemu_co_mutex_assert_locked() |
25 | qemu-img: Use BDRV_REQ_NO_FALLBACK for pre-zeroing | 29 | qcow2: Fix corruption bug in qcow2_detect_metadata_preallocation() |
26 | qemu-io: Add write -n for BDRV_REQ_NO_FALLBACK | 30 | |
31 | Pavel Dovgaluk (1): | ||
32 | qapi: add support for blkreplay driver | ||
27 | 33 | ||
28 | Vladimir Sementsov-Ogievskiy (1): | 34 | Vladimir Sementsov-Ogievskiy (1): |
29 | iotests: add 248: test resume mirror after auto pause on ENOSPC | 35 | block/backup: drop dead code from backup_job_create |
30 | 36 | ||
31 | include/block/block.h | 7 ++++- | 37 | qapi/block-core.json | 18 ++++++++++++++++-- |
32 | include/block/raw-aio.h | 1 + | 38 | include/qemu/coroutine.h | 15 +++++++++++++++ |
33 | block/blkdebug.c | 2 +- | 39 | block/backup.c | 5 +---- |
34 | block/copy-on-read.c | 7 ++--- | 40 | block/qcow2-refcount.c | 2 ++ |
35 | block/file-posix.c | 24 ++++++++++------ | 41 | block/qcow2.c | 3 ++- |
36 | block/io.c | 16 +++++++---- | 42 | blockdev.c | 7 +++---- |
37 | block/mirror.c | 3 +- | 43 | qemu-options.hx | 22 +++++++++++++++++++++- |
38 | block/raw-format.c | 2 +- | 44 | tests/qemu-iotests/118 | 3 +++ |
39 | qemu-img.c | 2 +- | 45 | tests/qemu-iotests/iotests.py | 10 ++++++++++ |
40 | qemu-io-cmds.c | 13 +++++++-- | 46 | 9 files changed, 73 insertions(+), 12 deletions(-) |
41 | tests/qemu-iotests/248 | 71 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
42 | tests/qemu-iotests/248.out | 8 ++++++ | ||
43 | tests/qemu-iotests/group | 1 + | ||
44 | 13 files changed, 133 insertions(+), 24 deletions(-) | ||
45 | create mode 100755 tests/qemu-iotests/248 | ||
46 | create mode 100644 tests/qemu-iotests/248.out | ||
47 | 47 | ||
48 | diff view generated by jsdifflib |
1 | We know that the kernel implements a slow fallback code path for | 1 | From: Pavel Dovgalyuk <pavel.dovgaluk@gmail.com> |
---|---|---|---|
2 | BLKZEROOUT, so if BDRV_REQ_NO_FALLBACK is given, we shouldn't call it. | ||
3 | The other operations we call in the context of .bdrv_co_pwrite_zeroes | ||
4 | should usually be quick, so no modification should be needed for them. | ||
5 | If we ever notice that there are additional problematic cases, we can | ||
6 | still make these conditional as well. | ||
7 | 2 | ||
3 | This patch adds support for blkreplay driver to the blockdev options. | ||
4 | Now blkreplay can be used with -blockdev command line option | ||
5 | in the following format: | ||
6 | -blockdev driver=blkreplay,image=file-node-name,node-name=replay-node-name | ||
7 | |||
8 | This option makes possible implementation of the better command | ||
9 | line support for record/replay invocations. | ||
10 | |||
11 | Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
9 | Acked-by: Eric Blake <eblake@redhat.com> | ||
10 | --- | 13 | --- |
11 | include/block/raw-aio.h | 1 + | 14 | qapi/block-core.json | 18 ++++++++++++++++-- |
12 | block/file-posix.c | 24 ++++++++++++++++-------- | 15 | 1 file changed, 16 insertions(+), 2 deletions(-) |
13 | 2 files changed, 17 insertions(+), 8 deletions(-) | ||
14 | 16 | ||
15 | diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h | 17 | diff --git a/qapi/block-core.json b/qapi/block-core.json |
16 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/include/block/raw-aio.h | 19 | --- a/qapi/block-core.json |
18 | +++ b/include/block/raw-aio.h | 20 | +++ b/qapi/block-core.json |
19 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ |
20 | /* AIO flags */ | 22 | # @nvme: Since 2.12 |
21 | #define QEMU_AIO_MISALIGNED 0x1000 | 23 | # @copy-on-read: Since 3.0 |
22 | #define QEMU_AIO_BLKDEV 0x2000 | 24 | # @blklogwrites: Since 3.0 |
23 | +#define QEMU_AIO_NO_FALLBACK 0x4000 | 25 | +# @blkreplay: Since 4.2 |
24 | 26 | # | |
25 | 27 | # Since: 2.9 | |
26 | /* linux-aio.c - Linux native implementation */ | 28 | ## |
27 | diff --git a/block/file-posix.c b/block/file-posix.c | 29 | { 'enum': 'BlockdevDriver', |
28 | index XXXXXXX..XXXXXXX 100644 | 30 | - 'data': [ 'blkdebug', 'blklogwrites', 'blkverify', 'bochs', 'cloop', |
29 | --- a/block/file-posix.c | 31 | - 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster', |
30 | +++ b/block/file-posix.c | 32 | + 'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs', |
31 | @@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options, | 33 | + 'cloop', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster', |
32 | } | 34 | 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks', |
33 | #endif | 35 | 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow', |
34 | 36 | 'qcow2', 'qed', 'quorum', 'raw', 'rbd', | |
35 | - bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; | 37 | @@ -XXX,XX +XXX,XX @@ |
36 | + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; | 38 | 'data': { 'test': 'BlockdevRef', |
37 | ret = 0; | 39 | 'raw': 'BlockdevRef' } } |
38 | fail: | 40 | |
39 | if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { | 41 | +## |
40 | @@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb) | 42 | +# @BlockdevOptionsBlkreplay: |
41 | } | 43 | +# |
42 | 44 | +# Driver specific block device options for blkreplay. | |
43 | #ifdef BLKZEROOUT | 45 | +# |
44 | - do { | 46 | +# @image: disk image which should be controlled with blkreplay |
45 | - uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes }; | 47 | +# |
46 | - if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) { | 48 | +# Since: 4.2 |
47 | - return 0; | 49 | +## |
48 | - } | 50 | +{ 'struct': 'BlockdevOptionsBlkreplay', |
49 | - } while (errno == EINTR); | 51 | + 'data': { 'image': 'BlockdevRef' } } |
50 | + /* The BLKZEROOUT implementation in the kernel doesn't set | 52 | + |
51 | + * BLKDEV_ZERO_NOFALLBACK, so we can't call this if we have to avoid slow | 53 | ## |
52 | + * fallbacks. */ | 54 | # @QuorumReadPattern: |
53 | + if (!(aiocb->aio_type & QEMU_AIO_NO_FALLBACK)) { | 55 | # |
54 | + do { | 56 | @@ -XXX,XX +XXX,XX @@ |
55 | + uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes }; | 57 | 'blkdebug': 'BlockdevOptionsBlkdebug', |
56 | + if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) { | 58 | 'blklogwrites':'BlockdevOptionsBlklogwrites', |
57 | + return 0; | 59 | 'blkverify': 'BlockdevOptionsBlkverify', |
58 | + } | 60 | + 'blkreplay': 'BlockdevOptionsBlkreplay', |
59 | + } while (errno == EINTR); | 61 | 'bochs': 'BlockdevOptionsGenericFormat', |
60 | 62 | 'cloop': 'BlockdevOptionsGenericFormat', | |
61 | - ret = translate_err(-errno); | 63 | 'copy-on-read':'BlockdevOptionsGenericFormat', |
62 | + ret = translate_err(-errno); | ||
63 | + } | ||
64 | #endif | ||
65 | |||
66 | if (ret == -ENOTSUP) { | ||
67 | @@ -XXX,XX +XXX,XX @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes, | ||
68 | if (blkdev) { | ||
69 | acb.aio_type |= QEMU_AIO_BLKDEV; | ||
70 | } | ||
71 | + if (flags & BDRV_REQ_NO_FALLBACK) { | ||
72 | + acb.aio_type |= QEMU_AIO_NO_FALLBACK; | ||
73 | + } | ||
74 | |||
75 | if (flags & BDRV_REQ_MAY_UNMAP) { | ||
76 | acb.aio_type |= QEMU_AIO_DISCARD; | ||
77 | -- | 64 | -- |
78 | 2.20.1 | 65 | 2.20.1 |
79 | 66 | ||
80 | 67 | diff view generated by jsdifflib |
1 | This makes the new BDRV_REQ_NO_FALLBACK flag available in the qemu-io | 1 | Some tests in 118 use chmod to remove write permissions from the file |
---|---|---|---|
2 | write command. | 2 | and assume that the image can indeed not be opened read-write |
3 | afterwards. This doesn't work when the test is run as root, because root | ||
4 | can still open the file as writable even when the permission bit isn't | ||
5 | set. | ||
6 | |||
7 | Introduce a @skip_if_root decorator and use it in 118 to skip the tests | ||
8 | in question when the script is run as root. | ||
3 | 9 | ||
4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
5 | Acked-by: Eric Blake <eblake@redhat.com> | 11 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
6 | --- | 12 | --- |
7 | qemu-io-cmds.c | 13 +++++++++++-- | 13 | tests/qemu-iotests/118 | 3 +++ |
8 | 1 file changed, 11 insertions(+), 2 deletions(-) | 14 | tests/qemu-iotests/iotests.py | 10 ++++++++++ |
15 | 2 files changed, 13 insertions(+) | ||
9 | 16 | ||
10 | diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c | 17 | diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118 |
18 | index XXXXXXX..XXXXXXX 100755 | ||
19 | --- a/tests/qemu-iotests/118 | ||
20 | +++ b/tests/qemu-iotests/118 | ||
21 | @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): | ||
22 | self.assert_qmp(result, 'return[0]/inserted/ro', True) | ||
23 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | ||
24 | |||
25 | + @iotests.skip_if_user_is_root | ||
26 | def test_rw_ro_retain(self): | ||
27 | os.chmod(new_img, 0o444) | ||
28 | self.vm.add_drive(old_img, 'media=disk', 'none') | ||
29 | @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): | ||
30 | self.assert_qmp(result, 'return[0]/inserted/ro', True) | ||
31 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | ||
32 | |||
33 | + @iotests.skip_if_user_is_root | ||
34 | def test_make_ro_rw(self): | ||
35 | os.chmod(new_img, 0o444) | ||
36 | self.vm.add_drive(old_img, 'media=disk', 'none') | ||
37 | @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): | ||
38 | self.assert_qmp(result, 'return[0]/inserted/ro', True) | ||
39 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | ||
40 | |||
41 | + @iotests.skip_if_user_is_root | ||
42 | def test_make_ro_rw_by_retain(self): | ||
43 | os.chmod(new_img, 0o444) | ||
44 | self.vm.add_drive(old_img, 'media=disk', 'none') | ||
45 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
11 | index XXXXXXX..XXXXXXX 100644 | 46 | index XXXXXXX..XXXXXXX 100644 |
12 | --- a/qemu-io-cmds.c | 47 | --- a/tests/qemu-iotests/iotests.py |
13 | +++ b/qemu-io-cmds.c | 48 | +++ b/tests/qemu-iotests/iotests.py |
14 | @@ -XXX,XX +XXX,XX @@ static void write_help(void) | 49 | @@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=[], read_only=False): |
15 | " -b, -- write to the VM state rather than the virtual disk\n" | 50 | return func_wrapper |
16 | " -c, -- write compressed data with blk_write_compressed\n" | 51 | return skip_test_decorator |
17 | " -f, -- use Force Unit Access semantics\n" | 52 | |
18 | +" -n, -- with -z, don't allow slow fallback\n" | 53 | +def skip_if_user_is_root(func): |
19 | " -p, -- ignored for backwards compatibility\n" | 54 | + '''Skip Test Decorator |
20 | " -P, -- use different pattern to fill file\n" | 55 | + Runs the test only without root permissions''' |
21 | " -C, -- report statistics in a machine parsable format\n" | 56 | + def func_wrapper(*args, **kwargs): |
22 | @@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = { | 57 | + if os.getuid() == 0: |
23 | .perm = BLK_PERM_WRITE, | 58 | + case_notrun('{}: cannot be run as root'.format(args[0])) |
24 | .argmin = 2, | 59 | + else: |
25 | .argmax = -1, | 60 | + return func(*args, **kwargs) |
26 | - .args = "[-bcCfquz] [-P pattern] off len", | 61 | + return func_wrapper |
27 | + .args = "[-bcCfnquz] [-P pattern] off len", | ||
28 | .oneline = "writes a number of bytes at a specified offset", | ||
29 | .help = write_help, | ||
30 | }; | ||
31 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
32 | int64_t total = 0; | ||
33 | int pattern = 0xcd; | ||
34 | |||
35 | - while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) { | ||
36 | + while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) { | ||
37 | switch (c) { | ||
38 | case 'b': | ||
39 | bflag = true; | ||
40 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
41 | case 'f': | ||
42 | flags |= BDRV_REQ_FUA; | ||
43 | break; | ||
44 | + case 'n': | ||
45 | + flags |= BDRV_REQ_NO_FALLBACK; | ||
46 | + break; | ||
47 | case 'p': | ||
48 | /* Ignored for backwards compatibility */ | ||
49 | break; | ||
50 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
51 | return -EINVAL; | ||
52 | } | ||
53 | |||
54 | + if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) { | ||
55 | + printf("-n requires -z to be specified\n"); | ||
56 | + return -EINVAL; | ||
57 | + } | ||
58 | + | 62 | + |
59 | if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) { | 63 | def execute_unittest(output, verbosity, debug): |
60 | printf("-u requires -z to be specified\n"); | 64 | runner = unittest.TextTestRunner(stream=output, descriptions=True, |
61 | return -EINVAL; | 65 | verbosity=verbosity) |
62 | -- | 66 | -- |
63 | 2.20.1 | 67 | 2.20.1 |
64 | 68 | ||
65 | 69 | diff view generated by jsdifflib |
1 | If qemu-img convert sees that the target image isn't zero-initialised | 1 | Instead of using monitor_printf() to report errors, hmp_commit() should |
---|---|---|---|
2 | yet, it tries to do an efficient zero write for the whole image first | 2 | use error_report() like other places do. |
3 | to save the overhead of repeated explicit zero writes during the | ||
4 | conversion. Obviously, this provides only an advantage if the | ||
5 | pre-zeroing is actually efficient. Otherwise, we can end up writing | ||
6 | zeroes slowly while zeroing out the whole image, and then overwrite the | ||
7 | same blocks again with real data, potentially doubling the written data. | ||
8 | |||
9 | Pass BDRV_REQ_NO_FALLBACK to blk_make_zero() to avoid this case. If we | ||
10 | can't efficiently zero out, we'll instead write explicit zeroes only if | ||
11 | there is no data to be written to a block. | ||
12 | 3 | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
14 | Acked-by: Eric Blake <eblake@redhat.com> | 5 | Reviewed-by: Eric Blake <eblake@redhat.com> |
6 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
15 | --- | 7 | --- |
16 | qemu-img.c | 2 +- | 8 | blockdev.c | 7 +++---- |
17 | 1 file changed, 1 insertion(+), 1 deletion(-) | 9 | 1 file changed, 3 insertions(+), 4 deletions(-) |
18 | 10 | ||
19 | diff --git a/qemu-img.c b/qemu-img.c | 11 | diff --git a/blockdev.c b/blockdev.c |
20 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/qemu-img.c | 13 | --- a/blockdev.c |
22 | +++ b/qemu-img.c | 14 | +++ b/blockdev.c |
23 | @@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s) | 15 | @@ -XXX,XX +XXX,XX @@ void hmp_commit(Monitor *mon, const QDict *qdict) |
24 | if (!s->has_zero_init && !s->target_has_backing && | 16 | |
25 | bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) | 17 | blk = blk_by_name(device); |
26 | { | 18 | if (!blk) { |
27 | - ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP); | 19 | - monitor_printf(mon, "Device '%s' not found\n", device); |
28 | + ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); | 20 | + error_report("Device '%s' not found", device); |
29 | if (ret == 0) { | 21 | return; |
30 | s->has_zero_init = true; | ||
31 | } | 22 | } |
23 | if (!blk_is_available(blk)) { | ||
24 | - monitor_printf(mon, "Device '%s' has no medium\n", device); | ||
25 | + error_report("Device '%s' has no medium", device); | ||
26 | return; | ||
27 | } | ||
28 | |||
29 | @@ -XXX,XX +XXX,XX @@ void hmp_commit(Monitor *mon, const QDict *qdict) | ||
30 | aio_context_release(aio_context); | ||
31 | } | ||
32 | if (ret < 0) { | ||
33 | - monitor_printf(mon, "'commit' error for '%s': %s\n", device, | ||
34 | - strerror(-ret)); | ||
35 | + error_report("'commit' error for '%s': %s", device, strerror(-ret)); | ||
36 | } | ||
37 | } | ||
38 | |||
32 | -- | 39 | -- |
33 | 2.20.1 | 40 | 2.20.1 |
34 | 41 | ||
35 | 42 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
---|---|---|---|
2 | 2 | ||
3 | Test that mirror job actually resume on resume command after being | 3 | After commit 00e30f05de1d195, there is no more "goto error" points |
4 | automatically paused on ENOSPC error. | 4 | after job creation, so after "error:" @job is always NULL and we don't |
5 | need roll-back job creation. | ||
5 | 6 | ||
6 | It's a follow-up test for 8d9648cbf3e | 7 | Reported-by: Coverity (CID 1406402) |
7 | "blockjob: fix user pause in block_job_error_action" | ||
8 | |||
9 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 8 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
10 | Tested-by: John Snow <jsnow@redhat.com> | 9 | Acked-by: Stefano Garzarella <sgarzare@redhat.com> |
11 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
13 | --- | 11 | --- |
14 | tests/qemu-iotests/248 | 71 ++++++++++++++++++++++++++++++++++++++ | 12 | block/backup.c | 5 +---- |
15 | tests/qemu-iotests/248.out | 8 +++++ | 13 | 1 file changed, 1 insertion(+), 4 deletions(-) |
16 | tests/qemu-iotests/group | 1 + | ||
17 | 3 files changed, 80 insertions(+) | ||
18 | create mode 100755 tests/qemu-iotests/248 | ||
19 | create mode 100644 tests/qemu-iotests/248.out | ||
20 | 14 | ||
21 | diff --git a/tests/qemu-iotests/248 b/tests/qemu-iotests/248 | 15 | diff --git a/block/backup.c b/block/backup.c |
22 | new file mode 100755 | ||
23 | index XXXXXXX..XXXXXXX | ||
24 | --- /dev/null | ||
25 | +++ b/tests/qemu-iotests/248 | ||
26 | @@ -XXX,XX +XXX,XX @@ | ||
27 | +#!/usr/bin/env python | ||
28 | +# | ||
29 | +# Test resume mirror after auto pause on ENOSPC | ||
30 | +# | ||
31 | +# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. | ||
32 | +# | ||
33 | +# This program is free software; you can redistribute it and/or modify | ||
34 | +# it under the terms of the GNU General Public License as published by | ||
35 | +# the Free Software Foundation; either version 2 of the License, or | ||
36 | +# (at your option) any later version. | ||
37 | +# | ||
38 | +# This program is distributed in the hope that it will be useful, | ||
39 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
40 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
41 | +# GNU General Public License for more details. | ||
42 | +# | ||
43 | +# You should have received a copy of the GNU General Public License | ||
44 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
45 | +# | ||
46 | + | ||
47 | +import iotests | ||
48 | +from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles | ||
49 | + | ||
50 | +iotests.verify_image_format(supported_fmts=['qcow2']) | ||
51 | + | ||
52 | +source, target = file_path('source', 'target') | ||
53 | +size = 5 * 1024 * 1024 | ||
54 | +limit = 2 * 1024 * 1024 | ||
55 | + | ||
56 | +qemu_img_create('-f', iotests.imgfmt, source, str(size)) | ||
57 | +qemu_img_create('-f', iotests.imgfmt, target, str(size)) | ||
58 | +qemu_io('-c', 'write 0 {}'.format(size), source) | ||
59 | + | ||
60 | +# raw format don't like empty files | ||
61 | +qemu_io('-c', 'write 0 {}'.format(size), target) | ||
62 | + | ||
63 | +vm = iotests.VM().add_drive(source) | ||
64 | +vm.launch() | ||
65 | + | ||
66 | +blockdev_opts = { | ||
67 | + 'driver': iotests.imgfmt, | ||
68 | + 'node-name': 'target', | ||
69 | + 'file': { | ||
70 | + 'driver': 'raw', | ||
71 | + 'size': limit, | ||
72 | + 'file': { | ||
73 | + 'driver': 'file', | ||
74 | + 'filename': target | ||
75 | + } | ||
76 | + } | ||
77 | +} | ||
78 | +vm.qmp_log('blockdev-add', filters=[filter_qmp_testfiles], **blockdev_opts) | ||
79 | + | ||
80 | +vm.qmp_log('blockdev-mirror', device='drive0', sync='full', target='target', | ||
81 | + on_target_error='enospc') | ||
82 | + | ||
83 | +vm.event_wait('JOB_STATUS_CHANGE', timeout=3.0, | ||
84 | + match={'data': {'status': 'paused'}}) | ||
85 | + | ||
86 | +# drop other cached events, to not interfere with further wait for 'running' | ||
87 | +vm.get_qmp_events() | ||
88 | + | ||
89 | +del blockdev_opts['file']['size'] | ||
90 | +vm.qmp_log('x-blockdev-reopen', filters=[filter_qmp_testfiles], | ||
91 | + **blockdev_opts) | ||
92 | + | ||
93 | +vm.qmp_log('block-job-resume', device='drive0') | ||
94 | +vm.event_wait('JOB_STATUS_CHANGE', timeout=1.0, | ||
95 | + match={'data': {'status': 'running'}}) | ||
96 | + | ||
97 | +vm.shutdown() | ||
98 | diff --git a/tests/qemu-iotests/248.out b/tests/qemu-iotests/248.out | ||
99 | new file mode 100644 | ||
100 | index XXXXXXX..XXXXXXX | ||
101 | --- /dev/null | ||
102 | +++ b/tests/qemu-iotests/248.out | ||
103 | @@ -XXX,XX +XXX,XX @@ | ||
104 | +{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}, "size": 2097152}, "node-name": "target"}} | ||
105 | +{"return": {}} | ||
106 | +{"execute": "blockdev-mirror", "arguments": {"device": "drive0", "on-target-error": "enospc", "sync": "full", "target": "target"}} | ||
107 | +{"return": {}} | ||
108 | +{"execute": "x-blockdev-reopen", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}}, "node-name": "target"}} | ||
109 | +{"return": {}} | ||
110 | +{"execute": "block-job-resume", "arguments": {"device": "drive0"}} | ||
111 | +{"return": {}} | ||
112 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
113 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
114 | --- a/tests/qemu-iotests/group | 17 | --- a/block/backup.c |
115 | +++ b/tests/qemu-iotests/group | 18 | +++ b/block/backup.c |
116 | @@ -XXX,XX +XXX,XX @@ | 19 | @@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, |
117 | 245 rw auto | 20 | if (sync_bitmap) { |
118 | 246 rw auto quick | 21 | bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL); |
119 | 247 rw auto quick | 22 | } |
120 | +248 rw auto quick | 23 | - if (job) { |
24 | - backup_clean(&job->common.job); | ||
25 | - job_early_fail(&job->common.job); | ||
26 | - } else if (backup_top) { | ||
27 | + if (backup_top) { | ||
28 | bdrv_backup_top_drop(backup_top); | ||
29 | } | ||
30 | |||
121 | -- | 31 | -- |
122 | 2.20.1 | 32 | 2.20.1 |
123 | 33 | ||
124 | 34 | diff view generated by jsdifflib |
1 | Filter drivers that support .bdrv_co_pwrite_zeroes can safely advertise | 1 | We added more generic options after introducing -blockdev and forgot to |
---|---|---|---|
2 | BDRV_REQ_NO_FALLBACK because they just forward the request flags to | 2 | update the documentation (man page and --help output) accordingly. Do |
3 | their child node. | 3 | that now. |
4 | 4 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
6 | Acked-by: Eric Blake <eblake@redhat.com> | 6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
7 | --- | 7 | --- |
8 | block/blkdebug.c | 2 +- | 8 | qemu-options.hx | 22 +++++++++++++++++++++- |
9 | block/copy-on-read.c | 7 +++---- | 9 | 1 file changed, 21 insertions(+), 1 deletion(-) |
10 | block/mirror.c | 3 ++- | ||
11 | block/raw-format.c | 2 +- | ||
12 | 4 files changed, 7 insertions(+), 7 deletions(-) | ||
13 | 10 | ||
14 | diff --git a/block/blkdebug.c b/block/blkdebug.c | 11 | diff --git a/qemu-options.hx b/qemu-options.hx |
15 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/block/blkdebug.c | 13 | --- a/qemu-options.hx |
17 | +++ b/block/blkdebug.c | 14 | +++ b/qemu-options.hx |
18 | @@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, | 15 | @@ -XXX,XX +XXX,XX @@ ETEXI |
19 | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | 16 | DEF("blockdev", HAS_ARG, QEMU_OPTION_blockdev, |
20 | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); | 17 | "-blockdev [driver=]driver[,node-name=N][,discard=ignore|unmap]\n" |
21 | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | 18 | " [,cache.direct=on|off][,cache.no-flush=on|off]\n" |
22 | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & | 19 | - " [,read-only=on|off][,detect-zeroes=on|off|unmap]\n" |
23 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | 20 | + " [,read-only=on|off][,auto-read-only=on|off]\n" |
24 | bs->file->bs->supported_zero_flags); | 21 | + " [,force-share=on|off][,detect-zeroes=on|off|unmap]\n" |
25 | ret = -EINVAL; | 22 | " [,driver specific parameters...]\n" |
26 | 23 | " configure a block backend\n", QEMU_ARCH_ALL) | |
27 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | 24 | STEXI |
28 | index XXXXXXX..XXXXXXX 100644 | 25 | @@ -XXX,XX +XXX,XX @@ name is not intended to be predictable and changes between QEMU invocations. |
29 | --- a/block/copy-on-read.c | 26 | For the top level, an explicit node name must be specified. |
30 | +++ b/block/copy-on-read.c | 27 | @item read-only |
31 | @@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, | 28 | Open the node read-only. Guest write attempts will fail. |
32 | } | 29 | + |
33 | 30 | +Note that some block drivers support only read-only access, either generally or | |
34 | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | 31 | +in certain configurations. In this case, the default value |
35 | - (BDRV_REQ_FUA & | 32 | +@option{read-only=off} does not work and the option must be specified |
36 | - bs->file->bs->supported_write_flags); | 33 | +explicitly. |
37 | + (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); | 34 | +@item auto-read-only |
38 | 35 | +If @option{auto-read-only=on} is set, QEMU may fall back to read-only usage | |
39 | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | 36 | +even when @option{read-only=off} is requested, or even switch between modes as |
40 | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & | 37 | +needed, e.g. depending on whether the image file is writable or whether a |
41 | - bs->file->bs->supported_zero_flags); | 38 | +writing user is attached to the node. |
42 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | 39 | +@item force-share |
43 | + bs->file->bs->supported_zero_flags); | 40 | +Override the image locking system of QEMU by forcing the node to utilize |
44 | 41 | +weaker shared access for permissions where it would normally request exclusive | |
45 | return 0; | 42 | +access. When there is the potential for multiple instances to have the same |
46 | } | 43 | +file open (whether this invocation of QEMU is the first or the second |
47 | diff --git a/block/mirror.c b/block/mirror.c | 44 | +instance), both instances must permit shared access for the second instance to |
48 | index XXXXXXX..XXXXXXX 100644 | 45 | +succeed at opening the file. |
49 | --- a/block/mirror.c | 46 | + |
50 | +++ b/block/mirror.c | 47 | +Enabling @option{force-share=on} requires @option{read-only=on}. |
51 | @@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, | 48 | @item cache.direct |
52 | } | 49 | The host page cache can be avoided with @option{cache.direct=on}. This will |
53 | mirror_top_bs->total_sectors = bs->total_sectors; | 50 | attempt to do disk IO directly to the guest's memory. QEMU may still perform an |
54 | mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED; | ||
55 | - mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED; | ||
56 | + mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
57 | + BDRV_REQ_NO_FALLBACK; | ||
58 | bs_opaque = g_new0(MirrorBDSOpaque, 1); | ||
59 | mirror_top_bs->opaque = bs_opaque; | ||
60 | bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs)); | ||
61 | diff --git a/block/raw-format.c b/block/raw-format.c | ||
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/block/raw-format.c | ||
64 | +++ b/block/raw-format.c | ||
65 | @@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, | ||
66 | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
67 | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); | ||
68 | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
69 | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & | ||
70 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | ||
71 | bs->file->bs->supported_zero_flags); | ||
72 | |||
73 | if (bs->probed && !bdrv_is_read_only(bs)) { | ||
74 | -- | 51 | -- |
75 | 2.20.1 | 52 | 2.20.1 |
76 | 53 | ||
77 | 54 | diff view generated by jsdifflib |
1 | There is only a single caller of bdrv_make_zero(), which is qemu-img | 1 | Some functions require that the caller holds a certain CoMutex for them |
---|---|---|---|
2 | convert. If the function fails, we just fall back to a different method | 2 | to operate correctly. Add a function so that they can assert the lock is |
3 | of zeroing out blocks on the target image. There is no good reason to | 3 | really held. |
4 | print error messages on stderr when the higher level operation will | ||
5 | actually succeed. | ||
6 | 4 | ||
5 | Cc: qemu-stable@nongnu.org | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | Acked-by: Eric Blake <eblake@redhat.com> | 7 | Tested-by: Michael Weiser <michael.weiser@gmx.de> |
8 | Reviewed-by: Michael Weiser <michael.weiser@gmx.de> | ||
9 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
10 | Reviewed-by: Denis V. Lunev <den@openvz.org> | ||
11 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | 12 | --- |
10 | block/io.c | 4 ---- | 13 | include/qemu/coroutine.h | 15 +++++++++++++++ |
11 | 1 file changed, 4 deletions(-) | 14 | 1 file changed, 15 insertions(+) |
12 | 15 | ||
13 | diff --git a/block/io.c b/block/io.c | 16 | diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h |
14 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/block/io.c | 18 | --- a/include/qemu/coroutine.h |
16 | +++ b/block/io.c | 19 | +++ b/include/qemu/coroutine.h |
17 | @@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) | 20 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); |
18 | } | 21 | */ |
19 | ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL); | 22 | void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); |
20 | if (ret < 0) { | 23 | |
21 | - error_report("error getting block status at offset %" PRId64 ": %s", | 24 | +/** |
22 | - offset, strerror(-ret)); | 25 | + * Assert that the current coroutine holds @mutex. |
23 | return ret; | 26 | + */ |
24 | } | 27 | +static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex) |
25 | if (ret & BDRV_BLOCK_ZERO) { | 28 | +{ |
26 | @@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) | 29 | + /* |
27 | } | 30 | + * mutex->holder doesn't need any synchronisation if the assertion holds |
28 | ret = bdrv_pwrite_zeroes(child, offset, bytes, flags); | 31 | + * true because the mutex protects it. If it doesn't hold true, we still |
29 | if (ret < 0) { | 32 | + * don't mind if another thread takes or releases mutex behind our back, |
30 | - error_report("error writing zeroes at offset %" PRId64 ": %s", | 33 | + * because the condition will be false no matter whether we read NULL or |
31 | - offset, strerror(-ret)); | 34 | + * the pointer for any other coroutine. |
32 | return ret; | 35 | + */ |
33 | } | 36 | + assert(atomic_read(&mutex->locked) && |
34 | offset += bytes; | 37 | + mutex->holder == qemu_coroutine_self()); |
38 | +} | ||
39 | |||
40 | /** | ||
41 | * CoQueues are a mechanism to queue coroutines in order to continue executing | ||
35 | -- | 42 | -- |
36 | 2.20.1 | 43 | 2.20.1 |
37 | 44 | ||
38 | 45 | diff view generated by jsdifflib |
1 | For qemu-img convert, we want an operation that zeroes out the whole | 1 | qcow2_detect_metadata_preallocation() calls qcow2_get_refcount() which |
---|---|---|---|
2 | image if this can be done efficiently, but that returns an error | 2 | requires s->lock to be taken to protect its accesses to the refcount |
3 | otherwise so we don't write explicit zeroes and immediately overwrite | 3 | table and refcount blocks. However, nothing in this code path actually |
4 | them with the real data, potentially doubling the amount of data to be | 4 | took the lock. This could cause the same cache entry to be used by two |
5 | written. | 5 | requests at the same time, for different tables at different offsets, |
6 | resulting in image corruption. | ||
6 | 7 | ||
8 | As it would be preferable to base the detection on consistent data (even | ||
9 | though it's just heuristics), let's take the lock not only around the | ||
10 | qcow2_get_refcount() calls, but around the whole function. | ||
11 | |||
12 | This patch takes the lock in qcow2_co_block_status() earlier and asserts | ||
13 | in qcow2_detect_metadata_preallocation() that we hold the lock. | ||
14 | |||
15 | Fixes: 69f47505ee66afaa513305de0c1895a224e52c45 | ||
16 | Cc: qemu-stable@nongnu.org | ||
17 | Reported-by: Michael Weiser <michael.weiser@gmx.de> | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | Acked-by: Eric Blake <eblake@redhat.com> | 19 | Tested-by: Michael Weiser <michael.weiser@gmx.de> |
20 | Reviewed-by: Michael Weiser <michael.weiser@gmx.de> | ||
21 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
22 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | 23 | --- |
10 | include/block/block.h | 7 ++++++- | 24 | block/qcow2-refcount.c | 2 ++ |
11 | block/io.c | 12 +++++++++++- | 25 | block/qcow2.c | 3 ++- |
12 | 2 files changed, 17 insertions(+), 2 deletions(-) | 26 | 2 files changed, 4 insertions(+), 1 deletion(-) |
13 | 27 | ||
14 | diff --git a/include/block/block.h b/include/block/block.h | 28 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c |
15 | index XXXXXXX..XXXXXXX 100644 | 29 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/include/block/block.h | 30 | --- a/block/qcow2-refcount.c |
17 | +++ b/include/block/block.h | 31 | +++ b/block/qcow2-refcount.c |
18 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 32 | @@ -XXX,XX +XXX,XX @@ int qcow2_detect_metadata_preallocation(BlockDriverState *bs) |
19 | */ | 33 | int64_t i, end_cluster, cluster_count = 0, threshold; |
20 | BDRV_REQ_SERIALISING = 0x80, | 34 | int64_t file_length, real_allocation, real_clusters; |
21 | 35 | ||
22 | + /* Execute the request only if the operation can be offloaded or otherwise | 36 | + qemu_co_mutex_assert_locked(&s->lock); |
23 | + * be executed efficiently, but return an error instead of using a slow | ||
24 | + * fallback. */ | ||
25 | + BDRV_REQ_NO_FALLBACK = 0x100, | ||
26 | + | 37 | + |
27 | /* Mask of valid flags */ | 38 | file_length = bdrv_getlength(bs->file->bs); |
28 | - BDRV_REQ_MASK = 0xff, | 39 | if (file_length < 0) { |
29 | + BDRV_REQ_MASK = 0x1ff, | 40 | return file_length; |
30 | } BdrvRequestFlags; | 41 | diff --git a/block/qcow2.c b/block/qcow2.c |
31 | |||
32 | typedef struct BlockSizes { | ||
33 | diff --git a/block/io.c b/block/io.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | 42 | index XXXXXXX..XXXXXXX 100644 |
35 | --- a/block/io.c | 43 | --- a/block/qcow2.c |
36 | +++ b/block/io.c | 44 | +++ b/block/qcow2.c |
37 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, | 45 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, |
38 | unsigned int nb_sectors; | 46 | unsigned int bytes; |
39 | 47 | int status = 0; | |
40 | assert(!(flags & ~BDRV_REQ_MASK)); | 48 | |
41 | + assert(!(flags & BDRV_REQ_NO_FALLBACK)); | 49 | + qemu_co_mutex_lock(&s->lock); |
42 | 50 | + | |
43 | if (!drv) { | 51 | if (!s->metadata_preallocation_checked) { |
44 | return -ENOMEDIUM; | 52 | ret = qcow2_detect_metadata_preallocation(bs); |
45 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, | 53 | s->metadata_preallocation = (ret == 1); |
46 | int ret; | 54 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, |
47 | |||
48 | assert(!(flags & ~BDRV_REQ_MASK)); | ||
49 | + assert(!(flags & BDRV_REQ_NO_FALLBACK)); | ||
50 | |||
51 | if (!drv) { | ||
52 | return -ENOMEDIUM; | ||
53 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, | ||
54 | return -ENOMEDIUM; | ||
55 | } | 55 | } |
56 | 56 | ||
57 | + if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) { | 57 | bytes = MIN(INT_MAX, count); |
58 | + return -ENOTSUP; | 58 | - qemu_co_mutex_lock(&s->lock); |
59 | + } | 59 | ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset); |
60 | + | 60 | qemu_co_mutex_unlock(&s->lock); |
61 | assert(alignment % bs->bl.request_alignment == 0); | 61 | if (ret < 0) { |
62 | head = offset % alignment; | ||
63 | tail = (offset + bytes) % alignment; | ||
64 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, | ||
65 | assert(!bs->supported_zero_flags); | ||
66 | } | ||
67 | |||
68 | - if (ret == -ENOTSUP) { | ||
69 | + if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) { | ||
70 | /* Fall back to bounce buffer if write zeroes is unsupported */ | ||
71 | BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE; | ||
72 | |||
73 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal( | ||
74 | BdrvTrackedRequest req; | ||
75 | int ret; | ||
76 | |||
77 | + /* TODO We can support BDRV_REQ_NO_FALLBACK here */ | ||
78 | + assert(!(read_flags & BDRV_REQ_NO_FALLBACK)); | ||
79 | + assert(!(write_flags & BDRV_REQ_NO_FALLBACK)); | ||
80 | + | ||
81 | if (!dst || !dst->bs) { | ||
82 | return -ENOMEDIUM; | ||
83 | } | ||
84 | -- | 62 | -- |
85 | 2.20.1 | 63 | 2.20.1 |
86 | 64 | ||
87 | 65 | diff view generated by jsdifflib |