|
|
0a122b |
From 8603c409443521f98a73652ebf30233da879c7de Mon Sep 17 00:00:00 2001
|
|
|
0a122b |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
0a122b |
Date: Thu, 28 Nov 2013 10:23:32 +0100
|
|
|
0a122b |
Subject: [PATCH 08/37] block: Don't use guest sector size for qemu_blockalign()
|
|
|
0a122b |
|
|
|
0a122b |
Message-id: <1392117622-28812-9-git-send-email-kwolf@redhat.com>
|
|
|
0a122b |
Patchwork-id: 57173
|
|
|
0a122b |
O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 08/37] block: Don't use guest sector size for qemu_blockalign()
|
|
|
0a122b |
Bugzilla: 748906
|
|
|
0a122b |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
0a122b |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
0a122b |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
0a122b |
|
|
|
0a122b |
bs->buffer_alignment is set by the device emulation and contains the
|
|
|
0a122b |
logical block size of the guest device. This isn't something that the
|
|
|
0a122b |
block layer should know, and even less something to use for determining
|
|
|
0a122b |
the right alignment of buffers to be used for the host.
|
|
|
0a122b |
|
|
|
0a122b |
The new BlockLimits field opt_mem_alignment tells the qemu block layer
|
|
|
0a122b |
the optimal alignment to be used so that no bounce buffer must be used
|
|
|
0a122b |
in the driver.
|
|
|
0a122b |
|
|
|
0a122b |
This patch may change the buffer alignment from 4k to 512 for all
|
|
|
0a122b |
callers that used qemu_blockalign() with the top-level image format
|
|
|
0a122b |
BlockDriverState. The value was never propagated to other levels in the
|
|
|
0a122b |
tree, so in particular raw-posix never required anything else than 512.
|
|
|
0a122b |
|
|
|
0a122b |
While on disks with 4k sectors direct I/O requires a 4k alignment,
|
|
|
0a122b |
memory may still be okay when aligned to 512 byte boundaries. This is
|
|
|
0a122b |
what must have happened in practice, because otherwise this would
|
|
|
0a122b |
already have failed earlier. Therefore I don't expect regressions even
|
|
|
0a122b |
with this intermediate state. Later, raw-posix can implement the hook
|
|
|
0a122b |
and expose a different memory alignment requirement.
|
|
|
0a122b |
|
|
|
0a122b |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
0a122b |
Reviewed-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
|
|
|
0a122b |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
0a122b |
(cherry picked from commit 339064d5063924e5176842abbf6c8089f3479c5b)
|
|
|
0a122b |
|
|
|
0a122b |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
0a122b |
---
|
|
|
0a122b |
block.c | 23 ++++++++++++++++++++---
|
|
|
0a122b |
include/block/block.h | 3 +++
|
|
|
0a122b |
include/block/block_int.h | 3 +++
|
|
|
0a122b |
3 files changed, 26 insertions(+), 3 deletions(-)
|
|
|
0a122b |
---
|
|
|
0a122b |
block.c | 23 ++++++++++++++++++++---
|
|
|
0a122b |
include/block/block.h | 3 +++
|
|
|
0a122b |
include/block/block_int.h | 3 +++
|
|
|
0a122b |
3 files changed, 26 insertions(+), 3 deletions(-)
|
|
|
0a122b |
|
|
|
0a122b |
diff --git a/block.c b/block.c
|
|
|
0a122b |
index 6c98ff7..c85f43e 100644
|
|
|
0a122b |
--- a/block.c
|
|
|
0a122b |
+++ b/block.c
|
|
|
0a122b |
@@ -185,6 +185,16 @@ static void bdrv_io_limits_intercept(BlockDriverState *bs,
|
|
|
0a122b |
qemu_co_queue_next(&bs->throttled_reqs);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
+size_t bdrv_opt_mem_align(BlockDriverState *bs)
|
|
|
0a122b |
+{
|
|
|
0a122b |
+ if (!bs || !bs->drv) {
|
|
|
0a122b |
+ /* 4k should be on the safe side */
|
|
|
0a122b |
+ return 4096;
|
|
|
0a122b |
+ }
|
|
|
0a122b |
+
|
|
|
0a122b |
+ return bs->bl.opt_mem_alignment;
|
|
|
0a122b |
+}
|
|
|
0a122b |
+
|
|
|
0a122b |
/* check if the path starts with "<protocol>:" */
|
|
|
0a122b |
static int path_has_protocol(const char *path)
|
|
|
0a122b |
{
|
|
|
0a122b |
@@ -460,6 +470,9 @@ int bdrv_refresh_limits(BlockDriverState *bs)
|
|
|
0a122b |
if (bs->file) {
|
|
|
0a122b |
bdrv_refresh_limits(bs->file);
|
|
|
0a122b |
bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
|
|
|
0a122b |
+ bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
|
|
|
0a122b |
+ } else {
|
|
|
0a122b |
+ bs->bl.opt_mem_alignment = 512;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
if (bs->backing_hd) {
|
|
|
0a122b |
@@ -467,6 +480,9 @@ int bdrv_refresh_limits(BlockDriverState *bs)
|
|
|
0a122b |
bs->bl.opt_transfer_length =
|
|
|
0a122b |
MAX(bs->bl.opt_transfer_length,
|
|
|
0a122b |
bs->backing_hd->bl.opt_transfer_length);
|
|
|
0a122b |
+ bs->bl.opt_mem_alignment =
|
|
|
0a122b |
+ MAX(bs->bl.opt_mem_alignment,
|
|
|
0a122b |
+ bs->backing_hd->bl.opt_mem_alignment);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
/* Then let the driver override it */
|
|
|
0a122b |
@@ -4729,7 +4745,7 @@ void bdrv_set_buffer_alignment(BlockDriverState *bs, int align)
|
|
|
0a122b |
|
|
|
0a122b |
void *qemu_blockalign(BlockDriverState *bs, size_t size)
|
|
|
0a122b |
{
|
|
|
0a122b |
- return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);
|
|
|
0a122b |
+ return qemu_memalign(bdrv_opt_mem_align(bs), size);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
/*
|
|
|
0a122b |
@@ -4738,12 +4754,13 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size)
|
|
|
0a122b |
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
|
|
0a122b |
{
|
|
|
0a122b |
int i;
|
|
|
0a122b |
+ size_t alignment = bdrv_opt_mem_align(bs);
|
|
|
0a122b |
|
|
|
0a122b |
for (i = 0; i < qiov->niov; i++) {
|
|
|
0a122b |
- if ((uintptr_t) qiov->iov[i].iov_base % bs->buffer_alignment) {
|
|
|
0a122b |
+ if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
|
|
|
0a122b |
return false;
|
|
|
0a122b |
}
|
|
|
0a122b |
- if (qiov->iov[i].iov_len % bs->buffer_alignment) {
|
|
|
0a122b |
+ if (qiov->iov[i].iov_len % alignment) {
|
|
|
0a122b |
return false;
|
|
|
0a122b |
}
|
|
|
0a122b |
}
|
|
|
0a122b |
diff --git a/include/block/block.h b/include/block/block.h
|
|
|
0a122b |
index 3e22fc2..9d1ce59 100644
|
|
|
0a122b |
--- a/include/block/block.h
|
|
|
0a122b |
+++ b/include/block/block.h
|
|
|
0a122b |
@@ -406,6 +406,9 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
|
|
0a122b |
char *options, uint64_t img_size, int flags,
|
|
|
0a122b |
Error **errp, bool quiet);
|
|
|
0a122b |
|
|
|
0a122b |
+/* Returns the alignment in bytes that is required so that no bounce buffer
|
|
|
0a122b |
+ * is required throughout the stack */
|
|
|
0a122b |
+size_t bdrv_opt_mem_align(BlockDriverState *bs);
|
|
|
0a122b |
void bdrv_set_buffer_alignment(BlockDriverState *bs, int align);
|
|
|
0a122b |
void *qemu_blockalign(BlockDriverState *bs, size_t size);
|
|
|
0a122b |
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
|
|
|
0a122b |
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
|
0a122b |
index 13a52e8..ddbd53d 100644
|
|
|
0a122b |
--- a/include/block/block_int.h
|
|
|
0a122b |
+++ b/include/block/block_int.h
|
|
|
0a122b |
@@ -239,6 +239,9 @@ typedef struct BlockLimits {
|
|
|
0a122b |
|
|
|
0a122b |
/* optimal transfer length in sectors */
|
|
|
0a122b |
int opt_transfer_length;
|
|
|
0a122b |
+
|
|
|
0a122b |
+ /* memory alignment so that no bounce buffer is needed */
|
|
|
0a122b |
+ size_t opt_mem_alignment;
|
|
|
0a122b |
} BlockLimits;
|
|
|
0a122b |
|
|
|
0a122b |
/*
|
|
|
0a122b |
--
|
|
|
0a122b |
1.7.1
|
|
|
0a122b |
|