summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/block-backend.c10
-rw-r--r--block/io.c23
-rw-r--r--block/iscsi.c23
-rw-r--r--block/nbd.c2
-rw-r--r--block/raw-posix.c4
5 files changed, 34 insertions, 28 deletions
diff --git a/block/block-backend.c b/block/block-backend.c
index 1fb070b4e4..e042544025 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1303,16 +1303,16 @@ int blk_get_flags(BlockBackend *blk)
}
}
-/* Returns the maximum transfer length, in sectors; guaranteed nonzero */
-int blk_get_max_transfer_length(BlockBackend *blk)
+/* Returns the maximum transfer length, in bytes; guaranteed nonzero */
+uint32_t blk_get_max_transfer(BlockBackend *blk)
{
BlockDriverState *bs = blk_bs(blk);
- int max = 0;
+ uint32_t max = 0;
if (bs) {
- max = bs->bl.max_transfer_length;
+ max = bs->bl.max_transfer;
}
- return MIN_NON_ZERO(max, BDRV_REQUEST_MAX_SECTORS);
+ return MIN_NON_ZERO(max, INT_MAX);
}
int blk_get_max_iov(BlockBackend *blk)
diff --git a/block/io.c b/block/io.c
index 323e822dd4..8ca9d43724 100644
--- a/block/io.c
+++ b/block/io.c
@@ -88,8 +88,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
error_propagate(errp, local_err);
return;
}
- bs->bl.opt_transfer_length = bs->file->bs->bl.opt_transfer_length;
- bs->bl.max_transfer_length = bs->file->bs->bl.max_transfer_length;
+ bs->bl.opt_transfer = bs->file->bs->bl.opt_transfer;
+ bs->bl.max_transfer = bs->file->bs->bl.max_transfer;
bs->bl.min_mem_alignment = bs->file->bs->bl.min_mem_alignment;
bs->bl.opt_mem_alignment = bs->file->bs->bl.opt_mem_alignment;
bs->bl.max_iov = bs->file->bs->bl.max_iov;
@@ -107,12 +107,10 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
error_propagate(errp, local_err);
return;
}
- bs->bl.opt_transfer_length =
- MAX(bs->bl.opt_transfer_length,
- bs->backing->bs->bl.opt_transfer_length);
- bs->bl.max_transfer_length =
- MIN_NON_ZERO(bs->bl.max_transfer_length,
- bs->backing->bs->bl.max_transfer_length);
+ bs->bl.opt_transfer = MAX(bs->bl.opt_transfer,
+ bs->backing->bs->bl.opt_transfer);
+ bs->bl.max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
+ bs->backing->bs->bl.max_transfer);
bs->bl.opt_mem_alignment =
MAX(bs->bl.opt_mem_alignment,
bs->backing->bs->bl.opt_mem_alignment);
@@ -1156,7 +1154,8 @@ int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov, 0);
}
-#define MAX_WRITE_ZEROES_BOUNCE_BUFFER 32768
+/* Maximum buffer for write zeroes fallback, in bytes */
+#define MAX_WRITE_ZEROES_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
int64_t offset, int count, BdrvRequestFlags flags)
@@ -1214,7 +1213,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
if (ret == -ENOTSUP) {
/* Fall back to bounce buffer if write zeroes is unsupported */
- int max_xfer_len = MIN_NON_ZERO(bs->bl.max_transfer_length,
+ int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
@@ -1225,7 +1224,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
write_flags &= ~BDRV_REQ_FUA;
need_flush = true;
}
- num = MIN(num, max_xfer_len << BDRV_SECTOR_BITS);
+ num = MIN(num, max_transfer);
iov.iov_len = num;
if (iov.iov_base == NULL) {
iov.iov_base = qemu_try_blockalign(bs, num);
@@ -1242,7 +1241,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
/* Keep bounce buffer around if it is big enough for all
* all future requests.
*/
- if (num < max_xfer_len << BDRV_SECTOR_BITS) {
+ if (num < max_transfer) {
qemu_vfree(iov.iov_base);
iov.iov_base = NULL;
}
diff --git a/block/iscsi.c b/block/iscsi.c
index 721afb7a74..bde4a04a74 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -473,9 +473,10 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
return -EINVAL;
}
- if (bs->bl.max_transfer_length && nb_sectors > bs->bl.max_transfer_length) {
+ if (bs->bl.max_transfer &&
+ nb_sectors << BDRV_SECTOR_BITS > bs->bl.max_transfer) {
error_report("iSCSI Error: Write of %d sectors exceeds max_xfer_len "
- "of %d sectors", nb_sectors, bs->bl.max_transfer_length);
+ "of %" PRIu32 " bytes", nb_sectors, bs->bl.max_transfer);
return -EINVAL;
}
@@ -650,9 +651,10 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
return -EINVAL;
}
- if (bs->bl.max_transfer_length && nb_sectors > bs->bl.max_transfer_length) {
+ if (bs->bl.max_transfer &&
+ nb_sectors << BDRV_SECTOR_BITS > bs->bl.max_transfer) {
error_report("iSCSI Error: Read of %d sectors exceeds max_xfer_len "
- "of %d sectors", nb_sectors, bs->bl.max_transfer_length);
+ "of %" PRIu32 " bytes", nb_sectors, bs->bl.max_transfer);
return -EINVAL;
}
@@ -1708,7 +1710,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
* iscsi_open(): iscsi targets don't change their limits. */
IscsiLun *iscsilun = bs->opaque;
- uint32_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff;
+ uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff;
bs->request_alignment = iscsilun->block_size;
@@ -1716,7 +1718,9 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
max_xfer_len = MIN(max_xfer_len, iscsilun->bl.max_xfer_len);
}
- bs->bl.max_transfer_length = sector_limits_lun2qemu(max_xfer_len, iscsilun);
+ if (max_xfer_len * iscsilun->block_size < INT_MAX) {
+ bs->bl.max_transfer = max_xfer_len * iscsilun->block_size;
+ }
if (iscsilun->lbp.lbpu) {
if (iscsilun->bl.max_unmap < 0xffffffff) {
@@ -1739,8 +1743,11 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
} else {
bs->bl.pwrite_zeroes_alignment = iscsilun->block_size;
}
- bs->bl.opt_transfer_length =
- sector_limits_lun2qemu(iscsilun->bl.opt_xfer_len, iscsilun);
+ if (iscsilun->bl.opt_xfer_len &&
+ iscsilun->bl.opt_xfer_len < INT_MAX / iscsilun->block_size) {
+ bs->bl.opt_transfer = pow2floor(iscsilun->bl.opt_xfer_len *
+ iscsilun->block_size);
+ }
}
/* Note that this will not re-establish a connection with an iSCSI target - it
diff --git a/block/nbd.c b/block/nbd.c
index bf67c8a70b..f5511ea1d4 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -363,7 +363,7 @@ static int nbd_co_flush(BlockDriverState *bs)
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
{
bs->bl.max_discard = NBD_MAX_SECTORS;
- bs->bl.max_transfer_length = NBD_MAX_SECTORS;
+ bs->bl.max_transfer = NBD_MAX_BUFFER_SIZE;
}
static int nbd_co_discard(BlockDriverState *bs, int64_t sector_num,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index bef7a671a6..8da2f94ec4 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -745,8 +745,8 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
if (!fstat(s->fd, &st)) {
if (S_ISBLK(st.st_mode)) {
int ret = hdev_get_max_transfer_length(s->fd);
- if (ret >= 0) {
- bs->bl.max_transfer_length = ret;
+ if (ret > 0 && ret <= BDRV_REQUEST_MAX_SECTORS) {
+ bs->bl.max_transfer = pow2floor(ret << BDRV_SECTOR_BITS);
}
}
}