diff mbox series

[v2] block: Reject misaligned write requests with BDRV_REQ_NO_FALLBACK

Message ID 20191014081545.29694-1-berto@igalia.com (mailing list archive)
State New, archived
Headers show
Series [v2] block: Reject misaligned write requests with BDRV_REQ_NO_FALLBACK | expand

Commit Message

Alberto Garcia Oct. 14, 2019, 8:15 a.m. UTC
The BDRV_REQ_NO_FALLBACK flag means that an operation should only be
performed if it can be offloaded or otherwise performed efficiently.

However a misaligned write request requires a RMW so we should return
an error and let the caller decide how to proceed.

This hits an assertion since commit c8bb23cbdb if the required
alignment is larger than the cluster size:

qemu-img create -f qcow2 -o cluster_size=2k img.qcow2 4G
qemu-io -c "open -o driver=qcow2,file.align=4k blkdebug::img.qcow2" \
        -c 'write 0 512'
qemu-io: block/io.c:1127: bdrv_driver_pwritev: Assertion `!(flags & BDRV_REQ_NO_FALLBACK)' failed.
Aborted

The reason is that when writing to an unallocated cluster we try to
skip the copy-on-write part and zeroize it using BDRV_REQ_NO_FALLBACK
instead, resulting in a write request that is too small (2KB cluster
size vs 4KB required alignment).

Signed-off-by: Alberto Garcia <berto@igalia.com>
---
v2:
- Use QEMU_IS_ALIGNED and (offset | bytes) [Nir]
- Fix typo in comment in iotest
- Expand commit message

v1:
- Initial version

 block/io.c                 |  6 +++++
 tests/qemu-iotests/268     | 55 ++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/268.out |  7 +++++
 tests/qemu-iotests/group   |  1 +
 4 files changed, 69 insertions(+)
 create mode 100755 tests/qemu-iotests/268
 create mode 100644 tests/qemu-iotests/268.out

Comments

no-reply@patchew.org Oct. 14, 2019, 8:41 a.m. UTC | #1
Patchew URL: https://patchew.org/QEMU/20191014081545.29694-1-berto@igalia.com/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#! /bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-mingw@fedora J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
make: *** [Makefile:994: docs/interop/index.html] Error 2
make: *** Waiting for unfinished jobs....
  CC      block/vhdx.o
Traceback (most recent call last):
---
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=5e3c9ceb0d0e48f1b7fdaee32bfbd2c2', '-u', '1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-t_sgxpzt/src/docker-src.2019-10-14-04.39.53.16659:/var/tmp/qemu:z,ro', 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=5e3c9ceb0d0e48f1b7fdaee32bfbd2c2
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-t_sgxpzt/src'
make: *** [docker-run-test-mingw@fedora] Error 2

real    1m53.697s
user    0m7.411s


The full log is available at
http://patchew.org/logs/20191014081545.29694-1-berto@igalia.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
Kevin Wolf Oct. 14, 2019, 9:26 a.m. UTC | #2
Am 14.10.2019 um 10:15 hat Alberto Garcia geschrieben:
> The BDRV_REQ_NO_FALLBACK flag means that an operation should only be
> performed if it can be offloaded or otherwise performed efficiently.
> 
> However a misaligned write request requires a RMW so we should return
> an error and let the caller decide how to proceed.
> 
> This hits an assertion since commit c8bb23cbdb if the required
> alignment is larger than the cluster size:
> 
> qemu-img create -f qcow2 -o cluster_size=2k img.qcow2 4G
> qemu-io -c "open -o driver=qcow2,file.align=4k blkdebug::img.qcow2" \
>         -c 'write 0 512'
> qemu-io: block/io.c:1127: bdrv_driver_pwritev: Assertion `!(flags & BDRV_REQ_NO_FALLBACK)' failed.
> Aborted
> 
> The reason is that when writing to an unallocated cluster we try to
> skip the copy-on-write part and zeroize it using BDRV_REQ_NO_FALLBACK
> instead, resulting in a write request that is too small (2KB cluster
> size vs 4KB required alignment).
> 
> Signed-off-by: Alberto Garcia <berto@igalia.com>

Thanks, applied to the block branch.

Kevin
Alberto Garcia Oct. 14, 2019, 11:22 a.m. UTC | #3
On Mon 14 Oct 2019 11:26:01 AM CEST, Kevin Wolf wrote:
>> Signed-off-by: Alberto Garcia <berto@igalia.com>
>
> Thanks, applied to the block branch.

I'm a bit late now, but a possible trivial optimization is to flip the
conditions, because checking the flag should be faster than checking the
alignment and it's going to be false in almost all cases:

    if ((flags & BDRV_REQ_NO_FALLBACK) &&
        !QEMU_IS_ALIGNED(offset | bytes, align)) {
        return -ENOTSUP;
    }

Feel free to edit the commit if you want.

Berto
Kevin Wolf Oct. 14, 2019, 2:21 p.m. UTC | #4
Am 14.10.2019 um 13:22 hat Alberto Garcia geschrieben:
> On Mon 14 Oct 2019 11:26:01 AM CEST, Kevin Wolf wrote:
> >> Signed-off-by: Alberto Garcia <berto@igalia.com>
> >
> > Thanks, applied to the block branch.
> 
> I'm a bit late now, but a possible trivial optimization is to flip the
> conditions, because checking the flag should be faster than checking the
> alignment and it's going to be false in almost all cases:
> 
>     if ((flags & BDRV_REQ_NO_FALLBACK) &&
>         !QEMU_IS_ALIGNED(offset | bytes, align)) {
>         return -ENOTSUP;
>     }
> 
> Feel free to edit the commit if you want.

Ok, I'll update it.

Kevin
diff mbox series

Patch

diff --git a/block/io.c b/block/io.c
index 4f9ee97c2b..18d842382a 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2071,6 +2071,12 @@  int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
         return ret;
     }
 
+    /* If the request is misaligned then we can't make it efficient */
+    if (!QEMU_IS_ALIGNED(offset | bytes, align) &&
+        (flags & BDRV_REQ_NO_FALLBACK)) {
+        return -ENOTSUP;
+    }
+
     bdrv_inc_in_flight(bs);
     /*
      * Align write if necessary by performing a read-modify-write cycle.
diff --git a/tests/qemu-iotests/268 b/tests/qemu-iotests/268
new file mode 100755
index 0000000000..78c3f4db3a
--- /dev/null
+++ b/tests/qemu-iotests/268
@@ -0,0 +1,55 @@ 
+#!/usr/bin/env bash
+#
+# Test write request with required alignment larger than the cluster size
+#
+# Copyright (C) 2019 Igalia, S.L.
+# Author: Alberto Garcia <berto@igalia.com>
+#
+# 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/>.
+#
+
+# creator
+owner=berto@igalia.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file
+
+echo
+echo "== Required alignment larger than cluster size =="
+
+CLUSTER_SIZE=2k _make_test_img 1M
+# Since commit c8bb23cbdb writing to an unallocated cluster fills the
+# empty COW areas with bdrv_write_zeroes(flags=BDRV_REQ_NO_FALLBACK)
+$QEMU_IO -c "open -o driver=$IMGFMT,file.align=4k blkdebug::$TEST_IMG" \
+         -c "write 0 512" | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/268.out b/tests/qemu-iotests/268.out
new file mode 100644
index 0000000000..2ed6c68529
--- /dev/null
+++ b/tests/qemu-iotests/268.out
@@ -0,0 +1,7 @@ 
+QA output created by 268
+
+== Required alignment larger than cluster size ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 5805a79d9e..4c861f7eed 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -278,3 +278,4 @@ 
 265 rw auto quick
 266 rw quick
 267 rw auto quick snapshot
+268 rw auto quick