Skip to content

Commit 1bd2e35

Browse files
committed
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches: - Fix slow pre-zeroing in qemu-img convert - Test case for block job pausing on I/O errors # gpg: Signature made Tue 26 Mar 2019 15:28:00 GMT # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <[email protected]>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: qemu-io: Add write -n for BDRV_REQ_NO_FALLBACK qemu-img: Use BDRV_REQ_NO_FALLBACK for pre-zeroing file-posix: Support BDRV_REQ_NO_FALLBACK for zero writes block: Advertise BDRV_REQ_NO_FALLBACK in filter drivers block: Add BDRV_REQ_NO_FALLBACK block: Remove error messages in bdrv_make_zero() iotests: add 248: test resume mirror after auto pause on ENOSPC Signed-off-by: Peter Maydell <[email protected]>
2 parents 905870b + c6e3f52 commit 1bd2e35

File tree

13 files changed

+133
-24
lines changed

13 files changed

+133
-24
lines changed

block/blkdebug.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
401401
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
402402
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
403403
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
404-
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
404+
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
405405
bs->file->bs->supported_zero_flags);
406406
ret = -EINVAL;
407407

block/copy-on-read.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
3434
}
3535

3636
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
37-
(BDRV_REQ_FUA &
38-
bs->file->bs->supported_write_flags);
37+
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
3938

4039
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
41-
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
42-
bs->file->bs->supported_zero_flags);
40+
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
41+
bs->file->bs->supported_zero_flags);
4342

4443
return 0;
4544
}

block/file-posix.c

+16-8
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
652652
}
653653
#endif
654654

655-
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP;
655+
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
656656
ret = 0;
657657
fail:
658658
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
@@ -1500,14 +1500,19 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb)
15001500
}
15011501

15021502
#ifdef BLKZEROOUT
1503-
do {
1504-
uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes };
1505-
if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) {
1506-
return 0;
1507-
}
1508-
} while (errno == EINTR);
1503+
/* The BLKZEROOUT implementation in the kernel doesn't set
1504+
* BLKDEV_ZERO_NOFALLBACK, so we can't call this if we have to avoid slow
1505+
* fallbacks. */
1506+
if (!(aiocb->aio_type & QEMU_AIO_NO_FALLBACK)) {
1507+
do {
1508+
uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes };
1509+
if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) {
1510+
return 0;
1511+
}
1512+
} while (errno == EINTR);
15091513

1510-
ret = translate_err(-errno);
1514+
ret = translate_err(-errno);
1515+
}
15111516
#endif
15121517

15131518
if (ret == -ENOTSUP) {
@@ -2659,6 +2664,9 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
26592664
if (blkdev) {
26602665
acb.aio_type |= QEMU_AIO_BLKDEV;
26612666
}
2667+
if (flags & BDRV_REQ_NO_FALLBACK) {
2668+
acb.aio_type |= QEMU_AIO_NO_FALLBACK;
2669+
}
26622670

26632671
if (flags & BDRV_REQ_MAY_UNMAP) {
26642672
acb.aio_type |= QEMU_AIO_DISCARD;

block/io.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
909909
}
910910
ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL);
911911
if (ret < 0) {
912-
error_report("error getting block status at offset %" PRId64 ": %s",
913-
offset, strerror(-ret));
914912
return ret;
915913
}
916914
if (ret & BDRV_BLOCK_ZERO) {
@@ -919,8 +917,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
919917
}
920918
ret = bdrv_pwrite_zeroes(child, offset, bytes, flags);
921919
if (ret < 0) {
922-
error_report("error writing zeroes at offset %" PRId64 ": %s",
923-
offset, strerror(-ret));
924920
return ret;
925921
}
926922
offset += bytes;
@@ -1019,6 +1015,7 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
10191015
unsigned int nb_sectors;
10201016

10211017
assert(!(flags & ~BDRV_REQ_MASK));
1018+
assert(!(flags & BDRV_REQ_NO_FALLBACK));
10221019

10231020
if (!drv) {
10241021
return -ENOMEDIUM;
@@ -1065,6 +1062,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
10651062
int ret;
10661063

10671064
assert(!(flags & ~BDRV_REQ_MASK));
1065+
assert(!(flags & BDRV_REQ_NO_FALLBACK));
10681066

10691067
if (!drv) {
10701068
return -ENOMEDIUM;
@@ -1471,6 +1469,10 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
14711469
return -ENOMEDIUM;
14721470
}
14731471

1472+
if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) {
1473+
return -ENOTSUP;
1474+
}
1475+
14741476
assert(alignment % bs->bl.request_alignment == 0);
14751477
head = offset % alignment;
14761478
tail = (offset + bytes) % alignment;
@@ -1514,7 +1516,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
15141516
assert(!bs->supported_zero_flags);
15151517
}
15161518

1517-
if (ret == -ENOTSUP) {
1519+
if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) {
15181520
/* Fall back to bounce buffer if write zeroes is unsupported */
15191521
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
15201522

@@ -2953,6 +2955,10 @@ static int coroutine_fn bdrv_co_copy_range_internal(
29532955
BdrvTrackedRequest req;
29542956
int ret;
29552957

2958+
/* TODO We can support BDRV_REQ_NO_FALLBACK here */
2959+
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
2960+
assert(!(write_flags & BDRV_REQ_NO_FALLBACK));
2961+
29562962
if (!dst || !dst->bs) {
29572963
return -ENOMEDIUM;
29582964
}

block/mirror.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1548,7 +1548,8 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
15481548
}
15491549
mirror_top_bs->total_sectors = bs->total_sectors;
15501550
mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
1551-
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
1551+
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
1552+
BDRV_REQ_NO_FALLBACK;
15521553
bs_opaque = g_new0(MirrorBDSOpaque, 1);
15531554
mirror_top_bs->opaque = bs_opaque;
15541555
bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));

block/raw-format.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
434434
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
435435
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
436436
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
437-
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
437+
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
438438
bs->file->bs->supported_zero_flags);
439439

440440
if (bs->probed && !bdrv_is_read_only(bs)) {

include/block/block.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,13 @@ typedef enum {
8383
*/
8484
BDRV_REQ_SERIALISING = 0x80,
8585

86+
/* Execute the request only if the operation can be offloaded or otherwise
87+
* be executed efficiently, but return an error instead of using a slow
88+
* fallback. */
89+
BDRV_REQ_NO_FALLBACK = 0x100,
90+
8691
/* Mask of valid flags */
87-
BDRV_REQ_MASK = 0xff,
92+
BDRV_REQ_MASK = 0x1ff,
8893
} BdrvRequestFlags;
8994

9095
typedef struct BlockSizes {

include/block/raw-aio.h

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
/* AIO flags */
4141
#define QEMU_AIO_MISALIGNED 0x1000
4242
#define QEMU_AIO_BLKDEV 0x2000
43+
#define QEMU_AIO_NO_FALLBACK 0x4000
4344

4445

4546
/* linux-aio.c - Linux native implementation */

qemu-img.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,7 @@ static int convert_do_copy(ImgConvertState *s)
19321932
if (!s->has_zero_init && !s->target_has_backing &&
19331933
bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)))
19341934
{
1935-
ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP);
1935+
ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK);
19361936
if (ret == 0) {
19371937
s->has_zero_init = true;
19381938
}

qemu-io-cmds.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ static void write_help(void)
946946
" -b, -- write to the VM state rather than the virtual disk\n"
947947
" -c, -- write compressed data with blk_write_compressed\n"
948948
" -f, -- use Force Unit Access semantics\n"
949+
" -n, -- with -z, don't allow slow fallback\n"
949950
" -p, -- ignored for backwards compatibility\n"
950951
" -P, -- use different pattern to fill file\n"
951952
" -C, -- report statistics in a machine parsable format\n"
@@ -964,7 +965,7 @@ static const cmdinfo_t write_cmd = {
964965
.perm = BLK_PERM_WRITE,
965966
.argmin = 2,
966967
.argmax = -1,
967-
.args = "[-bcCfquz] [-P pattern] off len",
968+
.args = "[-bcCfnquz] [-P pattern] off len",
968969
.oneline = "writes a number of bytes at a specified offset",
969970
.help = write_help,
970971
};
@@ -983,7 +984,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
983984
int64_t total = 0;
984985
int pattern = 0xcd;
985986

986-
while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) {
987+
while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) {
987988
switch (c) {
988989
case 'b':
989990
bflag = true;
@@ -997,6 +998,9 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
997998
case 'f':
998999
flags |= BDRV_REQ_FUA;
9991000
break;
1001+
case 'n':
1002+
flags |= BDRV_REQ_NO_FALLBACK;
1003+
break;
10001004
case 'p':
10011005
/* Ignored for backwards compatibility */
10021006
break;
@@ -1037,6 +1041,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
10371041
return -EINVAL;
10381042
}
10391043

1044+
if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1045+
printf("-n requires -z to be specified\n");
1046+
return -EINVAL;
1047+
}
1048+
10401049
if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
10411050
printf("-u requires -z to be specified\n");
10421051
return -EINVAL;

tests/qemu-iotests/248

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env python
2+
#
3+
# Test resume mirror after auto pause on ENOSPC
4+
#
5+
# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
6+
#
7+
# This program is free software; you can redistribute it and/or modify
8+
# it under the terms of the GNU General Public License as published by
9+
# the Free Software Foundation; either version 2 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
#
20+
21+
import iotests
22+
from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles
23+
24+
iotests.verify_image_format(supported_fmts=['qcow2'])
25+
26+
source, target = file_path('source', 'target')
27+
size = 5 * 1024 * 1024
28+
limit = 2 * 1024 * 1024
29+
30+
qemu_img_create('-f', iotests.imgfmt, source, str(size))
31+
qemu_img_create('-f', iotests.imgfmt, target, str(size))
32+
qemu_io('-c', 'write 0 {}'.format(size), source)
33+
34+
# raw format don't like empty files
35+
qemu_io('-c', 'write 0 {}'.format(size), target)
36+
37+
vm = iotests.VM().add_drive(source)
38+
vm.launch()
39+
40+
blockdev_opts = {
41+
'driver': iotests.imgfmt,
42+
'node-name': 'target',
43+
'file': {
44+
'driver': 'raw',
45+
'size': limit,
46+
'file': {
47+
'driver': 'file',
48+
'filename': target
49+
}
50+
}
51+
}
52+
vm.qmp_log('blockdev-add', filters=[filter_qmp_testfiles], **blockdev_opts)
53+
54+
vm.qmp_log('blockdev-mirror', device='drive0', sync='full', target='target',
55+
on_target_error='enospc')
56+
57+
vm.event_wait('JOB_STATUS_CHANGE', timeout=3.0,
58+
match={'data': {'status': 'paused'}})
59+
60+
# drop other cached events, to not interfere with further wait for 'running'
61+
vm.get_qmp_events()
62+
63+
del blockdev_opts['file']['size']
64+
vm.qmp_log('x-blockdev-reopen', filters=[filter_qmp_testfiles],
65+
**blockdev_opts)
66+
67+
vm.qmp_log('block-job-resume', device='drive0')
68+
vm.event_wait('JOB_STATUS_CHANGE', timeout=1.0,
69+
match={'data': {'status': 'running'}})
70+
71+
vm.shutdown()

tests/qemu-iotests/248.out

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}, "size": 2097152}, "node-name": "target"}}
2+
{"return": {}}
3+
{"execute": "blockdev-mirror", "arguments": {"device": "drive0", "on-target-error": "enospc", "sync": "full", "target": "target"}}
4+
{"return": {}}
5+
{"execute": "x-blockdev-reopen", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}}, "node-name": "target"}}
6+
{"return": {}}
7+
{"execute": "block-job-resume", "arguments": {"device": "drive0"}}
8+
{"return": {}}

tests/qemu-iotests/group

+1
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,4 @@
246246
245 rw auto
247247
246 rw auto quick
248248
247 rw auto quick
249+
248 rw auto quick

0 commit comments

Comments
 (0)