aboutsummaryrefslogtreecommitdiff
path: root/block/io.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2019-10-01 19:48:26 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2019-10-08 14:28:25 +0100
commit8644476e51fa33d7ab637b36b1306d0d4c66177c (patch)
tree2e998bc1cc853fcb7665074003c2630f40aed03b /block/io.c
parent9b92fbcf45ed6ed1daceba8480b0d9e8a327b5ce (diff)
downloadqemu-8644476e51fa33d7ab637b36b1306d0d4c66177c.zip
qemu-8644476e51fa33d7ab637b36b1306d0d4c66177c.tar.gz
qemu-8644476e51fa33d7ab637b36b1306d0d4c66177c.tar.bz2
block: Skip COR for inactive nodes
We must not write data to inactive nodes, and a COR is certainly something we can simply not do without upsetting anyone. So skip COR operations on inactive nodes. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20191001174827.11081-2-mreitz@redhat.com Message-Id: <20191001174827.11081-2-mreitz@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/io.c')
-rw-r--r--block/io.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/block/io.c b/block/io.c
index f8c3596..4f9ee97 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1246,11 +1246,18 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
BDRV_REQUEST_MAX_BYTES);
unsigned int progress = 0;
+ bool skip_write;
if (!drv) {
return -ENOMEDIUM;
}
+ /*
+ * Do not write anything when the BDS is inactive. That is not
+ * allowed, and it would not help.
+ */
+ skip_write = (bs->open_flags & BDRV_O_INACTIVE);
+
/* FIXME We cannot require callers to have write permissions when all they
* are doing is a read request. If we did things right, write permissions
* would be obtained anyway, but internally by the copy-on-read code. As
@@ -1274,23 +1281,29 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
while (cluster_bytes) {
int64_t pnum;
- ret = bdrv_is_allocated(bs, cluster_offset,
- MIN(cluster_bytes, max_transfer), &pnum);
- if (ret < 0) {
- /* Safe to treat errors in querying allocation as if
- * unallocated; we'll probably fail again soon on the
- * read, but at least that will set a decent errno.
- */
+ if (skip_write) {
+ ret = 1; /* "already allocated", so nothing will be copied */
pnum = MIN(cluster_bytes, max_transfer);
- }
+ } else {
+ ret = bdrv_is_allocated(bs, cluster_offset,
+ MIN(cluster_bytes, max_transfer), &pnum);
+ if (ret < 0) {
+ /*
+ * Safe to treat errors in querying allocation as if
+ * unallocated; we'll probably fail again soon on the
+ * read, but at least that will set a decent errno.
+ */
+ pnum = MIN(cluster_bytes, max_transfer);
+ }
- /* Stop at EOF if the image ends in the middle of the cluster */
- if (ret == 0 && pnum == 0) {
- assert(progress >= bytes);
- break;
- }
+ /* Stop at EOF if the image ends in the middle of the cluster */
+ if (ret == 0 && pnum == 0) {
+ assert(progress >= bytes);
+ break;
+ }
- assert(skip_bytes < pnum);
+ assert(skip_bytes < pnum);
+ }
if (ret <= 0) {
QEMUIOVector local_qiov;