aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c11
-rw-r--r--block/io.c7
-rw-r--r--block/raw-posix.c1
-rw-r--r--include/block/block.h2
-rw-r--r--include/block/block_int.h3
5 files changed, 23 insertions, 1 deletions
diff --git a/block.c b/block.c
index 7904098c64..e293907c2b 100644
--- a/block.c
+++ b/block.c
@@ -113,6 +113,16 @@ size_t bdrv_opt_mem_align(BlockDriverState *bs)
return bs->bl.opt_mem_alignment;
}
+size_t bdrv_min_mem_align(BlockDriverState *bs)
+{
+ if (!bs || !bs->drv) {
+ /* 4k should be on the safe side */
+ return 4096;
+ }
+
+ return bs->bl.min_mem_alignment;
+}
+
/* check if the path starts with "<protocol>:" */
int path_has_protocol(const char *path)
{
@@ -890,6 +900,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
}
assert(bdrv_opt_mem_align(bs) != 0);
+ assert(bdrv_min_mem_align(bs) != 0);
assert((bs->request_alignment != 0) || bs->sg);
return 0;
diff --git a/block/io.c b/block/io.c
index a05ad677d3..e6c363921d 100644
--- a/block/io.c
+++ b/block/io.c
@@ -201,8 +201,10 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
}
bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
bs->bl.max_transfer_length = bs->file->bl.max_transfer_length;
+ bs->bl.min_mem_alignment = bs->file->bl.min_mem_alignment;
bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
} else {
+ bs->bl.min_mem_alignment = 512;
bs->bl.opt_mem_alignment = 512;
}
@@ -221,6 +223,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
bs->bl.opt_mem_alignment =
MAX(bs->bl.opt_mem_alignment,
bs->backing_hd->bl.opt_mem_alignment);
+ bs->bl.min_mem_alignment =
+ MAX(bs->bl.min_mem_alignment,
+ bs->backing_hd->bl.min_mem_alignment);
}
/* Then let the driver override it */
@@ -2489,7 +2494,7 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
{
int i;
- size_t alignment = bdrv_opt_mem_align(bs);
+ size_t alignment = bdrv_min_mem_align(bs);
for (i = 0; i < qiov->niov; i++) {
if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 24d85826c4..70839245fd 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -725,6 +725,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
BDRVRawState *s = bs->opaque;
raw_probe_alignment(bs, s->fd, errp);
+ bs->bl.min_mem_alignment = s->buf_align;
bs->bl.opt_mem_alignment = s->buf_align;
}
diff --git a/include/block/block.h b/include/block/block.h
index 7d1a7174f6..c1c963eb5c 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -440,6 +440,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
/* Returns the alignment in bytes that is required so that no bounce buffer
* is required throughout the stack */
+size_t bdrv_min_mem_align(BlockDriverState *bs);
+/* Returns optimal alignment in bytes for bounce buffer */
size_t bdrv_opt_mem_align(BlockDriverState *bs);
void bdrv_set_guest_block_size(BlockDriverState *bs, int align);
void *qemu_blockalign(BlockDriverState *bs, size_t size);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index db29b7424e..f004378d58 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -313,6 +313,9 @@ typedef struct BlockLimits {
int max_transfer_length;
/* memory alignment so that no bounce buffer is needed */
+ size_t min_mem_alignment;
+
+ /* memory alignment for bounce buffer */
size_t opt_mem_alignment;
} BlockLimits;