| /* | |
| * 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 "system/block-backend.h" | |
| #include "qemu/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 "system/replay.h" | |
| #include "qemu/units.h" | |
| #include "qemu/atomic.h" | |
| /* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */ | |
| #define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS) | |
| /* Maximum read size for checking if data reads as zero, in bytes */ | |
| #define MAX_ZERO_CHECK_BUFFER (128 * KiB) | |
| static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, | |
| int64_t offset, int64_t bytes, BdrvRequestFlags flags); | |
| static void coroutine_fn | |
| bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self); | |
| 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) { | |
| 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); | |
| } | |
| } 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(); | |
| /* 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); | |
| } | |
| 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); | |
| } | |
| 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 (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) | |
| { | |
| 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); | |
| /* Re-enable things in child-to-parent order */ | |
| if (--bs->quiesce_counter == 0) { | |
| 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 hold the BQL, | |
| * so iterating bdrv_next_all_states() is safe. | |
| */ | |
| while ((bs = bdrv_next_all_states(bs))) { | |
| result |= bdrv_drain_poll(bs, NULL, true); | |
| } | |
| 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))) { | |
| bdrv_do_drained_begin(bs, NULL, false); | |
| } | |
| } | |
| 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))) { | |
| bdrv_do_drained_end(bs, NULL); | |
| } | |
| 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, | |
| .active_owner = 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); | |
| /* | |
| * Set .waiting_for while we're holding the lock, otherwise we'd open a race | |
| * window where another request in the middle of its RMW cycle starts | |
| * waiting for us, leading to potential data corruption if this request | |
| * overwrites a block the RMW request has already read. | |
| */ | |
| bdrv_wait_serialising_requests_locked(req); | |
| 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))) { | |
| /* | |
| * If this request is the active owner of the data blocks it accesses, | |
| * no other conflicting request may exist; other requests have to wait | |
| * for this one, not the other way around. If this condition is | |
| * violated, RMW operations may be interrupted in the middle, operate on | |
| * stale data and introduce data corruption. | |
| */ | |
| assert(!self->active_owner); | |
| 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(); | |
| QEMU_LOCK_GUARD(&bs->reqs_lock); | |
| 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); | |
| } | |
| 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); | |
| req->active_owner = true; | |
| 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 (bs->open_flags & BDRV_O_NO_FLUSH) { | |
| flags &= ~BDRV_REQ_FUA; | |
| } | |
| 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)); | |
| } | |
| 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; | |
| } | |
| /* | |
| * For prefetching in stream_populate(), no qiov is passed along, because | |
| * only copy-on-read matters. | |
| */ | |
| if (*qiov) { | |
| 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; | |
| } | |
| *qiov = &pad->local_qiov; | |
| *qiov_offset = 0; | |
| } | |
| *bytes += pad->head + pad->tail; | |
| *offset -= pad->head; | |
| 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; | |
| } | |
| /* If opened with discard=off we should never unmap. */ | |
| if (!(bs->open_flags & BDRV_O_UNMAP)) { | |
| flags &= ~BDRV_REQ_MAY_UNMAP; | |
| } | |
| /* 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); | |
| } | |
| /* | |
| * TODO The ret == -EINVAL && num < alignment case is a workaround for | |
| * when request_alignment is 1 on files with cache=writeback. The Linux | |
| * ioctl(BLKZEROOUT) requires block alignment and will fail with | |
| * EINVAL. The block layer should align the request to | |
| * write_zeroes_alignment instead of trying the syscall, failing, and | |
| * falling back to a bounce buffer. Doing that is not easy so for now | |
| * we use a bounce buffer: | |
| * https://lore.kernel.org/qemu-devel/20260109120837.2772961-1-f.ebner@proxmox.com/ | |
| */ | |
| if ((ret == -ENOTSUP || (ret == -EINVAL && num < alignment)) && | |
| !(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); | |
| } | |
| 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_co_parent_cb_resize(bs); | |
| bdrv_dirty_bitmap_truncate(bs, end_sector << BDRV_SECTOR_BITS); | |
| } | |
| if (req->bytes) { | |
| switch (req->type) { | |
| case BDRV_TRACKED_WRITE: | |
| { | |
| uint64_t new = offset + bytes; | |
| uint64_t old = qatomic_read(&bs->wr_highest_offset); | |
| while (old < new) { | |
| old = qatomic_cmpxchg(&bs->wr_highest_offset, old, new); | |
| } | |
| } | |
| /* 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(); | |
| 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)) { | |
| int ret = bdrv_flush(bs); | |
| if (ret < 0 && !result) { | |
| result = ret; | |
| } | |
| } | |
| 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. | |
| * | |
| * 'mode' serves as a hint as to which results are favored; see the | |
| * BDRV_WANT_* macros for details. | |
| * | |
| * 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, unsigned int mode, | |
| 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, mode, 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 mode, because we only want to update the cache when we | |
| * have accurate information about what is zero and what is data. | |
| */ | |
| if (mode == BDRV_WANT_PRECISE && | |
| 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, mode, 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 (mode == BDRV_WANT_PRECISE) { | |
| int64_t size2 = bdrv_co_getlength(cow_bs); | |
| if (size2 >= 0 && offset >= size2) { | |
| ret |= BDRV_BLOCK_ZERO; | |
| } | |
| } | |
| } | |
| if (mode == BDRV_WANT_PRECISE && 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, mode, 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, | |
| unsigned int mode, | |
| 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, mode, 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, mode, 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, | |
| BDRV_WANT_PRECISE, 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; but a return of 1 is reliable. | |
| */ | |
| int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, | |
| int64_t bytes) | |
| { | |
| int ret; | |
| int64_t pnum; | |
| IO_CODE(); | |
| while (bytes) { | |
| ret = bdrv_co_common_block_status_above(bs, NULL, false, | |
| BDRV_WANT_ZERO, offset, bytes, | |
| &pnum, NULL, NULL, NULL); | |
| if (ret < 0) { | |
| return ret; | |
| } | |
| if (!(ret & BDRV_BLOCK_ZERO)) { | |
| return 0; | |
| } | |
| offset += pnum; | |
| bytes -= pnum; | |
| } | |
| return 1; | |
| } | |
| /* | |
| * Check @bs (and its backing chain) to see if the entire image 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; however, a return of 1 is reliable, | |
| * and this function can report 1 in more cases than bdrv_co_is_zero_fast. | |
| */ | |
| int coroutine_fn bdrv_co_is_all_zeroes(BlockDriverState *bs) | |
| { | |
| int ret; | |
| int64_t pnum, bytes; | |
| char *buf; | |
| QEMUIOVector local_qiov; | |
| IO_CODE(); | |
| bytes = bdrv_co_getlength(bs); | |
| if (bytes < 0) { | |
| return bytes; | |
| } | |
| /* First probe - see if the entire image reads as zero */ | |
| ret = bdrv_co_common_block_status_above(bs, NULL, false, BDRV_WANT_ZERO, | |
| 0, bytes, &pnum, NULL, NULL, | |
| NULL); | |
| if (ret < 0) { | |
| return ret; | |
| } | |
| if (ret & BDRV_BLOCK_ZERO) { | |
| return bdrv_co_is_zero_fast(bs, pnum, bytes - pnum); | |
| } | |
| /* | |
| * Because of the way 'blockdev-create' works, raw files tend to | |
| * be created with a non-sparse region at the front to make | |
| * alignment probing easier. If the block starts with only a | |
| * small allocated region, it is still worth the effort to see if | |
| * the rest of the image is still sparse, coupled with manually | |
| * reading the first region to see if it reads zero after all. | |
| */ | |
| if (pnum > MAX_ZERO_CHECK_BUFFER) { | |
| return 0; | |
| } | |
| ret = bdrv_co_is_zero_fast(bs, pnum, bytes - pnum); | |
| if (ret <= 0) { | |
| return ret; | |
| } | |
| /* Only the head of the image is unknown, and it's small. Read it. */ | |
| buf = qemu_blockalign(bs, pnum); | |
| qemu_iovec_init_buf(&local_qiov, buf, pnum); | |
| ret = bdrv_driver_preadv(bs, 0, pnum, &local_qiov, 0, 0); | |
| if (ret >= 0) { | |
| ret = buffer_is_zero(buf, pnum); | |
| } | |
| qemu_vfree(buf); | |
| return ret; | |
| } | |
| 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, BDRV_WANT_ALLOCATED, | |
| 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, | |
| BDRV_WANT_ALLOCATED, | |
| 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) { | |
| 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 reject unaligned requests with | |
| * -EINVAL or -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; | |
| } | |
| ret = bs->drv->bdrv_co_pdiscard(bs, offset, num); | |
| if (ret && ret != -ENOTSUP) { | |
| if (ret == -EINVAL && (offset % align != 0 || num % align != 0)) { | |
| /* Silently skip rejected unaligned head/tail requests */ | |
| } else { | |
| goto out; /* bail 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)); | |
| 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); | |
| } | |
| void coroutine_fn bdrv_co_parent_cb_resize(BlockDriverState *bs) | |
| { | |
| BdrvChild *c; | |
| IO_CODE(); | |
| 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, unsigned int mode, | |
| 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, mode, 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; | |
| } |