mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 17:53:56 -06:00
nbd patches for 2021-02-02
- more cleanup from iotest python conversion - progress towards consistent use of signed 64-bit types through block layer - fix some crashes related to NBD reconnect -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEccLMIrHEYCkn0vOqp6FrSiUnQ2oFAmAasREACgkQp6FrSiUn Q2q0bAgAqkkrQtMhTcQ6cZenLhBc7qIojOybnOnO8hXb7SpndHjE9f9OF0f0+OOm 9vk24KyohvCFc7IwMHA/lccvHYH4Ftb8VPgYEs+U+iCxzdyM8M1goy8tbOp82Fgg 8ahxRbBP4VTkBUiXNcCxO2KbBQL2m+YkLKvfbw+XN0KbxER6hoikfNsSty97/3su ZKtfEqBPH7Tl7kJz0JBfGTpCSPa6cXFzIwxK+m8pq7IKeNrICg1Uu0VR49QfTWlh 2ptIxvKx+QkxLV+QoW7m/fqXFaIFye0tQAwTr/5b3/jBtAkgg8Yznn0TMgiqwXMr SuxbUpjNWqBtjjhwavSje020VhrD2w== =7eUe -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2021-02-02-v2' into staging nbd patches for 2021-02-02 - more cleanup from iotest python conversion - progress towards consistent use of signed 64-bit types through block layer - fix some crashes related to NBD reconnect # gpg: Signature made Wed 03 Feb 2021 14:20:01 GMT # gpg: using RSA key 71C2CC22B1C4602927D2F3AAA7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full] # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full] # gpg: aka "[jpeg image of size 6874]" [full] # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * remotes/ericb/tags/pull-nbd-2021-02-02-v2: nbd: make nbd_read* return -EIO on error block/nbd: only enter connection coroutine if it's present block/nbd: only detach existing iochannel from aio_context block/io: use int64_t bytes in copy_range block/io: support int64_t bytes in read/write wrappers block/io: support int64_t bytes in bdrv_co_p{read,write}v_part() block/io: support int64_t bytes in bdrv_aligned_preadv() block/io: support int64_t bytes in bdrv_co_do_copy_on_readv() block/io: support int64_t bytes in bdrv_aligned_pwritev() block/io: support int64_t bytes in bdrv_co_do_pwrite_zeroes() block/io: use int64_t bytes in driver wrappers block: use int64_t as bytes type in tracked requests block/io: improve bdrv_check_request: check qiov too block/throttle-groups: throttle_group_co_io_limits_intercept(): 64bit bytes block/io: bdrv_pad_request(): support qemu_iovec_init_extended failure block/io: refactor bdrv_pad_request(): move bdrv_pad_request() up block: fix theoretical overflow in bdrv_init_padding() util/iov: make qemu_iovec_init_extended() honest block: refactor bdrv_check_request: add errp iotests: Fix expected whitespace for 185 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1ed9228f63
15 changed files with 275 additions and 133 deletions
|
@ -31,7 +31,7 @@ typedef struct BlkverifyRequest {
|
||||||
uint64_t bytes;
|
uint64_t bytes;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
int (*request_fn)(BdrvChild *, int64_t, unsigned int, QEMUIOVector *,
|
int (*request_fn)(BdrvChild *, int64_t, int64_t, QEMUIOVector *,
|
||||||
BdrvRequestFlags);
|
BdrvRequestFlags);
|
||||||
|
|
||||||
int ret; /* test image result */
|
int ret; /* test image result */
|
||||||
|
|
|
@ -2969,7 +2969,7 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
|
||||||
|
|
||||||
req->bytes = BDRV_MAX_LENGTH - req->offset;
|
req->bytes = BDRV_MAX_LENGTH - req->offset;
|
||||||
|
|
||||||
assert(bdrv_check_request(req->offset, req->bytes) == 0);
|
bdrv_check_request(req->offset, req->bytes, &error_abort);
|
||||||
|
|
||||||
bdrv_make_request_serialising(req, bs->bl.request_alignment);
|
bdrv_make_request_serialising(req, bs->bl.request_alignment);
|
||||||
}
|
}
|
||||||
|
|
268
block/io.c
268
block/io.c
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
static void bdrv_parent_cb_resize(BlockDriverState *bs);
|
static void bdrv_parent_cb_resize(BlockDriverState *bs);
|
||||||
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t offset, int bytes, BdrvRequestFlags flags);
|
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
|
||||||
|
|
||||||
static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
|
static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
|
||||||
bool ignore_bds_parents)
|
bool ignore_bds_parents)
|
||||||
|
@ -717,10 +717,10 @@ static void tracked_request_end(BdrvTrackedRequest *req)
|
||||||
static void tracked_request_begin(BdrvTrackedRequest *req,
|
static void tracked_request_begin(BdrvTrackedRequest *req,
|
||||||
BlockDriverState *bs,
|
BlockDriverState *bs,
|
||||||
int64_t offset,
|
int64_t offset,
|
||||||
uint64_t bytes,
|
int64_t bytes,
|
||||||
enum BdrvTrackedRequestType type)
|
enum BdrvTrackedRequestType type)
|
||||||
{
|
{
|
||||||
assert(bytes <= INT64_MAX && offset <= INT64_MAX - bytes);
|
bdrv_check_request(offset, bytes, &error_abort);
|
||||||
|
|
||||||
*req = (BdrvTrackedRequest){
|
*req = (BdrvTrackedRequest){
|
||||||
.bs = bs,
|
.bs = bs,
|
||||||
|
@ -741,8 +741,10 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool tracked_request_overlaps(BdrvTrackedRequest *req,
|
static bool tracked_request_overlaps(BdrvTrackedRequest *req,
|
||||||
int64_t offset, uint64_t bytes)
|
int64_t offset, int64_t bytes)
|
||||||
{
|
{
|
||||||
|
bdrv_check_request(offset, bytes, &error_abort);
|
||||||
|
|
||||||
/* aaaa bbbb */
|
/* aaaa bbbb */
|
||||||
if (offset >= req->overlap_offset + req->overlap_bytes) {
|
if (offset >= req->overlap_offset + req->overlap_bytes) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -810,8 +812,10 @@ static void tracked_request_set_serialising(BdrvTrackedRequest *req,
|
||||||
uint64_t align)
|
uint64_t align)
|
||||||
{
|
{
|
||||||
int64_t overlap_offset = req->offset & ~(align - 1);
|
int64_t overlap_offset = req->offset & ~(align - 1);
|
||||||
uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
|
int64_t overlap_bytes =
|
||||||
- overlap_offset;
|
ROUND_UP(req->offset + req->bytes, align) - overlap_offset;
|
||||||
|
|
||||||
|
bdrv_check_request(req->offset, req->bytes, &error_abort);
|
||||||
|
|
||||||
if (!req->serialising) {
|
if (!req->serialising) {
|
||||||
qatomic_inc(&req->bs->serialising_in_flight);
|
qatomic_inc(&req->bs->serialising_in_flight);
|
||||||
|
@ -920,26 +924,75 @@ bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
|
||||||
return waited;
|
return waited;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_check_request(int64_t offset, int64_t bytes)
|
static int bdrv_check_qiov_request(int64_t offset, int64_t bytes,
|
||||||
|
QEMUIOVector *qiov, size_t qiov_offset,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (offset < 0 || bytes < 0) {
|
/*
|
||||||
|
* Check generic offset/bytes correctness
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (offset < 0) {
|
||||||
|
error_setg(errp, "offset is negative: %" PRIi64, offset);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes < 0) {
|
||||||
|
error_setg(errp, "bytes is negative: %" PRIi64, bytes);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes > BDRV_MAX_LENGTH) {
|
if (bytes > BDRV_MAX_LENGTH) {
|
||||||
|
error_setg(errp, "bytes(%" PRIi64 ") exceeds maximum(%" PRIi64 ")",
|
||||||
|
bytes, BDRV_MAX_LENGTH);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > BDRV_MAX_LENGTH) {
|
||||||
|
error_setg(errp, "offset(%" PRIi64 ") exceeds maximum(%" PRIi64 ")",
|
||||||
|
offset, BDRV_MAX_LENGTH);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset > BDRV_MAX_LENGTH - bytes) {
|
if (offset > BDRV_MAX_LENGTH - bytes) {
|
||||||
|
error_setg(errp, "sum of offset(%" PRIi64 ") and bytes(%" PRIi64 ") "
|
||||||
|
"exceeds maximum(%" PRIi64 ")", offset, bytes,
|
||||||
|
BDRV_MAX_LENGTH);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qiov) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check qiov and qiov_offset
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (qiov_offset > qiov->size) {
|
||||||
|
error_setg(errp, "qiov_offset(%zu) overflow io vector size(%zu)",
|
||||||
|
qiov_offset, qiov->size);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes > qiov->size - qiov_offset) {
|
||||||
|
error_setg(errp, "bytes(%" PRIi64 ") + qiov_offset(%zu) overflow io "
|
||||||
|
"vector size(%zu)", bytes, qiov_offset, qiov->size);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdrv_check_request32(int64_t offset, int64_t bytes)
|
int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp)
|
||||||
{
|
{
|
||||||
int ret = bdrv_check_request(offset, bytes);
|
return bdrv_check_qiov_request(offset, bytes, NULL, 0, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bdrv_check_request32(int64_t offset, int64_t bytes,
|
||||||
|
QEMUIOVector *qiov, size_t qiov_offset)
|
||||||
|
{
|
||||||
|
int ret = bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -952,7 +1005,7 @@ static int bdrv_check_request32(int64_t offset, int64_t bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||||
int bytes, BdrvRequestFlags flags)
|
int64_t bytes, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
return bdrv_pwritev(child, offset, bytes, NULL,
|
return bdrv_pwritev(child, offset, bytes, NULL,
|
||||||
BDRV_REQ_ZERO_WRITE | flags);
|
BDRV_REQ_ZERO_WRITE | flags);
|
||||||
|
@ -1000,7 +1053,7 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See bdrv_pwrite() for the return codes */
|
/* See bdrv_pwrite() for the return codes */
|
||||||
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes)
|
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||||
|
@ -1020,7 +1073,8 @@ int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes)
|
||||||
-EINVAL Invalid offset or number of bytes
|
-EINVAL Invalid offset or number of bytes
|
||||||
-EACCES Trying to write a read-only device
|
-EACCES Trying to write a read-only device
|
||||||
*/
|
*/
|
||||||
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes)
|
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
|
||||||
|
int64_t bytes)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||||
|
@ -1041,7 +1095,7 @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes)
|
||||||
* Returns 0 on success, -errno in error cases.
|
* Returns 0 on success, -errno in error cases.
|
||||||
*/
|
*/
|
||||||
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
||||||
const void *buf, int count)
|
const void *buf, int64_t count)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1072,7 +1126,7 @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
|
static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
|
||||||
uint64_t offset, uint64_t bytes,
|
int64_t offset, int64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
size_t qiov_offset, int flags)
|
size_t qiov_offset, int flags)
|
||||||
{
|
{
|
||||||
|
@ -1082,6 +1136,7 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
|
||||||
QEMUIOVector local_qiov;
|
QEMUIOVector local_qiov;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
|
||||||
assert(!(flags & ~BDRV_REQ_MASK));
|
assert(!(flags & ~BDRV_REQ_MASK));
|
||||||
assert(!(flags & BDRV_REQ_NO_FALLBACK));
|
assert(!(flags & BDRV_REQ_NO_FALLBACK));
|
||||||
|
|
||||||
|
@ -1141,7 +1196,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
|
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
|
||||||
uint64_t offset, uint64_t bytes,
|
int64_t offset, int64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
size_t qiov_offset, int flags)
|
size_t qiov_offset, int flags)
|
||||||
{
|
{
|
||||||
|
@ -1151,6 +1206,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
|
||||||
QEMUIOVector local_qiov;
|
QEMUIOVector local_qiov;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
|
||||||
assert(!(flags & ~BDRV_REQ_MASK));
|
assert(!(flags & ~BDRV_REQ_MASK));
|
||||||
assert(!(flags & BDRV_REQ_NO_FALLBACK));
|
assert(!(flags & BDRV_REQ_NO_FALLBACK));
|
||||||
|
|
||||||
|
@ -1221,14 +1277,16 @@ emulate_flags:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn
|
static int coroutine_fn
|
||||||
bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
|
||||||
uint64_t bytes, QEMUIOVector *qiov,
|
int64_t bytes, QEMUIOVector *qiov,
|
||||||
size_t qiov_offset)
|
size_t qiov_offset)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
QEMUIOVector local_qiov;
|
QEMUIOVector local_qiov;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
@ -1254,7 +1312,7 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
|
static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||||
size_t qiov_offset, int flags)
|
size_t qiov_offset, int flags)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = child->bs;
|
BlockDriverState *bs = child->bs;
|
||||||
|
@ -1269,13 +1327,15 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
int64_t cluster_offset;
|
int64_t cluster_offset;
|
||||||
int64_t cluster_bytes;
|
int64_t cluster_bytes;
|
||||||
size_t skip_bytes;
|
int64_t skip_bytes;
|
||||||
int ret;
|
int ret;
|
||||||
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
||||||
BDRV_REQUEST_MAX_BYTES);
|
BDRV_REQUEST_MAX_BYTES);
|
||||||
unsigned int progress = 0;
|
int64_t progress = 0;
|
||||||
bool skip_write;
|
bool skip_write;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
@ -1416,15 +1476,16 @@ err:
|
||||||
* reads; any other features must be implemented by the caller.
|
* reads; any other features must be implemented by the caller.
|
||||||
*/
|
*/
|
||||||
static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
|
static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
|
||||||
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
|
BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
|
||||||
int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
|
int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = child->bs;
|
BlockDriverState *bs = child->bs;
|
||||||
int64_t total_bytes, max_bytes;
|
int64_t total_bytes, max_bytes;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint64_t bytes_remaining = bytes;
|
int64_t bytes_remaining = bytes;
|
||||||
int max_transfer;
|
int max_transfer;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
|
||||||
assert(is_power_of_2(align));
|
assert(is_power_of_2(align));
|
||||||
assert((offset & (align - 1)) == 0);
|
assert((offset & (align - 1)) == 0);
|
||||||
assert((bytes & (align - 1)) == 0);
|
assert((bytes & (align - 1)) == 0);
|
||||||
|
@ -1486,7 +1547,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bytes_remaining) {
|
while (bytes_remaining) {
|
||||||
int num;
|
int64_t num;
|
||||||
|
|
||||||
if (max_bytes) {
|
if (max_bytes) {
|
||||||
num = MIN(bytes_remaining, MIN(max_bytes, max_transfer));
|
num = MIN(bytes_remaining, MIN(max_bytes, max_transfer));
|
||||||
|
@ -1548,8 +1609,12 @@ static bool bdrv_init_padding(BlockDriverState *bs,
|
||||||
int64_t offset, int64_t bytes,
|
int64_t offset, int64_t bytes,
|
||||||
BdrvRequestPadding *pad)
|
BdrvRequestPadding *pad)
|
||||||
{
|
{
|
||||||
uint64_t align = bs->bl.request_alignment;
|
int64_t align = bs->bl.request_alignment;
|
||||||
size_t sum;
|
int64_t sum;
|
||||||
|
|
||||||
|
bdrv_check_request(offset, bytes, &error_abort);
|
||||||
|
assert(align <= INT_MAX); /* documented in block/block_int.h */
|
||||||
|
assert(align <= SIZE_MAX / 2); /* so we can allocate the buffer */
|
||||||
|
|
||||||
memset(pad, 0, sizeof(*pad));
|
memset(pad, 0, sizeof(*pad));
|
||||||
|
|
||||||
|
@ -1589,7 +1654,7 @@ static int bdrv_padding_rmw_read(BdrvChild *child,
|
||||||
assert(req->serialising && pad->buf);
|
assert(req->serialising && pad->buf);
|
||||||
|
|
||||||
if (pad->head || pad->merge_reads) {
|
if (pad->head || pad->merge_reads) {
|
||||||
uint64_t bytes = pad->merge_reads ? pad->buf_len : align;
|
int64_t bytes = pad->merge_reads ? pad->buf_len : align;
|
||||||
|
|
||||||
qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
|
qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
|
||||||
|
|
||||||
|
@ -1644,6 +1709,7 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
||||||
qemu_vfree(pad->buf);
|
qemu_vfree(pad->buf);
|
||||||
qemu_iovec_destroy(&pad->local_qiov);
|
qemu_iovec_destroy(&pad->local_qiov);
|
||||||
}
|
}
|
||||||
|
memset(pad, 0, sizeof(*pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1653,40 +1719,55 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
||||||
* read of padding, bdrv_padding_rmw_read() should be called separately if
|
* read of padding, bdrv_padding_rmw_read() should be called separately if
|
||||||
* needed.
|
* needed.
|
||||||
*
|
*
|
||||||
* All parameters except @bs are in-out: they represent original request at
|
* Request parameters (@qiov, &qiov_offset, &offset, &bytes) are in-out:
|
||||||
* function call and padded (if padding needed) at function finish.
|
* - on function start they represent original request
|
||||||
*
|
* - on failure or when padding is not needed they are unchanged
|
||||||
* Function always succeeds.
|
* - on success when padding is needed they represent padded request
|
||||||
*/
|
*/
|
||||||
static bool bdrv_pad_request(BlockDriverState *bs,
|
static int bdrv_pad_request(BlockDriverState *bs,
|
||||||
QEMUIOVector **qiov, size_t *qiov_offset,
|
QEMUIOVector **qiov, size_t *qiov_offset,
|
||||||
int64_t *offset, unsigned int *bytes,
|
int64_t *offset, int64_t *bytes,
|
||||||
BdrvRequestPadding *pad)
|
BdrvRequestPadding *pad, bool *padded)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(*offset, *bytes, *qiov, *qiov_offset, &error_abort);
|
||||||
|
|
||||||
if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
|
if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
|
||||||
return false;
|
if (padded) {
|
||||||
|
*padded = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
|
ret = qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
|
||||||
*qiov, *qiov_offset, *bytes,
|
*qiov, *qiov_offset, *bytes,
|
||||||
pad->buf + pad->buf_len - pad->tail, pad->tail);
|
pad->buf + pad->buf_len - pad->tail,
|
||||||
|
pad->tail);
|
||||||
|
if (ret < 0) {
|
||||||
|
bdrv_padding_destroy(pad);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
*bytes += pad->head + pad->tail;
|
*bytes += pad->head + pad->tail;
|
||||||
*offset -= pad->head;
|
*offset -= pad->head;
|
||||||
*qiov = &pad->local_qiov;
|
*qiov = &pad->local_qiov;
|
||||||
*qiov_offset = 0;
|
*qiov_offset = 0;
|
||||||
|
if (padded) {
|
||||||
|
*padded = true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags);
|
return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes,
|
int64_t offset, int64_t bytes,
|
||||||
QEMUIOVector *qiov, size_t qiov_offset,
|
QEMUIOVector *qiov, size_t qiov_offset,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
|
@ -1695,13 +1776,13 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
||||||
BdrvRequestPadding pad;
|
BdrvRequestPadding pad;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
trace_bdrv_co_preadv(bs, offset, bytes, flags);
|
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
|
||||||
|
|
||||||
if (!bdrv_is_inserted(bs)) {
|
if (!bdrv_is_inserted(bs)) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_check_request32(offset, bytes);
|
ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1725,7 +1806,11 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
||||||
flags |= BDRV_REQ_COPY_ON_READ;
|
flags |= BDRV_REQ_COPY_ON_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad);
|
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
|
||||||
|
NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
|
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
|
||||||
ret = bdrv_aligned_preadv(child, &req, offset, bytes,
|
ret = bdrv_aligned_preadv(child, &req, offset, bytes,
|
||||||
|
@ -1740,7 +1825,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t offset, int bytes, BdrvRequestFlags flags)
|
int64_t offset, int64_t bytes, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
|
@ -1755,6 +1840,8 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||||
bs->bl.request_alignment);
|
bs->bl.request_alignment);
|
||||||
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
|
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
|
||||||
|
|
||||||
|
bdrv_check_request(offset, bytes, &error_abort);
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
@ -1770,7 +1857,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||||
assert(max_write_zeroes >= bs->bl.request_alignment);
|
assert(max_write_zeroes >= bs->bl.request_alignment);
|
||||||
|
|
||||||
while (bytes > 0 && !ret) {
|
while (bytes > 0 && !ret) {
|
||||||
int num = bytes;
|
int64_t num = bytes;
|
||||||
|
|
||||||
/* Align request. Block drivers can expect the "bulk" of the request
|
/* Align request. Block drivers can expect the "bulk" of the request
|
||||||
* to be aligned, and that unaligned requests do not cross cluster
|
* to be aligned, and that unaligned requests do not cross cluster
|
||||||
|
@ -1851,11 +1938,12 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int coroutine_fn
|
static inline int coroutine_fn
|
||||||
bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
|
bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
|
||||||
BdrvTrackedRequest *req, int flags)
|
BdrvTrackedRequest *req, int flags)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = child->bs;
|
BlockDriverState *bs = child->bs;
|
||||||
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
|
|
||||||
|
bdrv_check_request(offset, bytes, &error_abort);
|
||||||
|
|
||||||
if (bs->read_only) {
|
if (bs->read_only) {
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
@ -1882,7 +1970,8 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
|
||||||
|
|
||||||
assert(req->overlap_offset <= offset);
|
assert(req->overlap_offset <= offset);
|
||||||
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
|
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
|
||||||
assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
|
assert(offset + bytes <= bs->total_sectors * BDRV_SECTOR_SIZE ||
|
||||||
|
child->perm & BLK_PERM_RESIZE);
|
||||||
|
|
||||||
switch (req->type) {
|
switch (req->type) {
|
||||||
case BDRV_TRACKED_WRITE:
|
case BDRV_TRACKED_WRITE:
|
||||||
|
@ -1903,12 +1992,14 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void coroutine_fn
|
static inline void coroutine_fn
|
||||||
bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
|
bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
|
||||||
BdrvTrackedRequest *req, int ret)
|
BdrvTrackedRequest *req, int ret)
|
||||||
{
|
{
|
||||||
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
|
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
|
||||||
BlockDriverState *bs = child->bs;
|
BlockDriverState *bs = child->bs;
|
||||||
|
|
||||||
|
bdrv_check_request(offset, bytes, &error_abort);
|
||||||
|
|
||||||
qatomic_inc(&bs->write_gen);
|
qatomic_inc(&bs->write_gen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1945,16 +2036,18 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
|
||||||
* after possibly fragmenting it.
|
* after possibly fragmenting it.
|
||||||
*/
|
*/
|
||||||
static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
|
static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
|
||||||
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
|
BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
|
||||||
int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
|
int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = child->bs;
|
BlockDriverState *bs = child->bs;
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
uint64_t bytes_remaining = bytes;
|
int64_t bytes_remaining = bytes;
|
||||||
int max_transfer;
|
int max_transfer;
|
||||||
|
|
||||||
|
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
@ -1966,7 +2059,6 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
|
||||||
assert(is_power_of_2(align));
|
assert(is_power_of_2(align));
|
||||||
assert((offset & (align - 1)) == 0);
|
assert((offset & (align - 1)) == 0);
|
||||||
assert((bytes & (align - 1)) == 0);
|
assert((bytes & (align - 1)) == 0);
|
||||||
assert(!qiov || qiov_offset + bytes <= qiov->size);
|
|
||||||
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
|
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
|
||||||
align);
|
align);
|
||||||
|
|
||||||
|
@ -2028,7 +2120,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
|
||||||
|
|
||||||
static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
||||||
int64_t offset,
|
int64_t offset,
|
||||||
unsigned int bytes,
|
int64_t bytes,
|
||||||
BdrvRequestFlags flags,
|
BdrvRequestFlags flags,
|
||||||
BdrvTrackedRequest *req)
|
BdrvTrackedRequest *req)
|
||||||
{
|
{
|
||||||
|
@ -2065,7 +2157,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
||||||
assert(!bytes || (offset & (align - 1)) == 0);
|
assert(!bytes || (offset & (align - 1)) == 0);
|
||||||
if (bytes >= align) {
|
if (bytes >= align) {
|
||||||
/* Write the aligned part in the middle. */
|
/* Write the aligned part in the middle. */
|
||||||
uint64_t aligned_bytes = bytes & ~(align - 1);
|
int64_t aligned_bytes = bytes & ~(align - 1);
|
||||||
ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
|
ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
|
||||||
NULL, 0, flags);
|
NULL, 0, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -2095,14 +2187,14 @@ out:
|
||||||
* Handle a write request in coroutine context
|
* Handle a write request in coroutine context
|
||||||
*/
|
*/
|
||||||
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags);
|
return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov, size_t qiov_offset,
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = child->bs;
|
BlockDriverState *bs = child->bs;
|
||||||
|
@ -2110,14 +2202,15 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
||||||
uint64_t align = bs->bl.request_alignment;
|
uint64_t align = bs->bl.request_alignment;
|
||||||
BdrvRequestPadding pad;
|
BdrvRequestPadding pad;
|
||||||
int ret;
|
int ret;
|
||||||
|
bool padded = false;
|
||||||
|
|
||||||
trace_bdrv_co_pwritev(child->bs, offset, bytes, flags);
|
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
|
||||||
|
|
||||||
if (!bdrv_is_inserted(bs)) {
|
if (!bdrv_is_inserted(bs)) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_check_request32(offset, bytes);
|
ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2141,20 +2234,35 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_inc_in_flight(bs);
|
if (!(flags & BDRV_REQ_ZERO_WRITE)) {
|
||||||
/*
|
/*
|
||||||
* Align write if necessary by performing a read-modify-write cycle.
|
* Pad request for following read-modify-write cycle.
|
||||||
* Pad qiov with the read parts and be sure to have a tracked request not
|
* bdrv_co_do_zero_pwritev() does aligning by itself, so, we do
|
||||||
* only for bdrv_aligned_pwritev, but also for the reads of the RMW cycle.
|
* alignment only if there is no ZERO flag.
|
||||||
*/
|
*/
|
||||||
|
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
|
||||||
|
&padded);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bdrv_inc_in_flight(bs);
|
||||||
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE);
|
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE);
|
||||||
|
|
||||||
if (flags & BDRV_REQ_ZERO_WRITE) {
|
if (flags & BDRV_REQ_ZERO_WRITE) {
|
||||||
|
assert(!padded);
|
||||||
ret = bdrv_co_do_zero_pwritev(child, offset, bytes, flags, &req);
|
ret = bdrv_co_do_zero_pwritev(child, offset, bytes, flags, &req);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad)) {
|
if (padded) {
|
||||||
|
/*
|
||||||
|
* Request was unaligned to request_alignment and therefore
|
||||||
|
* padded. We are going to do read-modify-write, and must
|
||||||
|
* serialize the request to prevent interactions of the
|
||||||
|
* widened region with other transactions.
|
||||||
|
*/
|
||||||
bdrv_make_request_serialising(&req, align);
|
bdrv_make_request_serialising(&req, align);
|
||||||
bdrv_padding_rmw_read(child, &req, &pad, false);
|
bdrv_padding_rmw_read(child, &req, &pad, false);
|
||||||
}
|
}
|
||||||
|
@ -2172,7 +2280,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||||
int bytes, BdrvRequestFlags flags)
|
int64_t bytes, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
|
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
|
||||||
|
|
||||||
|
@ -2847,7 +2955,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_check_request(offset, bytes);
|
ret = bdrv_check_request(offset, bytes, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3093,8 +3201,8 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_co_copy_range_internal(
|
static int coroutine_fn bdrv_co_copy_range_internal(
|
||||||
BdrvChild *src, uint64_t src_offset, BdrvChild *dst,
|
BdrvChild *src, int64_t src_offset, BdrvChild *dst,
|
||||||
uint64_t dst_offset, uint64_t bytes,
|
int64_t dst_offset, int64_t bytes,
|
||||||
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
|
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
|
||||||
bool recurse_src)
|
bool recurse_src)
|
||||||
{
|
{
|
||||||
|
@ -3108,7 +3216,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
|
||||||
if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) {
|
if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
ret = bdrv_check_request32(dst_offset, bytes);
|
ret = bdrv_check_request32(dst_offset, bytes, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3119,7 +3227,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
|
||||||
if (!src || !src->bs || !bdrv_is_inserted(src->bs)) {
|
if (!src || !src->bs || !bdrv_is_inserted(src->bs)) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
ret = bdrv_check_request32(src_offset, bytes);
|
ret = bdrv_check_request32(src_offset, bytes, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3172,9 +3280,9 @@ static int coroutine_fn bdrv_co_copy_range_internal(
|
||||||
*
|
*
|
||||||
* See the comment of bdrv_co_copy_range for the parameter and return value
|
* See the comment of bdrv_co_copy_range for the parameter and return value
|
||||||
* semantics. */
|
* semantics. */
|
||||||
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
|
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
|
||||||
BdrvChild *dst, uint64_t dst_offset,
|
BdrvChild *dst, int64_t dst_offset,
|
||||||
uint64_t bytes,
|
int64_t bytes,
|
||||||
BdrvRequestFlags read_flags,
|
BdrvRequestFlags read_flags,
|
||||||
BdrvRequestFlags write_flags)
|
BdrvRequestFlags write_flags)
|
||||||
{
|
{
|
||||||
|
@ -3188,9 +3296,9 @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
|
||||||
*
|
*
|
||||||
* See the comment of bdrv_co_copy_range for the parameter and return value
|
* See the comment of bdrv_co_copy_range for the parameter and return value
|
||||||
* semantics. */
|
* semantics. */
|
||||||
int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
|
int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
|
||||||
BdrvChild *dst, uint64_t dst_offset,
|
BdrvChild *dst, int64_t dst_offset,
|
||||||
uint64_t bytes,
|
int64_t bytes,
|
||||||
BdrvRequestFlags read_flags,
|
BdrvRequestFlags read_flags,
|
||||||
BdrvRequestFlags write_flags)
|
BdrvRequestFlags write_flags)
|
||||||
{
|
{
|
||||||
|
@ -3200,9 +3308,9 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
|
||||||
bytes, read_flags, write_flags, false);
|
bytes, read_flags, write_flags, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
|
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
|
||||||
BdrvChild *dst, uint64_t dst_offset,
|
BdrvChild *dst, int64_t dst_offset,
|
||||||
uint64_t bytes, BdrvRequestFlags read_flags,
|
int64_t bytes, BdrvRequestFlags read_flags,
|
||||||
BdrvRequestFlags write_flags)
|
BdrvRequestFlags write_flags)
|
||||||
{
|
{
|
||||||
return bdrv_co_copy_range_from(src, src_offset,
|
return bdrv_co_copy_range_from(src, src_offset,
|
||||||
|
@ -3249,10 +3357,8 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_check_request(offset, 0);
|
ret = bdrv_check_request(offset, 0, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg(errp, "Required too big image size, it must be not greater "
|
|
||||||
"than %" PRId64, BDRV_MAX_LENGTH);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
block/nbd.c
15
block/nbd.c
|
@ -235,7 +235,14 @@ static void nbd_client_detach_aio_context(BlockDriverState *bs)
|
||||||
|
|
||||||
/* Timer is deleted in nbd_client_co_drain_begin() */
|
/* Timer is deleted in nbd_client_co_drain_begin() */
|
||||||
assert(!s->reconnect_delay_timer);
|
assert(!s->reconnect_delay_timer);
|
||||||
|
/*
|
||||||
|
* If reconnect is in progress we may have no ->ioc. It will be
|
||||||
|
* re-instantiated in the proper aio context once the connection is
|
||||||
|
* reestablished.
|
||||||
|
*/
|
||||||
|
if (s->ioc) {
|
||||||
qio_channel_detach_aio_context(QIO_CHANNEL(s->ioc));
|
qio_channel_detach_aio_context(QIO_CHANNEL(s->ioc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nbd_client_attach_aio_context_bh(void *opaque)
|
static void nbd_client_attach_aio_context_bh(void *opaque)
|
||||||
|
@ -243,13 +250,15 @@ static void nbd_client_attach_aio_context_bh(void *opaque)
|
||||||
BlockDriverState *bs = opaque;
|
BlockDriverState *bs = opaque;
|
||||||
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
|
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
|
||||||
|
|
||||||
|
if (s->connection_co) {
|
||||||
/*
|
/*
|
||||||
* The node is still drained, so we know the coroutine has yielded in
|
* The node is still drained, so we know the coroutine has yielded in
|
||||||
* nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is
|
* nbd_read_eof(), the only place where bs->in_flight can reach 0, or
|
||||||
* entered for the first time. Both places are safe for entering the
|
* it is entered for the first time. Both places are safe for entering
|
||||||
* coroutine.
|
* the coroutine.
|
||||||
*/
|
*/
|
||||||
qemu_aio_coroutine_enter(bs->aio_context, s->connection_co);
|
qemu_aio_coroutine_enter(bs->aio_context, s->connection_co);
|
||||||
|
}
|
||||||
bdrv_dec_in_flight(bs);
|
bdrv_dec_in_flight(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -358,12 +358,15 @@ static void schedule_next_request(ThrottleGroupMember *tgm, bool is_write)
|
||||||
* @is_write: the type of operation (read/write)
|
* @is_write: the type of operation (read/write)
|
||||||
*/
|
*/
|
||||||
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
|
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
|
||||||
unsigned int bytes,
|
int64_t bytes,
|
||||||
bool is_write)
|
bool is_write)
|
||||||
{
|
{
|
||||||
bool must_wait;
|
bool must_wait;
|
||||||
ThrottleGroupMember *token;
|
ThrottleGroupMember *token;
|
||||||
ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
|
ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
|
||||||
|
|
||||||
|
assert(bytes >= 0);
|
||||||
|
|
||||||
qemu_mutex_lock(&tg->lock);
|
qemu_mutex_lock(&tg->lock);
|
||||||
|
|
||||||
/* First we check if this I/O has to be throttled. */
|
/* First we check if this I/O has to be throttled. */
|
||||||
|
|
|
@ -11,12 +11,12 @@ blk_root_attach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
|
||||||
blk_root_detach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
|
blk_root_detach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
|
||||||
|
|
||||||
# io.c
|
# io.c
|
||||||
bdrv_co_preadv(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
|
bdrv_co_preadv_part(void *bs, int64_t offset, int64_t bytes, unsigned int flags) "bs %p offset %" PRId64 " bytes %" PRId64 " flags 0x%x"
|
||||||
bdrv_co_pwritev(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
|
bdrv_co_pwritev_part(void *bs, int64_t offset, int64_t bytes, unsigned int flags) "bs %p offset %" PRId64 " bytes %" PRId64 " flags 0x%x"
|
||||||
bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int count, int flags) "bs %p offset %"PRId64" count %d flags 0x%x"
|
bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int64_t bytes, int flags) "bs %p offset %" PRId64 " bytes %" PRId64 " flags 0x%x"
|
||||||
bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, int64_t cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %"PRId64
|
bdrv_co_do_copy_on_readv(void *bs, int64_t offset, int64_t bytes, int64_t cluster_offset, int64_t cluster_bytes) "bs %p offset %" PRId64 " bytes %" PRId64 " cluster_offset %" PRId64 " cluster_bytes %" PRId64
|
||||||
bdrv_co_copy_range_from(void *src, uint64_t src_offset, void *dst, uint64_t dst_offset, uint64_t bytes, int read_flags, int write_flags) "src %p offset %"PRIu64" dst %p offset %"PRIu64" bytes %"PRIu64" rw flags 0x%x 0x%x"
|
bdrv_co_copy_range_from(void *src, int64_t src_offset, void *dst, int64_t dst_offset, int64_t bytes, int read_flags, int write_flags) "src %p offset %" PRId64 " dst %p offset %" PRId64 " bytes %" PRId64 " rw flags 0x%x 0x%x"
|
||||||
bdrv_co_copy_range_to(void *src, uint64_t src_offset, void *dst, uint64_t dst_offset, uint64_t bytes, int read_flags, int write_flags) "src %p offset %"PRIu64" dst %p offset %"PRIu64" bytes %"PRIu64" rw flags 0x%x 0x%x"
|
bdrv_co_copy_range_to(void *src, int64_t src_offset, void *dst, int64_t dst_offset, int64_t bytes, int read_flags, int write_flags) "src %p offset %" PRId64 " dst %p offset %" PRId64 " bytes %" PRId64 " rw flags 0x%x 0x%x"
|
||||||
|
|
||||||
# stream.c
|
# stream.c
|
||||||
stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
|
stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
|
||||||
|
|
|
@ -392,12 +392,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
|
||||||
void bdrv_reopen_commit(BDRVReopenState *reopen_state);
|
void bdrv_reopen_commit(BDRVReopenState *reopen_state);
|
||||||
void bdrv_reopen_abort(BDRVReopenState *reopen_state);
|
void bdrv_reopen_abort(BDRVReopenState *reopen_state);
|
||||||
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||||
int bytes, BdrvRequestFlags flags);
|
int64_t bytes, BdrvRequestFlags flags);
|
||||||
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
|
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
|
||||||
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes);
|
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes);
|
||||||
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes);
|
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
|
||||||
|
int64_t bytes);
|
||||||
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
||||||
const void *buf, int count);
|
const void *buf, int64_t bytes);
|
||||||
/*
|
/*
|
||||||
* Efficiently zero a region of the disk image. Note that this is a regular
|
* Efficiently zero a region of the disk image. Note that this is a regular
|
||||||
* I/O request like read or write and should have a reasonable size. This
|
* I/O request like read or write and should have a reasonable size. This
|
||||||
|
@ -405,7 +406,7 @@ int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
||||||
* because it may allocate memory for the entire region.
|
* because it may allocate memory for the entire region.
|
||||||
*/
|
*/
|
||||||
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||||
int bytes, BdrvRequestFlags flags);
|
int64_t bytes, BdrvRequestFlags flags);
|
||||||
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
|
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
|
||||||
const char *backing_file);
|
const char *backing_file);
|
||||||
void bdrv_refresh_filename(BlockDriverState *bs);
|
void bdrv_refresh_filename(BlockDriverState *bs);
|
||||||
|
@ -844,8 +845,8 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host);
|
||||||
*
|
*
|
||||||
* Returns: 0 if succeeded; negative error code if failed.
|
* Returns: 0 if succeeded; negative error code if failed.
|
||||||
**/
|
**/
|
||||||
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
|
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
|
||||||
BdrvChild *dst, uint64_t dst_offset,
|
BdrvChild *dst, int64_t dst_offset,
|
||||||
uint64_t bytes, BdrvRequestFlags read_flags,
|
int64_t bytes, BdrvRequestFlags read_flags,
|
||||||
BdrvRequestFlags write_flags);
|
BdrvRequestFlags write_flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,12 +79,12 @@ enum BdrvTrackedRequestType {
|
||||||
typedef struct BdrvTrackedRequest {
|
typedef struct BdrvTrackedRequest {
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
uint64_t bytes;
|
int64_t bytes;
|
||||||
enum BdrvTrackedRequestType type;
|
enum BdrvTrackedRequestType type;
|
||||||
|
|
||||||
bool serialising;
|
bool serialising;
|
||||||
int64_t overlap_offset;
|
int64_t overlap_offset;
|
||||||
uint64_t overlap_bytes;
|
int64_t overlap_bytes;
|
||||||
|
|
||||||
QLIST_ENTRY(BdrvTrackedRequest) list;
|
QLIST_ENTRY(BdrvTrackedRequest) list;
|
||||||
Coroutine *co; /* owner, used for deadlock detection */
|
Coroutine *co; /* owner, used for deadlock detection */
|
||||||
|
@ -93,7 +93,7 @@ typedef struct BdrvTrackedRequest {
|
||||||
struct BdrvTrackedRequest *waiting_for;
|
struct BdrvTrackedRequest *waiting_for;
|
||||||
} BdrvTrackedRequest;
|
} BdrvTrackedRequest;
|
||||||
|
|
||||||
int bdrv_check_request(int64_t offset, int64_t bytes);
|
int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp);
|
||||||
|
|
||||||
struct BlockDriver {
|
struct BlockDriver {
|
||||||
const char *format_name;
|
const char *format_name;
|
||||||
|
@ -1032,16 +1032,16 @@ extern BlockDriver bdrv_raw;
|
||||||
extern BlockDriver bdrv_qcow2;
|
extern BlockDriver bdrv_qcow2;
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||||
BdrvRequestFlags flags);
|
BdrvRequestFlags flags);
|
||||||
int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes,
|
int64_t offset, int64_t bytes,
|
||||||
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
|
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
|
||||||
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||||
BdrvRequestFlags flags);
|
BdrvRequestFlags flags);
|
||||||
int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
||||||
int64_t offset, unsigned int bytes,
|
int64_t offset, int64_t bytes,
|
||||||
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
|
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
|
||||||
|
|
||||||
static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
|
static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
|
||||||
|
@ -1357,14 +1357,14 @@ void bdrv_dec_in_flight(BlockDriverState *bs);
|
||||||
|
|
||||||
void blockdev_close_all_bdrv_states(void);
|
void blockdev_close_all_bdrv_states(void);
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
|
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
|
||||||
BdrvChild *dst, uint64_t dst_offset,
|
BdrvChild *dst, int64_t dst_offset,
|
||||||
uint64_t bytes,
|
int64_t bytes,
|
||||||
BdrvRequestFlags read_flags,
|
BdrvRequestFlags read_flags,
|
||||||
BdrvRequestFlags write_flags);
|
BdrvRequestFlags write_flags);
|
||||||
int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
|
int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
|
||||||
BdrvChild *dst, uint64_t dst_offset,
|
BdrvChild *dst, int64_t dst_offset,
|
||||||
uint64_t bytes,
|
int64_t bytes,
|
||||||
BdrvRequestFlags read_flags,
|
BdrvRequestFlags read_flags,
|
||||||
BdrvRequestFlags write_flags);
|
BdrvRequestFlags write_flags);
|
||||||
|
|
||||||
|
|
|
@ -364,7 +364,7 @@ static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
|
||||||
if (desc) {
|
if (desc) {
|
||||||
error_prepend(errp, "Failed to read %s: ", desc);
|
error_prepend(errp, "Failed to read %s: ", desc);
|
||||||
}
|
}
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -375,8 +375,9 @@ static inline int nbd_read##bits(QIOChannel *ioc, \
|
||||||
uint##bits##_t *val, \
|
uint##bits##_t *val, \
|
||||||
const char *desc, Error **errp) \
|
const char *desc, Error **errp) \
|
||||||
{ \
|
{ \
|
||||||
if (nbd_read(ioc, val, sizeof(*val), desc, errp) < 0) { \
|
int ret = nbd_read(ioc, val, sizeof(*val), desc, errp); \
|
||||||
return -1; \
|
if (ret < 0) { \
|
||||||
|
return ret; \
|
||||||
} \
|
} \
|
||||||
*val = be##bits##_to_cpu(*val); \
|
*val = be##bits##_to_cpu(*val); \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
|
|
@ -77,7 +77,7 @@ void throttle_group_unregister_tgm(ThrottleGroupMember *tgm);
|
||||||
void throttle_group_restart_tgm(ThrottleGroupMember *tgm);
|
void throttle_group_restart_tgm(ThrottleGroupMember *tgm);
|
||||||
|
|
||||||
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
|
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
|
||||||
unsigned int bytes,
|
int64_t bytes,
|
||||||
bool is_write);
|
bool is_write);
|
||||||
void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
|
void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
|
||||||
AioContext *new_context);
|
AioContext *new_context);
|
||||||
|
|
|
@ -222,7 +222,7 @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
|
||||||
|
|
||||||
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
|
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
|
||||||
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
|
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
|
||||||
void qemu_iovec_init_extended(
|
int qemu_iovec_init_extended(
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
void *head_buf, size_t head_len,
|
void *head_buf, size_t head_len,
|
||||||
QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
|
QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
|
||||||
|
|
|
@ -89,7 +89,7 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
|
||||||
'format': 'IMGFMT',
|
'format': 'IMGFMT',
|
||||||
'sync': 'full',
|
'sync': 'full',
|
||||||
'speed': 65536,
|
'speed': 65536,
|
||||||
'x-perf': { 'max-chunk': 65536 } } }
|
'x-perf': {'max-chunk': 65536} } }
|
||||||
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||||
|
|
|
@ -180,7 +180,7 @@ Job failed: Could not resize image: Image size cannot be negative
|
||||||
|
|
||||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
|
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
Job failed: Could not resize image: Required too big image size, it must be not greater than 9223372035781033984
|
Job failed: Could not resize image: offset(9223372036854775296) exceeds maximum(9223372035781033984)
|
||||||
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "block/write-threshold.h"
|
#include "block/write-threshold.h"
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ static void test_threshold_not_trigger(void)
|
||||||
req.offset = 1024;
|
req.offset = 1024;
|
||||||
req.bytes = 1024;
|
req.bytes = 1024;
|
||||||
|
|
||||||
assert(bdrv_check_request(req.offset, req.bytes) == 0);
|
bdrv_check_request(req.offset, req.bytes, &error_abort);
|
||||||
|
|
||||||
bdrv_write_threshold_set(&bs, threshold);
|
bdrv_write_threshold_set(&bs, threshold);
|
||||||
amount = bdrv_write_threshold_exceeded(&bs, &req);
|
amount = bdrv_write_threshold_exceeded(&bs, &req);
|
||||||
|
@ -84,7 +85,7 @@ static void test_threshold_trigger(void)
|
||||||
req.offset = (4 * 1024 * 1024) - 1024;
|
req.offset = (4 * 1024 * 1024) - 1024;
|
||||||
req.bytes = 2 * 1024;
|
req.bytes = 2 * 1024;
|
||||||
|
|
||||||
assert(bdrv_check_request(req.offset, req.bytes) == 0);
|
bdrv_check_request(req.offset, req.bytes, &error_abort);
|
||||||
|
|
||||||
bdrv_write_threshold_set(&bs, threshold);
|
bdrv_write_threshold_set(&bs, threshold);
|
||||||
amount = bdrv_write_threshold_exceeded(&bs, &req);
|
amount = bdrv_write_threshold_exceeded(&bs, &req);
|
||||||
|
|
25
util/iov.c
25
util/iov.c
|
@ -415,7 +415,7 @@ int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len)
|
||||||
* Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
|
* Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
|
||||||
* and @tail_buf buffer into new qiov.
|
* and @tail_buf buffer into new qiov.
|
||||||
*/
|
*/
|
||||||
void qemu_iovec_init_extended(
|
int qemu_iovec_init_extended(
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
void *head_buf, size_t head_len,
|
void *head_buf, size_t head_len,
|
||||||
QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
|
QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
|
||||||
|
@ -425,12 +425,24 @@ void qemu_iovec_init_extended(
|
||||||
int total_niov, mid_niov = 0;
|
int total_niov, mid_niov = 0;
|
||||||
struct iovec *p, *mid_iov = NULL;
|
struct iovec *p, *mid_iov = NULL;
|
||||||
|
|
||||||
|
assert(mid_qiov->niov <= IOV_MAX);
|
||||||
|
|
||||||
|
if (SIZE_MAX - head_len < mid_len ||
|
||||||
|
SIZE_MAX - head_len - mid_len < tail_len)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (mid_len) {
|
if (mid_len) {
|
||||||
mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len,
|
mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len,
|
||||||
&mid_head, &mid_tail, &mid_niov);
|
&mid_head, &mid_tail, &mid_niov);
|
||||||
}
|
}
|
||||||
|
|
||||||
total_niov = !!head_len + mid_niov + !!tail_len;
|
total_niov = !!head_len + mid_niov + !!tail_len;
|
||||||
|
if (total_niov > IOV_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (total_niov == 1) {
|
if (total_niov == 1) {
|
||||||
qemu_iovec_init_buf(qiov, NULL, 0);
|
qemu_iovec_init_buf(qiov, NULL, 0);
|
||||||
p = &qiov->local_iov;
|
p = &qiov->local_iov;
|
||||||
|
@ -459,6 +471,8 @@ void qemu_iovec_init_extended(
|
||||||
p->iov_base = tail_buf;
|
p->iov_base = tail_buf;
|
||||||
p->iov_len = tail_len;
|
p->iov_len = tail_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -492,7 +506,14 @@ bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t offset, size_t bytes)
|
||||||
void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
|
void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
|
||||||
size_t offset, size_t len)
|
size_t offset, size_t len)
|
||||||
{
|
{
|
||||||
qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0);
|
int ret;
|
||||||
|
|
||||||
|
assert(source->size >= len);
|
||||||
|
assert(source->size - len >= offset);
|
||||||
|
|
||||||
|
/* We shrink the request, so we can't overflow neither size_t nor MAX_IOV */
|
||||||
|
ret = qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0);
|
||||||
|
assert(ret == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_iovec_destroy(QEMUIOVector *qiov)
|
void qemu_iovec_destroy(QEMUIOVector *qiov)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue