/* * block_copy API * * Copyright (C) 2013 Proxmox Server Solutions * Copyright (c) 2019 Virtuozzo International GmbH. * * Authors: * Dietmar Maurer (dietmar@proxmox.com) * Vladimir Sementsov-Ogievskiy * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ #ifndef BLOCK_COPY_H #define BLOCK_COPY_H #include "block/block.h" #include "qemu/co-shared-resource.h" typedef struct BlockCopyInFlightReq { int64_t start_byte; int64_t end_byte; QLIST_ENTRY(BlockCopyInFlightReq) list; CoQueue wait_queue; /* coroutines blocked on this request */ } BlockCopyInFlightReq; typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque); typedef void (*ProgressResetCallbackFunc)(void *opaque); typedef struct BlockCopyState { /* * BdrvChild objects are not owned or managed by block-copy. They are * provided by block-copy user and user is responsible for appropriate * permissions on these children. */ BdrvChild *source; BdrvChild *target; BdrvDirtyBitmap *copy_bitmap; int64_t cluster_size; bool use_copy_range; int64_t copy_size; uint64_t len; QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs; BdrvRequestFlags write_flags; /* * skip_unallocated: * * Used by sync=top jobs, which first scan the source node for unallocated * areas and clear them in the copy_bitmap. During this process, the bitmap * is thus not fully initialized: It may still have bits set for areas that * are unallocated and should actually not be copied. * * This is indicated by skip_unallocated. * * In this case, block_copy() will query the source’s allocation status, * skip unallocated regions, clear them in the copy_bitmap, and invoke * block_copy_reset_unallocated() every time it does. */ bool skip_unallocated; /* progress_bytes_callback: called when some copying progress is done. */ ProgressBytesCallbackFunc progress_bytes_callback; /* * progress_reset_callback: called when some bytes reset from copy_bitmap * (see @skip_unallocated above). The callee is assumed to recalculate how * many bytes remain based on the dirty bit count of copy_bitmap. */ ProgressResetCallbackFunc progress_reset_callback; void *progress_opaque; SharedResource *mem; } BlockCopyState; BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target, int64_t cluster_size, BdrvRequestFlags write_flags, Error **errp); void block_copy_set_callbacks( BlockCopyState *s, ProgressBytesCallbackFunc progress_bytes_callback, ProgressResetCallbackFunc progress_reset_callback, void *progress_opaque); void block_copy_state_free(BlockCopyState *s); int64_t block_copy_reset_unallocated(BlockCopyState *s, int64_t offset, int64_t *count); int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes, bool *error_is_read); #endif /* BLOCK_COPY_H */