Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into s…
Browse files Browse the repository at this point in the history
…taging

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 <kwolf@redhat.com>" [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 <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Mar 26, 2019
2 parents 905870b + c6e3f52 commit 1bd2e35
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 24 deletions.
2 changes: 1 addition & 1 deletion block/blkdebug.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);
ret = -EINVAL;

Expand Down
7 changes: 3 additions & 4 deletions block/copy-on-read.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
}

bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
(BDRV_REQ_FUA &
bs->file->bs->supported_write_flags);
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);

bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
bs->file->bs->supported_zero_flags);
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);

return 0;
}
Expand Down
24 changes: 16 additions & 8 deletions block/file-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
}
#endif

bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP;
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
ret = 0;
fail:
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
Expand Down Expand Up @@ -1500,14 +1500,19 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb)
}

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

ret = translate_err(-errno);
ret = translate_err(-errno);
}
#endif

if (ret == -ENOTSUP) {
Expand Down Expand Up @@ -2659,6 +2664,9 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
if (blkdev) {
acb.aio_type |= QEMU_AIO_BLKDEV;
}
if (flags & BDRV_REQ_NO_FALLBACK) {
acb.aio_type |= QEMU_AIO_NO_FALLBACK;
}

if (flags & BDRV_REQ_MAY_UNMAP) {
acb.aio_type |= QEMU_AIO_DISCARD;
Expand Down
16 changes: 11 additions & 5 deletions block/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,8 +909,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
}
ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL);
if (ret < 0) {
error_report("error getting block status at offset %" PRId64 ": %s",
offset, strerror(-ret));
return ret;
}
if (ret & BDRV_BLOCK_ZERO) {
Expand All @@ -919,8 +917,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
}
ret = bdrv_pwrite_zeroes(child, offset, bytes, flags);
if (ret < 0) {
error_report("error writing zeroes at offset %" PRId64 ": %s",
offset, strerror(-ret));
return ret;
}
offset += bytes;
Expand Down Expand Up @@ -1019,6 +1015,7 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
unsigned int nb_sectors;

assert(!(flags & ~BDRV_REQ_MASK));
assert(!(flags & BDRV_REQ_NO_FALLBACK));

if (!drv) {
return -ENOMEDIUM;
Expand Down Expand Up @@ -1065,6 +1062,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
int ret;

assert(!(flags & ~BDRV_REQ_MASK));
assert(!(flags & BDRV_REQ_NO_FALLBACK));

if (!drv) {
return -ENOMEDIUM;
Expand Down Expand Up @@ -1471,6 +1469,10 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
return -ENOMEDIUM;
}

if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) {
return -ENOTSUP;
}

assert(alignment % bs->bl.request_alignment == 0);
head = offset % alignment;
tail = (offset + bytes) % alignment;
Expand Down Expand Up @@ -1514,7 +1516,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
assert(!bs->supported_zero_flags);
}

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

Expand Down Expand Up @@ -2953,6 +2955,10 @@ static int coroutine_fn bdrv_co_copy_range_internal(
BdrvTrackedRequest req;
int ret;

/* TODO We can support BDRV_REQ_NO_FALLBACK here */
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
assert(!(write_flags & BDRV_REQ_NO_FALLBACK));

if (!dst || !dst->bs) {
return -ENOMEDIUM;
}
Expand Down
3 changes: 2 additions & 1 deletion block/mirror.c
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,8 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
}
mirror_top_bs->total_sectors = bs->total_sectors;
mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
BDRV_REQ_NO_FALLBACK;
bs_opaque = g_new0(MirrorBDSOpaque, 1);
mirror_top_bs->opaque = bs_opaque;
bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));
Expand Down
2 changes: 1 addition & 1 deletion block/raw-format.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);

if (bs->probed && !bdrv_is_read_only(bs)) {
Expand Down
7 changes: 6 additions & 1 deletion include/block/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,13 @@ typedef enum {
*/
BDRV_REQ_SERIALISING = 0x80,

/* Execute the request only if the operation can be offloaded or otherwise
* be executed efficiently, but return an error instead of using a slow
* fallback. */
BDRV_REQ_NO_FALLBACK = 0x100,

/* Mask of valid flags */
BDRV_REQ_MASK = 0xff,
BDRV_REQ_MASK = 0x1ff,
} BdrvRequestFlags;

typedef struct BlockSizes {
Expand Down
1 change: 1 addition & 0 deletions include/block/raw-aio.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
/* AIO flags */
#define QEMU_AIO_MISALIGNED 0x1000
#define QEMU_AIO_BLKDEV 0x2000
#define QEMU_AIO_NO_FALLBACK 0x4000


/* linux-aio.c - Linux native implementation */
Expand Down
2 changes: 1 addition & 1 deletion qemu-img.c
Original file line number Diff line number Diff line change
Expand Up @@ -1932,7 +1932,7 @@ static int convert_do_copy(ImgConvertState *s)
if (!s->has_zero_init && !s->target_has_backing &&
bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)))
{
ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP);
ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK);
if (ret == 0) {
s->has_zero_init = true;
}
Expand Down
13 changes: 11 additions & 2 deletions qemu-io-cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ static void write_help(void)
" -b, -- write to the VM state rather than the virtual disk\n"
" -c, -- write compressed data with blk_write_compressed\n"
" -f, -- use Force Unit Access semantics\n"
" -n, -- with -z, don't allow slow fallback\n"
" -p, -- ignored for backwards compatibility\n"
" -P, -- use different pattern to fill file\n"
" -C, -- report statistics in a machine parsable format\n"
Expand All @@ -964,7 +965,7 @@ static const cmdinfo_t write_cmd = {
.perm = BLK_PERM_WRITE,
.argmin = 2,
.argmax = -1,
.args = "[-bcCfquz] [-P pattern] off len",
.args = "[-bcCfnquz] [-P pattern] off len",
.oneline = "writes a number of bytes at a specified offset",
.help = write_help,
};
Expand All @@ -983,7 +984,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
int64_t total = 0;
int pattern = 0xcd;

while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) {
while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) {
switch (c) {
case 'b':
bflag = true;
Expand All @@ -997,6 +998,9 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
case 'f':
flags |= BDRV_REQ_FUA;
break;
case 'n':
flags |= BDRV_REQ_NO_FALLBACK;
break;
case 'p':
/* Ignored for backwards compatibility */
break;
Expand Down Expand Up @@ -1037,6 +1041,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
return -EINVAL;
}

if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
printf("-n requires -z to be specified\n");
return -EINVAL;
}

if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
printf("-u requires -z to be specified\n");
return -EINVAL;
Expand Down
71 changes: 71 additions & 0 deletions tests/qemu-iotests/248
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python
#
# Test resume mirror after auto pause on ENOSPC
#
# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import iotests
from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles

iotests.verify_image_format(supported_fmts=['qcow2'])

source, target = file_path('source', 'target')
size = 5 * 1024 * 1024
limit = 2 * 1024 * 1024

qemu_img_create('-f', iotests.imgfmt, source, str(size))
qemu_img_create('-f', iotests.imgfmt, target, str(size))
qemu_io('-c', 'write 0 {}'.format(size), source)

# raw format don't like empty files
qemu_io('-c', 'write 0 {}'.format(size), target)

vm = iotests.VM().add_drive(source)
vm.launch()

blockdev_opts = {
'driver': iotests.imgfmt,
'node-name': 'target',
'file': {
'driver': 'raw',
'size': limit,
'file': {
'driver': 'file',
'filename': target
}
}
}
vm.qmp_log('blockdev-add', filters=[filter_qmp_testfiles], **blockdev_opts)

vm.qmp_log('blockdev-mirror', device='drive0', sync='full', target='target',
on_target_error='enospc')

vm.event_wait('JOB_STATUS_CHANGE', timeout=3.0,
match={'data': {'status': 'paused'}})

# drop other cached events, to not interfere with further wait for 'running'
vm.get_qmp_events()

del blockdev_opts['file']['size']
vm.qmp_log('x-blockdev-reopen', filters=[filter_qmp_testfiles],
**blockdev_opts)

vm.qmp_log('block-job-resume', device='drive0')
vm.event_wait('JOB_STATUS_CHANGE', timeout=1.0,
match={'data': {'status': 'running'}})

vm.shutdown()
8 changes: 8 additions & 0 deletions tests/qemu-iotests/248.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}, "size": 2097152}, "node-name": "target"}}
{"return": {}}
{"execute": "blockdev-mirror", "arguments": {"device": "drive0", "on-target-error": "enospc", "sync": "full", "target": "target"}}
{"return": {}}
{"execute": "x-blockdev-reopen", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}}, "node-name": "target"}}
{"return": {}}
{"execute": "block-job-resume", "arguments": {"device": "drive0"}}
{"return": {}}
1 change: 1 addition & 0 deletions tests/qemu-iotests/group
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,4 @@
245 rw auto
246 rw auto quick
247 rw auto quick
248 rw auto quick

0 comments on commit 1bd2e35

Please sign in to comment.