/* * Block layer I/O functions * * Copyright (c) 2003 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "qemu/osdep.h" #include "trace.h" #include "sysemu/block-backend.h" #include "block/aio-wait.h" #include "block/blockjob.h" #include "block/blockjob_int.h" #include "block/block_int.h" #include "block/coroutines.h" #include "block/dirty-bitmap.h" #include "block/write-threshold.h" #include "qemu/cutils.h" #include "qemu/memalign.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "sysemu/replay.h" /* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */ #define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS) static void coroutine_fn GRAPH_RDLOCK bdrv_parent_cb_resize(BlockDriverState *bs); static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvRequestFlags flags); static void GRAPH_RDLOCK bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore) { BdrvChild *c, *next; IO_OR_GS_CODE(); assert_bdrv_graph_readable(); QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) { if (c == ignore) { continue; } bdrv_parent_drained_begin_single(c); } } void bdrv_parent_drained_end_single(BdrvChild *c) { GLOBAL_STATE_CODE(); assert(c->quiesced_parent); c->quiesced_parent = false; if (c->klass->drained_end) { c->klass->drained_end(c); } } static void GRAPH_RDLOCK bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore) { BdrvChild *c; IO_OR_GS_CODE(); assert_bdrv_graph_readable(); QLIST_FOREACH(c, &bs->parents, next_parent) { if (c == ignore) { continue; } bdrv_parent_drained_end_single(c); } } bool bdrv_parent_drained_poll_single(BdrvChild *c) { IO_OR_GS_CODE(); if (c->klass->drained_poll) { return c->klass->drained_poll(c); } return false; } static bool GRAPH_RDLOCK bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore, bool ignore_bds_parents) { BdrvChild *c, *next; bool busy = false; IO_OR_GS_CODE(); assert_bdrv_graph_readable(); QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) { if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) { continue; } busy |= bdrv_parent_drained_poll_single(c); } return busy; } void bdrv_parent_drained_begin_single(BdrvChild *c) { GLOBAL_STATE_CODE(); assert(!c->quiesced_parent); c->quiesced_parent = true; if (c->klass->drained_begin) { /* called with rdlock taken, but it doesn't really need it. */ c->klass->drained_begin(c); } } static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src) { dst->pdiscard_alignment = MAX(dst->pdiscard_alignment, src->pdiscard_alignment); dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer); dst->max_transfer = MIN_NON_ZERO(dst->max_transfer, src->max_transfer); dst->max_hw_transfer = MIN_NON_ZERO(dst->max_hw_transfer, src->max_hw_transfer); dst->opt_mem_alignment = MAX(dst->opt_mem_alignment, src->opt_mem_alignment); dst->min_mem_alignment = MAX(dst->min_mem_alignment, src->min_mem_alignment); dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov); dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov); } typedef struct BdrvRefreshLimitsState { BlockDriverState *bs; BlockLimits old_bl; } BdrvRefreshLimitsState; static void bdrv_refresh_limits_abort(void *opaque) { BdrvRefreshLimitsState *s = opaque; s->bs->bl = s->old_bl; } static TransactionActionDrv bdrv_refresh_limits_drv = { .abort = bdrv_refresh_limits_abort, .clean = g_free, }; /* @tran is allowed to be NULL, in this case no rollback is possible. */ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp) { ERRP_GUARD(); BlockDriver *drv = bs->drv; BdrvChild *c; bool have_limits; GLOBAL_STATE_CODE(); if (tran) { BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1); *s = (BdrvRefreshLimitsState) { .bs = bs, .old_bl = bs->bl, }; tran_add(tran, &bdrv_refresh_limits_drv, s); } memset(&bs->bl, 0, sizeof(bs->bl)); if (!drv) { return; } /* Default alignment based on whether driver has byte interface */ bs->bl.request_alignment = (drv->bdrv_co_preadv || drv->bdrv_aio_preadv || drv->bdrv_co_preadv_part) ? 1 : 512; /* Take some limits from the children as a default */ have_limits = false; QLIST_FOREACH(c, &bs->children, next) { if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW)) { bdrv_merge_limits(&bs->bl, &c->bs->bl); have_limits = true; } if (c->role & BDRV_CHILD_FILTERED) { bs->bl.has_variable_length |= c->bs->bl.has_variable_length; } } if (!have_limits) { bs->bl.min_mem_alignment = 512; bs->bl.opt_mem_alignment = qemu_real_host_page_size(); /* Safe default since most protocols use readv()/writev()/etc */ bs->bl.max_iov = IOV_MAX; } /* Then let the driver override it */ if (drv->bdrv_refresh_limits) { drv->bdrv_refresh_limits(bs, errp); if (*errp) { return; } } if (bs->bl.request_alignment > BDRV_MAX_ALIGNMENT) { error_setg(errp, "Driver requires too large request alignment"); } } /** * The copy-on-read flag is actually a reference count so multiple users may * use the feature without worrying about clobbering its previous state. * Copy-on-read stays enabled until all users have called to disable it. */ void bdrv_enable_copy_on_read(BlockDriverState *bs) { IO_CODE(); qatomic_inc(&bs->copy_on_read); } void bdrv_disable_copy_on_read(BlockDriverState *bs) { int old = qatomic_fetch_dec(&bs->copy_on_read); IO_CODE(); assert(old >= 1); } typedef struct { Coroutine *co; BlockDriverState *bs; bool done; bool begin; bool poll; BdrvChild *parent; } BdrvCoDrainData; /* Returns true if BDRV_POLL_WHILE() should go into a blocking aio_poll() */ bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent, bool ignore_bds_parents) { GLOBAL_STATE_CODE(); if (bdrv_parent_drained_poll(bs, ignore_parent, ignore_bds_parents)) { return true; } if (qatomic_read(&bs->in_flight)) { return true; } return false; } static bool bdrv_drain_poll_top_level(BlockDriverState *bs, BdrvChild *ignore_parent) { GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); return bdrv_drain_poll(bs, ignore_parent, false); } static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent, bool poll); static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent); static void bdrv_co_drain_bh_cb(void *opaque) { BdrvCoDrainData *data = opaque; Coroutine *co = data->co; BlockDriverState *bs = data->bs; if (bs) { AioContext *ctx = bdrv_get_aio_context(bs); aio_context_acquire(ctx); bdrv_dec_in_flight(bs); if (data->begin) { bdrv_do_drained_begin(bs, data->parent, data->poll); } else { assert(!data->poll); bdrv_do_drained_end(bs, data->parent); } aio_context_release(ctx); } else { assert(data->begin); bdrv_drain_all_begin(); } data->done = true; aio_co_wake(co); } static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, bool begin, BdrvChild *parent, bool poll) { BdrvCoDrainData data; Coroutine *self = qemu_coroutine_self(); AioContext *ctx = bdrv_get_aio_context(bs); AioContext *co_ctx = qemu_coroutine_get_aio_context(self); /* Calling bdrv_drain() from a BH ensures the current coroutine yields and * other coroutines run if they were queued by aio_co_enter(). */ assert(qemu_in_coroutine()); data = (BdrvCoDrainData) { .co = self, .bs = bs, .done = false, .begin = begin, .parent = parent, .poll = poll, }; if (bs) { bdrv_inc_in_flight(bs); } /* * Temporarily drop the lock across yield or we would get deadlocks. * bdrv_co_drain_bh_cb() reaquires the lock as needed. * * When we yield below, the lock for the current context will be * released, so if this is actually the lock that protects bs, don't drop * it a second time. */ if (ctx != co_ctx) { aio_context_release(ctx); } replay_bh_schedule_oneshot_event(qemu_get_aio_context(), bdrv_co_drain_bh_cb, &data); qemu_coroutine_yield(); /* If we are resumed from some other event (such as an aio completion or a * timer callback), it is a bug in the caller that should be fixed. */ assert(data.done); /* Reacquire the AioContext of bs if we dropped it */ if (ctx != co_ctx) { aio_context_acquire(ctx); } } static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent, bool poll) { IO_OR_GS_CODE(); if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(bs, true, parent, poll); return; } GLOBAL_STATE_CODE(); /* Stop things in parent-to-child order */ if (qatomic_fetch_inc(&bs->quiesce_counter) == 0) { GRAPH_RDLOCK_GUARD_MAINLOOP(); bdrv_parent_drained_begin(bs, parent); if (bs->drv && bs->drv->bdrv_drain_begin) { bs->drv->bdrv_drain_begin(bs); } } /* * Wait for drained requests to finish. * * Calling BDRV_POLL_WHILE() only once for the top-level node is okay: The * call is needed so things in this AioContext can make progress even * though we don't return to the main AioContext loop - this automatically * includes other nodes in the same AioContext and therefore all child * nodes. */ if (poll) { BDRV_POLL_WHILE(bs, bdrv_drain_poll_top_level(bs, parent)); } } void bdrv_do_drained_begin_quiesce(BlockDriverState *bs, BdrvChild *parent) { bdrv_do_drained_begin(bs, parent, false); } void coroutine_mixed_fn bdrv_drained_begin(BlockDriverState *bs) { IO_OR_GS_CODE(); bdrv_do_drained_begin(bs, NULL, true); } /** * This function does not poll, nor must any of its recursively called * functions. */ static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent) { int old_quiesce_counter; IO_OR_GS_CODE(); if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(bs, false, parent, false); return; } /* At this point, we should be always running in the main loop. */ GLOBAL_STATE_CODE(); assert(bs->quiesce_counter > 0); GLOBAL_STATE_CODE(); /* Re-enable things in child-to-parent order */ old_quiesce_counter = qatomic_fetch_dec(&bs->quiesce_counter); if (old_quiesce_counter == 1) { GRAPH_RDLOCK_GUARD_MAINLOOP(); if (bs->drv && bs->drv->bdrv_drain_end) { bs->drv->bdrv_drain_end(bs); } bdrv_parent_drained_end(bs, parent); } } void bdrv_drained_end(BlockDriverState *bs) { IO_OR_GS_CODE(); bdrv_do_drained_end(bs, NULL); } void bdrv_drain(BlockDriverState *bs) { IO_OR_GS_CODE(); bdrv_drained_begin(bs); bdrv_drained_end(bs); } static void bdrv_drain_assert_idle(BlockDriverState *bs) { BdrvChild *child, *next; GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); assert(qatomic_read(&bs->in_flight) == 0); QLIST_FOREACH_SAFE(child, &bs->children, next, next) { bdrv_drain_assert_idle(child->bs); } } unsigned int bdrv_drain_all_count = 0; static bool bdrv_drain_all_poll(void) { BlockDriverState *bs = NULL; bool result = false; GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); /* bdrv_drain_poll() can't make changes to the graph and we are holding the * main AioContext lock, so iterating bdrv_next_all_states() is safe. */ while ((bs = bdrv_next_all_states(bs))) { AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); result |= bdrv_drain_poll(bs, NULL, true); aio_context_release(aio_context); } return result; } /* * Wait for pending requests to complete across all BlockDriverStates * * This function does not flush data to disk, use bdrv_flush_all() for that * after calling this function. * * This pauses all block jobs and disables external clients. It must * be paired with bdrv_drain_all_end(). * * NOTE: no new block jobs or BlockDriverStates can be created between * the bdrv_drain_all_begin() and bdrv_drain_all_end() calls. */ void bdrv_drain_all_begin_nopoll(void) { BlockDriverState *bs = NULL; GLOBAL_STATE_CODE(); /* * bdrv queue is managed by record/replay, * waiting for finishing the I/O requests may * be infinite */ if (replay_events_enabled()) { return; } /* AIO_WAIT_WHILE() with a NULL context can only be called from the main * loop AioContext, so make sure we're in the main context. */ assert(qemu_get_current_aio_context() == qemu_get_aio_context()); assert(bdrv_drain_all_count < INT_MAX); bdrv_drain_all_count++; /* Quiesce all nodes, without polling in-flight requests yet. The graph * cannot change during this loop. */ while ((bs = bdrv_next_all_states(bs))) { AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); bdrv_do_drained_begin(bs, NULL, false); aio_context_release(aio_context); } } void coroutine_mixed_fn bdrv_drain_all_begin(void) { BlockDriverState *bs = NULL; if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(NULL, true, NULL, true); return; } /* * bdrv queue is managed by record/replay, * waiting for finishing the I/O requests may * be infinite */ if (replay_events_enabled()) { return; } bdrv_drain_all_begin_nopoll(); /* Now poll the in-flight requests */ AIO_WAIT_WHILE_UNLOCKED(NULL, bdrv_drain_all_poll()); while ((bs = bdrv_next_all_states(bs))) { bdrv_drain_assert_idle(bs); } } void bdrv_drain_all_end_quiesce(BlockDriverState *bs) { GLOBAL_STATE_CODE(); g_assert(bs->quiesce_counter > 0); g_assert(!bs->refcnt); while (bs->quiesce_counter) { bdrv_do_drained_end(bs, NULL); } } void bdrv_drain_all_end(void) { BlockDriverState *bs = NULL; GLOBAL_STATE_CODE(); /* * bdrv queue is managed by record/replay, * waiting for finishing the I/O requests may * be endless */ if (replay_events_enabled()) { return; } while ((bs = bdrv_next_all_states(bs))) { AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); bdrv_do_drained_end(bs, NULL); aio_context_release(aio_context); } assert(qemu_get_current_aio_context() == qemu_get_aio_context()); assert(bdrv_drain_all_count > 0); bdrv_drain_all_count--; } void bdrv_drain_all(void) { GLOBAL_STATE_CODE(); bdrv_drain_all_begin(); bdrv_drain_all_end(); } /** * Remove an active request from the tracked requests list * * This function should be called when a tracked request is completing. */ static void coroutine_fn tracked_request_end(BdrvTrackedRequest *req) { if (req->serialising) { qatomic_dec(&req->bs->serialising_in_flight); } qemu_mutex_lock(&req->bs->reqs_lock); QLIST_REMOVE(req, list); qemu_mutex_unlock(&req->bs->reqs_lock); /* * At this point qemu_co_queue_wait(&req->wait_queue, ...) won't be called * anymore because the request has been removed from the list, so it's safe * to restart the queue outside reqs_lock to minimize the critical section. */ qemu_co_queue_restart_all(&req->wait_queue); } /** * Add an active request to the tracked requests list */ static void coroutine_fn tracked_request_begin(BdrvTrackedRequest *req, BlockDriverState *bs, int64_t offset, int64_t bytes, enum BdrvTrackedRequestType type) { bdrv_check_request(offset, bytes, &error_abort); *req = (BdrvTrackedRequest){ .bs = bs, .offset = offset, .bytes = bytes, .type = type, .co = qemu_coroutine_self(), .serialising = false, .overlap_offset = offset, .overlap_bytes = bytes, }; qemu_co_queue_init(&req->wait_queue); qemu_mutex_lock(&bs->reqs_lock); QLIST_INSERT_HEAD(&bs->tracked_requests, req, list); qemu_mutex_unlock(&bs->reqs_lock); } static bool tracked_request_overlaps(BdrvTrackedRequest *req, int64_t offset, int64_t bytes) { bdrv_check_request(offset, bytes, &error_abort); /* aaaa bbbb */ if (offset >= req->overlap_offset + req->overlap_bytes) { return false; } /* bbbb aaaa */ if (req->overlap_offset >= offset + bytes) { return false; } return true; } /* Called with self->bs->reqs_lock held */ static coroutine_fn BdrvTrackedRequest * bdrv_find_conflicting_request(BdrvTrackedRequest *self) { BdrvTrackedRequest *req; QLIST_FOREACH(req, &self->bs->tracked_requests, list) { if (req == self || (!req->serialising && !self->serialising)) { continue; } if (tracked_request_overlaps(req, self->overlap_offset, self->overlap_bytes)) { /* * Hitting this means there was a reentrant request, for * example, a block driver issuing nested requests. This must * never happen since it means deadlock. */ assert(qemu_coroutine_self() != req->co); /* * If the request is already (indirectly) waiting for us, or * will wait for us as soon as it wakes up, then just go on * (instead of producing a deadlock in the former case). */ if (!req->waiting_for) { return req; } } } return NULL; } /* Called with self->bs->reqs_lock held */ static void coroutine_fn bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self) { BdrvTrackedRequest *req; while ((req = bdrv_find_conflicting_request(self))) { self->waiting_for = req; qemu_co_queue_wait(&req->wait_queue, &self->bs->reqs_lock); self->waiting_for = NULL; } } /* Called with req->bs->reqs_lock held */ static void tracked_request_set_serialising(BdrvTrackedRequest *req, uint64_t align) { int64_t overlap_offset = req->offset & ~(align - 1); int64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align) - overlap_offset; bdrv_check_request(req->offset, req->bytes, &error_abort); if (!req->serialising) { qatomic_inc(&req->bs->serialising_in_flight); req->serialising = true; } req->overlap_offset = MIN(req->overlap_offset, overlap_offset); req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes); } /** * Return the tracked request on @bs for the current coroutine, or * NULL if there is none. */ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs) { BdrvTrackedRequest *req; Coroutine *self = qemu_coroutine_self(); IO_CODE(); QLIST_FOREACH(req, &bs->tracked_requests, list) { if (req->co == self) { return req; } } return NULL; } /** * Round a region to subcluster (if supported) or cluster boundaries */ void coroutine_fn GRAPH_RDLOCK bdrv_round_to_subclusters(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *align_offset, int64_t *align_bytes) { BlockDriverInfo bdi; IO_CODE(); if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.subcluster_size == 0) { *align_offset = offset; *align_bytes = bytes; } else { int64_t c = bdi.subcluster_size; *align_offset = QEMU_ALIGN_DOWN(offset, c); *align_bytes = QEMU_ALIGN_UP(offset - *align_offset + bytes, c); } } static int coroutine_fn GRAPH_RDLOCK bdrv_get_cluster_size(BlockDriverState *bs) { BlockDriverInfo bdi; int ret; ret = bdrv_co_get_info(bs, &bdi); if (ret < 0 || bdi.cluster_size == 0) { return bs->bl.request_alignment; } else { return bdi.cluster_size; } } void bdrv_inc_in_flight(BlockDriverState *bs) { IO_CODE(); qatomic_inc(&bs->in_flight); } void bdrv_wakeup(BlockDriverState *bs) { IO_CODE(); aio_wait_kick(); } void bdrv_dec_in_flight(BlockDriverState *bs) { IO_CODE(); qatomic_dec(&bs->in_flight); bdrv_wakeup(bs); } static void coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self) { BlockDriverState *bs = self->bs; if (!qatomic_read(&bs->serialising_in_flight)) { return; } qemu_mutex_lock(&bs->reqs_lock); bdrv_wait_serialising_requests_locked(self); qemu_mutex_unlock(&bs->reqs_lock); } void coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, uint64_t align) { IO_CODE(); qemu_mutex_lock(&req->bs->reqs_lock); tracked_request_set_serialising(req, align); bdrv_wait_serialising_requests_locked(req); qemu_mutex_unlock(&req->bs->reqs_lock); } int bdrv_check_qiov_request(int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, Error **errp) { /* * 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; } 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; } 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 0; } int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp) { 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) { return ret; } if (bytes > BDRV_REQUEST_MAX_BYTES) { return -EIO; } return 0; } /* * Completely zero out a block device with the help of bdrv_pwrite_zeroes. * The operation is sped up by checking the block status and only writing * zeroes to the device if they currently do not return zeroes. Optional * flags are passed through to bdrv_pwrite_zeroes (e.g. BDRV_REQ_MAY_UNMAP, * BDRV_REQ_FUA). * * Returns < 0 on error, 0 on success. For error codes see bdrv_pwrite(). */ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) { int ret; int64_t target_size, bytes, offset = 0; BlockDriverState *bs = child->bs; IO_CODE(); target_size = bdrv_getlength(bs); if (target_size < 0) { return target_size; } for (;;) { bytes = MIN(target_size - offset, BDRV_REQUEST_MAX_BYTES); if (bytes <= 0) { return 0; } ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL); if (ret < 0) { return ret; } if (ret & BDRV_BLOCK_ZERO) { offset += bytes; continue; } ret = bdrv_pwrite_zeroes(child, offset, bytes, flags); if (ret < 0) { return ret; } offset += bytes; } } /* * Writes to the file and ensures that no writes are reordered across this * request (acts as a barrier) * * Returns 0 on success, -errno in error cases. */ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags) { int ret; IO_CODE(); assert_bdrv_graph_readable(); ret = bdrv_co_pwrite(child, offset, bytes, buf, flags); if (ret < 0) { return ret; } ret = bdrv_co_flush(child->bs); if (ret < 0) { return ret; } return 0; } typedef struct CoroutineIOCompletion { Coroutine *coroutine; int ret; } CoroutineIOCompletion; static void bdrv_co_io_em_complete(void *opaque, int ret) { CoroutineIOCompletion *co = opaque; co->ret = ret; aio_co_wake(co->coroutine); } static int coroutine_fn GRAPH_RDLOCK bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriver *drv = bs->drv; int64_t sector_num; unsigned int nb_sectors; QEMUIOVector local_qiov; int ret; assert_bdrv_graph_readable(); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); assert(!(flags & ~bs->supported_read_flags)); if (!drv) { return -ENOMEDIUM; } if (drv->bdrv_co_preadv_part) { return drv->bdrv_co_preadv_part(bs, offset, bytes, qiov, qiov_offset, flags); } if (qiov_offset > 0 || bytes != qiov->size) { qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes); qiov = &local_qiov; } if (drv->bdrv_co_preadv) { ret = drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags); goto out; } if (drv->bdrv_aio_preadv) { BlockAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags, bdrv_co_io_em_complete, &co); if (acb == NULL) { ret = -EIO; goto out; } else { qemu_coroutine_yield(); ret = co.ret; goto out; } } sector_num = offset >> BDRV_SECTOR_BITS; nb_sectors = bytes >> BDRV_SECTOR_BITS; assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); assert(bytes <= BDRV_REQUEST_MAX_BYTES); assert(drv->bdrv_co_readv); ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); out: if (qiov == &local_qiov) { qemu_iovec_destroy(&local_qiov); } return ret; } static int coroutine_fn GRAPH_RDLOCK bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags) { BlockDriver *drv = bs->drv; bool emulate_fua = false; int64_t sector_num; unsigned int nb_sectors; QEMUIOVector local_qiov; int ret; assert_bdrv_graph_readable(); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { return -ENOMEDIUM; } if ((flags & BDRV_REQ_FUA) && (~bs->supported_write_flags & BDRV_REQ_FUA)) { flags &= ~BDRV_REQ_FUA; emulate_fua = true; } flags &= bs->supported_write_flags; if (drv->bdrv_co_pwritev_part) { ret = drv->bdrv_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset, flags); goto emulate_flags; } if (qiov_offset > 0 || bytes != qiov->size) { qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes); qiov = &local_qiov; } if (drv->bdrv_co_pwritev) { ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov, flags); goto emulate_flags; } if (drv->bdrv_aio_pwritev) { BlockAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; acb = drv->bdrv_aio_pwritev(bs, offset, bytes, qiov, flags, bdrv_co_io_em_complete, &co); if (acb == NULL) { ret = -EIO; } else { qemu_coroutine_yield(); ret = co.ret; } goto emulate_flags; } sector_num = offset >> BDRV_SECTOR_BITS; nb_sectors = bytes >> BDRV_SECTOR_BITS; assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); assert(bytes <= BDRV_REQUEST_MAX_BYTES); assert(drv->bdrv_co_writev); ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov, flags); emulate_flags: if (ret == 0 && emulate_fua) { ret = bdrv_co_flush(bs); } if (qiov == &local_qiov) { qemu_iovec_destroy(&local_qiov); } return ret; } static int coroutine_fn GRAPH_RDLOCK bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) { BlockDriver *drv = bs->drv; QEMUIOVector local_qiov; int ret; assert_bdrv_graph_readable(); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { return -ENOMEDIUM; } if (!block_driver_can_compress(drv)) { return -ENOTSUP; } if (drv->bdrv_co_pwritev_compressed_part) { return drv->bdrv_co_pwritev_compressed_part(bs, offset, bytes, qiov, qiov_offset); } if (qiov_offset == 0) { return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov); } qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes); ret = drv->bdrv_co_pwritev_compressed(bs, offset, bytes, &local_qiov); qemu_iovec_destroy(&local_qiov); return ret; } static int coroutine_fn GRAPH_RDLOCK bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; /* Perform I/O through a temporary buffer so that users who scribble over * their read buffer while the operation is in progress do not end up * modifying the image file. This is critical for zero-copy guest I/O * where anything might happen inside guest memory. */ void *bounce_buffer = NULL; BlockDriver *drv = bs->drv; int64_t align_offset; int64_t align_bytes; int64_t skip_bytes; int ret; int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, BDRV_REQUEST_MAX_BYTES); int64_t progress = 0; bool skip_write; bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); 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 * long as it is implemented here rather than in a separate filter driver, * the copy-on-read code doesn't have its own BdrvChild, however, for which * it could request permissions. Therefore we have to bypass the permission * system for the moment. */ // assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE)); /* Cover entire cluster so no additional backing file I/O is required when * allocating cluster in the image file. Note that this value may exceed * BDRV_REQUEST_MAX_BYTES (even when the original read did not), which * is one reason we loop rather than doing it all at once. */ bdrv_round_to_subclusters(bs, offset, bytes, &align_offset, &align_bytes); skip_bytes = offset - align_offset; trace_bdrv_co_do_copy_on_readv(bs, offset, bytes, align_offset, align_bytes); while (align_bytes) { int64_t pnum; if (skip_write) { ret = 1; /* "already allocated", so nothing will be copied */ pnum = MIN(align_bytes, max_transfer); } else { ret = bdrv_co_is_allocated(bs, align_offset, MIN(align_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(align_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; } assert(skip_bytes < pnum); } if (ret <= 0) { QEMUIOVector local_qiov; /* Must copy-on-read; use the bounce buffer */ pnum = MIN(pnum, MAX_BOUNCE_BUFFER); if (!bounce_buffer) { int64_t max_we_need = MAX(pnum, align_bytes - pnum); int64_t max_allowed = MIN(max_transfer, MAX_BOUNCE_BUFFER); int64_t bounce_buffer_len = MIN(max_we_need, max_allowed); bounce_buffer = qemu_try_blockalign(bs, bounce_buffer_len); if (!bounce_buffer) { ret = -ENOMEM; goto err; } } qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum); ret = bdrv_driver_preadv(bs, align_offset, pnum, &local_qiov, 0, 0); if (ret < 0) { goto err; } bdrv_co_debug_event(bs, BLKDBG_COR_WRITE); if (drv->bdrv_co_pwrite_zeroes && buffer_is_zero(bounce_buffer, pnum)) { /* FIXME: Should we (perhaps conditionally) be setting * BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy * that still correctly reads as zero? */ ret = bdrv_co_do_pwrite_zeroes(bs, align_offset, pnum, BDRV_REQ_WRITE_UNCHANGED); } else { /* This does not change the data on the disk, it is not * necessary to flush even in cache=writethrough mode. */ ret = bdrv_driver_pwritev(bs, align_offset, pnum, &local_qiov, 0, BDRV_REQ_WRITE_UNCHANGED); } if (ret < 0) { /* It might be okay to ignore write errors for guest * requests. If this is a deliberate copy-on-read * then we don't want to ignore the error. Simply * report it in all cases. */ goto err; } if (!(flags & BDRV_REQ_PREFETCH)) { qemu_iovec_from_buf(qiov, qiov_offset + progress, bounce_buffer + skip_bytes, MIN(pnum - skip_bytes, bytes - progress)); } } else if (!(flags & BDRV_REQ_PREFETCH)) { /* Read directly into the destination */ ret = bdrv_driver_preadv(bs, offset + progress, MIN(pnum - skip_bytes, bytes - progress), qiov, qiov_offset + progress, 0); if (ret < 0) { goto err; } } align_offset += pnum; align_bytes -= pnum; progress += pnum - skip_bytes; skip_bytes = 0; } ret = 0; err: qemu_vfree(bounce_buffer); return ret; } /* * Forwards an already correctly aligned request to the BlockDriver. This * handles copy on read, zeroing after EOF, and fragmentation of large * reads; any other features must be implemented by the caller. */ static int coroutine_fn GRAPH_RDLOCK bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req, int64_t offset, int64_t bytes, int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; int64_t total_bytes, max_bytes; int ret = 0; int64_t bytes_remaining = bytes; int max_transfer; bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); assert(is_power_of_2(align)); assert((offset & (align - 1)) == 0); assert((bytes & (align - 1)) == 0); assert((bs->open_flags & BDRV_O_NO_IO) == 0); max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX), align); /* * TODO: We would need a per-BDS .supported_read_flags and * potential fallback support, if we ever implement any read flags * to pass through to drivers. For now, there aren't any * passthrough flags except the BDRV_REQ_REGISTERED_BUF optimization hint. */ assert(!(flags & ~(BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH | BDRV_REQ_REGISTERED_BUF))); /* Handle Copy on Read and associated serialisation */ if (flags & BDRV_REQ_COPY_ON_READ) { /* If we touch the same cluster it counts as an overlap. This * guarantees that allocating writes will be serialized and not race * with each other for the same cluster. For example, in copy-on-read * it ensures that the CoR read and write operations are atomic and * guest writes cannot interleave between them. */ bdrv_make_request_serialising(req, bdrv_get_cluster_size(bs)); } else { bdrv_wait_serialising_requests(req); } if (flags & BDRV_REQ_COPY_ON_READ) { int64_t pnum; /* The flag BDRV_REQ_COPY_ON_READ has reached its addressee */ flags &= ~BDRV_REQ_COPY_ON_READ; ret = bdrv_co_is_allocated(bs, offset, bytes, &pnum); if (ret < 0) { goto out; } if (!ret || pnum != bytes) { ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, qiov_offset, flags); goto out; } else if (flags & BDRV_REQ_PREFETCH) { goto out; } } /* Forward the request to the BlockDriver, possibly fragmenting it */ total_bytes = bdrv_co_getlength(bs); if (total_bytes < 0) { ret = total_bytes; goto out; } assert(!(flags & ~(bs->supported_read_flags | BDRV_REQ_REGISTERED_BUF))); max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align); if (bytes <= max_bytes && bytes <= max_transfer) { ret = bdrv_driver_preadv(bs, offset, bytes, qiov, qiov_offset, flags); goto out; } while (bytes_remaining) { int64_t num; if (max_bytes) { num = MIN(bytes_remaining, MIN(max_bytes, max_transfer)); assert(num); ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining, num, qiov, qiov_offset + bytes - bytes_remaining, flags); max_bytes -= num; } else { num = bytes_remaining; ret = qemu_iovec_memset(qiov, qiov_offset + bytes - bytes_remaining, 0, bytes_remaining); } if (ret < 0) { goto out; } bytes_remaining -= num; } out: return ret < 0 ? ret : 0; } /* * Request padding * * |<---- align ----->| |<----- align ---->| * |<- head ->|<------------- bytes ------------->|<-- tail -->| * | | | | | | * -*----------$-------*-------- ... --------*-----$------------*--- * | | | | | | * | offset | | end | * ALIGN_DOWN(offset) ALIGN_UP(offset) ALIGN_DOWN(end) ALIGN_UP(end) * [buf ... ) [tail_buf ) * * @buf is an aligned allocation needed to store @head and @tail paddings. @head * is placed at the beginning of @buf and @tail at the @end. * * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk * around tail, if tail exists. * * @merge_reads is true for small requests, * if @buf_len == @head + bytes + @tail. In this case it is possible that both * head and tail exist but @buf_len == align and @tail_buf == @buf. * * @write is true for write requests, false for read requests. * * If padding makes the vector too long (exceeding IOV_MAX), then we need to * merge existing vector elements into a single one. @collapse_bounce_buf acts * as the bounce buffer in such cases. @pre_collapse_qiov has the pre-collapse * I/O vector elements so for read requests, the data can be copied back after * the read is done. */ typedef struct BdrvRequestPadding { uint8_t *buf; size_t buf_len; uint8_t *tail_buf; size_t head; size_t tail; bool merge_reads; bool write; QEMUIOVector local_qiov; uint8_t *collapse_bounce_buf; size_t collapse_len; QEMUIOVector pre_collapse_qiov; } BdrvRequestPadding; static bool bdrv_init_padding(BlockDriverState *bs, int64_t offset, int64_t bytes, bool write, BdrvRequestPadding *pad) { int64_t align = bs->bl.request_alignment; 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)); pad->head = offset & (align - 1); pad->tail = ((offset + bytes) & (align - 1)); if (pad->tail) { pad->tail = align - pad->tail; } if (!pad->head && !pad->tail) { return false; } assert(bytes); /* Nothing good in aligning zero-length requests */ sum = pad->head + bytes + pad->tail; pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align; pad->buf = qemu_blockalign(bs, pad->buf_len); pad->merge_reads = sum == pad->buf_len; if (pad->tail) { pad->tail_buf = pad->buf + pad->buf_len - align; } pad->write = write; return true; } static int coroutine_fn GRAPH_RDLOCK bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req, BdrvRequestPadding *pad, bool zero_middle) { QEMUIOVector local_qiov; BlockDriverState *bs = child->bs; uint64_t align = bs->bl.request_alignment; int ret; assert(req->serialising && pad->buf); if (pad->head || pad->merge_reads) { int64_t bytes = pad->merge_reads ? pad->buf_len : align; qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); if (pad->head) { bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); } if (pad->merge_reads && pad->tail) { bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); } ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, align, &local_qiov, 0, 0); if (ret < 0) { return ret; } if (pad->head) { bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); } if (pad->merge_reads && pad->tail) { bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); } if (pad->merge_reads) { goto zero_mem; } } if (pad->tail) { qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); ret = bdrv_aligned_preadv( child, req, req->overlap_offset + req->overlap_bytes - align, align, align, &local_qiov, 0, 0); if (ret < 0) { return ret; } bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); } zero_mem: if (zero_middle) { memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->tail); } return 0; } /** * Free *pad's associated buffers, and perform any necessary finalization steps. */ static void bdrv_padding_finalize(BdrvRequestPadding *pad) { if (pad->collapse_bounce_buf) { if (!pad->write) { /* * If padding required elements in the vector to be collapsed into a * bounce buffer, copy the bounce buffer content back */ qemu_iovec_from_buf(&pad->pre_collapse_qiov, 0, pad->collapse_bounce_buf, pad->collapse_len); } qemu_vfree(pad->collapse_bounce_buf); qemu_iovec_destroy(&pad->pre_collapse_qiov); } if (pad->buf) { qemu_vfree(pad->buf); qemu_iovec_destroy(&pad->local_qiov); } memset(pad, 0, sizeof(*pad)); } /* * Create pad->local_qiov by wrapping @iov in the padding head and tail, while * ensuring that the resulting vector will not exceed IOV_MAX elements. * * To ensure this, when necessary, the first two or three elements of @iov are * merged into pad->collapse_bounce_buf and replaced by a reference to that * bounce buffer in pad->local_qiov. * * After performing a read request, the data from the bounce buffer must be * copied back into pad->pre_collapse_qiov (e.g. by bdrv_padding_finalize()). */ static int bdrv_create_padded_qiov(BlockDriverState *bs, BdrvRequestPadding *pad, struct iovec *iov, int niov, size_t iov_offset, size_t bytes) { int padded_niov, surplus_count, collapse_count; /* Assert this invariant */ assert(niov <= IOV_MAX); /* * Cannot pad if resulting length would exceed SIZE_MAX. Returning an error * to the guest is not ideal, but there is little else we can do. At least * this will practically never happen on 64-bit systems. */ if (SIZE_MAX - pad->head < bytes || SIZE_MAX - pad->head - bytes < pad->tail) { return -EINVAL; } /* Length of the resulting IOV if we just concatenated everything */ padded_niov = !!pad->head + niov + !!pad->tail; qemu_iovec_init(&pad->local_qiov, MIN(padded_niov, IOV_MAX)); if (pad->head) { qemu_iovec_add(&pad->local_qiov, pad->buf, pad->head); } /* * If padded_niov > IOV_MAX, we cannot just concatenate everything. * Instead, merge the first two or three elements of @iov to reduce the * number of vector elements as necessary. */ if (padded_niov > IOV_MAX) { /* * Only head and tail can have lead to the number of entries exceeding * IOV_MAX, so we can exceed it by the head and tail at most. We need * to reduce the number of elements by `surplus_count`, so we merge that * many elements plus one into one element. */ surplus_count = padded_niov - IOV_MAX; assert(surplus_count <= !!pad->head + !!pad->tail); collapse_count = surplus_count + 1; /* * Move the elements to collapse into `pad->pre_collapse_qiov`, then * advance `iov` (and associated variables) by those elements. */ qemu_iovec_init(&pad->pre_collapse_qiov, collapse_count); qemu_iovec_concat_iov(&pad->pre_collapse_qiov, iov, collapse_count, iov_offset, SIZE_MAX); iov += collapse_count; iov_offset = 0; niov -= collapse_count; bytes -= pad->pre_collapse_qiov.size; /* * Construct the bounce buffer to match the length of the to-collapse * vector elements, and for write requests, initialize it with the data * from those elements. Then add it to `pad->local_qiov`. */ pad->collapse_len = pad->pre_collapse_qiov.size; pad->collapse_bounce_buf = qemu_blockalign(bs, pad->collapse_len); if (pad->write) { qemu_iovec_to_buf(&pad->pre_collapse_qiov, 0, pad->collapse_bounce_buf, pad->collapse_len); } qemu_iovec_add(&pad->local_qiov, pad->collapse_bounce_buf, pad->collapse_len); } qemu_iovec_concat_iov(&pad->local_qiov, iov, niov, iov_offset, bytes); if (pad->tail) { qemu_iovec_add(&pad->local_qiov, pad->buf + pad->buf_len - pad->tail, pad->tail); } assert(pad->local_qiov.niov == MIN(padded_niov, IOV_MAX)); return 0; } /* * bdrv_pad_request * * Exchange request parameters with padded request if needed. Don't include RMW * read of padding, bdrv_padding_rmw_read() should be called separately if * needed. * * @write is true for write requests, false for read requests. * * Request parameters (@qiov, &qiov_offset, &offset, &bytes) are in-out: * - on function start they represent original request * - on failure or when padding is not needed they are unchanged * - on success when padding is needed they represent padded request */ static int bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, size_t *qiov_offset, int64_t *offset, int64_t *bytes, bool write, BdrvRequestPadding *pad, bool *padded, BdrvRequestFlags *flags) { int ret; struct iovec *sliced_iov; int sliced_niov; size_t sliced_head, sliced_tail; /* Should have been checked by the caller already */ ret = bdrv_check_request32(*offset, *bytes, *qiov, *qiov_offset); if (ret < 0) { return ret; } if (!bdrv_init_padding(bs, *offset, *bytes, write, pad)) { if (padded) { *padded = false; } return 0; } sliced_iov = qemu_iovec_slice(*qiov, *qiov_offset, *bytes, &sliced_head, &sliced_tail, &sliced_niov); /* Guaranteed by bdrv_check_request32() */ assert(*bytes <= SIZE_MAX); ret = bdrv_create_padded_qiov(bs, pad, sliced_iov, sliced_niov, sliced_head, *bytes); if (ret < 0) { bdrv_padding_finalize(pad); return ret; } *bytes += pad->head + pad->tail; *offset -= pad->head; *qiov = &pad->local_qiov; *qiov_offset = 0; if (padded) { *padded = true; } if (flags) { /* Can't use optimization hint with bounce buffer */ *flags &= ~BDRV_REQ_REGISTERED_BUF; } return 0; } int coroutine_fn bdrv_co_preadv(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { IO_CODE(); return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags); } int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; BdrvTrackedRequest req; BdrvRequestPadding pad; int ret; IO_CODE(); trace_bdrv_co_preadv_part(bs, offset, bytes, flags); if (!bdrv_co_is_inserted(bs)) { return -ENOMEDIUM; } ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset); if (ret < 0) { return ret; } if (bytes == 0 && !QEMU_IS_ALIGNED(offset, bs->bl.request_alignment)) { /* * Aligning zero request is nonsense. Even if driver has special meaning * of zero-length (like qcow2_co_pwritev_compressed_part), we can't pass * it to driver due to request_alignment. * * Still, no reason to return an error if someone do unaligned * zero-length read occasionally. */ return 0; } bdrv_inc_in_flight(bs); /* Don't do copy-on-read if we read data before write operation */ if (qatomic_read(&bs->copy_on_read)) { flags |= BDRV_REQ_COPY_ON_READ; } ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, false, &pad, NULL, &flags); if (ret < 0) { goto fail; } tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); ret = bdrv_aligned_preadv(child, &req, offset, bytes, bs->bl.request_alignment, qiov, qiov_offset, flags); tracked_request_end(&req); bdrv_padding_finalize(&pad); fail: bdrv_dec_in_flight(bs); return ret; } static int coroutine_fn GRAPH_RDLOCK bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvRequestFlags flags) { BlockDriver *drv = bs->drv; QEMUIOVector qiov; void *buf = NULL; int ret = 0; bool need_flush = false; int head = 0; int tail = 0; int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT64_MAX); int alignment = MAX(bs->bl.pwrite_zeroes_alignment, bs->bl.request_alignment); int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER); assert_bdrv_graph_readable(); bdrv_check_request(offset, bytes, &error_abort); if (!drv) { return -ENOMEDIUM; } if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) { return -ENOTSUP; } /* By definition there is no user buffer so this flag doesn't make sense */ if (flags & BDRV_REQ_REGISTERED_BUF) { return -EINVAL; } /* Invalidate the cached block-status data range if this write overlaps */ bdrv_bsc_invalidate_range(bs, offset, bytes); assert(alignment % bs->bl.request_alignment == 0); head = offset % alignment; tail = (offset + bytes) % alignment; max_write_zeroes = QEMU_ALIGN_DOWN(max_write_zeroes, alignment); assert(max_write_zeroes >= bs->bl.request_alignment); while (bytes > 0 && !ret) { int64_t num = bytes; /* Align request. Block drivers can expect the "bulk" of the request * to be aligned, and that unaligned requests do not cross cluster * boundaries. */ if (head) { /* Make a small request up to the first aligned sector. For * convenience, limit this request to max_transfer even if * we don't need to fall back to writes. */ num = MIN(MIN(bytes, max_transfer), alignment - head); head = (head + num) % alignment; assert(num < max_write_zeroes); } else if (tail && num > alignment) { /* Shorten the request to the last aligned sector. */ num -= tail; } /* limit request size */ if (num > max_write_zeroes) { num = max_write_zeroes; } ret = -ENOTSUP; /* First try the efficient write zeroes operation */ if (drv->bdrv_co_pwrite_zeroes) { ret = drv->bdrv_co_pwrite_zeroes(bs, offset, num, flags & bs->supported_zero_flags); if (ret != -ENOTSUP && (flags & BDRV_REQ_FUA) && !(bs->supported_zero_flags & BDRV_REQ_FUA)) { need_flush = true; } } else { assert(!bs->supported_zero_flags); } if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) { /* Fall back to bounce buffer if write zeroes is unsupported */ BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE; if ((flags & BDRV_REQ_FUA) && !(bs->supported_write_flags & BDRV_REQ_FUA)) { /* No need for bdrv_driver_pwrite() to do a fallback * flush on each chunk; use just one at the end */ write_flags &= ~BDRV_REQ_FUA; need_flush = true; } num = MIN(num, max_transfer); if (buf == NULL) { buf = qemu_try_blockalign0(bs, num); if (buf == NULL) { ret = -ENOMEM; goto fail; } } qemu_iovec_init_buf(&qiov, buf, num); ret = bdrv_driver_pwritev(bs, offset, num, &qiov, 0, write_flags); /* Keep bounce buffer around if it is big enough for all * all future requests. */ if (num < max_transfer) { qemu_vfree(buf); buf = NULL; } } offset += num; bytes -= num; } fail: if (ret == 0 && need_flush) { ret = bdrv_co_flush(bs); } qemu_vfree(buf); return ret; } static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes, BdrvTrackedRequest *req, int flags) { BlockDriverState *bs = child->bs; bdrv_check_request(offset, bytes, &error_abort); if (bdrv_is_read_only(bs)) { return -EPERM; } assert(!(bs->open_flags & BDRV_O_INACTIVE)); assert((bs->open_flags & BDRV_O_NO_IO) == 0); assert(!(flags & ~BDRV_REQ_MASK)); assert(!((flags & BDRV_REQ_NO_WAIT) && !(flags & BDRV_REQ_SERIALISING))); if (flags & BDRV_REQ_SERIALISING) { QEMU_LOCK_GUARD(&bs->reqs_lock); tracked_request_set_serialising(req, bdrv_get_cluster_size(bs)); if ((flags & BDRV_REQ_NO_WAIT) && bdrv_find_conflicting_request(req)) { return -EBUSY; } bdrv_wait_serialising_requests_locked(req); } else { bdrv_wait_serialising_requests(req); } assert(req->overlap_offset <= offset); assert(offset + bytes <= req->overlap_offset + req->overlap_bytes); assert(offset + bytes <= bs->total_sectors * BDRV_SECTOR_SIZE || child->perm & BLK_PERM_RESIZE); switch (req->type) { case BDRV_TRACKED_WRITE: case BDRV_TRACKED_DISCARD: if (flags & BDRV_REQ_WRITE_UNCHANGED) { assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE)); } else { assert(child->perm & BLK_PERM_WRITE); } bdrv_write_threshold_check_write(bs, offset, bytes); return 0; case BDRV_TRACKED_TRUNCATE: assert(child->perm & BLK_PERM_RESIZE); return 0; default: abort(); } } static inline void coroutine_fn GRAPH_RDLOCK bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes, BdrvTrackedRequest *req, int ret) { int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE); BlockDriverState *bs = child->bs; bdrv_check_request(offset, bytes, &error_abort); qatomic_inc(&bs->write_gen); /* * Discard cannot extend the image, but in error handling cases, such as * when reverting a qcow2 cluster allocation, the discarded range can pass * the end of image file, so we cannot assert about BDRV_TRACKED_DISCARD * here. Instead, just skip it, since semantically a discard request * beyond EOF cannot expand the image anyway. */ if (ret == 0 && (req->type == BDRV_TRACKED_TRUNCATE || end_sector > bs->total_sectors) && req->type != BDRV_TRACKED_DISCARD) { bs->total_sectors = end_sector; bdrv_parent_cb_resize(bs); bdrv_dirty_bitmap_truncate(bs, end_sector << BDRV_SECTOR_BITS); } if (req->bytes) { switch (req->type) { case BDRV_TRACKED_WRITE: stat64_max(&bs->wr_highest_offset, offset + bytes); /* fall through, to set dirty bits */ case BDRV_TRACKED_DISCARD: bdrv_set_dirty(bs, offset, bytes); break; default: break; } } } /* * Forwards an already correctly aligned write request to the BlockDriver, * after possibly fragmenting it. */ static int coroutine_fn GRAPH_RDLOCK bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req, int64_t offset, int64_t bytes, int64_t align, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; BlockDriver *drv = bs->drv; int ret; int64_t bytes_remaining = bytes; int max_transfer; bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { return -ENOMEDIUM; } if (bdrv_has_readonly_bitmaps(bs)) { return -EPERM; } assert(is_power_of_2(align)); assert((offset & (align - 1)) == 0); assert((bytes & (align - 1)) == 0); max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX), align); ret = bdrv_co_write_req_prepare(child, offset, bytes, req, flags); if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF && !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes && qemu_iovec_is_zero(qiov, qiov_offset, bytes)) { flags |= BDRV_REQ_ZERO_WRITE; if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) { flags |= BDRV_REQ_MAY_UNMAP; } /* Can't use optimization hint with bufferless zero write */ flags &= ~BDRV_REQ_REGISTERED_BUF; } if (ret < 0) { /* Do nothing, write notifier decided to fail this request */ } else if (flags & BDRV_REQ_ZERO_WRITE) { bdrv_co_debug_event(bs, BLKDBG_PWRITEV_ZERO); ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags); } else if (flags & BDRV_REQ_WRITE_COMPRESSED) { ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, qiov_offset); } else if (bytes <= max_transfer) { bdrv_co_debug_event(bs, BLKDBG_PWRITEV); ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags); } else { bdrv_co_debug_event(bs, BLKDBG_PWRITEV); while (bytes_remaining) { int num = MIN(bytes_remaining, max_transfer); int local_flags = flags; assert(num); if (num < bytes_remaining && (flags & BDRV_REQ_FUA) && !(bs->supported_write_flags & BDRV_REQ_FUA)) { /* If FUA is going to be emulated by flush, we only * need to flush on the last iteration */ local_flags &= ~BDRV_REQ_FUA; } ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining, num, qiov, qiov_offset + bytes - bytes_remaining, local_flags); if (ret < 0) { break; } bytes_remaining -= num; } } bdrv_co_debug_event(bs, BLKDBG_PWRITEV_DONE); if (ret >= 0) { ret = 0; } bdrv_co_write_req_finish(child, offset, bytes, req, ret); return ret; } static int coroutine_fn GRAPH_RDLOCK bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, BdrvRequestFlags flags, BdrvTrackedRequest *req) { BlockDriverState *bs = child->bs; QEMUIOVector local_qiov; uint64_t align = bs->bl.request_alignment; int ret = 0; bool padding; BdrvRequestPadding pad; /* This flag doesn't make sense for padding or zero writes */ flags &= ~BDRV_REQ_REGISTERED_BUF; padding = bdrv_init_padding(bs, offset, bytes, true, &pad); if (padding) { assert(!(flags & BDRV_REQ_NO_WAIT)); bdrv_make_request_serialising(req, align); bdrv_padding_rmw_read(child, req, &pad, true); if (pad.head || pad.merge_reads) { int64_t aligned_offset = offset & ~(align - 1); int64_t write_bytes = pad.merge_reads ? pad.buf_len : align; qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes, align, &local_qiov, 0, flags & ~BDRV_REQ_ZERO_WRITE); if (ret < 0 || pad.merge_reads) { /* Error or all work is done */ goto out; } offset += write_bytes - pad.head; bytes -= write_bytes - pad.head; } } assert(!bytes || (offset & (align - 1)) == 0); if (bytes >= align) { /* Write the aligned part in the middle. */ int64_t aligned_bytes = bytes & ~(align - 1); ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align, NULL, 0, flags); if (ret < 0) { goto out; } bytes -= aligned_bytes; offset += aligned_bytes; } assert(!bytes || (offset & (align - 1)) == 0); if (bytes) { assert(align == pad.tail + bytes); qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); ret = bdrv_aligned_pwritev(child, req, offset, align, align, &local_qiov, 0, flags & ~BDRV_REQ_ZERO_WRITE); } out: bdrv_padding_finalize(&pad); return ret; } /* * Handle a write request in coroutine context */ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { IO_CODE(); return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags); } int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; BdrvTrackedRequest req; uint64_t align = bs->bl.request_alignment; BdrvRequestPadding pad; int ret; bool padded = false; IO_CODE(); trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags); if (!bdrv_co_is_inserted(bs)) { return -ENOMEDIUM; } if (flags & BDRV_REQ_ZERO_WRITE) { ret = bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, NULL); } else { ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset); } if (ret < 0) { return ret; } /* If the request is misaligned then we can't make it efficient */ if ((flags & BDRV_REQ_NO_FALLBACK) && !QEMU_IS_ALIGNED(offset | bytes, align)) { return -ENOTSUP; } if (bytes == 0 && !QEMU_IS_ALIGNED(offset, bs->bl.request_alignment)) { /* * Aligning zero request is nonsense. Even if driver has special meaning * of zero-length (like qcow2_co_pwritev_compressed_part), we can't pass * it to driver due to request_alignment. * * Still, no reason to return an error if someone do unaligned * zero-length write occasionally. */ return 0; } if (!(flags & BDRV_REQ_ZERO_WRITE)) { /* * Pad request for following read-modify-write cycle. * bdrv_co_do_zero_pwritev() does aligning by itself, so, we do * alignment only if there is no ZERO flag. */ ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, true, &pad, &padded, &flags); if (ret < 0) { return ret; } } bdrv_inc_in_flight(bs); tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE); if (flags & BDRV_REQ_ZERO_WRITE) { assert(!padded); ret = bdrv_co_do_zero_pwritev(child, offset, bytes, flags, &req); goto out; } 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. */ assert(!(flags & BDRV_REQ_NO_WAIT)); bdrv_make_request_serialising(&req, align); bdrv_padding_rmw_read(child, &req, &pad, false); } ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align, qiov, qiov_offset, flags); bdrv_padding_finalize(&pad); out: tracked_request_end(&req); bdrv_dec_in_flight(bs); return ret; } int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes, BdrvRequestFlags flags) { IO_CODE(); trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags); assert_bdrv_graph_readable(); if (!(child->bs->open_flags & BDRV_O_UNMAP)) { flags &= ~BDRV_REQ_MAY_UNMAP; } return bdrv_co_pwritev(child, offset, bytes, NULL, BDRV_REQ_ZERO_WRITE | flags); } /* * Flush ALL BDSes regardless of if they are reachable via a BlkBackend or not. */ int bdrv_flush_all(void) { BdrvNextIterator it; BlockDriverState *bs = NULL; int result = 0; GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); /* * bdrv queue is managed by record/replay, * creating new flush request for stopping * the VM may break the determinism */ if (replay_events_enabled()) { return result; } for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { AioContext *aio_context = bdrv_get_aio_context(bs); int ret; aio_context_acquire(aio_context); ret = bdrv_flush(bs); if (ret < 0 && !result) { result = ret; } aio_context_release(aio_context); } return result; } /* * Returns the allocation status of the specified sectors. * Drivers not implementing the functionality are assumed to not support * backing files, hence all their sectors are reported as allocated. * * If 'want_zero' is true, the caller is querying for mapping * purposes, with a focus on valid BDRV_BLOCK_OFFSET_VALID, _DATA, and * _ZERO where possible; otherwise, the result favors larger 'pnum', * with a focus on accurate BDRV_BLOCK_ALLOCATED. * * If 'offset' is beyond the end of the disk image the return value is * BDRV_BLOCK_EOF and 'pnum' is set to 0. * * 'bytes' is the max value 'pnum' should be set to. If bytes goes * beyond the end of the disk image it will be clamped; if 'pnum' is set to * the end of the image, then the returned value will include BDRV_BLOCK_EOF. * * 'pnum' is set to the number of bytes (including and immediately * following the specified offset) that are easily known to be in the * same allocated/unallocated state. Note that a second call starting * at the original offset plus returned pnum may have the same status. * The returned value is non-zero on success except at end-of-file. * * Returns negative errno on failure. Otherwise, if the * BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are * set to the host mapping and BDS corresponding to the guest offset. */ static int coroutine_fn GRAPH_RDLOCK bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { int64_t total_size; int64_t n; /* bytes */ int ret; int64_t local_map = 0; BlockDriverState *local_file = NULL; int64_t aligned_offset, aligned_bytes; uint32_t align; bool has_filtered_child; assert(pnum); assert_bdrv_graph_readable(); *pnum = 0; total_size = bdrv_co_getlength(bs); if (total_size < 0) { ret = total_size; goto early_out; } if (offset >= total_size) { ret = BDRV_BLOCK_EOF; goto early_out; } if (!bytes) { ret = 0; goto early_out; } n = total_size - offset; if (n < bytes) { bytes = n; } /* Must be non-NULL or bdrv_co_getlength() would have failed */ assert(bs->drv); has_filtered_child = bdrv_filter_child(bs); if (!bs->drv->bdrv_co_block_status && !has_filtered_child) { *pnum = bytes; ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED; if (offset + bytes == total_size) { ret |= BDRV_BLOCK_EOF; } if (bs->drv->protocol_name) { ret |= BDRV_BLOCK_OFFSET_VALID; local_map = offset; local_file = bs; } goto early_out; } bdrv_inc_in_flight(bs); /* Round out to request_alignment boundaries */ align = bs->bl.request_alignment; aligned_offset = QEMU_ALIGN_DOWN(offset, align); aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset; if (bs->drv->bdrv_co_block_status) { /* * Use the block-status cache only for protocol nodes: Format * drivers are generally quick to inquire the status, but protocol * drivers often need to get information from outside of qemu, so * we do not have control over the actual implementation. There * have been cases where inquiring the status took an unreasonably * long time, and we can do nothing in qemu to fix it. * This is especially problematic for images with large data areas, * because finding the few holes in them and giving them special * treatment does not gain much performance. Therefore, we try to * cache the last-identified data region. * * Second, limiting ourselves to protocol nodes allows us to assume * the block status for data regions to be DATA | OFFSET_VALID, and * that the host offset is the same as the guest offset. * * Note that it is possible that external writers zero parts of * the cached regions without the cache being invalidated, and so * we may report zeroes as data. This is not catastrophic, * however, because reporting zeroes as data is fine. */ if (QLIST_EMPTY(&bs->children) && bdrv_bsc_is_data(bs, aligned_offset, pnum)) { ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID; local_file = bs; local_map = aligned_offset; } else { ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset, aligned_bytes, pnum, &local_map, &local_file); /* * Note that checking QLIST_EMPTY(&bs->children) is also done when * the cache is queried above. Technically, we do not need to check * it here; the worst that can happen is that we fill the cache for * non-protocol nodes, and then it is never used. However, filling * the cache requires an RCU update, so double check here to avoid * such an update if possible. * * Check want_zero, because we only want to update the cache when we * have accurate information about what is zero and what is data. */ if (want_zero && ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) && QLIST_EMPTY(&bs->children)) { /* * When a protocol driver reports BLOCK_OFFSET_VALID, the * returned local_map value must be the same as the offset we * have passed (aligned_offset), and local_bs must be the node * itself. * Assert this, because we follow this rule when reading from * the cache (see the `local_file = bs` and * `local_map = aligned_offset` assignments above), and the * result the cache delivers must be the same as the driver * would deliver. */ assert(local_file == bs); assert(local_map == aligned_offset); bdrv_bsc_fill(bs, aligned_offset, *pnum); } } } else { /* Default code for filters */ local_file = bdrv_filter_bs(bs); assert(local_file); *pnum = aligned_bytes; local_map = aligned_offset; ret = BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID; } if (ret < 0) { *pnum = 0; goto out; } /* * The driver's result must be a non-zero multiple of request_alignment. * Clamp pnum and adjust map to original request. */ assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset); if (ret & BDRV_BLOCK_RECURSE) { assert(ret & BDRV_BLOCK_DATA); assert(ret & BDRV_BLOCK_OFFSET_VALID); assert(!(ret & BDRV_BLOCK_ZERO)); } *pnum -= offset - aligned_offset; if (*pnum > bytes) { *pnum = bytes; } if (ret & BDRV_BLOCK_OFFSET_VALID) { local_map += offset - aligned_offset; } if (ret & BDRV_BLOCK_RAW) { assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file); ret = bdrv_co_do_block_status(local_file, want_zero, local_map, *pnum, pnum, &local_map, &local_file); goto out; } if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) { ret |= BDRV_BLOCK_ALLOCATED; } else if (bs->drv->supports_backing) { BlockDriverState *cow_bs = bdrv_cow_bs(bs); if (!cow_bs) { ret |= BDRV_BLOCK_ZERO; } else if (want_zero) { int64_t size2 = bdrv_co_getlength(cow_bs); if (size2 >= 0 && offset >= size2) { ret |= BDRV_BLOCK_ZERO; } } } if (want_zero && ret & BDRV_BLOCK_RECURSE && local_file && local_file != bs && (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && (ret & BDRV_BLOCK_OFFSET_VALID)) { int64_t file_pnum; int ret2; ret2 = bdrv_co_do_block_status(local_file, want_zero, local_map, *pnum, &file_pnum, NULL, NULL); if (ret2 >= 0) { /* Ignore errors. This is just providing extra information, it * is useful but not necessary. */ if (ret2 & BDRV_BLOCK_EOF && (!file_pnum || ret2 & BDRV_BLOCK_ZERO)) { /* * It is valid for the format block driver to read * beyond the end of the underlying file's current * size; such areas read as zero. */ ret |= BDRV_BLOCK_ZERO; } else { /* Limit request to the range reported by the protocol driver */ *pnum = file_pnum; ret |= (ret2 & BDRV_BLOCK_ZERO); } } /* * Now that the recursive search was done, clear the flag. Otherwise, * with more complicated block graphs like snapshot-access -> * copy-before-write -> qcow2, where the return value will be propagated * further up to a parent bdrv_co_do_block_status() call, both the * BDRV_BLOCK_RECURSE and BDRV_BLOCK_ZERO flags would be set, which is * not allowed. */ ret &= ~BDRV_BLOCK_RECURSE; } out: bdrv_dec_in_flight(bs); if (ret >= 0 && offset + *pnum == total_size) { ret |= BDRV_BLOCK_EOF; } early_out: if (file) { *file = local_file; } if (map) { *map = local_map; } return ret; } int coroutine_fn bdrv_co_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, bool include_base, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file, int *depth) { int ret; BlockDriverState *p; int64_t eof = 0; int dummy; IO_CODE(); assert(!include_base || base); /* Can't include NULL base */ assert_bdrv_graph_readable(); if (!depth) { depth = &dummy; } *depth = 0; if (!include_base && bs == base) { *pnum = bytes; return 0; } ret = bdrv_co_do_block_status(bs, want_zero, offset, bytes, pnum, map, file); ++*depth; if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) { return ret; } if (ret & BDRV_BLOCK_EOF) { eof = offset + *pnum; } assert(*pnum <= bytes); bytes = *pnum; for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base; p = bdrv_filter_or_cow_bs(p)) { ret = bdrv_co_do_block_status(p, want_zero, offset, bytes, pnum, map, file); ++*depth; if (ret < 0) { return ret; } if (*pnum == 0) { /* * The top layer deferred to this layer, and because this layer is * short, any zeroes that we synthesize beyond EOF behave as if they * were allocated at this layer. * * We don't include BDRV_BLOCK_EOF into ret, as upper layer may be * larger. We'll add BDRV_BLOCK_EOF if needed at function end, see * below. */ assert(ret & BDRV_BLOCK_EOF); *pnum = bytes; if (file) { *file = p; } ret = BDRV_BLOCK_ZERO | BDRV_BLOCK_ALLOCATED; break; } if (ret & BDRV_BLOCK_ALLOCATED) { /* * We've found the node and the status, we must break. * * Drop BDRV_BLOCK_EOF, as it's not for upper layer, which may be * larger. We'll add BDRV_BLOCK_EOF if needed at function end, see * below. */ ret &= ~BDRV_BLOCK_EOF; break; } if (p == base) { assert(include_base); break; } /* * OK, [offset, offset + *pnum) region is unallocated on this layer, * let's continue the diving. */ assert(*pnum <= bytes); bytes = *pnum; } if (offset + *pnum == eof) { ret |= BDRV_BLOCK_EOF; } return ret; } int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { IO_CODE(); return bdrv_co_common_block_status_above(bs, base, false, true, offset, bytes, pnum, map, file, NULL); } int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { IO_CODE(); return bdrv_co_block_status_above(bs, bdrv_filter_or_cow_bs(bs), offset, bytes, pnum, map, file); } /* * Check @bs (and its backing chain) to see if the range defined * by @offset and @bytes is known to read as zeroes. * Return 1 if that is the case, 0 otherwise and -errno on error. * This test is meant to be fast rather than accurate so returning 0 * does not guarantee non-zero data. */ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes) { int ret; int64_t pnum = bytes; IO_CODE(); if (!bytes) { return 1; } ret = bdrv_co_common_block_status_above(bs, NULL, false, false, offset, bytes, &pnum, NULL, NULL, NULL); if (ret < 0) { return ret; } return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO); } int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum) { int ret; int64_t dummy; IO_CODE(); ret = bdrv_co_common_block_status_above(bs, bs, true, false, offset, bytes, pnum ? pnum : &dummy, NULL, NULL, NULL); if (ret < 0) { return ret; } return !!(ret & BDRV_BLOCK_ALLOCATED); } /* * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP] * * Return a positive depth if (a prefix of) the given range is allocated * in any image between BASE and TOP (BASE is only included if include_base * is set). Depth 1 is TOP, 2 is the first backing layer, and so forth. * BASE can be NULL to check if the given offset is allocated in any * image of the chain. Return 0 otherwise, or negative errno on * failure. * * 'pnum' is set to the number of bytes (including and immediately * following the specified offset) that are known to be in the same * allocated/unallocated state. Note that a subsequent call starting * at 'offset + *pnum' may return the same allocation status (in other * words, the result is not necessarily the maximum possible range); * but 'pnum' will only be 0 when end of file is reached. */ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *bs, BlockDriverState *base, bool include_base, int64_t offset, int64_t bytes, int64_t *pnum) { int depth; int ret; IO_CODE(); ret = bdrv_co_common_block_status_above(bs, base, include_base, false, offset, bytes, pnum, NULL, NULL, &depth); if (ret < 0) { return ret; } if (ret & BDRV_BLOCK_ALLOCATED) { return depth; } return 0; } int coroutine_fn bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { BlockDriver *drv = bs->drv; BlockDriverState *child_bs = bdrv_primary_bs(bs); int ret; IO_CODE(); assert_bdrv_graph_readable(); ret = bdrv_check_qiov_request(pos, qiov->size, qiov, 0, NULL); if (ret < 0) { return ret; } if (!drv) { return -ENOMEDIUM; } bdrv_inc_in_flight(bs); if (drv->bdrv_co_load_vmstate) { ret = drv->bdrv_co_load_vmstate(bs, qiov, pos); } else if (child_bs) { ret = bdrv_co_readv_vmstate(child_bs, qiov, pos); } else { ret = -ENOTSUP; } bdrv_dec_in_flight(bs); return ret; } int coroutine_fn bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { BlockDriver *drv = bs->drv; BlockDriverState *child_bs = bdrv_primary_bs(bs); int ret; IO_CODE(); assert_bdrv_graph_readable(); ret = bdrv_check_qiov_request(pos, qiov->size, qiov, 0, NULL); if (ret < 0) { return ret; } if (!drv) { return -ENOMEDIUM; } bdrv_inc_in_flight(bs); if (drv->bdrv_co_save_vmstate) { ret = drv->bdrv_co_save_vmstate(bs, qiov, pos); } else if (child_bs) { ret = bdrv_co_writev_vmstate(child_bs, qiov, pos); } else { ret = -ENOTSUP; } bdrv_dec_in_flight(bs); return ret; } int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size) { QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size); int ret = bdrv_writev_vmstate(bs, &qiov, pos); IO_CODE(); return ret < 0 ? ret : size; } int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size) { QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size); int ret = bdrv_readv_vmstate(bs, &qiov, pos); IO_CODE(); return ret < 0 ? ret : size; } /**************************************************************/ /* async I/Os */ /** * Synchronously cancels an acb. Must be called with the BQL held and the acb * must be processed with the BQL held too (IOThreads are not allowed). * * Use bdrv_aio_cancel_async() instead when possible. */ void bdrv_aio_cancel(BlockAIOCB *acb) { GLOBAL_STATE_CODE(); qemu_aio_ref(acb); bdrv_aio_cancel_async(acb); AIO_WAIT_WHILE_UNLOCKED(NULL, acb->refcnt > 1); qemu_aio_unref(acb); } /* Async version of aio cancel. The caller is not blocked if the acb implements * cancel_async, otherwise we do nothing and let the request normally complete. * In either case the completion callback must be called. */ void bdrv_aio_cancel_async(BlockAIOCB *acb) { IO_CODE(); if (acb->aiocb_info->cancel_async) { acb->aiocb_info->cancel_async(acb); } } /**************************************************************/ /* Coroutine block device emulation */ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) { BdrvChild *primary_child = bdrv_primary_child(bs); BdrvChild *child; int current_gen; int ret = 0; IO_CODE(); assert_bdrv_graph_readable(); bdrv_inc_in_flight(bs); if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) || bdrv_is_sg(bs)) { goto early_exit; } qemu_mutex_lock(&bs->reqs_lock); current_gen = qatomic_read(&bs->write_gen); /* Wait until any previous flushes are completed */ while (bs->active_flush_req) { qemu_co_queue_wait(&bs->flush_queue, &bs->reqs_lock); } /* Flushes reach this point in nondecreasing current_gen order. */ bs->active_flush_req = true; qemu_mutex_unlock(&bs->reqs_lock); /* Write back all layers by calling one driver function */ if (bs->drv->bdrv_co_flush) { ret = bs->drv->bdrv_co_flush(bs); goto out; } /* Write back cached data to the OS even with cache=unsafe */ BLKDBG_CO_EVENT(primary_child, BLKDBG_FLUSH_TO_OS); if (bs->drv->bdrv_co_flush_to_os) { ret = bs->drv->bdrv_co_flush_to_os(bs); if (ret < 0) { goto out; } } /* But don't actually force it to the disk with cache=unsafe */ if (bs->open_flags & BDRV_O_NO_FLUSH) { goto flush_children; } /* Check if we really need to flush anything */ if (bs->flushed_gen == current_gen) { goto flush_children; } BLKDBG_CO_EVENT(primary_child, BLKDBG_FLUSH_TO_DISK); if (!bs->drv) { /* bs->drv->bdrv_co_flush() might have ejected the BDS * (even in case of apparent success) */ ret = -ENOMEDIUM; goto out; } if (bs->drv->bdrv_co_flush_to_disk) { ret = bs->drv->bdrv_co_flush_to_disk(bs); } else if (bs->drv->bdrv_aio_flush) { BlockAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; acb = bs->drv->bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); if (acb == NULL) { ret = -EIO; } else { qemu_coroutine_yield(); ret = co.ret; } } else { /* * Some block drivers always operate in either writethrough or unsafe * mode and don't support bdrv_flush therefore. Usually qemu doesn't * know how the server works (because the behaviour is hardcoded or * depends on server-side configuration), so we can't ensure that * everything is safe on disk. Returning an error doesn't work because * that would break guests even if the server operates in writethrough * mode. * * Let's hope the user knows what he's doing. */ ret = 0; } if (ret < 0) { goto out; } /* Now flush the underlying protocol. It will also have BDRV_O_NO_FLUSH * in the case of cache=unsafe, so there are no useless flushes. */ flush_children: ret = 0; QLIST_FOREACH(child, &bs->children, next) { if (child->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) { int this_child_ret = bdrv_co_flush(child->bs); if (!ret) { ret = this_child_ret; } } } out: /* Notify any pending flushes that we have completed */ if (ret == 0) { bs->flushed_gen = current_gen; } qemu_mutex_lock(&bs->reqs_lock); bs->active_flush_req = false; /* Return value is ignored - it's ok if wait queue is empty */ qemu_co_queue_next(&bs->flush_queue); qemu_mutex_unlock(&bs->reqs_lock); early_exit: bdrv_dec_in_flight(bs); return ret; } int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes) { BdrvTrackedRequest req; int ret; int64_t max_pdiscard; int head, tail, align; BlockDriverState *bs = child->bs; IO_CODE(); assert_bdrv_graph_readable(); if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) { return -ENOMEDIUM; } if (bdrv_has_readonly_bitmaps(bs)) { return -EPERM; } ret = bdrv_check_request(offset, bytes, NULL); if (ret < 0) { return ret; } /* Do nothing if disabled. */ if (!(bs->open_flags & BDRV_O_UNMAP)) { return 0; } if (!bs->drv->bdrv_co_pdiscard && !bs->drv->bdrv_aio_pdiscard) { return 0; } /* Invalidate the cached block-status data range if this discard overlaps */ bdrv_bsc_invalidate_range(bs, offset, bytes); /* Discard is advisory, but some devices track and coalesce * unaligned requests, so we must pass everything down rather than * round here. Still, most devices will just silently ignore * unaligned requests (by returning -ENOTSUP), so we must fragment * the request accordingly. */ align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment); assert(align % bs->bl.request_alignment == 0); head = offset % align; tail = (offset + bytes) % align; bdrv_inc_in_flight(bs); tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_DISCARD); ret = bdrv_co_write_req_prepare(child, offset, bytes, &req, 0); if (ret < 0) { goto out; } max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT64_MAX), align); assert(max_pdiscard >= bs->bl.request_alignment); while (bytes > 0) { int64_t num = bytes; if (head) { /* Make small requests to get to alignment boundaries. */ num = MIN(bytes, align - head); if (!QEMU_IS_ALIGNED(num, bs->bl.request_alignment)) { num %= bs->bl.request_alignment; } head = (head + num) % align; assert(num < max_pdiscard); } else if (tail) { if (num > align) { /* Shorten the request to the last aligned cluster. */ num -= tail; } else if (!QEMU_IS_ALIGNED(tail, bs->bl.request_alignment) && tail > bs->bl.request_alignment) { tail %= bs->bl.request_alignment; num -= tail; } } /* limit request size */ if (num > max_pdiscard) { num = max_pdiscard; } if (!bs->drv) { ret = -ENOMEDIUM; goto out; } if (bs->drv->bdrv_co_pdiscard) { ret = bs->drv->bdrv_co_pdiscard(bs, offset, num); } else { BlockAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; acb = bs->drv->bdrv_aio_pdiscard(bs, offset, num, bdrv_co_io_em_complete, &co); if (acb == NULL) { ret = -EIO; goto out; } else { qemu_coroutine_yield(); ret = co.ret; } } if (ret && ret != -ENOTSUP) { goto out; } offset += num; bytes -= num; } ret = 0; out: bdrv_co_write_req_finish(child, req.offset, req.bytes, &req, ret); tracked_request_end(&req); bdrv_dec_in_flight(bs); return ret; } int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf) { BlockDriver *drv = bs->drv; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; BlockAIOCB *acb; IO_CODE(); assert_bdrv_graph_readable(); bdrv_inc_in_flight(bs); if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) { co.ret = -ENOTSUP; goto out; } if (drv->bdrv_co_ioctl) { co.ret = drv->bdrv_co_ioctl(bs, req, buf); } else { acb = drv->bdrv_aio_ioctl(bs, req, buf, bdrv_co_io_em_complete, &co); if (!acb) { co.ret = -ENOTSUP; goto out; } qemu_coroutine_yield(); } out: bdrv_dec_in_flight(bs); return co.ret; } int coroutine_fn bdrv_co_zone_report(BlockDriverState *bs, int64_t offset, unsigned int *nr_zones, BlockZoneDescriptor *zones) { BlockDriver *drv = bs->drv; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; IO_CODE(); bdrv_inc_in_flight(bs); if (!drv || !drv->bdrv_co_zone_report || bs->bl.zoned == BLK_Z_NONE) { co.ret = -ENOTSUP; goto out; } co.ret = drv->bdrv_co_zone_report(bs, offset, nr_zones, zones); out: bdrv_dec_in_flight(bs); return co.ret; } int coroutine_fn bdrv_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, int64_t offset, int64_t len) { BlockDriver *drv = bs->drv; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; IO_CODE(); bdrv_inc_in_flight(bs); if (!drv || !drv->bdrv_co_zone_mgmt || bs->bl.zoned == BLK_Z_NONE) { co.ret = -ENOTSUP; goto out; } co.ret = drv->bdrv_co_zone_mgmt(bs, op, offset, len); out: bdrv_dec_in_flight(bs); return co.ret; } int coroutine_fn bdrv_co_zone_append(BlockDriverState *bs, int64_t *offset, QEMUIOVector *qiov, BdrvRequestFlags flags) { int ret; BlockDriver *drv = bs->drv; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; IO_CODE(); ret = bdrv_check_qiov_request(*offset, qiov->size, qiov, 0, NULL); if (ret < 0) { return ret; } bdrv_inc_in_flight(bs); if (!drv || !drv->bdrv_co_zone_append || bs->bl.zoned == BLK_Z_NONE) { co.ret = -ENOTSUP; goto out; } co.ret = drv->bdrv_co_zone_append(bs, offset, qiov, flags); out: bdrv_dec_in_flight(bs); return co.ret; } void *qemu_blockalign(BlockDriverState *bs, size_t size) { IO_CODE(); return qemu_memalign(bdrv_opt_mem_align(bs), size); } void *qemu_blockalign0(BlockDriverState *bs, size_t size) { IO_CODE(); return memset(qemu_blockalign(bs, size), 0, size); } void *qemu_try_blockalign(BlockDriverState *bs, size_t size) { size_t align = bdrv_opt_mem_align(bs); IO_CODE(); /* Ensure that NULL is never returned on success */ assert(align > 0); if (size == 0) { size = align; } return qemu_try_memalign(align, size); } void *qemu_try_blockalign0(BlockDriverState *bs, size_t size) { void *mem = qemu_try_blockalign(bs, size); IO_CODE(); if (mem) { memset(mem, 0, size); } return mem; } /* Helper that undoes bdrv_register_buf() when it fails partway through */ static void GRAPH_RDLOCK bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size, BdrvChild *final_child) { BdrvChild *child; GLOBAL_STATE_CODE(); assert_bdrv_graph_readable(); QLIST_FOREACH(child, &bs->children, next) { if (child == final_child) { break; } bdrv_unregister_buf(child->bs, host, size); } if (bs->drv && bs->drv->bdrv_unregister_buf) { bs->drv->bdrv_unregister_buf(bs, host, size); } } bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size, Error **errp) { BdrvChild *child; GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); if (bs->drv && bs->drv->bdrv_register_buf) { if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) { return false; } } QLIST_FOREACH(child, &bs->children, next) { if (!bdrv_register_buf(child->bs, host, size, errp)) { bdrv_register_buf_rollback(bs, host, size, child); return false; } } return true; } void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size) { BdrvChild *child; GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); if (bs->drv && bs->drv->bdrv_unregister_buf) { bs->drv->bdrv_unregister_buf(bs, host, size); } QLIST_FOREACH(child, &bs->children, next) { bdrv_unregister_buf(child->bs, host, size); } } static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal( BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags, bool recurse_src) { BdrvTrackedRequest req; int ret; assert_bdrv_graph_readable(); /* TODO We can support BDRV_REQ_NO_FALLBACK here */ assert(!(read_flags & BDRV_REQ_NO_FALLBACK)); assert(!(write_flags & BDRV_REQ_NO_FALLBACK)); assert(!(read_flags & BDRV_REQ_NO_WAIT)); assert(!(write_flags & BDRV_REQ_NO_WAIT)); if (!dst || !dst->bs || !bdrv_co_is_inserted(dst->bs)) { return -ENOMEDIUM; } ret = bdrv_check_request32(dst_offset, bytes, NULL, 0); if (ret) { return ret; } if (write_flags & BDRV_REQ_ZERO_WRITE) { return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags); } if (!src || !src->bs || !bdrv_co_is_inserted(src->bs)) { return -ENOMEDIUM; } ret = bdrv_check_request32(src_offset, bytes, NULL, 0); if (ret) { return ret; } if (!src->bs->drv->bdrv_co_copy_range_from || !dst->bs->drv->bdrv_co_copy_range_to || src->bs->encrypted || dst->bs->encrypted) { return -ENOTSUP; } if (recurse_src) { bdrv_inc_in_flight(src->bs); tracked_request_begin(&req, src->bs, src_offset, bytes, BDRV_TRACKED_READ); /* BDRV_REQ_SERIALISING is only for write operation */ assert(!(read_flags & BDRV_REQ_SERIALISING)); bdrv_wait_serialising_requests(&req); ret = src->bs->drv->bdrv_co_copy_range_from(src->bs, src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); tracked_request_end(&req); bdrv_dec_in_flight(src->bs); } else { bdrv_inc_in_flight(dst->bs); tracked_request_begin(&req, dst->bs, dst_offset, bytes, BDRV_TRACKED_WRITE); ret = bdrv_co_write_req_prepare(dst, dst_offset, bytes, &req, write_flags); if (!ret) { ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs, src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); } bdrv_co_write_req_finish(dst, dst_offset, bytes, &req, ret); tracked_request_end(&req); bdrv_dec_in_flight(dst->bs); } return ret; } /* Copy range from @src to @dst. * * See the comment of bdrv_co_copy_range for the parameter and return value * semantics. */ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags) { IO_CODE(); assert_bdrv_graph_readable(); trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags, true); } /* Copy range from @src to @dst. * * See the comment of bdrv_co_copy_range for the parameter and return value * semantics. */ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags) { IO_CODE(); assert_bdrv_graph_readable(); trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags, false); } int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags) { IO_CODE(); assert_bdrv_graph_readable(); return bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); } static void coroutine_fn GRAPH_RDLOCK bdrv_parent_cb_resize(BlockDriverState *bs) { BdrvChild *c; assert_bdrv_graph_readable(); QLIST_FOREACH(c, &bs->parents, next_parent) { if (c->klass->resize) { c->klass->resize(c); } } } /** * Truncate file to 'offset' bytes (needed only for file protocols) * * If 'exact' is true, the file must be resized to exactly the given * 'offset'. Otherwise, it is sufficient for the node to be at least * 'offset' bytes in length. */ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) { BlockDriverState *bs = child->bs; BdrvChild *filtered, *backing; BlockDriver *drv = bs->drv; BdrvTrackedRequest req; int64_t old_size, new_bytes; int ret; IO_CODE(); assert_bdrv_graph_readable(); /* if bs->drv == NULL, bs is closed, so there's nothing to do here */ if (!drv) { error_setg(errp, "No medium inserted"); return -ENOMEDIUM; } if (offset < 0) { error_setg(errp, "Image size cannot be negative"); return -EINVAL; } ret = bdrv_check_request(offset, 0, errp); if (ret < 0) { return ret; } old_size = bdrv_co_getlength(bs); if (old_size < 0) { error_setg_errno(errp, -old_size, "Failed to get old image size"); return old_size; } if (bdrv_is_read_only(bs)) { error_setg(errp, "Image is read-only"); return -EACCES; } if (offset > old_size) { new_bytes = offset - old_size; } else { new_bytes = 0; } bdrv_inc_in_flight(bs); tracked_request_begin(&req, bs, offset - new_bytes, new_bytes, BDRV_TRACKED_TRUNCATE); /* If we are growing the image and potentially using preallocation for the * new area, we need to make sure that no write requests are made to it * concurrently or they might be overwritten by preallocation. */ if (new_bytes) { bdrv_make_request_serialising(&req, 1); } ret = bdrv_co_write_req_prepare(child, offset - new_bytes, new_bytes, &req, 0); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to prepare request for truncation"); goto out; } filtered = bdrv_filter_child(bs); backing = bdrv_cow_child(bs); /* * If the image has a backing file that is large enough that it would * provide data for the new area, we cannot leave it unallocated because * then the backing file content would become visible. Instead, zero-fill * the new area. * * Note that if the image has a backing file, but was opened without the * backing file, taking care of keeping things consistent with that backing * file is the user's responsibility. */ if (new_bytes && backing) { int64_t backing_len; backing_len = bdrv_co_getlength(backing->bs); if (backing_len < 0) { ret = backing_len; error_setg_errno(errp, -ret, "Could not get backing file size"); goto out; } if (backing_len > old_size) { flags |= BDRV_REQ_ZERO_WRITE; } } if (drv->bdrv_co_truncate) { if (flags & ~bs->supported_truncate_flags) { error_setg(errp, "Block driver does not support requested flags"); ret = -ENOTSUP; goto out; } ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp); } else if (filtered) { ret = bdrv_co_truncate(filtered, offset, exact, prealloc, flags, errp); } else { error_setg(errp, "Image format driver does not support resize"); ret = -ENOTSUP; goto out; } if (ret < 0) { goto out; } ret = bdrv_co_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); if (ret < 0) { error_setg_errno(errp, -ret, "Could not refresh total sector count"); } else { offset = bs->total_sectors * BDRV_SECTOR_SIZE; } /* * It's possible that truncation succeeded but bdrv_refresh_total_sectors * failed, but the latter doesn't affect how we should finish the request. * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */ bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0); out: tracked_request_end(&req); bdrv_dec_in_flight(bs); return ret; } void bdrv_cancel_in_flight(BlockDriverState *bs) { GLOBAL_STATE_CODE(); GRAPH_RDLOCK_GUARD_MAINLOOP(); if (!bs || !bs->drv) { return; } if (bs->drv->bdrv_cancel_in_flight) { bs->drv->bdrv_cancel_in_flight(bs); } } int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) { BlockDriverState *bs = child->bs; BlockDriver *drv = bs->drv; int ret; IO_CODE(); assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; } if (!drv->bdrv_co_preadv_snapshot) { return -ENOTSUP; } bdrv_inc_in_flight(bs); ret = drv->bdrv_co_preadv_snapshot(bs, offset, bytes, qiov, qiov_offset); bdrv_dec_in_flight(bs); return ret; } int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { BlockDriver *drv = bs->drv; int ret; IO_CODE(); assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; } if (!drv->bdrv_co_snapshot_block_status) { return -ENOTSUP; } bdrv_inc_in_flight(bs); ret = drv->bdrv_co_snapshot_block_status(bs, want_zero, offset, bytes, pnum, map, file); bdrv_dec_in_flight(bs); return ret; } int coroutine_fn bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes) { BlockDriver *drv = bs->drv; int ret; IO_CODE(); assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; } if (!drv->bdrv_co_pdiscard_snapshot) { return -ENOTSUP; } bdrv_inc_in_flight(bs); ret = drv->bdrv_co_pdiscard_snapshot(bs, offset, bytes); bdrv_dec_in_flight(bs); return ret; }