Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
commit
cf256aa081
11315 files changed
+3598369
No files matched your search
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* QEMU System Emulator block accounting
|
||||
*
|
||||
* Copyright (c) 2011 Christoph Hellwig
|
||||
* Copyright (c) 2015 Igalia, S.L.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_ACCOUNTING_H
|
||||
#define BLOCK_ACCOUNTING_H
|
||||
|
||||
#include "qemu/timed-average.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qapi/qapi-types-common.h"
|
||||
|
||||
typedef struct BlockAcctTimedStats BlockAcctTimedStats;
|
||||
typedef struct BlockAcctStats BlockAcctStats;
|
||||
|
||||
enum BlockAcctType {
|
||||
BLOCK_ACCT_NONE = 0,
|
||||
BLOCK_ACCT_READ,
|
||||
BLOCK_ACCT_WRITE,
|
||||
BLOCK_ACCT_FLUSH,
|
||||
BLOCK_ACCT_ZONE_APPEND,
|
||||
BLOCK_ACCT_UNMAP,
|
||||
BLOCK_MAX_IOTYPE,
|
||||
};
|
||||
|
||||
struct BlockAcctTimedStats {
|
||||
BlockAcctStats *stats;
|
||||
TimedAverage latency[BLOCK_MAX_IOTYPE];
|
||||
unsigned interval_length; /* in seconds */
|
||||
QSLIST_ENTRY(BlockAcctTimedStats) entries;
|
||||
};
|
||||
|
||||
typedef struct BlockLatencyHistogram {
|
||||
/* The following histogram is represented like this:
|
||||
*
|
||||
* 5| *
|
||||
* 4| *
|
||||
* 3| * *
|
||||
* 2| * * *
|
||||
* 1| * * * *
|
||||
* +------------------
|
||||
* 10 50 100
|
||||
*
|
||||
* BlockLatencyHistogram histogram = {
|
||||
* .nbins = 4,
|
||||
* .boundaries = {10, 50, 100},
|
||||
* .bins = {3, 1, 5, 2},
|
||||
* };
|
||||
*
|
||||
* @boundaries array define histogram intervals as follows:
|
||||
* [0, boundaries[0]), [boundaries[0], boundaries[1]), ...
|
||||
* [boundaries[nbins-2], +inf)
|
||||
*
|
||||
* So, for example above, histogram intervals are:
|
||||
* [0, 10), [10, 50), [50, 100), [100, +inf)
|
||||
*/
|
||||
int nbins;
|
||||
uint64_t *boundaries; /* @nbins-1 numbers here
|
||||
(all boundaries, except 0 and +inf) */
|
||||
uint64_t *bins;
|
||||
} BlockLatencyHistogram;
|
||||
|
||||
struct BlockAcctStats {
|
||||
QemuMutex lock;
|
||||
uint64_t nr_bytes[BLOCK_MAX_IOTYPE];
|
||||
uint64_t nr_ops[BLOCK_MAX_IOTYPE];
|
||||
uint64_t invalid_ops[BLOCK_MAX_IOTYPE];
|
||||
uint64_t failed_ops[BLOCK_MAX_IOTYPE];
|
||||
uint64_t total_time_ns[BLOCK_MAX_IOTYPE];
|
||||
uint64_t merged[BLOCK_MAX_IOTYPE];
|
||||
int64_t last_access_time_ns;
|
||||
QSLIST_HEAD(, BlockAcctTimedStats) intervals;
|
||||
bool account_invalid;
|
||||
bool account_failed;
|
||||
BlockLatencyHistogram latency_histogram[BLOCK_MAX_IOTYPE];
|
||||
};
|
||||
|
||||
typedef struct BlockAcctCookie {
|
||||
int64_t bytes;
|
||||
int64_t start_time_ns;
|
||||
enum BlockAcctType type;
|
||||
} BlockAcctCookie;
|
||||
|
||||
void block_acct_init(BlockAcctStats *stats);
|
||||
bool block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
|
||||
enum OnOffAuto account_failed, uint32_t *stats_intervals,
|
||||
uint32_t num_stats_intervals, Error **errp);
|
||||
void block_acct_cleanup(BlockAcctStats *stats);
|
||||
void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length);
|
||||
BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats,
|
||||
BlockAcctTimedStats *s);
|
||||
void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
|
||||
int64_t bytes, enum BlockAcctType type);
|
||||
void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie);
|
||||
void block_acct_failed(BlockAcctStats *stats, BlockAcctCookie *cookie);
|
||||
void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type);
|
||||
void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
|
||||
int num_requests);
|
||||
int64_t block_acct_idle_time_ns(BlockAcctStats *stats);
|
||||
/* Caller must hold stats->stats->lock. */
|
||||
double block_acct_queue_depth(BlockAcctTimedStats *stats,
|
||||
enum BlockAcctType type);
|
||||
int block_latency_histogram_set(BlockAcctStats *stats, enum BlockAcctType type,
|
||||
uint64List *boundaries);
|
||||
void block_latency_histograms_clear(BlockAcctStats *stats);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Aio tasks loops
|
||||
*
|
||||
* Copyright (c) 2019 Virtuozzo International GmbH.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_AIO_TASK_H
|
||||
#define BLOCK_AIO_TASK_H
|
||||
|
||||
typedef struct AioTaskPool AioTaskPool;
|
||||
typedef struct AioTask AioTask;
|
||||
typedef int coroutine_fn (*AioTaskFunc)(AioTask *task);
|
||||
struct AioTask {
|
||||
AioTaskPool *pool;
|
||||
AioTaskFunc func;
|
||||
int ret;
|
||||
};
|
||||
|
||||
AioTaskPool *coroutine_fn aio_task_pool_new(int max_busy_tasks);
|
||||
void aio_task_pool_free(AioTaskPool *);
|
||||
|
||||
/* error code of failed task or 0 if all is OK */
|
||||
int aio_task_pool_status(AioTaskPool *pool);
|
||||
|
||||
/* User provides filled @task, however task->pool will be set automatically */
|
||||
void coroutine_fn aio_task_pool_start_task(AioTaskPool *pool, AioTask *task);
|
||||
|
||||
void coroutine_fn aio_task_pool_wait_slot(AioTaskPool *pool);
|
||||
void coroutine_fn aio_task_pool_wait_one(AioTaskPool *pool);
|
||||
void coroutine_fn aio_task_pool_wait_all(AioTaskPool *pool);
|
||||
|
||||
#endif /* BLOCK_AIO_TASK_H */
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_COMMON_H
|
||||
#define BLOCK_COMMON_H
|
||||
|
||||
#include "qapi/qapi-types-block-core.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
/*
|
||||
* co_wrapper{*}: Function specifiers used by block-coroutine-wrapper.py
|
||||
*
|
||||
* Function specifiers, which do nothing but mark functions to be
|
||||
* generated by scripts/block-coroutine-wrapper.py
|
||||
*
|
||||
* Usage: read docs/devel/block-coroutine-wrapper.rst
|
||||
*
|
||||
* There are 4 kind of specifiers:
|
||||
* - co_wrapper functions can be called by only non-coroutine context, because
|
||||
* they always generate a new coroutine.
|
||||
* - co_wrapper_mixed functions can be called by both coroutine and
|
||||
* non-coroutine context.
|
||||
* - co_wrapper_bdrv_rdlock are co_wrapper functions but automatically take and
|
||||
* release the graph rdlock when creating a new coroutine
|
||||
* - co_wrapper_mixed_bdrv_rdlock are co_wrapper_mixed functions but
|
||||
* automatically take and release the graph rdlock when creating a new
|
||||
* coroutine.
|
||||
*
|
||||
* These functions should not be called from a coroutine_fn; instead,
|
||||
* call the wrapped function directly.
|
||||
*/
|
||||
#define co_wrapper no_coroutine_fn
|
||||
#define co_wrapper_mixed no_coroutine_fn coroutine_mixed_fn
|
||||
#define co_wrapper_bdrv_rdlock no_coroutine_fn
|
||||
#define co_wrapper_mixed_bdrv_rdlock no_coroutine_fn coroutine_mixed_fn
|
||||
|
||||
/*
|
||||
* no_co_wrapper: Function specifier used by block-coroutine-wrapper.py
|
||||
*
|
||||
* Function specifier which does nothing but mark functions to be generated by
|
||||
* scripts/block-coroutine-wrapper.py.
|
||||
*
|
||||
* A no_co_wrapper function declaration creates a coroutine_fn wrapper around
|
||||
* functions that must not be called in coroutine context. It achieves this by
|
||||
* scheduling a BH in the bottom half that runs the respective non-coroutine
|
||||
* function. The coroutine yields after scheduling the BH and is reentered when
|
||||
* the wrapped function returns.
|
||||
*
|
||||
* A no_co_wrapper_bdrv_rdlock function is a no_co_wrapper function that
|
||||
* automatically takes the graph rdlock when calling the wrapped function. In
|
||||
* the same way, no_co_wrapper_bdrv_wrlock functions automatically take the
|
||||
* graph wrlock.
|
||||
*/
|
||||
#define no_co_wrapper
|
||||
#define no_co_wrapper_bdrv_rdlock
|
||||
#define no_co_wrapper_bdrv_wrlock
|
||||
|
||||
#include "block/blockjob.h"
|
||||
|
||||
/* block.c */
|
||||
typedef struct BlockDriver BlockDriver;
|
||||
typedef struct BdrvChild BdrvChild;
|
||||
typedef struct BdrvChildClass BdrvChildClass;
|
||||
|
||||
typedef enum BlockZoneOp {
|
||||
BLK_ZO_OPEN,
|
||||
BLK_ZO_CLOSE,
|
||||
BLK_ZO_FINISH,
|
||||
BLK_ZO_RESET,
|
||||
} BlockZoneOp;
|
||||
|
||||
typedef enum BlockZoneModel {
|
||||
BLK_Z_NONE = 0x0, /* Regular block device */
|
||||
BLK_Z_HM = 0x1, /* Host-managed zoned block device */
|
||||
BLK_Z_HA = 0x2, /* Host-aware zoned block device */
|
||||
} BlockZoneModel;
|
||||
|
||||
typedef enum BlockZoneState {
|
||||
BLK_ZS_NOT_WP = 0x0,
|
||||
BLK_ZS_EMPTY = 0x1,
|
||||
BLK_ZS_IOPEN = 0x2,
|
||||
BLK_ZS_EOPEN = 0x3,
|
||||
BLK_ZS_CLOSED = 0x4,
|
||||
BLK_ZS_RDONLY = 0xD,
|
||||
BLK_ZS_FULL = 0xE,
|
||||
BLK_ZS_OFFLINE = 0xF,
|
||||
} BlockZoneState;
|
||||
|
||||
typedef enum BlockZoneType {
|
||||
BLK_ZT_CONV = 0x1, /* Conventional random writes supported */
|
||||
BLK_ZT_SWR = 0x2, /* Sequential writes required */
|
||||
BLK_ZT_SWP = 0x3, /* Sequential writes preferred */
|
||||
} BlockZoneType;
|
||||
|
||||
/*
|
||||
* Zone descriptor data structure.
|
||||
* Provides information on a zone with all position and size values in bytes.
|
||||
*/
|
||||
typedef struct BlockZoneDescriptor {
|
||||
uint64_t start;
|
||||
uint64_t length;
|
||||
uint64_t cap;
|
||||
uint64_t wp;
|
||||
BlockZoneType type;
|
||||
BlockZoneState state;
|
||||
} BlockZoneDescriptor;
|
||||
|
||||
/*
|
||||
* Track write pointers of a zone in bytes.
|
||||
*/
|
||||
typedef struct BlockZoneWps {
|
||||
CoMutex colock;
|
||||
uint64_t wp[];
|
||||
} BlockZoneWps;
|
||||
|
||||
typedef struct BlockDriverInfo {
|
||||
/* in bytes, 0 if irrelevant */
|
||||
int cluster_size;
|
||||
/*
|
||||
* A fraction of cluster_size, if supported (currently QCOW2 only); if
|
||||
* disabled or unsupported, set equal to cluster_size.
|
||||
*/
|
||||
int subcluster_size;
|
||||
/* offset at which the VM state can be saved (0 if not possible) */
|
||||
int64_t vm_state_offset;
|
||||
bool is_dirty;
|
||||
/*
|
||||
* True if this block driver only supports compressed writes
|
||||
*/
|
||||
bool needs_compressed_writes;
|
||||
} BlockDriverInfo;
|
||||
|
||||
typedef struct BlockFragInfo {
|
||||
uint64_t allocated_clusters;
|
||||
uint64_t total_clusters;
|
||||
uint64_t fragmented_clusters;
|
||||
uint64_t compressed_clusters;
|
||||
} BlockFragInfo;
|
||||
|
||||
typedef enum {
|
||||
BDRV_REQ_COPY_ON_READ = 0x1,
|
||||
BDRV_REQ_ZERO_WRITE = 0x2,
|
||||
|
||||
/*
|
||||
* The BDRV_REQ_MAY_UNMAP flag is used in write_zeroes requests to indicate
|
||||
* that the block driver should unmap (discard) blocks if it is guaranteed
|
||||
* that the result will read back as zeroes. The flag is only passed to the
|
||||
* driver if the block device is opened with BDRV_O_UNMAP.
|
||||
*/
|
||||
BDRV_REQ_MAY_UNMAP = 0x4,
|
||||
|
||||
/*
|
||||
* An optimization hint when all QEMUIOVector elements are within
|
||||
* previously registered bdrv_register_buf() memory ranges.
|
||||
*
|
||||
* Code that replaces the user's QEMUIOVector elements with bounce buffers
|
||||
* must take care to clear this flag.
|
||||
*/
|
||||
BDRV_REQ_REGISTERED_BUF = 0x8,
|
||||
|
||||
BDRV_REQ_FUA = 0x10,
|
||||
BDRV_REQ_WRITE_COMPRESSED = 0x20,
|
||||
|
||||
/*
|
||||
* Signifies that this write request will not change the visible disk
|
||||
* content.
|
||||
*/
|
||||
BDRV_REQ_WRITE_UNCHANGED = 0x40,
|
||||
|
||||
/*
|
||||
* Forces request serialisation. Use only with write requests.
|
||||
*/
|
||||
BDRV_REQ_SERIALISING = 0x80,
|
||||
|
||||
/*
|
||||
* Execute the request only if the operation can be offloaded or otherwise
|
||||
* be executed efficiently, but return an error instead of using a slow
|
||||
* fallback.
|
||||
*/
|
||||
BDRV_REQ_NO_FALLBACK = 0x100,
|
||||
|
||||
/*
|
||||
* BDRV_REQ_PREFETCH makes sense only in the context of copy-on-read
|
||||
* (i.e., together with the BDRV_REQ_COPY_ON_READ flag or when a COR
|
||||
* filter is involved), in which case it signals that the COR operation
|
||||
* need not read the data into memory (qiov) but only ensure they are
|
||||
* copied to the top layer (i.e., that COR operation is done).
|
||||
*/
|
||||
BDRV_REQ_PREFETCH = 0x200,
|
||||
|
||||
/*
|
||||
* If we need to wait for other requests, just fail immediately. Used
|
||||
* only together with BDRV_REQ_SERIALISING. Used only with requests aligned
|
||||
* to request_alignment (corresponding assertions are in block/io.c).
|
||||
*/
|
||||
BDRV_REQ_NO_WAIT = 0x400,
|
||||
|
||||
/*
|
||||
* Used between blk_co_start_request() and blk_end_request() to avoid
|
||||
* that the request waits in a drained BlockBackend until the drained
|
||||
* section ends. Waiting would cause a deadlock because drain waits for
|
||||
* blk_end_request() to be called, but the request never completes
|
||||
* because it waits for the drain to end.
|
||||
*/
|
||||
BDRV_REQ_NO_QUEUE = 0x800,
|
||||
|
||||
/* Mask of valid flags */
|
||||
BDRV_REQ_MASK = 0xfff,
|
||||
} BdrvRequestFlags;
|
||||
|
||||
#define BDRV_O_NO_SHARE 0x0001 /* don't share permissions */
|
||||
#define BDRV_O_RDWR 0x0002
|
||||
#define BDRV_O_RESIZE 0x0004 /* request permission for resizing the node */
|
||||
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save
|
||||
writes in a snapshot */
|
||||
#define BDRV_O_TEMPORARY 0x0010 /* delete the file after use */
|
||||
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
|
||||
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the
|
||||
thread pool */
|
||||
#define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */
|
||||
#define BDRV_O_NO_FLUSH 0x0200 /* disable flushing on this disk */
|
||||
#define BDRV_O_COPY_ON_READ 0x0400 /* copy read backing sectors into image */
|
||||
#define BDRV_O_INACTIVE 0x0800 /* consistency hint for migration handoff */
|
||||
#define BDRV_O_CHECK 0x1000 /* open solely for consistency check */
|
||||
#define BDRV_O_ALLOW_RDWR 0x2000 /* allow reopen to change from r/o to r/w */
|
||||
#define BDRV_O_UNMAP 0x4000 /* execute guest UNMAP/TRIM operations */
|
||||
#define BDRV_O_PROTOCOL 0x8000 /* if no block driver is explicitly given:
|
||||
select an appropriate protocol driver,
|
||||
ignoring the format layer */
|
||||
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
|
||||
#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening
|
||||
read-write fails */
|
||||
#define BDRV_O_IO_URING 0x40000 /* use io_uring instead of the thread pool */
|
||||
|
||||
#define BDRV_O_CBW_DISCARD_SOURCE 0x80000 /* for copy-before-write filter */
|
||||
|
||||
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
|
||||
|
||||
|
||||
/* Option names of options parsed by the block layer */
|
||||
|
||||
#define BDRV_OPT_CACHE_WB "cache.writeback"
|
||||
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
|
||||
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
|
||||
#define BDRV_OPT_READ_ONLY "read-only"
|
||||
#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
|
||||
#define BDRV_OPT_DISCARD "discard"
|
||||
#define BDRV_OPT_FORCE_SHARE "force-share"
|
||||
#define BDRV_OPT_ACTIVE "active"
|
||||
|
||||
|
||||
#define BDRV_SECTOR_BITS 9
|
||||
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
|
||||
|
||||
/*
|
||||
* Get the first most significant bit of wp. If it is zero, then
|
||||
* the zone type is SWR.
|
||||
*/
|
||||
#define BDRV_ZT_IS_CONV(wp) (wp & (1ULL << 63))
|
||||
|
||||
#define BDRV_REQUEST_MAX_SECTORS MIN_CONST(SIZE_MAX >> BDRV_SECTOR_BITS, \
|
||||
INT_MAX >> BDRV_SECTOR_BITS)
|
||||
#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
|
||||
|
||||
/*
|
||||
* We want allow aligning requests and disk length up to any 32bit alignment
|
||||
* and don't afraid of overflow.
|
||||
* To achieve it, and in the same time use some pretty number as maximum disk
|
||||
* size, let's define maximum "length" (a limit for any offset/bytes request and
|
||||
* for disk size) to be the greatest power of 2 less than INT64_MAX.
|
||||
*/
|
||||
#define BDRV_MAX_ALIGNMENT (1L << 30)
|
||||
#define BDRV_MAX_LENGTH (QEMU_ALIGN_DOWN(INT64_MAX, BDRV_MAX_ALIGNMENT))
|
||||
|
||||
/*
|
||||
* Allocation status flags for bdrv_block_status() and friends.
|
||||
*
|
||||
* Public flags:
|
||||
* BDRV_BLOCK_DATA: allocation for data at offset is tied to this layer
|
||||
* BDRV_BLOCK_ZERO: offset reads as zero
|
||||
* BDRV_BLOCK_OFFSET_VALID: an associated offset exists for accessing raw data
|
||||
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
|
||||
* layer rather than any backing, set by block layer
|
||||
* BDRV_BLOCK_EOF: the returned pnum covers through end of file for this
|
||||
* layer, set by block layer
|
||||
* BDRV_BLOCK_COMPRESSED: the underlying data is compressed; only valid for
|
||||
* the formats supporting compression: qcow, qcow2
|
||||
*
|
||||
* Internal flags:
|
||||
* BDRV_BLOCK_RAW: for use by passthrough drivers, such as raw, to request
|
||||
* that the block layer recompute the answer from the returned
|
||||
* BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
|
||||
* BDRV_BLOCK_RECURSE: request that the block layer will recursively search for
|
||||
* zeroes in file child of current block node inside
|
||||
* returned region. Only valid together with both
|
||||
* BDRV_BLOCK_DATA and BDRV_BLOCK_OFFSET_VALID. Should not
|
||||
* appear with BDRV_BLOCK_ZERO.
|
||||
*
|
||||
* If BDRV_BLOCK_OFFSET_VALID is set, the map parameter represents the
|
||||
* host offset within the returned BDS that is allocated for the
|
||||
* corresponding raw guest data. However, whether that offset
|
||||
* actually contains data also depends on BDRV_BLOCK_DATA, as follows:
|
||||
*
|
||||
* DATA ZERO OFFSET_VALID
|
||||
* t t t sectors read as zero, returned file is zero at offset
|
||||
* t f t sectors read as valid from file at offset
|
||||
* f t t sectors preallocated, read as zero, returned file not
|
||||
* necessarily zero at offset
|
||||
* f f t sectors preallocated but read from backing_hd,
|
||||
* returned file contains garbage at offset
|
||||
* t t f sectors preallocated, read as zero, unknown offset
|
||||
* t f f sectors read from unknown file or offset
|
||||
* f t f not allocated or unknown offset, read as zero
|
||||
* f f f not allocated or unknown offset, read from backing_hd
|
||||
*/
|
||||
#define BDRV_BLOCK_DATA 0x01
|
||||
#define BDRV_BLOCK_ZERO 0x02
|
||||
#define BDRV_BLOCK_OFFSET_VALID 0x04
|
||||
#define BDRV_BLOCK_RAW 0x08
|
||||
#define BDRV_BLOCK_ALLOCATED 0x10
|
||||
#define BDRV_BLOCK_EOF 0x20
|
||||
#define BDRV_BLOCK_RECURSE 0x40
|
||||
#define BDRV_BLOCK_COMPRESSED 0x80
|
||||
|
||||
/*
|
||||
* Block status hints: the bitwise-or of these flags emphasize what
|
||||
* the caller hopes to learn, and some drivers may be able to give
|
||||
* faster answers by doing less work when the hint permits.
|
||||
*/
|
||||
#define BDRV_WANT_ZERO BDRV_BLOCK_ZERO
|
||||
#define BDRV_WANT_OFFSET_VALID BDRV_BLOCK_OFFSET_VALID
|
||||
#define BDRV_WANT_ALLOCATED BDRV_BLOCK_ALLOCATED
|
||||
#define BDRV_WANT_PRECISE (BDRV_WANT_ZERO | BDRV_WANT_OFFSET_VALID | \
|
||||
BDRV_WANT_OFFSET_VALID)
|
||||
|
||||
typedef QTAILQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
|
||||
|
||||
typedef struct BDRVReopenState {
|
||||
BlockDriverState *bs;
|
||||
int flags;
|
||||
BlockdevDetectZeroesOptions detect_zeroes;
|
||||
bool backing_missing;
|
||||
BlockDriverState *old_backing_bs; /* keep pointer for permissions update */
|
||||
BlockDriverState *old_file_bs; /* keep pointer for permissions update */
|
||||
QDict *options;
|
||||
QDict *explicit_options;
|
||||
void *opaque;
|
||||
} BDRVReopenState;
|
||||
|
||||
/*
|
||||
* Block operation types
|
||||
*/
|
||||
typedef enum BlockOpType {
|
||||
BLOCK_OP_TYPE_BACKUP_SOURCE,
|
||||
BLOCK_OP_TYPE_BACKUP_TARGET,
|
||||
BLOCK_OP_TYPE_CHANGE,
|
||||
BLOCK_OP_TYPE_COMMIT_SOURCE,
|
||||
BLOCK_OP_TYPE_COMMIT_TARGET,
|
||||
BLOCK_OP_TYPE_DRIVE_DEL,
|
||||
BLOCK_OP_TYPE_EJECT,
|
||||
BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
|
||||
BLOCK_OP_TYPE_INTERNAL_SNAPSHOT,
|
||||
BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
|
||||
BLOCK_OP_TYPE_MIRROR_SOURCE,
|
||||
BLOCK_OP_TYPE_MIRROR_TARGET,
|
||||
BLOCK_OP_TYPE_RESIZE,
|
||||
BLOCK_OP_TYPE_STREAM,
|
||||
BLOCK_OP_TYPE_REPLACE,
|
||||
BLOCK_OP_TYPE_MAX,
|
||||
} BlockOpType;
|
||||
|
||||
/* Block node permission constants */
|
||||
enum {
|
||||
/**
|
||||
* A user that has the "permission" of consistent reads is guaranteed that
|
||||
* their view of the contents of the block device is complete and
|
||||
* self-consistent, representing the contents of a disk at a specific
|
||||
* point.
|
||||
*
|
||||
* For most block devices (including their backing files) this is true, but
|
||||
* the property cannot be maintained in a few situations like for
|
||||
* intermediate nodes of a commit block job.
|
||||
*/
|
||||
BLK_PERM_CONSISTENT_READ = 0x01,
|
||||
|
||||
/** This permission is required to change the visible disk contents. */
|
||||
BLK_PERM_WRITE = 0x02,
|
||||
|
||||
/**
|
||||
* This permission (which is weaker than BLK_PERM_WRITE) is both enough and
|
||||
* required for writes to the block node when the caller promises that
|
||||
* the visible disk content doesn't change.
|
||||
*
|
||||
* As the BLK_PERM_WRITE permission is strictly stronger, either is
|
||||
* sufficient to perform an unchanging write.
|
||||
*/
|
||||
BLK_PERM_WRITE_UNCHANGED = 0x04,
|
||||
|
||||
/** This permission is required to change the size of a block node. */
|
||||
BLK_PERM_RESIZE = 0x08,
|
||||
|
||||
/**
|
||||
* There was a now-removed bit BLK_PERM_GRAPH_MOD, with value of 0x10. QEMU
|
||||
* 6.1 and earlier may still lock the corresponding byte in block/file-posix
|
||||
* locking. So, implementing some new permission should be very careful to
|
||||
* not interfere with this old unused thing.
|
||||
*/
|
||||
|
||||
BLK_PERM_ALL = 0x0f,
|
||||
|
||||
DEFAULT_PERM_PASSTHROUGH = BLK_PERM_CONSISTENT_READ
|
||||
| BLK_PERM_WRITE
|
||||
| BLK_PERM_WRITE_UNCHANGED
|
||||
| BLK_PERM_RESIZE,
|
||||
|
||||
DEFAULT_PERM_UNCHANGED = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags that parent nodes assign to child nodes to specify what kind of
|
||||
* role(s) they take.
|
||||
*
|
||||
* At least one of DATA, METADATA, FILTERED, or COW must be set for
|
||||
* every child.
|
||||
*
|
||||
*
|
||||
* = Connection with bs->children, bs->file and bs->backing fields =
|
||||
*
|
||||
* 1. Filters
|
||||
*
|
||||
* Filter drivers have drv->is_filter = true.
|
||||
*
|
||||
* Filter node has exactly one FILTERED|PRIMARY child, and may have other
|
||||
* children which must not have these bits (one example is the
|
||||
* copy-before-write filter, which also has its target DATA child).
|
||||
*
|
||||
* Filter nodes never have COW children.
|
||||
*
|
||||
* For most filters, the filtered child is linked in bs->file, bs->backing is
|
||||
* NULL. For some filters (as an exception), it is the other way around; those
|
||||
* drivers will have drv->filtered_child_is_backing set to true (see that
|
||||
* field’s documentation for what drivers this concerns)
|
||||
*
|
||||
* 2. "raw" driver (block/raw-format.c)
|
||||
*
|
||||
* Formally it's not a filter (drv->is_filter = false)
|
||||
*
|
||||
* bs->backing is always NULL
|
||||
*
|
||||
* Only has one child, linked in bs->file. Its role is either FILTERED|PRIMARY
|
||||
* (like filter) or DATA|PRIMARY depending on options.
|
||||
*
|
||||
* 3. Other drivers
|
||||
*
|
||||
* Don't have any FILTERED children.
|
||||
*
|
||||
* May have at most one COW child. In this case it's linked in bs->backing.
|
||||
* Otherwise bs->backing is NULL. COW child is never PRIMARY.
|
||||
*
|
||||
* May have at most one PRIMARY child. In this case it's linked in bs->file.
|
||||
* Otherwise bs->file is NULL.
|
||||
*
|
||||
* May also have some other children that don't have the PRIMARY or COW bit set.
|
||||
*/
|
||||
enum BdrvChildRoleBits {
|
||||
/*
|
||||
* This child stores data.
|
||||
* Any node may have an arbitrary number of such children.
|
||||
*/
|
||||
BDRV_CHILD_DATA = (1 << 0),
|
||||
|
||||
/*
|
||||
* This child stores metadata.
|
||||
* Any node may have an arbitrary number of metadata-storing
|
||||
* children.
|
||||
*/
|
||||
BDRV_CHILD_METADATA = (1 << 1),
|
||||
|
||||
/*
|
||||
* A child that always presents exactly the same visible data as
|
||||
* the parent, e.g. by virtue of the parent forwarding all reads
|
||||
* and writes.
|
||||
* This flag is mutually exclusive with DATA, METADATA, and COW.
|
||||
* Any node may have at most one filtered child at a time.
|
||||
*/
|
||||
BDRV_CHILD_FILTERED = (1 << 2),
|
||||
|
||||
/*
|
||||
* Child from which to read all data that isn't allocated in the
|
||||
* parent (i.e., the backing child); such data is copied to the
|
||||
* parent through COW (and optionally COR).
|
||||
* This field is mutually exclusive with DATA, METADATA, and
|
||||
* FILTERED.
|
||||
* Any node may have at most one such backing child at a time.
|
||||
*/
|
||||
BDRV_CHILD_COW = (1 << 3),
|
||||
|
||||
/*
|
||||
* The primary child. For most drivers, this is the child whose
|
||||
* filename applies best to the parent node.
|
||||
* Any node may have at most one primary child at a time.
|
||||
*/
|
||||
BDRV_CHILD_PRIMARY = (1 << 4),
|
||||
|
||||
/* Useful combination of flags */
|
||||
BDRV_CHILD_IMAGE = BDRV_CHILD_DATA
|
||||
| BDRV_CHILD_METADATA
|
||||
| BDRV_CHILD_PRIMARY,
|
||||
};
|
||||
|
||||
/* Mask of BdrvChildRoleBits values */
|
||||
typedef unsigned int BdrvChildRole;
|
||||
|
||||
typedef struct BdrvCheckResult {
|
||||
int corruptions;
|
||||
int leaks;
|
||||
int check_errors;
|
||||
int corruptions_fixed;
|
||||
int leaks_fixed;
|
||||
int64_t image_end_offset;
|
||||
BlockFragInfo bfi;
|
||||
} BdrvCheckResult;
|
||||
|
||||
typedef enum {
|
||||
BDRV_FIX_LEAKS = 1,
|
||||
BDRV_FIX_ERRORS = 2,
|
||||
} BdrvCheckMode;
|
||||
|
||||
typedef struct BlockSizes {
|
||||
uint32_t phys;
|
||||
uint32_t log;
|
||||
} BlockSizes;
|
||||
|
||||
typedef struct HDGeometry {
|
||||
uint32_t heads;
|
||||
uint32_t sectors;
|
||||
uint32_t cylinders;
|
||||
} HDGeometry;
|
||||
|
||||
/*
|
||||
* Common functions that are neither I/O nor Global State.
|
||||
*
|
||||
* These functions must never call any function from other categories
|
||||
* (I/O, "I/O or GS", Global State) except this one, but can be invoked by
|
||||
* all of them.
|
||||
*/
|
||||
|
||||
char *bdrv_perm_names(uint64_t perm);
|
||||
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
|
||||
|
||||
void bdrv_init_with_whitelist(void);
|
||||
bool bdrv_uses_whitelist(void);
|
||||
int bdrv_is_whitelisted(BlockDriver *drv, bool read_only);
|
||||
|
||||
int bdrv_parse_aio(const char *mode, int *flags);
|
||||
int bdrv_parse_cache_mode(const char *mode, int *flags, bool *writethrough);
|
||||
int bdrv_parse_discard_flags(const char *mode, int *flags);
|
||||
|
||||
int path_has_protocol(const char *path);
|
||||
int path_is_absolute(const char *path);
|
||||
char *path_combine(const char *base_path, const char *filename);
|
||||
|
||||
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
|
||||
const char *backing,
|
||||
Error **errp);
|
||||
|
||||
#endif /* BLOCK_COMMON_H */
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* block_copy API
|
||||
*
|
||||
* Copyright (C) 2013 Proxmox Server Solutions
|
||||
* Copyright (c) 2019 Virtuozzo International GmbH.
|
||||
*
|
||||
* Authors:
|
||||
* Dietmar Maurer ([email protected])
|
||||
* Vladimir Sementsov-Ogievskiy <[email protected]>
|
||||
*
|
||||
* 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-common.h"
|
||||
#include "block/graph-lock.h"
|
||||
#include "qemu/progress_meter.h"
|
||||
|
||||
/* All APIs are thread-safe */
|
||||
|
||||
typedef void (*BlockCopyAsyncCallbackFunc)(void *opaque);
|
||||
typedef struct BlockCopyState BlockCopyState;
|
||||
typedef struct BlockCopyCallState BlockCopyCallState;
|
||||
|
||||
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
|
||||
BlockDriverState *copy_bitmap_bs,
|
||||
const BdrvDirtyBitmap *bitmap,
|
||||
bool discard_source,
|
||||
uint64_t min_cluster_size,
|
||||
Error **errp);
|
||||
|
||||
/* Function should be called prior any actual copy request */
|
||||
void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
|
||||
bool compress);
|
||||
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
|
||||
|
||||
void block_copy_state_free(BlockCopyState *s);
|
||||
|
||||
void block_copy_reset(BlockCopyState *s, int64_t offset, int64_t bytes);
|
||||
|
||||
int64_t coroutine_fn GRAPH_RDLOCK
|
||||
block_copy_reset_unallocated(BlockCopyState *s, int64_t offset, int64_t *count);
|
||||
|
||||
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
|
||||
bool ignore_ratelimit, uint64_t timeout_ns,
|
||||
BlockCopyAsyncCallbackFunc cb,
|
||||
void *cb_opaque);
|
||||
|
||||
/*
|
||||
* Run block-copy in a coroutine, create corresponding BlockCopyCallState
|
||||
* object and return pointer to it. Never returns NULL.
|
||||
*
|
||||
* Caller is responsible to call block_copy_call_free() to free
|
||||
* BlockCopyCallState object.
|
||||
*
|
||||
* @max_workers means maximum of parallel coroutines to execute sub-requests,
|
||||
* must be > 0.
|
||||
*
|
||||
* @max_chunk means maximum length for one IO operation. Zero means unlimited.
|
||||
*/
|
||||
BlockCopyCallState *block_copy_async(BlockCopyState *s,
|
||||
int64_t offset, int64_t bytes,
|
||||
int max_workers, int64_t max_chunk,
|
||||
BlockCopyAsyncCallbackFunc cb,
|
||||
void *cb_opaque);
|
||||
|
||||
/*
|
||||
* Free finished BlockCopyCallState. Trying to free running
|
||||
* block-copy will crash.
|
||||
*/
|
||||
void block_copy_call_free(BlockCopyCallState *call_state);
|
||||
|
||||
/*
|
||||
* Note, that block-copy call is marked finished prior to calling
|
||||
* the callback.
|
||||
*/
|
||||
bool block_copy_call_finished(BlockCopyCallState *call_state);
|
||||
bool block_copy_call_succeeded(BlockCopyCallState *call_state);
|
||||
bool block_copy_call_failed(BlockCopyCallState *call_state);
|
||||
bool block_copy_call_cancelled(BlockCopyCallState *call_state);
|
||||
int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read);
|
||||
|
||||
void block_copy_set_speed(BlockCopyState *s, uint64_t speed);
|
||||
void block_copy_kick(BlockCopyCallState *call_state);
|
||||
|
||||
/*
|
||||
* Cancel running block-copy call.
|
||||
*
|
||||
* Cancel leaves block-copy state valid: dirty bits are correct and you may use
|
||||
* cancel + <run block_copy with same parameters> to emulate pause/resume.
|
||||
*
|
||||
* Note also, that the cancel is async: it only marks block-copy call to be
|
||||
* cancelled. So, the call may be cancelled (block_copy_call_cancelled() reports
|
||||
* true) but not yet finished (block_copy_call_finished() reports false).
|
||||
*/
|
||||
void block_copy_call_cancel(BlockCopyCallState *call_state);
|
||||
|
||||
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
|
||||
int64_t block_copy_cluster_size(BlockCopyState *s);
|
||||
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
|
||||
|
||||
#endif /* BLOCK_COPY_H */
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_GLOBAL_STATE_H
|
||||
#define BLOCK_GLOBAL_STATE_H
|
||||
|
||||
#include "qemu/aiocb.h"
|
||||
#include "block/graph-lock.h"
|
||||
#include "block/block-common.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/transactions.h"
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* If a function modifies the graph, it also uses the graph lock to be sure it
|
||||
* has unique access. The graph lock is needed together with BQL because of the
|
||||
* thread-safe I/O API that concurrently runs and accesses the graph without
|
||||
* the BQL.
|
||||
*
|
||||
* It is important to note that not all of these functions are
|
||||
* necessarily limited to running under the BQL, but they would
|
||||
* require additional auditing and many small thread-safety changes
|
||||
* to move them into the I/O API. Often it's not worth doing that
|
||||
* work since the APIs are only used with the BQL held at the
|
||||
* moment, so they have been placed in the GS API (for now).
|
||||
*
|
||||
* These functions can call any function from this and other categories
|
||||
* (I/O, "I/O or GS", Common), but must be invoked only by other GS APIs.
|
||||
*
|
||||
* All functions in this header must use the macro
|
||||
* GLOBAL_STATE_CODE();
|
||||
* to catch when they are accidentally called without the BQL.
|
||||
*/
|
||||
|
||||
void bdrv_init(void);
|
||||
BlockDriver *bdrv_find_protocol(const char *filename,
|
||||
bool allow_protocol_prefix,
|
||||
Error **errp);
|
||||
BlockDriver *bdrv_find_format(const char *format_name);
|
||||
|
||||
int coroutine_fn GRAPH_UNLOCKED
|
||||
bdrv_co_create(BlockDriver *drv, const char *filename, QemuOpts *opts,
|
||||
Error **errp);
|
||||
|
||||
int co_wrapper bdrv_create(BlockDriver *drv, const char *filename,
|
||||
QemuOpts *opts, Error **errp);
|
||||
|
||||
int coroutine_fn GRAPH_UNLOCKED
|
||||
bdrv_co_create_file(const char *filename, QemuOpts *opts,
|
||||
bool allow_protocol_prefix, Error **errp);
|
||||
|
||||
BlockDriverState *bdrv_new(void);
|
||||
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
|
||||
Error **errp);
|
||||
|
||||
int GRAPH_WRLOCK
|
||||
bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, Error **errp);
|
||||
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, Error **errp);
|
||||
BlockDriverState * GRAPH_UNLOCKED
|
||||
bdrv_insert_node(BlockDriverState *bs, QDict *node_options, int flags,
|
||||
Error **errp);
|
||||
int bdrv_drop_filter(BlockDriverState *bs, Error **errp);
|
||||
|
||||
BdrvChild * no_coroutine_fn GRAPH_UNLOCKED
|
||||
bdrv_open_child(const char *filename, QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role, bool allow_none, Error **errp);
|
||||
|
||||
BdrvChild * coroutine_fn no_co_wrapper
|
||||
bdrv_co_open_child(const char *filename, QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role, bool allow_none, Error **errp);
|
||||
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_open_file_child(const char *filename, QDict *options,
|
||||
const char *bdref_key, BlockDriverState *parent,
|
||||
Error **errp);
|
||||
|
||||
BlockDriverState * no_coroutine_fn
|
||||
bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
|
||||
|
||||
BlockDriverState * coroutine_fn no_co_wrapper
|
||||
bdrv_co_open_blockdev_ref(BlockdevRef *ref, Error **errp);
|
||||
|
||||
int GRAPH_WRLOCK
|
||||
bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
Error **errp);
|
||||
|
||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
const char *bdref_key, Error **errp);
|
||||
|
||||
BlockDriverState * no_coroutine_fn
|
||||
bdrv_open(const char *filename, const char *reference, QDict *options,
|
||||
int flags, Error **errp);
|
||||
|
||||
BlockDriverState * coroutine_fn no_co_wrapper
|
||||
bdrv_co_open(const char *filename, const char *reference,
|
||||
QDict *options, int flags, Error **errp);
|
||||
|
||||
BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
|
||||
const char *node_name,
|
||||
QDict *options, int flags,
|
||||
Error **errp);
|
||||
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
|
||||
int flags, Error **errp);
|
||||
BlockReopenQueue * GRAPH_UNLOCKED
|
||||
bdrv_reopen_queue(BlockReopenQueue *bs_queue, BlockDriverState *bs,
|
||||
QDict *options, bool keep_old_opts);
|
||||
void bdrv_reopen_queue_free(BlockReopenQueue *bs_queue);
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
|
||||
int bdrv_reopen(BlockDriverState *bs, QDict *opts, bool keep_old_opts,
|
||||
Error **errp);
|
||||
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
|
||||
Error **errp);
|
||||
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
|
||||
const char *backing_file);
|
||||
void GRAPH_RDLOCK bdrv_refresh_filename(BlockDriverState *bs);
|
||||
|
||||
void GRAPH_RDLOCK
|
||||
bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
|
||||
|
||||
int bdrv_commit(BlockDriverState *bs);
|
||||
int GRAPH_RDLOCK bdrv_make_empty(BdrvChild *c, Error **errp);
|
||||
|
||||
void bdrv_register(BlockDriver *bdrv);
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
const char *backing_file_str,
|
||||
bool backing_mask_protocol);
|
||||
|
||||
BlockDriverState * GRAPH_RDLOCK
|
||||
bdrv_find_overlay(BlockDriverState *active, BlockDriverState *bs);
|
||||
|
||||
BlockDriverState * GRAPH_RDLOCK bdrv_find_base(BlockDriverState *bs);
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
|
||||
Error **errp);
|
||||
void GRAPH_RDLOCK
|
||||
bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
|
||||
|
||||
/*
|
||||
* The units of offset and total_work_size may be chosen arbitrarily by the
|
||||
* block driver; total_work_size may change during the course of the amendment
|
||||
* operation
|
||||
*/
|
||||
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
|
||||
int64_t total_work_size, void *opaque);
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
|
||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||
bool force, Error **errp);
|
||||
|
||||
/* check if a named node can be replaced when doing drive-mirror */
|
||||
BlockDriverState * GRAPH_RDLOCK
|
||||
check_to_replace_node(BlockDriverState *parent_bs, const char *node_name,
|
||||
Error **errp);
|
||||
|
||||
|
||||
bool GRAPH_RDLOCK bdrv_is_inactive(BlockDriverState *bs);
|
||||
|
||||
int no_coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_activate(BlockDriverState *bs, Error **errp);
|
||||
|
||||
int coroutine_fn no_co_wrapper_bdrv_rdlock
|
||||
bdrv_co_activate(BlockDriverState *bs, Error **errp);
|
||||
|
||||
int no_coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_inactivate(BlockDriverState *bs, Error **errp);
|
||||
|
||||
void bdrv_activate_all(Error **errp);
|
||||
int GRAPH_UNLOCKED bdrv_inactivate_all(void);
|
||||
|
||||
int bdrv_flush_all(void);
|
||||
void GRAPH_UNLOCKED bdrv_close_all(void);
|
||||
void GRAPH_UNLOCKED bdrv_drain_all_begin(void);
|
||||
void bdrv_drain_all_begin_nopoll(void);
|
||||
void bdrv_drain_all_end(void);
|
||||
void GRAPH_UNLOCKED bdrv_drain_all(void);
|
||||
|
||||
void bdrv_aio_cancel(BlockAIOCB *acb);
|
||||
|
||||
int bdrv_has_zero_init_1(BlockDriverState *bs);
|
||||
int coroutine_mixed_fn GRAPH_RDLOCK bdrv_has_zero_init(BlockDriverState *bs);
|
||||
BlockDriverState *bdrv_find_node(const char *node_name);
|
||||
BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, Error **errp);
|
||||
XDbgBlockGraph * GRAPH_RDLOCK bdrv_get_xdbg_block_graph(Error **errp);
|
||||
BlockDriverState *bdrv_lookup_bs(const char *device,
|
||||
const char *node_name,
|
||||
Error **errp);
|
||||
bool GRAPH_RDLOCK
|
||||
bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base);
|
||||
|
||||
BlockDriverState *bdrv_next_node(BlockDriverState *bs);
|
||||
BlockDriverState *bdrv_next_all_states(BlockDriverState *bs);
|
||||
|
||||
typedef struct BdrvNextIterator {
|
||||
enum {
|
||||
BDRV_NEXT_BACKEND_ROOTS,
|
||||
BDRV_NEXT_MONITOR_OWNED,
|
||||
} phase;
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
} BdrvNextIterator;
|
||||
|
||||
BlockDriverState * GRAPH_RDLOCK bdrv_first(BdrvNextIterator *it);
|
||||
BlockDriverState * GRAPH_RDLOCK bdrv_next(BdrvNextIterator *it);
|
||||
void bdrv_next_cleanup(BdrvNextIterator *it);
|
||||
|
||||
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
|
||||
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
||||
void *opaque, bool read_only);
|
||||
|
||||
char * GRAPH_RDLOCK
|
||||
bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
|
||||
|
||||
char * GRAPH_RDLOCK bdrv_dirname(BlockDriverState *bs, Error **errp);
|
||||
|
||||
void bdrv_img_create(const char *filename, const char *fmt,
|
||||
const char *base_filename, const char *base_fmt,
|
||||
char *options, uint64_t img_size, int flags,
|
||||
bool quiet, Error **errp);
|
||||
|
||||
void bdrv_ref(BlockDriverState *bs);
|
||||
void no_coroutine_fn bdrv_unref(BlockDriverState *bs);
|
||||
void coroutine_fn no_co_wrapper bdrv_co_unref(BlockDriverState *bs);
|
||||
void GRAPH_WRLOCK bdrv_schedule_unref(BlockDriverState *bs);
|
||||
|
||||
void GRAPH_WRLOCK
|
||||
bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
|
||||
|
||||
void coroutine_fn no_co_wrapper_bdrv_wrlock
|
||||
bdrv_co_unref_child(BlockDriverState *parent, BdrvChild *child);
|
||||
|
||||
BdrvChild * GRAPH_WRLOCK
|
||||
bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
const char *child_name,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
Error **errp);
|
||||
|
||||
bool GRAPH_RDLOCK
|
||||
bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
|
||||
|
||||
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);
|
||||
void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason);
|
||||
void bdrv_op_block_all(BlockDriverState *bs, Error *reason);
|
||||
void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason);
|
||||
bool bdrv_op_blocker_is_empty(BlockDriverState *bs);
|
||||
|
||||
int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
|
||||
const char *tag);
|
||||
int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag);
|
||||
int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
|
||||
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
|
||||
|
||||
bool GRAPH_RDLOCK
|
||||
bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
|
||||
GHashTable *visited, Transaction *tran,
|
||||
Error **errp);
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
|
||||
BdrvChild *ignore_child, Error **errp);
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_try_change_aio_context_locked(BlockDriverState *bs, AioContext *ctx,
|
||||
BdrvChild *ignore_child, Error **errp);
|
||||
|
||||
int GRAPH_RDLOCK bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
|
||||
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
|
||||
|
||||
void GRAPH_WRLOCK
|
||||
bdrv_add_child(BlockDriverState *parent, BlockDriverState *child, Error **errp);
|
||||
|
||||
void GRAPH_WRLOCK
|
||||
bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
|
||||
|
||||
/**
|
||||
*
|
||||
* bdrv_register_buf/bdrv_unregister_buf:
|
||||
*
|
||||
* Register/unregister a buffer for I/O. For example, VFIO drivers are
|
||||
* interested to know the memory areas that would later be used for I/O, so
|
||||
* that they can prepare IOMMU mapping etc., to get better performance.
|
||||
*
|
||||
* Buffers must not overlap and they must be unregistered with the same <host,
|
||||
* size> values that they were registered with.
|
||||
*
|
||||
* Returns: true on success, false on failure
|
||||
*/
|
||||
bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
|
||||
Error **errp);
|
||||
void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size);
|
||||
|
||||
void bdrv_cancel_in_flight(BlockDriverState *bs);
|
||||
|
||||
#endif /* BLOCK_GLOBAL_STATE_H */
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* HMP commands related to the block layer
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2020 Red Hat, Inc.
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_BLOCK_HMP_CMDS_H
|
||||
#define BLOCK_BLOCK_HMP_CMDS_H
|
||||
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
void hmp_drive_add(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_commit(Monitor *mon, const QDict *qdict);
|
||||
void hmp_drive_del(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_drive_mirror(Monitor *mon, const QDict *qdict);
|
||||
void hmp_drive_backup(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_pause(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_resume(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_complete(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
|
||||
void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict);
|
||||
void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_nbd_server_start(Monitor *mon, const QDict *qdict);
|
||||
void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict);
|
||||
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_stream(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_passwd(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
|
||||
void hmp_eject(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_qemu_io(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_info_block(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_blockstats(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_IO_H
|
||||
#define BLOCK_IO_H
|
||||
|
||||
#include "qemu/aiocb.h"
|
||||
#include "qemu/aio-wait.h"
|
||||
#include "block/block-common.h"
|
||||
#include "block/graph-lock.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/iov.h"
|
||||
|
||||
/*
|
||||
* I/O API functions. These functions are thread-safe, and therefore
|
||||
* can run in any thread.
|
||||
*
|
||||
* These functions can only call functions from I/O and Common categories,
|
||||
* but can be invoked by GS, "I/O or GS" and I/O APIs.
|
||||
*
|
||||
* All functions in this category must use the macro
|
||||
* IO_CODE();
|
||||
* to catch when they are accidentally called by the wrong API.
|
||||
*/
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_pwrite(BdrvChild *child, int64_t offset,int64_t bytes,
|
||||
const void *buf, BdrvRequestFlags flags);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
|
||||
const void *buf, BdrvRequestFlags flags);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
|
||||
const void *buf, BdrvRequestFlags flags);
|
||||
|
||||
/*
|
||||
* Efficiently zero a region of the disk image. Note that this is a regular
|
||||
* I/O request like read or write and should have a reasonable size. This
|
||||
* function is not suitable for zeroing the entire image in a single request
|
||||
* because it may allocate memory for the entire region.
|
||||
*/
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
|
||||
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
|
||||
|
||||
int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_nb_sectors(BlockDriverState *bs);
|
||||
int64_t coroutine_mixed_fn bdrv_nb_sectors(BlockDriverState *bs);
|
||||
|
||||
int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_getlength(BlockDriverState *bs);
|
||||
int64_t co_wrapper_mixed_bdrv_rdlock bdrv_getlength(BlockDriverState *bs);
|
||||
|
||||
int64_t coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_get_allocated_file_size(BlockDriverState *bs);
|
||||
|
||||
int64_t co_wrapper_bdrv_rdlock
|
||||
bdrv_get_allocated_file_size(BlockDriverState *bs);
|
||||
|
||||
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
|
||||
BlockDriverState *in_bs, Error **errp);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
|
||||
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_delete_file_noerr(BlockDriverState *bs);
|
||||
|
||||
|
||||
/* async block I/O */
|
||||
void bdrv_aio_cancel_async(BlockAIOCB *acb);
|
||||
|
||||
/* sg packet commands */
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
|
||||
|
||||
/* Ensure contents are flushed to disk. */
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||
int64_t bytes);
|
||||
|
||||
/* Report zone information of zone block device. */
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_report(BlockDriverState *bs,
|
||||
int64_t offset,
|
||||
unsigned int *nr_zones,
|
||||
BlockZoneDescriptor *zones);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_mgmt(BlockDriverState *bs,
|
||||
BlockZoneOp op,
|
||||
int64_t offset, int64_t len);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_append(BlockDriverState *bs,
|
||||
int64_t *offset,
|
||||
QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
int64_t *pnum, int64_t *map, BlockDriverState **file);
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
int64_t *pnum, int64_t *map, BlockDriverState **file);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base,
|
||||
int64_t offset, int64_t bytes, int64_t *pnum,
|
||||
int64_t *map, BlockDriverState **file);
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
|
||||
int64_t offset, int64_t bytes, int64_t *pnum,
|
||||
int64_t *map, BlockDriverState **file);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
int64_t *pnum);
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
|
||||
bool include_base, int64_t offset, int64_t bytes,
|
||||
int64_t *pnum);
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_is_allocated_above(BlockDriverState *bs, BlockDriverState *base,
|
||||
bool include_base, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_is_all_zeroes(BlockDriverState *bs);
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
|
||||
Error **errp);
|
||||
|
||||
bool bdrv_is_read_only(BlockDriverState *bs);
|
||||
bool bdrv_is_writable(BlockDriverState *bs);
|
||||
bool bdrv_is_sg(BlockDriverState *bs);
|
||||
int bdrv_get_flags(BlockDriverState *bs);
|
||||
|
||||
bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
|
||||
bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
|
||||
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
|
||||
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
|
||||
|
||||
const char *bdrv_get_format_name(BlockDriverState *bs);
|
||||
|
||||
bool GRAPH_RDLOCK bdrv_supports_compressed_writes(BlockDriverState *bs);
|
||||
const char *bdrv_get_node_name(const BlockDriverState *bs);
|
||||
|
||||
const char * GRAPH_RDLOCK
|
||||
bdrv_get_device_name(const BlockDriverState *bs);
|
||||
|
||||
const char * GRAPH_RDLOCK
|
||||
bdrv_get_device_or_node_name(const BlockDriverState *bs);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
|
||||
ImageInfoSpecific * GRAPH_RDLOCK
|
||||
bdrv_get_specific_info(BlockDriverState *bs, Error **errp);
|
||||
|
||||
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
|
||||
void bdrv_round_to_subclusters(BlockDriverState *bs,
|
||||
int64_t offset, int64_t bytes,
|
||||
int64_t *cluster_offset,
|
||||
int64_t *cluster_bytes);
|
||||
|
||||
void bdrv_get_backing_filename(BlockDriverState *bs,
|
||||
char *filename, int filename_size);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
|
||||
const char *backing_fmt, bool warn);
|
||||
|
||||
int co_wrapper_bdrv_rdlock
|
||||
bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
|
||||
const char *backing_fmt, bool warn);
|
||||
|
||||
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
||||
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
||||
/*
|
||||
* Returns the alignment in bytes that is required so that no bounce buffer
|
||||
* is required throughout the stack
|
||||
*/
|
||||
size_t bdrv_min_mem_align(BlockDriverState *bs);
|
||||
/* Returns optimal alignment in bytes for bounce buffer */
|
||||
size_t bdrv_opt_mem_align(BlockDriverState *bs);
|
||||
void *qemu_blockalign(BlockDriverState *bs, size_t size);
|
||||
void *qemu_blockalign0(BlockDriverState *bs, size_t size);
|
||||
void *qemu_try_blockalign(BlockDriverState *bs, size_t size);
|
||||
void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
|
||||
|
||||
void bdrv_enable_copy_on_read(BlockDriverState *bs);
|
||||
void bdrv_disable_copy_on_read(BlockDriverState *bs);
|
||||
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event);
|
||||
|
||||
void co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event);
|
||||
|
||||
#define BLKDBG_CO_EVENT(child, evt) \
|
||||
do { \
|
||||
if (child) { \
|
||||
bdrv_co_debug_event(child->bs, evt); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BLKDBG_EVENT(child, evt) \
|
||||
do { \
|
||||
if (child) { \
|
||||
bdrv_debug_event(child->bs, evt); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* bdrv_get_aio_context:
|
||||
*
|
||||
* Returns: the currently bound #AioContext
|
||||
*/
|
||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs);
|
||||
|
||||
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
|
||||
|
||||
/**
|
||||
* Move the current coroutine to the AioContext of @bs and return the old
|
||||
* AioContext of the coroutine. Increase bs->in_flight so that draining @bs
|
||||
* will wait for the operation to proceed until the corresponding
|
||||
* bdrv_co_leave().
|
||||
*
|
||||
* Consequently, you can't call drain inside a bdrv_co_enter/leave() section as
|
||||
* this will deadlock.
|
||||
*/
|
||||
AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* Ends a section started by bdrv_co_enter(). Move the current coroutine back
|
||||
* to old_ctx and decrease bs->in_flight again.
|
||||
*/
|
||||
void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
|
||||
|
||||
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
|
||||
|
||||
bool coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
|
||||
uint32_t granularity, Error **errp);
|
||||
bool co_wrapper_bdrv_rdlock
|
||||
bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
|
||||
uint32_t granularity, Error **errp);
|
||||
|
||||
/**
|
||||
*
|
||||
* bdrv_co_copy_range:
|
||||
*
|
||||
* Do offloaded copy between two children. If the operation is not implemented
|
||||
* by the driver, or if the backend storage doesn't support it, a negative
|
||||
* error code will be returned.
|
||||
*
|
||||
* Note: block layer doesn't emulate or fallback to a bounce buffer approach
|
||||
* because usually the caller shouldn't attempt offloaded copy any more (e.g.
|
||||
* calling copy_file_range(2)) after the first error, thus it should fall back
|
||||
* to a read+write path in the caller level.
|
||||
*
|
||||
* @src: Source child to copy data from
|
||||
* @src_offset: offset in @src image to read data
|
||||
* @dst: Destination child to copy data to
|
||||
* @dst_offset: offset in @dst image to write data
|
||||
* @bytes: number of bytes to copy
|
||||
* @flags: request flags. Supported flags:
|
||||
* BDRV_REQ_ZERO_WRITE - treat the @src range as zero data and do zero
|
||||
* write on @dst as if bdrv_co_pwrite_zeroes is
|
||||
* called. Used to simplify caller code, or
|
||||
* during BlockDriver.bdrv_co_copy_range_from()
|
||||
* recursion.
|
||||
* BDRV_REQ_NO_SERIALISING - do not serialize with other overlapping
|
||||
* requests currently in flight.
|
||||
*
|
||||
* Returns: 0 if succeeded; negative error code if failed.
|
||||
**/
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
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);
|
||||
|
||||
/*
|
||||
* "I/O or GS" API functions. These functions can run without
|
||||
* the BQL, but only in one specific iothread/main loop.
|
||||
*
|
||||
* More specifically, these functions use BDRV_POLL_WHILE(bs), which requires
|
||||
* the caller to be either in the main thread or directly in the home thread
|
||||
* that runs the bs AioContext. Calling them from another thread in another
|
||||
* AioContext would cause deadlocks.
|
||||
*
|
||||
* Therefore, these functions are not proper I/O, because they
|
||||
* can't run in *any* iothreads, but only in a specific one.
|
||||
*
|
||||
* These functions can call any function from I/O, Common and this
|
||||
* categories, but must be invoked only by other "I/O or GS" and GS APIs.
|
||||
*
|
||||
* All functions in this category must use the macro
|
||||
* IO_OR_GS_CODE();
|
||||
* to catch when they are accidentally called by the wrong API.
|
||||
*/
|
||||
|
||||
#define BDRV_POLL_WHILE(bs, cond) ({ \
|
||||
BlockDriverState *bs_ = (bs); \
|
||||
IO_OR_GS_CODE(); \
|
||||
AIO_WAIT_WHILE(bdrv_get_aio_context(bs_), \
|
||||
cond); })
|
||||
|
||||
void bdrv_drain(BlockDriverState *bs);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
|
||||
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
|
||||
|
||||
/* Invalidate any cached metadata used by image formats */
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock bdrv_flush(BlockDriverState *bs);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
|
||||
|
||||
/**
|
||||
* bdrv_parent_drained_begin_single:
|
||||
*
|
||||
* Begin a quiesced section for the parent of @c.
|
||||
*/
|
||||
void GRAPH_RDLOCK bdrv_parent_drained_begin_single(BdrvChild *c);
|
||||
|
||||
/**
|
||||
* bdrv_parent_drained_poll_single:
|
||||
*
|
||||
* Returns true if there is any pending activity to cease before @c can be
|
||||
* called quiesced, false otherwise.
|
||||
*/
|
||||
bool GRAPH_RDLOCK bdrv_parent_drained_poll_single(BdrvChild *c);
|
||||
|
||||
/**
|
||||
* bdrv_parent_drained_end_single:
|
||||
*
|
||||
* End a quiesced section for the parent of @c.
|
||||
*/
|
||||
void GRAPH_RDLOCK bdrv_parent_drained_end_single(BdrvChild *c);
|
||||
|
||||
/**
|
||||
* bdrv_drain_poll:
|
||||
*
|
||||
* Poll for pending requests in @bs and its parents (except for @ignore_parent).
|
||||
*
|
||||
* If @ignore_bds_parents is true, parents that are BlockDriverStates must
|
||||
* ignore the drain request because they will be drained separately (used for
|
||||
* drain_all).
|
||||
*
|
||||
* This is part of bdrv_drained_begin.
|
||||
*/
|
||||
bool GRAPH_RDLOCK
|
||||
bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
|
||||
bool ignore_bds_parents);
|
||||
|
||||
/**
|
||||
* bdrv_drained_begin:
|
||||
*
|
||||
* Begin a quiesced section for exclusive access to the BDS, by disabling
|
||||
* external request sources including NBD server, block jobs, and device model.
|
||||
*
|
||||
* This function can only be invoked by the main loop or a coroutine
|
||||
* (regardless of the AioContext where it is running).
|
||||
* If the coroutine is running in an Iothread AioContext, this function will
|
||||
* just schedule a BH to run in the main loop.
|
||||
* However, it cannot be directly called by an Iothread.
|
||||
*
|
||||
* This function can be recursive.
|
||||
*/
|
||||
void GRAPH_UNLOCKED bdrv_drained_begin(BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* bdrv_do_drained_begin_quiesce:
|
||||
*
|
||||
* Quiesces a BDS like bdrv_drained_begin(), but does not wait for already
|
||||
* running requests to complete.
|
||||
*/
|
||||
void bdrv_do_drained_begin_quiesce(BlockDriverState *bs, BdrvChild *parent);
|
||||
|
||||
/**
|
||||
* bdrv_drained_end:
|
||||
*
|
||||
* End a quiescent section started by bdrv_drained_begin().
|
||||
*
|
||||
* This function can only be invoked by the main loop or a coroutine
|
||||
* (regardless of the AioContext where it is running).
|
||||
* If the coroutine is running in an Iothread AioContext, this function will
|
||||
* just schedule a BH to run in the main loop.
|
||||
* However, it cannot be directly called by an Iothread.
|
||||
*/
|
||||
void bdrv_drained_end(BlockDriverState *bs);
|
||||
|
||||
#endif /* BLOCK_IO_H */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
#include "block/block-global-state.h"
|
||||
#include "block/block-io.h"
|
||||
|
||||
/* DO NOT ADD ANYTHING IN HERE. USE ONE OF THE HEADERS INCLUDED ABOVE */
|
||||
|
||||
#endif /* BLOCK_H */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* QEMU backup
|
||||
*
|
||||
* Copyright (c) 2013 Proxmox Server Solutions
|
||||
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2016 FUJITSU LIMITED
|
||||
*
|
||||
* Authors:
|
||||
* Dietmar Maurer <[email protected]>
|
||||
* Changlong Xie <[email protected]>
|
||||
*
|
||||
* 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_BACKUP_H
|
||||
#define BLOCK_BACKUP_H
|
||||
|
||||
#include "block/blockjob.h"
|
||||
|
||||
void backup_do_checkpoint(BlockJob *job, Error **errp);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_INT_GLOBAL_STATE_H
|
||||
#define BLOCK_INT_GLOBAL_STATE_H
|
||||
|
||||
#include "block/blockjob.h"
|
||||
#include "block/block_int-common.h"
|
||||
#include "qemu/hbitmap.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* See include/block/block-global-state.h for more information about
|
||||
* the GS API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* stream_start:
|
||||
* @job_id: The id of the newly-created job, or %NULL to use the
|
||||
* device name of @bs.
|
||||
* @bs: Block device to operate on.
|
||||
* @base: Block device that will become the new base, or %NULL to
|
||||
* flatten the whole backing file chain onto @bs.
|
||||
* @backing_file_str: The file name that will be written to @bs as the
|
||||
* the new backing file if the job completes. Ignored if @base is %NULL.
|
||||
* @backing_mask_protocol: Replace potential protocol name with 'raw' in
|
||||
* 'backing file format' header
|
||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
||||
* See @BlockJobCreateFlags
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @on_error: The action to take upon error.
|
||||
* @filter_node_name: The node name that should be assigned to the filter
|
||||
* driver that the stream job inserts into the graph above
|
||||
* @bs. NULL means that a node name should be autogenerated.
|
||||
* @errp: Error object.
|
||||
*
|
||||
* Start a streaming operation on @bs. Clusters that are unallocated
|
||||
* in @bs, but allocated in any image between @base and @bs (both
|
||||
* exclusive) will be written to @bs. At the end of a successful
|
||||
* streaming job, the backing file of @bs will be changed to
|
||||
* @backing_file_str in the written image and to @base in the live
|
||||
* BlockDriverState.
|
||||
*/
|
||||
void stream_start(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *base, const char *backing_file_str,
|
||||
bool backing_mask_protocol,
|
||||
BlockDriverState *bottom,
|
||||
int creation_flags, int64_t speed,
|
||||
BlockdevOnError on_error,
|
||||
const char *filter_node_name,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* commit_start:
|
||||
* @job_id: The id of the newly-created job, or %NULL to use the
|
||||
* device name of @bs.
|
||||
* @bs: Active block device.
|
||||
* @top: Top block device to be committed.
|
||||
* @base: Block device that will be written into, and become the new top.
|
||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
||||
* See @BlockJobCreateFlags
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @on_error: The action to take upon error.
|
||||
* @backing_file_str: String to use as the backing file in @top's overlay
|
||||
* @backing_mask_protocol: Replace potential protocol name with 'raw' in
|
||||
* 'backing file format' header
|
||||
* @filter_node_name: The node name that should be assigned to the filter
|
||||
* driver that the commit job inserts into the graph above @top. NULL means
|
||||
* that a node name should be autogenerated.
|
||||
* @errp: Error object.
|
||||
*
|
||||
*/
|
||||
void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *base, BlockDriverState *top,
|
||||
int creation_flags, int64_t speed,
|
||||
BlockdevOnError on_error, const char *backing_file_str,
|
||||
bool backing_mask_protocol,
|
||||
const char *filter_node_name, Error **errp);
|
||||
/**
|
||||
* commit_active_start:
|
||||
* @job_id: The id of the newly-created job, or %NULL to use the
|
||||
* device name of @bs.
|
||||
* @bs: Active block device to be committed.
|
||||
* @base: Block device that will be written into, and become the new top.
|
||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
||||
* See @BlockJobCreateFlags
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @on_error: The action to take upon error.
|
||||
* @filter_node_name: The node name that should be assigned to the filter
|
||||
* driver that the commit job inserts into the graph above @bs. NULL means that
|
||||
* a node name should be autogenerated.
|
||||
* @cb: Completion function for the job.
|
||||
* @opaque: Opaque pointer value passed to @cb.
|
||||
* @auto_complete: Auto complete the job.
|
||||
* @errp: Error object.
|
||||
*
|
||||
*/
|
||||
BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *base, int creation_flags,
|
||||
int64_t speed, BlockdevOnError on_error,
|
||||
const char *filter_node_name,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
bool auto_complete, Error **errp);
|
||||
/*
|
||||
* mirror_start:
|
||||
* @job_id: The id of the newly-created job, or %NULL to use the
|
||||
* device name of @bs.
|
||||
* @bs: Block device to operate on.
|
||||
* @target: Block device to write to.
|
||||
* @replaces: Block graph node name to replace once the mirror is done. Can
|
||||
* only be used when full mirroring is selected.
|
||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
||||
* See @BlockJobCreateFlags
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @granularity: The chosen granularity for the dirty bitmap.
|
||||
* @buf_size: The amount of data that can be in flight at one time.
|
||||
* @mode: Whether to collapse all images in the chain to the target.
|
||||
* @backing_mode: How to establish the target's backing chain after completion.
|
||||
* @target_is_zero: Whether the target already is zero-initialized.
|
||||
* @on_source_error: The action to take upon error reading from the source.
|
||||
* @on_target_error: The action to take upon error writing to the target.
|
||||
* @unmap: Whether to unmap target where source sectors only contain zeroes.
|
||||
* @filter_node_name: The node name that should be assigned to the filter
|
||||
* driver that the mirror job inserts into the graph above @bs. NULL means that
|
||||
* a node name should be autogenerated.
|
||||
* @copy_mode: When to trigger writes to the target.
|
||||
* @errp: Error object.
|
||||
*
|
||||
* Start a mirroring operation on @bs. Clusters that are allocated
|
||||
* in @bs will be written to @target until the job is cancelled or
|
||||
* manually completed. At the end of a successful mirroring job,
|
||||
* @bs will be switched to read from @target.
|
||||
*/
|
||||
void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *target, const char *replaces,
|
||||
int creation_flags, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
|
||||
bool target_is_zero,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool unmap, const char *filter_node_name,
|
||||
MirrorCopyMode copy_mode, Error **errp);
|
||||
|
||||
/*
|
||||
* backup_job_create:
|
||||
* @job_id: The id of the newly-created job, or %NULL to use the
|
||||
* device name of @bs.
|
||||
* @bs: Block device to operate on.
|
||||
* @target: Block device to write to.
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @sync_mode: What parts of the disk image should be copied to the destination.
|
||||
* @sync_bitmap: The dirty bitmap if sync_mode is 'bitmap' or 'incremental'
|
||||
* @bitmap_mode: The bitmap synchronization policy to use.
|
||||
* @perf: Performance options. All actual fields assumed to be present,
|
||||
* all ".has_*" fields are ignored.
|
||||
* @on_source_error: The action to take upon error reading from the source.
|
||||
* @on_target_error: The action to take upon error writing to the target.
|
||||
* @on_cbw_error: The action to take upon error in copy-before-write operations.
|
||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
||||
* See @BlockJobCreateFlags
|
||||
* @cb: Completion function for the job.
|
||||
* @opaque: Opaque pointer value passed to @cb.
|
||||
* @txn: Transaction that this job is part of (may be NULL).
|
||||
*
|
||||
* Create a backup operation on @bs. Clusters in @bs are written to @target
|
||||
* until the job is cancelled or manually completed.
|
||||
*/
|
||||
BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *target, int64_t speed,
|
||||
MirrorSyncMode sync_mode,
|
||||
BdrvDirtyBitmap *sync_bitmap,
|
||||
BitmapSyncMode bitmap_mode,
|
||||
bool compress, bool discard_source,
|
||||
const char *filter_node_name,
|
||||
BackupPerf *perf,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
OnCbwError on_cbw_error,
|
||||
int creation_flags,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
JobTxn *txn, Error **errp);
|
||||
|
||||
BdrvChild * GRAPH_WRLOCK
|
||||
bdrv_root_attach_child(BlockDriverState *child_bs, const char *child_name,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
uint64_t perm, uint64_t shared_perm,
|
||||
void *opaque, Error **errp);
|
||||
|
||||
void GRAPH_WRLOCK bdrv_root_unref_child(BdrvChild *child);
|
||||
|
||||
void GRAPH_RDLOCK bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
|
||||
uint64_t *shared_perm);
|
||||
|
||||
/**
|
||||
* Sets a BdrvChild's permissions. Avoid if the parent is a BDS; use
|
||||
* bdrv_child_refresh_perms() instead and make the parent's
|
||||
* .bdrv_child_perm() implementation return the correct values.
|
||||
*/
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* Calls bs->drv->bdrv_child_perm() and updates the child's permission
|
||||
* masks with the result.
|
||||
* Drivers should invoke this function whenever an event occurs that
|
||||
* makes their .bdrv_child_perm() implementation return different
|
||||
* values than before, but which will not result in the block layer
|
||||
* automatically refreshing the permissions.
|
||||
*/
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
|
||||
|
||||
bool GRAPH_RDLOCK bdrv_recurse_can_replace(BlockDriverState *bs,
|
||||
BlockDriverState *to_replace);
|
||||
|
||||
/*
|
||||
* Default implementation for BlockDriver.bdrv_child_perm() that can
|
||||
* be used by block filters and image formats, as long as they use the
|
||||
* child_of_bds child class and set an appropriate BdrvChildRole.
|
||||
*/
|
||||
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
|
||||
BdrvChildRole role, BlockReopenQueue *reopen_queue,
|
||||
uint64_t perm, uint64_t shared,
|
||||
uint64_t *nperm, uint64_t *nshared);
|
||||
|
||||
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp);
|
||||
bool blk_dev_has_removable_media(BlockBackend *blk);
|
||||
void blk_dev_eject_request(BlockBackend *blk, bool force);
|
||||
bool blk_dev_is_medium_locked(BlockBackend *blk);
|
||||
|
||||
void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup);
|
||||
|
||||
void bdrv_set_monitor_owned(BlockDriverState *bs);
|
||||
|
||||
void blockdev_close_all_bdrv_states(void);
|
||||
|
||||
BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp);
|
||||
|
||||
/**
|
||||
* Simple implementation of bdrv_co_create_opts for protocol drivers
|
||||
* which only support creation via opening a file
|
||||
* (usually existing raw storage device)
|
||||
*/
|
||||
int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
|
||||
const char *filename,
|
||||
QemuOpts *opts,
|
||||
Error **errp);
|
||||
|
||||
BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
|
||||
const char *name,
|
||||
BlockDriverState **pbs,
|
||||
Error **errp);
|
||||
BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
|
||||
BlockDirtyBitmapOrStrList *bms,
|
||||
HBitmap **backup, Error **errp);
|
||||
BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
|
||||
bool release,
|
||||
BlockDriverState **bitmap_bs,
|
||||
Error **errp);
|
||||
|
||||
|
||||
BlockDriverState * GRAPH_RDLOCK
|
||||
bdrv_skip_implicit_filters(BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* bdrv_add_aio_context_notifier:
|
||||
*
|
||||
* If a long-running job intends to be always run in the same AioContext as a
|
||||
* certain BDS, it may use this function to be notified of changes regarding the
|
||||
* association of the BDS to an AioContext.
|
||||
*
|
||||
* attached_aio_context() is called after the target BDS has been attached to a
|
||||
* new AioContext; detach_aio_context() is called before the target BDS is being
|
||||
* detached from its old AioContext.
|
||||
*/
|
||||
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
|
||||
void (*attached_aio_context)(AioContext *new_context, void *opaque),
|
||||
void (*detach_aio_context)(void *opaque), void *opaque);
|
||||
|
||||
/**
|
||||
* bdrv_remove_aio_context_notifier:
|
||||
*
|
||||
* Unsubscribe of change notifications regarding the BDS's AioContext. The
|
||||
* parameters given here have to be the same as those given to
|
||||
* bdrv_add_aio_context_notifier().
|
||||
*/
|
||||
void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
|
||||
void (*aio_context_attached)(AioContext *,
|
||||
void *),
|
||||
void (*aio_context_detached)(void *),
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* End all quiescent sections started by bdrv_drain_all_begin(). This is
|
||||
* needed when deleting a BDS before bdrv_drain_all_end() is called.
|
||||
*
|
||||
* NOTE: this is an internal helper for bdrv_close() *only*. No one else
|
||||
* should call it.
|
||||
*/
|
||||
void bdrv_drain_all_end_quiesce(BlockDriverState *bs);
|
||||
|
||||
#endif /* BLOCK_INT_GLOBAL_STATE_H */
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_INT_IO_H
|
||||
#define BLOCK_INT_IO_H
|
||||
|
||||
#include "block/block_int-common.h"
|
||||
#include "qemu/hbitmap.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
/*
|
||||
* I/O API functions. These functions are thread-safe.
|
||||
*
|
||||
* See include/block/block-io.h for more information about
|
||||
* the I/O API.
|
||||
*/
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status(
|
||||
BlockDriverState *bs, unsigned int mode, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
|
||||
int64_t offset, int64_t bytes);
|
||||
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_part(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags);
|
||||
int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev_part(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
|
||||
|
||||
static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pread(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
IO_CODE();
|
||||
assert_bdrv_graph_readable();
|
||||
|
||||
return bdrv_co_preadv(child, offset, bytes, &qiov, flags);
|
||||
}
|
||||
|
||||
static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pwrite(BdrvChild *child,
|
||||
int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
IO_CODE();
|
||||
assert_bdrv_graph_readable();
|
||||
|
||||
return bdrv_co_pwritev(child, offset, bytes, &qiov, flags);
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
|
||||
uint64_t align);
|
||||
BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs);
|
||||
|
||||
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
|
||||
const char *filename);
|
||||
|
||||
/**
|
||||
* bdrv_wakeup:
|
||||
* @bs: The BlockDriverState for which an I/O operation has been completed.
|
||||
*
|
||||
* Wake up the main thread if it is waiting on BDRV_POLL_WHILE. During
|
||||
* synchronous I/O on a BlockDriverState that is attached to another
|
||||
* I/O thread, the main thread lets the I/O thread's event loop run,
|
||||
* waiting for the I/O operation to complete. A bdrv_wakeup will wake
|
||||
* up the main thread if necessary.
|
||||
*
|
||||
* Manual calls to bdrv_wakeup are rarely necessary, because
|
||||
* bdrv_dec_in_flight already calls it.
|
||||
*/
|
||||
void bdrv_wakeup(BlockDriverState *bs);
|
||||
|
||||
const char * GRAPH_RDLOCK bdrv_get_parent_name(const BlockDriverState *bs);
|
||||
bool blk_dev_has_tray(BlockBackend *blk);
|
||||
bool blk_dev_is_tray_open(BlockBackend *blk);
|
||||
|
||||
void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes);
|
||||
|
||||
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out);
|
||||
void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
|
||||
const BdrvDirtyBitmap *src,
|
||||
HBitmap **backup, bool lock);
|
||||
|
||||
void bdrv_inc_in_flight(BlockDriverState *bs);
|
||||
void bdrv_dec_in_flight(BlockDriverState *bs);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
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);
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
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);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
|
||||
|
||||
int co_wrapper_mixed_bdrv_rdlock
|
||||
bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
|
||||
|
||||
BdrvChild * GRAPH_RDLOCK bdrv_cow_child(BlockDriverState *bs);
|
||||
BdrvChild * GRAPH_RDLOCK bdrv_filter_child(BlockDriverState *bs);
|
||||
BdrvChild * GRAPH_RDLOCK bdrv_filter_or_cow_child(BlockDriverState *bs);
|
||||
BdrvChild * GRAPH_RDLOCK bdrv_primary_child(BlockDriverState *bs);
|
||||
BlockDriverState * GRAPH_RDLOCK bdrv_skip_filters(BlockDriverState *bs);
|
||||
BlockDriverState * GRAPH_RDLOCK bdrv_backing_chain_next(BlockDriverState *bs);
|
||||
|
||||
static inline BlockDriverState * GRAPH_RDLOCK
|
||||
bdrv_cow_bs(BlockDriverState *bs)
|
||||
{
|
||||
IO_CODE();
|
||||
return child_bs(bdrv_cow_child(bs));
|
||||
}
|
||||
|
||||
static inline BlockDriverState * GRAPH_RDLOCK
|
||||
bdrv_filter_bs(BlockDriverState *bs)
|
||||
{
|
||||
IO_CODE();
|
||||
return child_bs(bdrv_filter_child(bs));
|
||||
}
|
||||
|
||||
static inline BlockDriverState * GRAPH_RDLOCK
|
||||
bdrv_filter_or_cow_bs(BlockDriverState *bs)
|
||||
{
|
||||
IO_CODE();
|
||||
return child_bs(bdrv_filter_or_cow_child(bs));
|
||||
}
|
||||
|
||||
static inline BlockDriverState * GRAPH_RDLOCK
|
||||
bdrv_primary_bs(BlockDriverState *bs)
|
||||
{
|
||||
IO_CODE();
|
||||
return child_bs(bdrv_primary_child(bs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given offset is in the cached block-status data
|
||||
* region.
|
||||
*
|
||||
* If it is, and @pnum is not NULL, *pnum is set to
|
||||
* `bsc.data_end - offset`, i.e. how many bytes, starting from
|
||||
* @offset, are data (according to the cache).
|
||||
* Otherwise, *pnum is not touched.
|
||||
*/
|
||||
bool bdrv_bsc_is_data(BlockDriverState *bs, int64_t offset, int64_t *pnum);
|
||||
|
||||
/**
|
||||
* If [offset, offset + bytes) overlaps with the currently cached
|
||||
* block-status region, invalidate the cache.
|
||||
*
|
||||
* (To be used by I/O paths that cause data regions to be zero or
|
||||
* holes.)
|
||||
*/
|
||||
void bdrv_bsc_invalidate_range(BlockDriverState *bs,
|
||||
int64_t offset, int64_t bytes);
|
||||
|
||||
/**
|
||||
* Mark the range [offset, offset + bytes) as a data region.
|
||||
*/
|
||||
void bdrv_bsc_fill(BlockDriverState *bs, int64_t offset, int64_t bytes);
|
||||
|
||||
/*
|
||||
* Notify all parents that the size of the child changed.
|
||||
*/
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_parent_cb_resize(BlockDriverState *bs);
|
||||
|
||||
#endif /* BLOCK_INT_IO_H */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* QEMU System Emulator block driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BLOCK_INT_H
|
||||
#define BLOCK_INT_H
|
||||
|
||||
#include "block/block_int-global-state.h"
|
||||
#include "block/block_int-io.h"
|
||||
#include "block/graph-lock.h"
|
||||
|
||||
/* DO NOT ADD ANYTHING IN HERE. USE ONE OF THE HEADERS INCLUDED ABOVE */
|
||||
|
||||
#endif /* BLOCK_INT_H */
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Declarations for long-running block device operations
|
||||
*
|
||||
* Copyright (c) 2011 IBM Corp.
|
||||
* Copyright (c) 2012 Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BLOCKJOB_H
|
||||
#define BLOCKJOB_H
|
||||
|
||||
#include "qapi/qapi-types-block-core.h"
|
||||
#include "qemu/job.h"
|
||||
#include "qemu/ratelimit.h"
|
||||
|
||||
#define BLOCK_JOB_SLICE_TIME 100000000ULL /* ns */
|
||||
|
||||
typedef struct BlockJobDriver BlockJobDriver;
|
||||
|
||||
/**
|
||||
* BlockJob:
|
||||
*
|
||||
* Long-running operation on a BlockDriverState.
|
||||
*/
|
||||
typedef struct BlockJob {
|
||||
/**
|
||||
* Data belonging to the generic Job infrastructure.
|
||||
* Protected by job mutex.
|
||||
*/
|
||||
Job job;
|
||||
|
||||
/**
|
||||
* Status that is published by the query-block-jobs QMP API.
|
||||
* Protected by job mutex.
|
||||
*/
|
||||
BlockDeviceIoStatus iostatus;
|
||||
|
||||
/**
|
||||
* Speed that was set with @block_job_set_speed.
|
||||
* Always modified and read under the BQL (GLOBAL_STATE_CODE).
|
||||
*/
|
||||
int64_t speed;
|
||||
|
||||
/**
|
||||
* Rate limiting data structure for implementing @speed.
|
||||
* RateLimit API is thread-safe.
|
||||
*/
|
||||
RateLimit limit;
|
||||
|
||||
/**
|
||||
* Block other operations when block job is running.
|
||||
* Always modified and read under the BQL (GLOBAL_STATE_CODE).
|
||||
*/
|
||||
Error *blocker;
|
||||
|
||||
/** All notifiers are set once in block_job_create() and never modified. */
|
||||
|
||||
/** Called when a cancelled job is finalised. */
|
||||
Notifier finalize_cancelled_notifier;
|
||||
|
||||
/** Called when a successfully completed job is finalised. */
|
||||
Notifier finalize_completed_notifier;
|
||||
|
||||
/** Called when the job transitions to PENDING */
|
||||
Notifier pending_notifier;
|
||||
|
||||
/** Called when the job transitions to READY */
|
||||
Notifier ready_notifier;
|
||||
|
||||
/** Called when the job coroutine yields or terminates */
|
||||
Notifier idle_notifier;
|
||||
|
||||
/**
|
||||
* BlockDriverStates that are involved in this block job.
|
||||
* Always modified and read under the BQL (GLOBAL_STATE_CODE).
|
||||
*/
|
||||
GSList *nodes;
|
||||
} BlockJob;
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* See include/block/block-global-state.h for more information about
|
||||
* the GS API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* block_job_next_locked:
|
||||
* @job: A block job, or %NULL.
|
||||
*
|
||||
* Get the next element from the list of block jobs after @job, or the
|
||||
* first one if @job is %NULL.
|
||||
*
|
||||
* Returns the requested job, or %NULL if there are no more jobs left.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
BlockJob *block_job_next_locked(BlockJob *job);
|
||||
|
||||
/**
|
||||
* block_job_get:
|
||||
* @id: The id of the block job.
|
||||
*
|
||||
* Get the block job identified by @id (which must not be %NULL).
|
||||
*
|
||||
* Returns the requested job, or %NULL if it doesn't exist.
|
||||
* Called with job lock *not* held.
|
||||
*/
|
||||
BlockJob *block_job_get(const char *id);
|
||||
|
||||
/* Same as block_job_get(), but called with job lock held. */
|
||||
BlockJob *block_job_get_locked(const char *id);
|
||||
|
||||
/**
|
||||
* block_job_add_bdrv:
|
||||
* @job: A block job
|
||||
* @name: The name to assign to the new BdrvChild
|
||||
* @bs: A BlockDriverState that is involved in @job
|
||||
* @perm, @shared_perm: Permissions to request on the node
|
||||
*
|
||||
* Add @bs to the list of BlockDriverState that are involved in
|
||||
* @job. This means that all operations will be blocked on @bs while
|
||||
* @job exists.
|
||||
*
|
||||
* All block nodes must be drained.
|
||||
*/
|
||||
int GRAPH_WRLOCK
|
||||
block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
||||
uint64_t perm, uint64_t shared_perm, Error **errp);
|
||||
|
||||
/**
|
||||
* block_job_remove_all_bdrv:
|
||||
* @job: The block job
|
||||
*
|
||||
* Remove all BlockDriverStates from the list of nodes that are involved in the
|
||||
* job. This removes the blockers added with block_job_add_bdrv().
|
||||
*/
|
||||
void GRAPH_UNLOCKED block_job_remove_all_bdrv(BlockJob *job);
|
||||
|
||||
/**
|
||||
* block_job_has_bdrv:
|
||||
* @job: The block job
|
||||
*
|
||||
* Searches for @bs in the list of nodes that are involved in the
|
||||
* job.
|
||||
*/
|
||||
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* block_job_set_speed_locked:
|
||||
* @job: The job to set the speed for.
|
||||
* @speed: The new value
|
||||
* @errp: Error object.
|
||||
*
|
||||
* Set a rate-limiting parameter for the job; the actual meaning may
|
||||
* vary depending on the job type.
|
||||
*
|
||||
* Called with job lock held, but might release it temporarily.
|
||||
*/
|
||||
bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp);
|
||||
|
||||
/**
|
||||
* block_job_change_locked:
|
||||
* @job: The job to change.
|
||||
* @opts: The new options.
|
||||
* @errp: Error object.
|
||||
*
|
||||
* Change the job according to opts.
|
||||
*/
|
||||
void block_job_change_locked(BlockJob *job, BlockJobChangeOptions *opts,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* block_job_query_locked:
|
||||
* @job: The job to get information about.
|
||||
*
|
||||
* Return information about a job.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp);
|
||||
|
||||
/**
|
||||
* block_job_iostatus_reset_locked:
|
||||
* @job: The job whose I/O status should be reset.
|
||||
*
|
||||
* Reset I/O status on @job and on BlockDriverState objects it uses,
|
||||
* other than job->blk.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void block_job_iostatus_reset_locked(BlockJob *job);
|
||||
|
||||
/*
|
||||
* block_job_get_aio_context:
|
||||
*
|
||||
* Returns aio context associated with a block job.
|
||||
*/
|
||||
AioContext *block_job_get_aio_context(BlockJob *job);
|
||||
|
||||
|
||||
/*
|
||||
* Common functions that are neither I/O nor Global State.
|
||||
*
|
||||
* See include/block/block-common.h for more information about
|
||||
* the Common API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* block_job_is_internal:
|
||||
* @job: The job to determine if it is user-visible or not.
|
||||
*
|
||||
* Returns true if the job should not be visible to the management layer.
|
||||
*/
|
||||
bool block_job_is_internal(BlockJob *job);
|
||||
|
||||
/**
|
||||
* block_job_driver:
|
||||
*
|
||||
* Returns the driver associated with a block job.
|
||||
*/
|
||||
const BlockJobDriver *block_job_driver(BlockJob *job);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Declarations for long-running block device operations
|
||||
*
|
||||
* Copyright (c) 2011 IBM Corp.
|
||||
* Copyright (c) 2012 Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BLOCKJOB_INT_H
|
||||
#define BLOCKJOB_INT_H
|
||||
|
||||
#include "block/blockjob.h"
|
||||
|
||||
/**
|
||||
* BlockJobDriver:
|
||||
*
|
||||
* A class type for block job driver.
|
||||
*/
|
||||
struct BlockJobDriver {
|
||||
/** Generic JobDriver callbacks and settings */
|
||||
JobDriver job_driver;
|
||||
|
||||
/*
|
||||
* I/O API functions. These functions are thread-safe.
|
||||
*
|
||||
* See include/block/block-io.h for more information about
|
||||
* the I/O API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Returns whether the job has pending requests for the child or will
|
||||
* submit new requests before the next pause point. This callback is polled
|
||||
* in the context of draining a job node after requesting that the job be
|
||||
* paused, until all activity on the child has stopped.
|
||||
*/
|
||||
bool (*drained_poll)(BlockJob *job);
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* See include/block/block-global-state.h for more information about
|
||||
* the GS API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If the callback is not NULL, it will be invoked before the job is
|
||||
* resumed in a new AioContext. This is the place to move any resources
|
||||
* besides job->blk to the new AioContext.
|
||||
*/
|
||||
void (*attached_aio_context)(BlockJob *job, AioContext *new_context);
|
||||
|
||||
void (*set_speed)(BlockJob *job, int64_t speed);
|
||||
|
||||
/*
|
||||
* Change the @job's options according to @opts.
|
||||
*
|
||||
* Note that this can already be called before the job coroutine is running.
|
||||
*/
|
||||
void (*change)(BlockJob *job, BlockJobChangeOptions *opts, Error **errp);
|
||||
|
||||
/*
|
||||
* Query information specific to this kind of block job.
|
||||
*/
|
||||
void (*query)(BlockJob *job, BlockJobInfo *info);
|
||||
};
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* See include/block/block-global-state.h for more information about
|
||||
* the GS API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* block_job_create:
|
||||
* @job_id: The id of the newly-created job, or %NULL to have one
|
||||
* generated automatically.
|
||||
* @driver: The class object for the newly-created job.
|
||||
* @txn: The transaction this job belongs to, if any. %NULL otherwise.
|
||||
* @bs: The block
|
||||
* @perm, @shared_perm: Permissions to request for @bs
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @flags: Creation flags for the Block Job. See @JobCreateFlags.
|
||||
* @cb: Completion function for the job.
|
||||
* @opaque: Opaque pointer value passed to @cb.
|
||||
* @errp: Error object.
|
||||
*
|
||||
* Create a new long-running block device job and return it. The job
|
||||
* will call @cb asynchronously when the job completes. Note that
|
||||
* @bs may have been closed at the time the @cb it is called. If
|
||||
* this is the case, the job may be reported as either cancelled or
|
||||
* completed.
|
||||
*
|
||||
* This function is not part of the public job interface; it should be
|
||||
* called from a wrapper that is specific to the job type.
|
||||
*/
|
||||
void * GRAPH_UNLOCKED
|
||||
block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
JobTxn *txn, BlockDriverState *bs, uint64_t perm,
|
||||
uint64_t shared_perm, int64_t speed, int flags,
|
||||
BlockCompletionFunc *cb, void *opaque, Error **errp);
|
||||
|
||||
/**
|
||||
* block_job_free:
|
||||
* Callback to be used for JobDriver.free in all block jobs. Frees block job
|
||||
* specific resources in @job.
|
||||
*/
|
||||
void block_job_free(Job *job);
|
||||
|
||||
/**
|
||||
* block_job_user_resume:
|
||||
* Callback to be used for JobDriver.user_resume in all block jobs. Resets the
|
||||
* iostatus when the user resumes @job.
|
||||
*/
|
||||
void block_job_user_resume(Job *job);
|
||||
|
||||
/*
|
||||
* I/O API functions. These functions are thread-safe.
|
||||
*
|
||||
* See include/block/block-io.h for more information about
|
||||
* the I/O API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* block_job_ratelimit_processed_bytes:
|
||||
*
|
||||
* To be called after some work has been done. Adjusts the delay for the next
|
||||
* request. See the documentation of ratelimit_calculate_delay() for details.
|
||||
*/
|
||||
void block_job_ratelimit_processed_bytes(BlockJob *job, uint64_t n);
|
||||
|
||||
/**
|
||||
* Put the job to sleep (assuming that it wasn't canceled) to throttle it to the
|
||||
* right speed according to its rate limiting.
|
||||
*/
|
||||
void block_job_ratelimit_sleep(BlockJob *job);
|
||||
|
||||
/**
|
||||
* block_job_error_action:
|
||||
* @job: The job to signal an error for.
|
||||
* @on_err: The error action setting.
|
||||
* @is_read: Whether the operation was a read.
|
||||
* @error: The error that was reported.
|
||||
*
|
||||
* Report an I/O error for a block job and possibly stop the VM. Return the
|
||||
* action that was selected based on @on_err and @error.
|
||||
*/
|
||||
BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
|
||||
int is_read, int error);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
#ifndef BLOCK_DIRTY_BITMAP_H
|
||||
#define BLOCK_DIRTY_BITMAP_H
|
||||
|
||||
#include "block/block-common.h"
|
||||
#include "block/graph-lock.h"
|
||||
#include "qapi/qapi-types-block-core.h"
|
||||
#include "qemu/hbitmap.h"
|
||||
|
||||
typedef enum BitmapCheckFlags {
|
||||
BDRV_BITMAP_BUSY = 1,
|
||||
BDRV_BITMAP_RO = 2,
|
||||
BDRV_BITMAP_INCONSISTENT = 4,
|
||||
} BitmapCheckFlags;
|
||||
|
||||
#define BDRV_BITMAP_DEFAULT (BDRV_BITMAP_BUSY | BDRV_BITMAP_RO | \
|
||||
BDRV_BITMAP_INCONSISTENT)
|
||||
#define BDRV_BITMAP_ALLOW_RO (BDRV_BITMAP_BUSY | BDRV_BITMAP_INCONSISTENT)
|
||||
|
||||
#define BDRV_BITMAP_MAX_NAME_SIZE 1023
|
||||
|
||||
bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs);
|
||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
|
||||
uint32_t granularity,
|
||||
const char *name,
|
||||
Error **errp);
|
||||
int bdrv_dirty_bitmap_create_successor(BdrvDirtyBitmap *bitmap,
|
||||
Error **errp);
|
||||
BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BdrvDirtyBitmap *bitmap,
|
||||
Error **errp);
|
||||
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BdrvDirtyBitmap *bitmap,
|
||||
Error **errp);
|
||||
void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap);
|
||||
BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs,
|
||||
const char *name);
|
||||
int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
|
||||
Error **errp);
|
||||
void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
|
||||
Error **errp);
|
||||
int co_wrapper_bdrv_rdlock
|
||||
bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
|
||||
Error **errp);
|
||||
|
||||
void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap);
|
||||
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
|
||||
uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs);
|
||||
uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap);
|
||||
bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap);
|
||||
bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap);
|
||||
const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap);
|
||||
int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
|
||||
int64_t offset, int64_t bytes);
|
||||
void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
|
||||
int64_t offset, int64_t bytes);
|
||||
BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter);
|
||||
|
||||
uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
|
||||
uint64_t offset, uint64_t bytes);
|
||||
uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap);
|
||||
uint64_t bdrv_dirty_bitmap_serialization_coverage(int serialized_chunk_size,
|
||||
const BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
|
||||
uint8_t *buf, uint64_t offset,
|
||||
uint64_t bytes);
|
||||
void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
|
||||
uint8_t *buf, uint64_t offset,
|
||||
uint64_t bytes, bool finish);
|
||||
void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
|
||||
uint64_t offset, uint64_t bytes,
|
||||
bool finish);
|
||||
void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
|
||||
uint64_t offset, uint64_t bytes,
|
||||
bool finish);
|
||||
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
|
||||
|
||||
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
|
||||
void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap,
|
||||
bool persistent);
|
||||
void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy);
|
||||
bool bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
|
||||
HBitmap **backup, Error **errp);
|
||||
void bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap *bitmap, bool skip);
|
||||
bool bdrv_dirty_bitmap_get(BdrvDirtyBitmap *bitmap, int64_t offset);
|
||||
|
||||
/* Functions that require manual locking. */
|
||||
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap);
|
||||
bool bdrv_dirty_bitmap_get_locked(BdrvDirtyBitmap *bitmap, int64_t offset);
|
||||
void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
|
||||
int64_t offset, int64_t bytes);
|
||||
void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
|
||||
int64_t offset, int64_t bytes);
|
||||
int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter);
|
||||
void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t offset);
|
||||
int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
|
||||
void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes);
|
||||
bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap);
|
||||
bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
|
||||
bool bdrv_has_named_bitmaps(BlockDriverState *bs);
|
||||
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
|
||||
bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap);
|
||||
bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap);
|
||||
|
||||
BdrvDirtyBitmap *bdrv_dirty_bitmap_first(BlockDriverState *bs);
|
||||
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BdrvDirtyBitmap *bitmap);
|
||||
#define FOR_EACH_DIRTY_BITMAP(bs, bitmap) \
|
||||
for (bitmap = bdrv_dirty_bitmap_first(bs); bitmap; \
|
||||
bitmap = bdrv_dirty_bitmap_next(bitmap))
|
||||
|
||||
char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp);
|
||||
int64_t bdrv_dirty_bitmap_next_dirty(BdrvDirtyBitmap *bitmap, int64_t offset,
|
||||
int64_t bytes);
|
||||
int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, int64_t offset,
|
||||
int64_t bytes);
|
||||
bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap *bitmap,
|
||||
int64_t start, int64_t end, int64_t max_dirty_count,
|
||||
int64_t *dirty_start, int64_t *dirty_count);
|
||||
bool bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap, int64_t offset,
|
||||
int64_t bytes, int64_t *count);
|
||||
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
|
||||
Error **errp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Declarations for block exports
|
||||
*
|
||||
* Copyright (c) 2012, 2020 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Paolo Bonzini <[email protected]>
|
||||
* Kevin Wolf <[email protected]>
|
||||
*
|
||||
* 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_EXPORT_H
|
||||
#define BLOCK_EXPORT_H
|
||||
|
||||
#include "qapi/qapi-types-block-export.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef struct BlockExport BlockExport;
|
||||
|
||||
typedef struct BlockExportDriver {
|
||||
/* The export type that this driver services */
|
||||
BlockExportType type;
|
||||
|
||||
/*
|
||||
* The size of the driver-specific state that contains BlockExport as its
|
||||
* first field.
|
||||
*/
|
||||
size_t instance_size;
|
||||
|
||||
/* True if the export type supports running on an inactive node */
|
||||
bool supports_inactive;
|
||||
|
||||
/*
|
||||
* Creates and starts a new block export.
|
||||
*
|
||||
* If the user passed a set of I/O threads for multi-threading, @multithread
|
||||
* is a list of the @multithread_count corresponding contexts (freed by the
|
||||
* caller). Note that @exp->ctx has no relation to that list.
|
||||
*/
|
||||
int (*create)(BlockExport *exp, BlockExportOptions *opts,
|
||||
AioContext *const *multithread, size_t multithread_count,
|
||||
Error **errp);
|
||||
|
||||
/*
|
||||
* Frees a removed block export. This function is only called after all
|
||||
* references have been dropped.
|
||||
*/
|
||||
void (*delete)(BlockExport *);
|
||||
|
||||
/*
|
||||
* Start to disconnect all clients and drop other references held
|
||||
* internally by the export driver. When the function returns, there may
|
||||
* still be active references while the export is in the process of
|
||||
* shutting down.
|
||||
*/
|
||||
void (*request_shutdown)(BlockExport *);
|
||||
} BlockExportDriver;
|
||||
|
||||
struct BlockExport {
|
||||
const BlockExportDriver *drv;
|
||||
|
||||
/* Unique identifier for the export */
|
||||
char *id;
|
||||
|
||||
/*
|
||||
* Reference count for this block export. This includes strong references
|
||||
* both from the owner (qemu-nbd or the monitor) and clients connected to
|
||||
* the export.
|
||||
*
|
||||
* Use atomics to access this field.
|
||||
*/
|
||||
int refcount;
|
||||
|
||||
/*
|
||||
* True if one of the references in refcount belongs to the user. After the
|
||||
* user has dropped their reference, they may not e.g. remove the same
|
||||
* export a second time (which would decrease the refcount without having
|
||||
* it incremented first).
|
||||
*/
|
||||
bool user_owned;
|
||||
|
||||
/* The AioContext whose lock protects this BlockExport object. */
|
||||
AioContext *ctx;
|
||||
|
||||
/* The block device to export */
|
||||
BlockBackend *blk;
|
||||
|
||||
/* List entry for block_exports */
|
||||
QLIST_ENTRY(BlockExport) next;
|
||||
};
|
||||
|
||||
BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp);
|
||||
BlockExport *blk_exp_find(const char *id);
|
||||
void blk_exp_ref(BlockExport *exp);
|
||||
void blk_exp_unref(BlockExport *exp);
|
||||
void blk_exp_request_shutdown(BlockExport *exp);
|
||||
void blk_exp_close_all(void);
|
||||
void blk_exp_close_all_type(BlockExportType type);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Present a block device as a raw image through FUSE
|
||||
*
|
||||
* Copyright (c) 2020 Max Reitz <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; under version 2 or later of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_FUSE_H
|
||||
#define BLOCK_FUSE_H
|
||||
|
||||
#ifdef CONFIG_FUSE
|
||||
|
||||
#include "block/export.h"
|
||||
|
||||
extern const BlockExportDriver blk_exp_fuse;
|
||||
|
||||
#endif /* CONFIG_FUSE */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Graph lock: rwlock to protect block layer graph manipulations (add/remove
|
||||
* edges and nodes)
|
||||
*
|
||||
* Copyright (c) 2022 Red Hat
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef GRAPH_LOCK_H
|
||||
#define GRAPH_LOCK_H
|
||||
|
||||
/**
|
||||
* Graph Lock API
|
||||
* This API provides a rwlock used to protect block layer
|
||||
* graph modifications like edge (BdrvChild) and node (BlockDriverState)
|
||||
* addition and removal.
|
||||
* Currently we have 1 writer only, the Main loop, and many
|
||||
* readers, mostly coroutines running in other AioContext thus other threads.
|
||||
*
|
||||
* We distinguish between writer (main loop, under BQL) that modifies the
|
||||
* graph, and readers (all other coroutines running in various AioContext),
|
||||
* that go through the graph edges, reading
|
||||
* BlockDriverState ->parents and->children.
|
||||
*
|
||||
* The writer (main loop) has an "exclusive" access, so it first waits for
|
||||
* current read to finish, and then prevents incoming ones from
|
||||
* entering while it has the exclusive access.
|
||||
*
|
||||
* The readers (coroutines in multiple AioContext) are free to
|
||||
* access the graph as long the writer is not modifying the graph.
|
||||
* In case it is, they go in a CoQueue and sleep until the writer
|
||||
* is done.
|
||||
*
|
||||
* If a coroutine changes AioContext, the counter in the original and new
|
||||
* AioContext are left intact, since the writer does not care where is the
|
||||
* reader, but only if there is one.
|
||||
* As a result, some AioContexts might have a negative reader count, to
|
||||
* balance the positive count of the AioContext that took the lock.
|
||||
* This also means that when an AioContext is deleted it may have a nonzero
|
||||
* reader count. In that case we transfer the count to a global shared counter
|
||||
* so that the writer is always aware of all readers.
|
||||
*/
|
||||
typedef struct BdrvGraphRWlock BdrvGraphRWlock;
|
||||
|
||||
/* Dummy lock object to use for Thread Safety Analysis (TSA) */
|
||||
typedef struct TSA_CAPABILITY("mutex") BdrvGraphLock {
|
||||
} BdrvGraphLock;
|
||||
|
||||
extern BdrvGraphLock graph_lock;
|
||||
|
||||
/*
|
||||
* clang doesn't check consistency in locking annotations between forward
|
||||
* declarations and the function definition. Having the annotation on the
|
||||
* definition, but not the declaration in a header file, may give the reader
|
||||
* a false sense of security because the condition actually remains unchecked
|
||||
* for callers in other source files.
|
||||
*
|
||||
* Therefore, as a convention, for public functions, GRAPH_RDLOCK and
|
||||
* GRAPH_WRLOCK annotations should be present only in the header file.
|
||||
*/
|
||||
#define GRAPH_WRLOCK TSA_REQUIRES(graph_lock)
|
||||
#define GRAPH_RDLOCK TSA_REQUIRES_SHARED(graph_lock)
|
||||
#define GRAPH_UNLOCKED TSA_EXCLUDES(graph_lock)
|
||||
|
||||
/*
|
||||
* TSA annotations are not part of function types, so checks are defeated when
|
||||
* using a function pointer. As a workaround, annotate function pointers with
|
||||
* this macro that will require that the lock is at least taken while reading
|
||||
* the pointer. In most cases this is equivalent to actually protecting the
|
||||
* function call.
|
||||
*/
|
||||
#define GRAPH_RDLOCK_PTR TSA_GUARDED_BY(graph_lock)
|
||||
#define GRAPH_WRLOCK_PTR TSA_GUARDED_BY(graph_lock)
|
||||
#define GRAPH_UNLOCKED_PTR
|
||||
|
||||
/*
|
||||
* register_aiocontext:
|
||||
* Add AioContext @ctx to the list of AioContext.
|
||||
* This list is used to obtain the total number of readers
|
||||
* currently running the graph.
|
||||
*/
|
||||
void register_aiocontext(AioContext *ctx);
|
||||
|
||||
/*
|
||||
* unregister_aiocontext:
|
||||
* Removes AioContext @ctx to the list of AioContext.
|
||||
*/
|
||||
void unregister_aiocontext(AioContext *ctx);
|
||||
|
||||
/*
|
||||
* bdrv_graph_wrlock:
|
||||
* Start an exclusive write operation to modify the graph. This means we are
|
||||
* adding or removing an edge or a node in the block layer graph. Nobody else
|
||||
* is allowed to access the graph.
|
||||
*
|
||||
* Must only be called from outside bdrv_graph_co_rdlock.
|
||||
*
|
||||
* The wrlock can only be taken from the main loop, with BQL held, as only the
|
||||
* main loop is allowed to modify the graph.
|
||||
*/
|
||||
void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_wrlock(void);
|
||||
|
||||
/*
|
||||
* bdrv_graph_wrlock_drained:
|
||||
* Similar to bdrv_graph_wrlock, but will begin a drained section before
|
||||
* locking.
|
||||
*/
|
||||
void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_wrlock_drained(void);
|
||||
|
||||
/*
|
||||
* bdrv_graph_wrunlock:
|
||||
* Write finished, reset global has_writer to 0 and restart
|
||||
* all readers that are waiting.
|
||||
*
|
||||
* Also ends the drained section if bdrv_graph_wrlock_drained() was used to lock
|
||||
* the graph.
|
||||
*/
|
||||
void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_wrunlock(void);
|
||||
|
||||
/*
|
||||
* bdrv_graph_co_rdlock:
|
||||
* Read the bs graph. This usually means traversing all nodes in
|
||||
* the graph, therefore it can't happen while another thread is
|
||||
* modifying it.
|
||||
* Increases the reader counter of the current aiocontext,
|
||||
* and if has_writer is set, it means that the writer is modifying
|
||||
* the graph, therefore wait in a coroutine queue.
|
||||
* The writer will then wake this coroutine once it is done.
|
||||
*
|
||||
* This lock should be taken from Iothreads (IO_CODE() class of functions)
|
||||
* because it signals the writer that there are some
|
||||
* readers currently running, or waits until the current
|
||||
* write is finished before continuing.
|
||||
* Calling this function from the Main Loop with BQL held
|
||||
* is not necessary, since the Main Loop itself is the only
|
||||
* writer, thus won't be able to read and write at the same time.
|
||||
* The only exception to that is when we can't take the lock in the
|
||||
* function/coroutine itself, and need to delegate the caller (usually main
|
||||
* loop) to take it and wait that the coroutine ends, so that
|
||||
* we always signal that a reader is running.
|
||||
*/
|
||||
void coroutine_fn TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_co_rdlock(void);
|
||||
|
||||
/*
|
||||
* bdrv_graph_rdunlock:
|
||||
* Read terminated, decrease the count of readers in the current aiocontext.
|
||||
* If the writer is waiting for reads to finish (has_writer == 1), signal
|
||||
* the writer that we are done via aio_wait_kick() to let it continue.
|
||||
*/
|
||||
void coroutine_fn TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_co_rdunlock(void);
|
||||
|
||||
/*
|
||||
* bdrv_graph_rd{un}lock_main_loop:
|
||||
* Just a placeholder to mark where the graph rdlock should be taken
|
||||
* in the main loop. It is just asserting that we are not
|
||||
* in a coroutine and in GLOBAL_STATE_CODE.
|
||||
*/
|
||||
void TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_rdlock_main_loop(void);
|
||||
|
||||
void TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
|
||||
bdrv_graph_rdunlock_main_loop(void);
|
||||
|
||||
/*
|
||||
* assert_bdrv_graph_readable:
|
||||
* Make sure that the reader is either the main loop,
|
||||
* or there is at least a reader helding the rdlock.
|
||||
* In this way an incoming writer is aware of the read and waits.
|
||||
*/
|
||||
void GRAPH_RDLOCK assert_bdrv_graph_readable(void);
|
||||
|
||||
/*
|
||||
* assert_bdrv_graph_writable:
|
||||
* Make sure that the writer is the main loop and has set @has_writer,
|
||||
* so that incoming readers will pause.
|
||||
*/
|
||||
void GRAPH_WRLOCK assert_bdrv_graph_writable(void);
|
||||
|
||||
/*
|
||||
* Calling this function tells TSA that we know that the lock is effectively
|
||||
* taken even though we cannot prove it (yet) with GRAPH_RDLOCK. This can be
|
||||
* useful in intermediate stages of a conversion to using the GRAPH_RDLOCK
|
||||
* macro.
|
||||
*/
|
||||
static inline void TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
|
||||
assume_graph_lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct GraphLockable { } GraphLockable;
|
||||
|
||||
/*
|
||||
* In C, compound literals have the lifetime of an automatic variable.
|
||||
* In C++ it would be different, but then C++ wouldn't need QemuLockable
|
||||
* either...
|
||||
*/
|
||||
#define GML_OBJ_() (&(GraphLockable) { })
|
||||
|
||||
/*
|
||||
* This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
|
||||
* cleanup attribute and would therefore complain that the graph is never
|
||||
* unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
|
||||
* we hold the lock while unlocking is left unchecked.
|
||||
*/
|
||||
static inline GraphLockable * TSA_ACQUIRE_SHARED(graph_lock) coroutine_fn
|
||||
graph_lockable_auto_lock(GraphLockable *x)
|
||||
{
|
||||
bdrv_graph_co_rdlock();
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void TSA_RELEASE_SHARED(graph_lock) coroutine_fn
|
||||
graph_lockable_auto_unlock(GraphLockable **x)
|
||||
{
|
||||
bdrv_graph_co_rdunlock();
|
||||
}
|
||||
|
||||
#define GRAPH_AUTO_UNLOCK __attribute__((cleanup(graph_lockable_auto_unlock)))
|
||||
|
||||
/*
|
||||
* @var is only used to break the loop after the first iteration.
|
||||
* @unlock_var can't be unlocked and then set to NULL because TSA wants the lock
|
||||
* to be held at the start of every iteration of the loop.
|
||||
*/
|
||||
#define WITH_GRAPH_RDLOCK_GUARD_(var) \
|
||||
for (GraphLockable *unlock_var GRAPH_AUTO_UNLOCK = \
|
||||
graph_lockable_auto_lock(GML_OBJ_()), \
|
||||
*var = unlock_var; \
|
||||
var; \
|
||||
var = NULL)
|
||||
|
||||
#define WITH_GRAPH_RDLOCK_GUARD() \
|
||||
WITH_GRAPH_RDLOCK_GUARD_(glue(graph_lockable_auto, __COUNTER__))
|
||||
|
||||
#define GRAPH_RDLOCK_GUARD(x) \
|
||||
GraphLockable * GRAPH_AUTO_UNLOCK \
|
||||
glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
|
||||
graph_lockable_auto_lock(GML_OBJ_())
|
||||
|
||||
|
||||
typedef struct GraphLockableMainloop { } GraphLockableMainloop;
|
||||
|
||||
/*
|
||||
* In C, compound literals have the lifetime of an automatic variable.
|
||||
* In C++ it would be different, but then C++ wouldn't need QemuLockable
|
||||
* either...
|
||||
*/
|
||||
#define GMLML_OBJ_() (&(GraphLockableMainloop) { })
|
||||
|
||||
/*
|
||||
* This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
|
||||
* cleanup attribute and would therefore complain that the graph is never
|
||||
* unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
|
||||
* we hold the lock while unlocking is left unchecked.
|
||||
*/
|
||||
static inline GraphLockableMainloop * TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
|
||||
graph_lockable_auto_lock_mainloop(GraphLockableMainloop *x)
|
||||
{
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void TSA_NO_TSA
|
||||
graph_lockable_auto_unlock_mainloop(GraphLockableMainloop *x)
|
||||
{
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockableMainloop,
|
||||
graph_lockable_auto_unlock_mainloop)
|
||||
|
||||
#define GRAPH_RDLOCK_GUARD_MAINLOOP(x) \
|
||||
g_autoptr(GraphLockableMainloop) \
|
||||
glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
|
||||
graph_lockable_auto_lock_mainloop(GMLML_OBJ_())
|
||||
|
||||
#endif /* GRAPH_LOCK_H */
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* Copyright Red Hat
|
||||
* Copyright (C) 2005 Anthony Liguori <[email protected]>
|
||||
*
|
||||
* Network Block Device
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NBD_H
|
||||
#define NBD_H
|
||||
|
||||
#include "block/export.h"
|
||||
#include "io/channel-socket.h"
|
||||
#include "crypto/tlscreds.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
typedef struct NBDExport NBDExport;
|
||||
typedef struct NBDClient NBDClient;
|
||||
typedef struct NBDClientConnection NBDClientConnection;
|
||||
typedef struct NBDMetaContexts NBDMetaContexts;
|
||||
|
||||
extern const BlockExportDriver blk_exp_nbd;
|
||||
|
||||
/*
|
||||
* NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must
|
||||
* succeed at NBD_OPT_GO before being forcefully dropped as too slow.
|
||||
*/
|
||||
#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
|
||||
|
||||
/*
|
||||
* NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at
|
||||
* once; must be large enough to allow a MULTI_CONN-aware client like
|
||||
* nbdcopy to create its typical number of 8-16 sockets.
|
||||
*/
|
||||
#define NBD_DEFAULT_MAX_CONNECTIONS 100
|
||||
|
||||
/* Handshake phase structs - this struct is passed on the wire */
|
||||
|
||||
typedef struct NBDOption {
|
||||
uint64_t magic; /* NBD_OPTS_MAGIC */
|
||||
uint32_t option; /* NBD_OPT_* */
|
||||
uint32_t length;
|
||||
} QEMU_PACKED NBDOption;
|
||||
|
||||
typedef struct NBDOptionReply {
|
||||
uint64_t magic; /* NBD_REP_MAGIC */
|
||||
uint32_t option; /* NBD_OPT_* */
|
||||
uint32_t type; /* NBD_REP_* */
|
||||
uint32_t length;
|
||||
} QEMU_PACKED NBDOptionReply;
|
||||
|
||||
typedef struct NBDOptionReplyMetaContext {
|
||||
NBDOptionReply h; /* h.type = NBD_REP_META_CONTEXT, h.length > 4 */
|
||||
uint32_t context_id;
|
||||
/* metadata context name follows */
|
||||
} QEMU_PACKED NBDOptionReplyMetaContext;
|
||||
|
||||
/* Track results of negotiation */
|
||||
typedef enum NBDMode {
|
||||
/* Keep this list in a continuum of increasing features. */
|
||||
NBD_MODE_OLDSTYLE, /* server lacks newstyle negotiation */
|
||||
NBD_MODE_EXPORT_NAME, /* newstyle but only OPT_EXPORT_NAME safe */
|
||||
NBD_MODE_SIMPLE, /* newstyle but only simple replies */
|
||||
NBD_MODE_STRUCTURED, /* newstyle, structured replies enabled */
|
||||
NBD_MODE_EXTENDED, /* newstyle, extended headers enabled */
|
||||
} NBDMode;
|
||||
|
||||
/* Transmission phase structs */
|
||||
|
||||
/*
|
||||
* Note: NBDRequest is _NOT_ the same as the network representation of an NBD
|
||||
* request!
|
||||
*/
|
||||
typedef struct NBDRequest {
|
||||
uint64_t cookie;
|
||||
uint64_t from; /* Offset touched by the command */
|
||||
uint64_t len; /* Effect length; 32 bit limit without extended headers */
|
||||
uint16_t flags; /* NBD_CMD_FLAG_* */
|
||||
uint16_t type; /* NBD_CMD_* */
|
||||
NBDMode mode; /* Determines which network representation to use */
|
||||
NBDMetaContexts *contexts; /* Used by NBD_CMD_BLOCK_STATUS */
|
||||
} NBDRequest;
|
||||
|
||||
typedef struct NBDSimpleReply {
|
||||
uint32_t magic; /* NBD_SIMPLE_REPLY_MAGIC */
|
||||
uint32_t error;
|
||||
uint64_t cookie;
|
||||
} QEMU_PACKED NBDSimpleReply;
|
||||
|
||||
/* Header of all structured replies */
|
||||
typedef struct NBDStructuredReplyChunk {
|
||||
uint32_t magic; /* NBD_STRUCTURED_REPLY_MAGIC */
|
||||
uint16_t flags; /* combination of NBD_REPLY_FLAG_* */
|
||||
uint16_t type; /* NBD_REPLY_TYPE_* */
|
||||
uint64_t cookie; /* request handle */
|
||||
uint32_t length; /* length of payload */
|
||||
} QEMU_PACKED NBDStructuredReplyChunk;
|
||||
|
||||
typedef struct NBDExtendedReplyChunk {
|
||||
uint32_t magic; /* NBD_EXTENDED_REPLY_MAGIC */
|
||||
uint16_t flags; /* combination of NBD_REPLY_FLAG_* */
|
||||
uint16_t type; /* NBD_REPLY_TYPE_* */
|
||||
uint64_t cookie; /* request handle */
|
||||
uint64_t offset; /* request offset */
|
||||
uint64_t length; /* length of payload */
|
||||
} QEMU_PACKED NBDExtendedReplyChunk;
|
||||
|
||||
typedef union NBDReply {
|
||||
NBDSimpleReply simple;
|
||||
NBDStructuredReplyChunk structured;
|
||||
NBDExtendedReplyChunk extended;
|
||||
struct {
|
||||
/*
|
||||
* @magic and @cookie fields have the same offset and size in all
|
||||
* forms of replies, so let them be accessible without ".simple.",
|
||||
* ".structured.", or ".extended." specifications.
|
||||
*/
|
||||
uint32_t magic;
|
||||
uint32_t _skip;
|
||||
uint64_t cookie;
|
||||
};
|
||||
} NBDReply;
|
||||
QEMU_BUILD_BUG_ON(offsetof(NBDReply, simple.cookie) !=
|
||||
offsetof(NBDReply, cookie));
|
||||
QEMU_BUILD_BUG_ON(offsetof(NBDReply, structured.cookie) !=
|
||||
offsetof(NBDReply, cookie));
|
||||
QEMU_BUILD_BUG_ON(offsetof(NBDReply, extended.cookie) !=
|
||||
offsetof(NBDReply, cookie));
|
||||
|
||||
/* Header of chunk for NBD_REPLY_TYPE_OFFSET_DATA */
|
||||
typedef struct NBDStructuredReadData {
|
||||
/* header's .length >= 9 */
|
||||
uint64_t offset;
|
||||
/* At least one byte of data payload follows, calculated from h.length */
|
||||
} QEMU_PACKED NBDStructuredReadData;
|
||||
|
||||
/* Complete chunk for NBD_REPLY_TYPE_OFFSET_HOLE */
|
||||
typedef struct NBDStructuredReadHole {
|
||||
/* header's length == 12 */
|
||||
uint64_t offset;
|
||||
uint32_t length;
|
||||
} QEMU_PACKED NBDStructuredReadHole;
|
||||
|
||||
/* Header of all NBD_REPLY_TYPE_ERROR* errors */
|
||||
typedef struct NBDStructuredError {
|
||||
/* header's length >= 6 */
|
||||
uint32_t error;
|
||||
uint16_t message_length;
|
||||
} QEMU_PACKED NBDStructuredError;
|
||||
|
||||
/* Header of NBD_REPLY_TYPE_BLOCK_STATUS */
|
||||
typedef struct NBDStructuredMeta {
|
||||
/* header's length >= 12 (at least one extent) */
|
||||
uint32_t context_id;
|
||||
/* NBDExtent32 extents[] follows, array length implied by header */
|
||||
} QEMU_PACKED NBDStructuredMeta;
|
||||
|
||||
/* Extent array element for NBD_REPLY_TYPE_BLOCK_STATUS */
|
||||
typedef struct NBDExtent32 {
|
||||
uint32_t length;
|
||||
uint32_t flags; /* NBD_STATE_* */
|
||||
} QEMU_PACKED NBDExtent32;
|
||||
|
||||
/* Header of NBD_REPLY_TYPE_BLOCK_STATUS_EXT */
|
||||
typedef struct NBDExtendedMeta {
|
||||
/* header's length >= 24 (at least one extent) */
|
||||
uint32_t context_id;
|
||||
uint32_t count; /* header length must be count * 16 + 8 */
|
||||
/* NBDExtent64 extents[count] follows */
|
||||
} QEMU_PACKED NBDExtendedMeta;
|
||||
|
||||
/* Extent array element for NBD_REPLY_TYPE_BLOCK_STATUS_EXT */
|
||||
typedef struct NBDExtent64 {
|
||||
uint64_t length;
|
||||
uint64_t flags; /* NBD_STATE_* */
|
||||
} QEMU_PACKED NBDExtent64;
|
||||
|
||||
/* Client payload for limiting NBD_CMD_BLOCK_STATUS reply */
|
||||
typedef struct NBDBlockStatusPayload {
|
||||
uint64_t effect_length;
|
||||
/* uint32_t ids[] follows, array length implied by header */
|
||||
} QEMU_PACKED NBDBlockStatusPayload;
|
||||
|
||||
/* Transmission (export) flags: sent from server to client during handshake,
|
||||
but describe what will happen during transmission */
|
||||
enum {
|
||||
NBD_FLAG_HAS_FLAGS_BIT = 0, /* Flags are there */
|
||||
NBD_FLAG_READ_ONLY_BIT = 1, /* Device is read-only */
|
||||
NBD_FLAG_SEND_FLUSH_BIT = 2, /* Send FLUSH */
|
||||
NBD_FLAG_SEND_FUA_BIT = 3, /* Send FUA (Force Unit Access) */
|
||||
NBD_FLAG_ROTATIONAL_BIT = 4, /* Use elevator algorithm -
|
||||
rotational media */
|
||||
NBD_FLAG_SEND_TRIM_BIT = 5, /* Send TRIM (discard) */
|
||||
NBD_FLAG_SEND_WRITE_ZEROES_BIT = 6, /* Send WRITE_ZEROES */
|
||||
NBD_FLAG_SEND_DF_BIT = 7, /* Send DF (Do not Fragment) */
|
||||
NBD_FLAG_CAN_MULTI_CONN_BIT = 8, /* Multi-client cache consistent */
|
||||
NBD_FLAG_SEND_RESIZE_BIT = 9, /* Send resize */
|
||||
NBD_FLAG_SEND_CACHE_BIT = 10, /* Send CACHE (prefetch) */
|
||||
NBD_FLAG_SEND_FAST_ZERO_BIT = 11, /* FAST_ZERO flag for WRITE_ZEROES */
|
||||
NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT = 12, /* PAYLOAD flag for BLOCK_STATUS */
|
||||
};
|
||||
|
||||
#define NBD_FLAG_HAS_FLAGS (1 << NBD_FLAG_HAS_FLAGS_BIT)
|
||||
#define NBD_FLAG_READ_ONLY (1 << NBD_FLAG_READ_ONLY_BIT)
|
||||
#define NBD_FLAG_SEND_FLUSH (1 << NBD_FLAG_SEND_FLUSH_BIT)
|
||||
#define NBD_FLAG_SEND_FUA (1 << NBD_FLAG_SEND_FUA_BIT)
|
||||
#define NBD_FLAG_ROTATIONAL (1 << NBD_FLAG_ROTATIONAL_BIT)
|
||||
#define NBD_FLAG_SEND_TRIM (1 << NBD_FLAG_SEND_TRIM_BIT)
|
||||
#define NBD_FLAG_SEND_WRITE_ZEROES (1 << NBD_FLAG_SEND_WRITE_ZEROES_BIT)
|
||||
#define NBD_FLAG_SEND_DF (1 << NBD_FLAG_SEND_DF_BIT)
|
||||
#define NBD_FLAG_CAN_MULTI_CONN (1 << NBD_FLAG_CAN_MULTI_CONN_BIT)
|
||||
#define NBD_FLAG_SEND_RESIZE (1 << NBD_FLAG_SEND_RESIZE_BIT)
|
||||
#define NBD_FLAG_SEND_CACHE (1 << NBD_FLAG_SEND_CACHE_BIT)
|
||||
#define NBD_FLAG_SEND_FAST_ZERO (1 << NBD_FLAG_SEND_FAST_ZERO_BIT)
|
||||
#define NBD_FLAG_BLOCK_STAT_PAYLOAD (1 << NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT)
|
||||
|
||||
/* New-style handshake (global) flags, sent from server to client, and
|
||||
control what will happen during handshake phase. */
|
||||
#define NBD_FLAG_FIXED_NEWSTYLE (1 << 0) /* Fixed newstyle protocol. */
|
||||
#define NBD_FLAG_NO_ZEROES (1 << 1) /* End handshake without zeroes. */
|
||||
|
||||
/* New-style client flags, sent from client to server to control what happens
|
||||
during handshake phase. */
|
||||
#define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0) /* Fixed newstyle protocol. */
|
||||
#define NBD_FLAG_C_NO_ZEROES (1 << 1) /* End handshake without zeroes. */
|
||||
|
||||
/* Option requests. */
|
||||
#define NBD_OPT_EXPORT_NAME (1)
|
||||
#define NBD_OPT_ABORT (2)
|
||||
#define NBD_OPT_LIST (3)
|
||||
/* #define NBD_OPT_PEEK_EXPORT (4) not in use */
|
||||
#define NBD_OPT_STARTTLS (5)
|
||||
#define NBD_OPT_INFO (6)
|
||||
#define NBD_OPT_GO (7)
|
||||
#define NBD_OPT_STRUCTURED_REPLY (8)
|
||||
#define NBD_OPT_LIST_META_CONTEXT (9)
|
||||
#define NBD_OPT_SET_META_CONTEXT (10)
|
||||
#define NBD_OPT_EXTENDED_HEADERS (11)
|
||||
|
||||
/* Option reply types. */
|
||||
#define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
|
||||
|
||||
#define NBD_REP_ACK (1) /* Data sending finished. */
|
||||
#define NBD_REP_SERVER (2) /* Export description. */
|
||||
#define NBD_REP_INFO (3) /* NBD_OPT_INFO/GO. */
|
||||
#define NBD_REP_META_CONTEXT (4) /* NBD_OPT_{LIST,SET}_META_CONTEXT */
|
||||
|
||||
#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1) /* Unknown option */
|
||||
#define NBD_REP_ERR_POLICY NBD_REP_ERR(2) /* Server denied */
|
||||
#define NBD_REP_ERR_INVALID NBD_REP_ERR(3) /* Invalid length */
|
||||
#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4) /* Not compiled in */
|
||||
#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5) /* TLS required */
|
||||
#define NBD_REP_ERR_UNKNOWN NBD_REP_ERR(6) /* Export unknown */
|
||||
#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */
|
||||
#define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8) /* Need INFO_BLOCK_SIZE */
|
||||
#define NBD_REP_ERR_TOO_BIG NBD_REP_ERR(9) /* Payload size overflow */
|
||||
#define NBD_REP_ERR_EXT_HEADER_REQD NBD_REP_ERR(10) /* Need extended headers */
|
||||
|
||||
/* Info types, used during NBD_REP_INFO */
|
||||
#define NBD_INFO_EXPORT 0
|
||||
#define NBD_INFO_NAME 1
|
||||
#define NBD_INFO_DESCRIPTION 2
|
||||
#define NBD_INFO_BLOCK_SIZE 3
|
||||
|
||||
/* Request flags, sent from client to server during transmission phase */
|
||||
#define NBD_CMD_FLAG_FUA (1 << 0) /* 'force unit access' during write */
|
||||
#define NBD_CMD_FLAG_NO_HOLE (1 << 1) /* don't punch hole on zero run */
|
||||
#define NBD_CMD_FLAG_DF (1 << 2) /* don't fragment structured read */
|
||||
#define NBD_CMD_FLAG_REQ_ONE (1 << 3) \
|
||||
/* only one extent in BLOCK_STATUS reply chunk */
|
||||
#define NBD_CMD_FLAG_FAST_ZERO (1 << 4) /* fail if WRITE_ZEROES is not fast */
|
||||
#define NBD_CMD_FLAG_PAYLOAD_LEN (1 << 5) \
|
||||
/* length describes payload, not effect; only with ext header */
|
||||
|
||||
/* Supported request types */
|
||||
enum {
|
||||
NBD_CMD_READ = 0,
|
||||
NBD_CMD_WRITE = 1,
|
||||
NBD_CMD_DISC = 2,
|
||||
NBD_CMD_FLUSH = 3,
|
||||
NBD_CMD_TRIM = 4,
|
||||
NBD_CMD_CACHE = 5,
|
||||
NBD_CMD_WRITE_ZEROES = 6,
|
||||
NBD_CMD_BLOCK_STATUS = 7,
|
||||
};
|
||||
|
||||
#define NBD_DEFAULT_PORT 10809
|
||||
|
||||
/* Maximum size of a single READ/WRITE data buffer */
|
||||
#define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024)
|
||||
|
||||
/*
|
||||
* Maximum size of a protocol string (export name, metadata context name,
|
||||
* etc.). Use malloc rather than stack allocation for storage of a
|
||||
* string.
|
||||
*/
|
||||
#define NBD_MAX_STRING_SIZE 4096
|
||||
|
||||
/* Two types of request structures, a given client will only use 1 */
|
||||
#define NBD_REQUEST_MAGIC 0x25609513
|
||||
#define NBD_EXTENDED_REQUEST_MAGIC 0x21e41c71
|
||||
|
||||
/*
|
||||
* Three types of reply structures, but what a client expects depends
|
||||
* on NBD_OPT_STRUCTURED_REPLY and NBD_OPT_EXTENDED_HEADERS.
|
||||
*/
|
||||
#define NBD_SIMPLE_REPLY_MAGIC 0x67446698
|
||||
#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef
|
||||
#define NBD_EXTENDED_REPLY_MAGIC 0x6e8a278c
|
||||
|
||||
/* Chunk reply flags (for structured and extended replies) */
|
||||
#define NBD_REPLY_FLAG_DONE (1 << 0) /* This reply-chunk is last */
|
||||
|
||||
/* Chunk reply types */
|
||||
#define NBD_REPLY_ERR(value) ((1 << 15) | (value))
|
||||
|
||||
#define NBD_REPLY_TYPE_NONE 0
|
||||
#define NBD_REPLY_TYPE_OFFSET_DATA 1
|
||||
#define NBD_REPLY_TYPE_OFFSET_HOLE 2
|
||||
#define NBD_REPLY_TYPE_BLOCK_STATUS 5
|
||||
#define NBD_REPLY_TYPE_BLOCK_STATUS_EXT 6
|
||||
#define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1)
|
||||
#define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2)
|
||||
|
||||
/* Extent flags for base:allocation in NBD_REPLY_TYPE_BLOCK_STATUS */
|
||||
#define NBD_STATE_HOLE (1 << 0)
|
||||
#define NBD_STATE_ZERO (1 << 1)
|
||||
|
||||
/* Extent flags for qemu:dirty-bitmap in NBD_REPLY_TYPE_BLOCK_STATUS */
|
||||
#define NBD_STATE_DIRTY (1 << 0)
|
||||
|
||||
/* No flags needed for qemu:allocation-depth in NBD_REPLY_TYPE_BLOCK_STATUS */
|
||||
|
||||
static inline bool nbd_reply_type_is_error(int type)
|
||||
{
|
||||
return type & (1 << 15);
|
||||
}
|
||||
|
||||
/* NBD errors are based on errno numbers, so there is a 1:1 mapping,
|
||||
* but only a limited set of errno values is specified in the protocol.
|
||||
* Everything else is squashed to EINVAL.
|
||||
*/
|
||||
#define NBD_SUCCESS 0
|
||||
#define NBD_EPERM 1
|
||||
#define NBD_EIO 5
|
||||
#define NBD_ENOMEM 12
|
||||
#define NBD_EINVAL 22
|
||||
#define NBD_ENOSPC 28
|
||||
#define NBD_EOVERFLOW 75
|
||||
#define NBD_ENOTSUP 95
|
||||
#define NBD_ESHUTDOWN 108
|
||||
|
||||
/* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */
|
||||
typedef struct NBDExportInfo {
|
||||
/* Set by client before nbd_receive_negotiate() */
|
||||
bool request_sizes;
|
||||
char *x_dirty_bitmap;
|
||||
|
||||
/* Set by client before nbd_receive_negotiate(), or by server results
|
||||
* during nbd_receive_export_list() */
|
||||
char *name; /* must be non-NULL */
|
||||
|
||||
/* In-out fields, set by client before nbd_receive_negotiate() and
|
||||
* updated by server results during nbd_receive_negotiate() */
|
||||
NBDMode mode; /* input maximum mode tolerated; output actual mode chosen */
|
||||
bool base_allocation; /* base:allocation context for NBD_CMD_BLOCK_STATUS */
|
||||
|
||||
/* Set by server results during nbd_receive_negotiate() and
|
||||
* nbd_receive_export_list() */
|
||||
uint64_t size;
|
||||
uint16_t flags;
|
||||
uint32_t min_block;
|
||||
uint32_t opt_block;
|
||||
uint32_t max_block;
|
||||
|
||||
uint32_t context_id;
|
||||
|
||||
/* Set by server results during nbd_receive_export_list() */
|
||||
char *description;
|
||||
int n_contexts;
|
||||
char **contexts;
|
||||
} NBDExportInfo;
|
||||
|
||||
int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
|
||||
const char *hostname, QIOChannel **outioc,
|
||||
NBDExportInfo *info, Error **errp);
|
||||
void nbd_free_export_list(NBDExportInfo *info, int count);
|
||||
int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
|
||||
const char *hostname, NBDExportInfo **info,
|
||||
Error **errp);
|
||||
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
|
||||
Error **errp);
|
||||
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
|
||||
int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
|
||||
NBDReply *reply, NBDMode mode,
|
||||
Error **errp);
|
||||
int nbd_client(int fd);
|
||||
int nbd_disconnect(int fd);
|
||||
int nbd_errno_to_system_errno(int err);
|
||||
|
||||
void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk);
|
||||
|
||||
AioContext *nbd_export_aio_context(NBDExport *exp);
|
||||
NBDExport *nbd_export_find(const char *name);
|
||||
|
||||
void nbd_client_new(QIOChannelSocket *sioc,
|
||||
uint32_t handshake_max_secs,
|
||||
QCryptoTLSCreds *tlscreds,
|
||||
const char *tlsauthz,
|
||||
void (*close_fn)(NBDClient *, bool),
|
||||
void *owner);
|
||||
void *nbd_client_owner(NBDClient *client);
|
||||
void nbd_client_get(NBDClient *client);
|
||||
void nbd_client_put(NBDClient *client);
|
||||
|
||||
void nbd_server_is_qemu_nbd(int max_connections);
|
||||
bool nbd_server_is_running(void);
|
||||
int nbd_server_max_connections(void);
|
||||
void nbd_server_start(SocketAddress *addr, uint32_t handshake_max_secs,
|
||||
const char *tls_creds, const char *tls_authz,
|
||||
uint32_t max_connections, Error **errp);
|
||||
void nbd_server_start_options(NbdServerOptions *arg, Error **errp);
|
||||
|
||||
/* nbd_read
|
||||
* Reads @size bytes from @ioc. Returns 0 on success.
|
||||
*/
|
||||
static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
|
||||
const char *desc, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
int ret = qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
|
||||
|
||||
if (ret < 0) {
|
||||
if (desc) {
|
||||
error_prepend(errp, "Failed to read %s: ", desc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEF_NBD_READ_N(bits) \
|
||||
static inline int nbd_read##bits(QIOChannel *ioc, \
|
||||
uint##bits##_t *val, \
|
||||
const char *desc, Error **errp) \
|
||||
{ \
|
||||
int ret = nbd_read(ioc, val, sizeof(*val), desc, errp); \
|
||||
if (ret < 0) { \
|
||||
return ret; \
|
||||
} \
|
||||
*val = be##bits##_to_cpu(*val); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
DEF_NBD_READ_N(16) /* Defines nbd_read16(). */
|
||||
DEF_NBD_READ_N(32) /* Defines nbd_read32(). */
|
||||
DEF_NBD_READ_N(64) /* Defines nbd_read64(). */
|
||||
|
||||
#undef DEF_NBD_READ_N
|
||||
|
||||
static inline bool nbd_reply_is_simple(NBDReply *reply)
|
||||
{
|
||||
return reply->magic == NBD_SIMPLE_REPLY_MAGIC;
|
||||
}
|
||||
|
||||
static inline bool nbd_reply_is_structured(NBDReply *reply)
|
||||
{
|
||||
return reply->magic == NBD_STRUCTURED_REPLY_MAGIC;
|
||||
}
|
||||
|
||||
const char *nbd_reply_type_lookup(uint16_t type);
|
||||
const char *nbd_opt_lookup(uint32_t opt);
|
||||
const char *nbd_rep_lookup(uint32_t rep);
|
||||
const char *nbd_info_lookup(uint16_t info);
|
||||
const char *nbd_cmd_lookup(uint16_t info);
|
||||
const char *nbd_err_lookup(int err);
|
||||
const char *nbd_mode_lookup(NBDMode mode);
|
||||
|
||||
/* nbd/client-connection.c */
|
||||
void nbd_client_connection_enable_retry(NBDClientConnection *conn);
|
||||
|
||||
NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
|
||||
bool do_negotiation,
|
||||
const char *export_name,
|
||||
const char *x_dirty_bitmap,
|
||||
QCryptoTLSCreds *tlscreds,
|
||||
const char *tlshostname);
|
||||
void nbd_client_connection_release(NBDClientConnection *conn);
|
||||
|
||||
QIOChannel *coroutine_fn
|
||||
nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info,
|
||||
bool blocking, Error **errp);
|
||||
|
||||
void nbd_co_establish_connection_cancel(NBDClientConnection *conn);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Block layer qmp and info dump related functions
|
||||
*
|
||||
* Copyright (c) 2003-2008 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.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_QAPI_H
|
||||
#define BLOCK_QAPI_H
|
||||
|
||||
#include "block/graph-lock.h"
|
||||
#include "block/snapshot.h"
|
||||
#include "qapi/qapi-types-block-core.h"
|
||||
|
||||
BlockDeviceInfo * GRAPH_RDLOCK
|
||||
bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
|
||||
bool flat, Error **errp);
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_query_snapshot_info_list(BlockDriverState *bs,
|
||||
SnapshotInfoList **p_list,
|
||||
Error **errp);
|
||||
void GRAPH_RDLOCK
|
||||
bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
|
||||
bool skip_implicit_filters, Error **errp);
|
||||
void GRAPH_RDLOCK
|
||||
bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
|
||||
bool limits, Error **errp);
|
||||
|
||||
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
|
||||
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
|
||||
const char *prefix,
|
||||
int indentation);
|
||||
void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol);
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Special QDict functions used by the block layer
|
||||
*
|
||||
* Copyright (c) 2013-2018 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_QDICT_H
|
||||
#define BLOCK_QDICT_H
|
||||
|
||||
#include "qobject/qdict.h"
|
||||
|
||||
QObject *qdict_crumple(const QDict *src, Error **errp);
|
||||
void qdict_flatten(QDict *qdict);
|
||||
|
||||
void qdict_copy_default(QDict *dst, QDict *src, const char *key);
|
||||
void qdict_set_default_str(QDict *dst, const char *key, const char *val);
|
||||
|
||||
void qdict_join(QDict *dest, QDict *src, bool overwrite);
|
||||
|
||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
||||
void qdict_array_split(QDict *src, QList **dst);
|
||||
int qdict_array_entries(QDict *src, const char *subqdict);
|
||||
|
||||
typedef struct QDictRenames {
|
||||
const char *from;
|
||||
const char *to;
|
||||
} QDictRenames;
|
||||
bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp);
|
||||
|
||||
Visitor *qobject_input_visitor_new_flat_confused(QDict *qdict,
|
||||
Error **errp);
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Declarations for AIO in the raw protocol
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_RAW_AIO_H
|
||||
#define QEMU_RAW_AIO_H
|
||||
|
||||
#include "qemu/aiocb.h"
|
||||
#include "qemu/aio.h"
|
||||
#include "block/block-common.h"
|
||||
#include "qemu/iov.h"
|
||||
|
||||
/* AIO request types */
|
||||
#define QEMU_AIO_READ 0x0001
|
||||
#define QEMU_AIO_WRITE 0x0002
|
||||
#define QEMU_AIO_IOCTL 0x0004
|
||||
#define QEMU_AIO_FLUSH 0x0008
|
||||
#define QEMU_AIO_DISCARD 0x0010
|
||||
#define QEMU_AIO_WRITE_ZEROES 0x0020
|
||||
#define QEMU_AIO_COPY_RANGE 0x0040
|
||||
#define QEMU_AIO_TRUNCATE 0x0080
|
||||
#define QEMU_AIO_ZONE_REPORT 0x0100
|
||||
#define QEMU_AIO_ZONE_MGMT 0x0200
|
||||
#define QEMU_AIO_ZONE_APPEND 0x0400
|
||||
#define QEMU_AIO_TYPE_MASK \
|
||||
(QEMU_AIO_READ | \
|
||||
QEMU_AIO_WRITE | \
|
||||
QEMU_AIO_IOCTL | \
|
||||
QEMU_AIO_FLUSH | \
|
||||
QEMU_AIO_DISCARD | \
|
||||
QEMU_AIO_WRITE_ZEROES | \
|
||||
QEMU_AIO_COPY_RANGE | \
|
||||
QEMU_AIO_TRUNCATE | \
|
||||
QEMU_AIO_ZONE_REPORT | \
|
||||
QEMU_AIO_ZONE_MGMT | \
|
||||
QEMU_AIO_ZONE_APPEND)
|
||||
|
||||
/* AIO flags */
|
||||
#define QEMU_AIO_MISALIGNED 0x1000
|
||||
#define QEMU_AIO_BLKDEV 0x2000
|
||||
#define QEMU_AIO_NO_FALLBACK 0x4000
|
||||
|
||||
|
||||
/* linux-aio.c - Linux native implementation */
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
typedef struct LinuxAioState LinuxAioState;
|
||||
LinuxAioState *laio_init(Error **errp);
|
||||
void laio_cleanup(LinuxAioState *s);
|
||||
|
||||
/* laio_co_submit: submit I/O requests in the thread's current AioContext. */
|
||||
int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
|
||||
int type, BdrvRequestFlags flags,
|
||||
uint64_t dev_max_batch);
|
||||
|
||||
bool laio_has_fdsync(int);
|
||||
bool laio_has_fua(void);
|
||||
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
|
||||
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
|
||||
#else
|
||||
static inline bool laio_has_fua(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
/* io_uring.c - Linux io_uring implementation */
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
/* luring_co_submit: submit I/O requests in the thread's current AioContext. */
|
||||
int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset,
|
||||
QEMUIOVector *qiov, int type,
|
||||
BdrvRequestFlags flags);
|
||||
bool luring_has_fua(void);
|
||||
#else
|
||||
static inline bool luring_has_fua(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
|
||||
QEMUWin32AIOState *win32_aio_init(void);
|
||||
void win32_aio_cleanup(QEMUWin32AIOState *aio);
|
||||
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
|
||||
BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
|
||||
QEMUWin32AIOState *aio, HANDLE hfile,
|
||||
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
|
||||
BlockCompletionFunc *cb, void *opaque, int type);
|
||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *old_context);
|
||||
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *new_context);
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_RAW_AIO_H */
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Replication filter
|
||||
*
|
||||
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2016 FUJITSU LIMITED
|
||||
*
|
||||
* Author:
|
||||
* Changlong Xie <[email protected]>
|
||||
*
|
||||
* 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 REPLICATION_H
|
||||
#define REPLICATION_H
|
||||
|
||||
#include "qapi/qapi-types-block-core.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef struct ReplicationOps ReplicationOps;
|
||||
typedef struct ReplicationState ReplicationState;
|
||||
|
||||
/**
|
||||
* SECTION:block/replication.h
|
||||
* @title:Base Replication System
|
||||
* @short_description: interfaces for handling replication
|
||||
*
|
||||
* The Replication Model provides a framework for handling Replication
|
||||
*
|
||||
* <example>
|
||||
* <title>How to use replication interfaces</title>
|
||||
* <programlisting>
|
||||
* #include "block/replication.h"
|
||||
*
|
||||
* typedef struct BDRVReplicationState {
|
||||
* ReplicationState *rs;
|
||||
* } BDRVReplicationState;
|
||||
*
|
||||
* static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
* Error **errp);
|
||||
* static void replication_do_checkpoint(ReplicationState *rs, Error **errp);
|
||||
* static void replication_get_error(ReplicationState *rs, Error **errp);
|
||||
* static void replication_stop(ReplicationState *rs, bool failover,
|
||||
* Error **errp);
|
||||
*
|
||||
* static ReplicationOps replication_ops = {
|
||||
* .start = replication_start,
|
||||
* .checkpoint = replication_do_checkpoint,
|
||||
* .get_error = replication_get_error,
|
||||
* .stop = replication_stop,
|
||||
* }
|
||||
*
|
||||
* static int replication_open(BlockDriverState *bs, QDict *options,
|
||||
* int flags, Error **errp)
|
||||
* {
|
||||
* BDRVReplicationState *s = bs->opaque;
|
||||
* s->rs = replication_new(bs, &replication_ops);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* static void replication_close(BlockDriverState *bs)
|
||||
* {
|
||||
* BDRVReplicationState *s = bs->opaque;
|
||||
* replication_remove(s->rs);
|
||||
* }
|
||||
*
|
||||
* BlockDriver bdrv_replication = {
|
||||
* .format_name = "replication",
|
||||
* .instance_size = sizeof(BDRVReplicationState),
|
||||
*
|
||||
* .bdrv_open = replication_open,
|
||||
* .bdrv_close = replication_close,
|
||||
* };
|
||||
*
|
||||
* static void bdrv_replication_init(void)
|
||||
* {
|
||||
* bdrv_register(&bdrv_replication);
|
||||
* }
|
||||
*
|
||||
* block_init(bdrv_replication_init);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* We create an example about how to use replication interfaces in above.
|
||||
* Then in migration, we can use replication_(start/stop/do_checkpoint/
|
||||
* get_error)_all to handle all replication operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ReplicationState:
|
||||
* @opaque: opaque pointer value passed to this ReplicationState
|
||||
* @ops: replication operation of this ReplicationState
|
||||
* @node: node that we will insert into @replication_states QLIST
|
||||
*/
|
||||
struct ReplicationState {
|
||||
void *opaque;
|
||||
ReplicationOps *ops;
|
||||
QLIST_ENTRY(ReplicationState) node;
|
||||
};
|
||||
|
||||
/**
|
||||
* ReplicationOps:
|
||||
* @start: callback to start replication
|
||||
* @stop: callback to stop replication
|
||||
* @checkpoint: callback to do checkpoint
|
||||
* @get_error: callback to check if error occurred during replication
|
||||
*/
|
||||
struct ReplicationOps {
|
||||
void (*start)(ReplicationState *rs, ReplicationMode mode, Error **errp);
|
||||
void (*stop)(ReplicationState *rs, bool failover, Error **errp);
|
||||
void (*checkpoint)(ReplicationState *rs, Error **errp);
|
||||
void (*get_error)(ReplicationState *rs, Error **errp);
|
||||
};
|
||||
|
||||
/**
|
||||
* replication_new:
|
||||
* @opaque: opaque pointer value passed to ReplicationState
|
||||
* @ops: replication operation of the new relevant ReplicationState
|
||||
*
|
||||
* Called to create a new ReplicationState instance, and then insert it
|
||||
* into @replication_states QLIST
|
||||
*
|
||||
* Returns: the new ReplicationState instance
|
||||
*/
|
||||
ReplicationState *replication_new(void *opaque, ReplicationOps *ops);
|
||||
|
||||
/**
|
||||
* replication_remove:
|
||||
* @rs: the ReplicationState instance to remove
|
||||
*
|
||||
* Called to remove a ReplicationState instance, and then delete it from
|
||||
* @replication_states QLIST
|
||||
*/
|
||||
void replication_remove(ReplicationState *rs);
|
||||
|
||||
/**
|
||||
* replication_start_all:
|
||||
* @mode: replication mode that could be "primary" or "secondary"
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Start replication, called in migration/checkpoint thread
|
||||
*
|
||||
* Note: the caller of the function MUST make sure vm stopped
|
||||
*/
|
||||
void replication_start_all(ReplicationMode mode, Error **errp);
|
||||
|
||||
/**
|
||||
* replication_do_checkpoint_all:
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* This interface is called after all VM state is transferred to Secondary QEMU
|
||||
*/
|
||||
void replication_do_checkpoint_all(Error **errp);
|
||||
|
||||
/**
|
||||
* replication_get_error_all:
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* This interface is called to check if error occurred during replication
|
||||
*/
|
||||
void replication_get_error_all(Error **errp);
|
||||
|
||||
/**
|
||||
* replication_stop_all:
|
||||
* @failover: boolean value that indicates if we need do failover or not
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* It is called on failover. The vm should be stopped before calling it, if you
|
||||
* use this API to shutdown the guest, or other things except failover
|
||||
*/
|
||||
void replication_stop_all(bool failover, Error **errp);
|
||||
|
||||
#endif /* REPLICATION_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* reqlist API
|
||||
*
|
||||
* Copyright (C) 2013 Proxmox Server Solutions
|
||||
* Copyright (c) 2021 Virtuozzo International GmbH.
|
||||
*
|
||||
* Authors:
|
||||
* Dietmar Maurer ([email protected])
|
||||
* Vladimir Sementsov-Ogievskiy <[email protected]>
|
||||
*
|
||||
* 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 REQLIST_H
|
||||
#define REQLIST_H
|
||||
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
/*
|
||||
* The API is not thread-safe and shouldn't be. The struct is public to be part
|
||||
* of other structures and protected by third-party locks, see
|
||||
* block/block-copy.c for example.
|
||||
*/
|
||||
|
||||
typedef struct BlockReq {
|
||||
int64_t offset;
|
||||
int64_t bytes;
|
||||
|
||||
CoQueue wait_queue; /* coroutines blocked on this req */
|
||||
QLIST_ENTRY(BlockReq) list;
|
||||
} BlockReq;
|
||||
|
||||
typedef QLIST_HEAD(, BlockReq) BlockReqList;
|
||||
|
||||
/*
|
||||
* Initialize new request and add it to the list. Caller must be sure that
|
||||
* there are no conflicting requests in the list.
|
||||
*/
|
||||
void reqlist_init_req(BlockReqList *reqs, BlockReq *req, int64_t offset,
|
||||
int64_t bytes);
|
||||
/* Search for request in the list intersecting with @offset/@bytes area. */
|
||||
BlockReq *reqlist_find_conflict(BlockReqList *reqs, int64_t offset,
|
||||
int64_t bytes);
|
||||
|
||||
/*
|
||||
* If there are no intersecting requests return false. Otherwise, wait for the
|
||||
* first found intersecting request to finish and return true.
|
||||
*
|
||||
* @lock is passed to qemu_co_queue_wait()
|
||||
* False return value proves that lock was released at no point.
|
||||
*/
|
||||
bool coroutine_fn reqlist_wait_one(BlockReqList *reqs, int64_t offset,
|
||||
int64_t bytes, CoMutex *lock);
|
||||
|
||||
/*
|
||||
* Wait for all intersecting requests. It just calls reqlist_wait_one() in a
|
||||
* loop, caller is responsible to stop producing new requests in this region
|
||||
* in parallel, otherwise reqlist_wait_all() may never return.
|
||||
*/
|
||||
void coroutine_fn reqlist_wait_all(BlockReqList *reqs, int64_t offset,
|
||||
int64_t bytes, CoMutex *lock);
|
||||
|
||||
/*
|
||||
* Shrink request and wake all waiting coroutines (maybe some of them are not
|
||||
* intersecting with shrunk request).
|
||||
*/
|
||||
void coroutine_fn reqlist_shrink_req(BlockReq *req, int64_t new_bytes);
|
||||
|
||||
/*
|
||||
* Remove request and wake all waiting coroutines. Do not release any memory.
|
||||
*/
|
||||
void coroutine_fn reqlist_remove_req(BlockReq *req);
|
||||
|
||||
#endif /* REQLIST_H */
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Block layer snapshot related functions
|
||||
*
|
||||
* Copyright (c) 2003-2008 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.
|
||||
*/
|
||||
|
||||
#ifndef SNAPSHOT_H
|
||||
#define SNAPSHOT_H
|
||||
|
||||
#include "block/graph-lock.h"
|
||||
#include "qapi/qapi-builtin-types.h"
|
||||
|
||||
#define SNAPSHOT_OPT_BASE "snapshot."
|
||||
#define SNAPSHOT_OPT_ID "snapshot.id"
|
||||
#define SNAPSHOT_OPT_NAME "snapshot.name"
|
||||
|
||||
extern QemuOptsList internal_snapshot_opts;
|
||||
|
||||
typedef struct QEMUSnapshotInfo {
|
||||
char id_str[128]; /* unique snapshot id */
|
||||
/* the following fields are informative. They are not needed for
|
||||
the consistency of the snapshot */
|
||||
char name[256]; /* user chosen name */
|
||||
uint64_t vm_state_size; /* VM state info size */
|
||||
uint32_t date_sec; /* UTC date of the snapshot */
|
||||
uint32_t date_nsec;
|
||||
uint64_t vm_clock_nsec; /* VM clock relative to boot */
|
||||
uint64_t icount; /* record/replay step */
|
||||
} QEMUSnapshotInfo;
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* See include/block/block-global-state.h for more information about
|
||||
* the GS API.
|
||||
*/
|
||||
|
||||
int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
|
||||
const char *name);
|
||||
bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
|
||||
const char *id,
|
||||
const char *name,
|
||||
QEMUSnapshotInfo *sn_info,
|
||||
Error **errp);
|
||||
|
||||
int GRAPH_RDLOCK bdrv_can_snapshot(BlockDriverState *bs);
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
|
||||
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_snapshot_goto(BlockDriverState *bs, const char *snapshot_id, Error **errp);
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id,
|
||||
const char *name, Error **errp);
|
||||
|
||||
int bdrv_snapshot_list(BlockDriverState *bs,
|
||||
QEMUSnapshotInfo **psn_info);
|
||||
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
|
||||
const char *snapshot_id,
|
||||
const char *name,
|
||||
Error **errp);
|
||||
int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
|
||||
const char *id_or_name,
|
||||
Error **errp);
|
||||
|
||||
|
||||
/*
|
||||
* Group operations. All block drivers are involved.
|
||||
*/
|
||||
|
||||
bool bdrv_all_can_snapshot(bool has_devices, strList *devices,
|
||||
Error **errp);
|
||||
int GRAPH_UNLOCKED
|
||||
bdrv_all_delete_snapshot(const char *name, bool has_devices, strList *devices,
|
||||
Error **errp);
|
||||
int bdrv_all_goto_snapshot(const char *name,
|
||||
bool has_devices, strList *devices,
|
||||
Error **errp);
|
||||
int bdrv_all_has_snapshot(const char *name,
|
||||
bool has_devices, strList *devices,
|
||||
Error **errp);
|
||||
int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
|
||||
BlockDriverState *vm_state_bs,
|
||||
uint64_t vm_state_size,
|
||||
bool has_devices,
|
||||
strList *devices,
|
||||
Error **errp);
|
||||
|
||||
BlockDriverState *bdrv_all_find_vmstate_bs(const char *vmstate_bs,
|
||||
bool has_devices, strList *devices,
|
||||
Error **errp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* QEMU block layer thread pool
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
* Copyright Red Hat, Inc. 2012
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
* Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_THREAD_POOL_H
|
||||
#define QEMU_THREAD_POOL_H
|
||||
|
||||
#include "qemu/aiocb.h"
|
||||
#include "qemu/aio.h"
|
||||
|
||||
#define THREAD_POOL_MAX_THREADS_DEFAULT 64
|
||||
|
||||
typedef int ThreadPoolFunc(void *opaque);
|
||||
|
||||
typedef struct ThreadPoolAio ThreadPoolAio;
|
||||
|
||||
ThreadPoolAio *thread_pool_new_aio(struct AioContext *ctx);
|
||||
void thread_pool_free_aio(ThreadPoolAio *pool);
|
||||
|
||||
/*
|
||||
* thread_pool_submit_{aio,co} API: submit I/O requests in the thread's
|
||||
* current AioContext.
|
||||
*/
|
||||
BlockAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
|
||||
BlockCompletionFunc *cb, void *opaque);
|
||||
int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg);
|
||||
void thread_pool_update_params(ThreadPoolAio *pool, struct AioContext *ctx);
|
||||
|
||||
/* ------------------------------------------- */
|
||||
/* Generic thread pool types and methods below */
|
||||
typedef struct ThreadPool ThreadPool;
|
||||
|
||||
/* Create a new thread pool. Never returns NULL. */
|
||||
ThreadPool *thread_pool_new(void);
|
||||
|
||||
/*
|
||||
* Free the thread pool.
|
||||
* Waits for all the previously submitted work to complete before performing
|
||||
* the actual freeing operation.
|
||||
*/
|
||||
void thread_pool_free(ThreadPool *pool);
|
||||
|
||||
/*
|
||||
* Submit a new work (task) for the pool.
|
||||
*
|
||||
* @opaque_destroy is an optional GDestroyNotify for the @opaque argument
|
||||
* to the work function at @func.
|
||||
*/
|
||||
void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func,
|
||||
void *opaque, GDestroyNotify opaque_destroy);
|
||||
|
||||
/*
|
||||
* Submit a new work (task) for the pool, making sure it starts getting
|
||||
* processed immediately, launching a new thread for it if necessary.
|
||||
*
|
||||
* @opaque_destroy is an optional GDestroyNotify for the @opaque argument
|
||||
* to the work function at @func.
|
||||
*/
|
||||
void thread_pool_submit_immediate(ThreadPool *pool, ThreadPoolFunc *func,
|
||||
void *opaque, GDestroyNotify opaque_destroy);
|
||||
|
||||
/*
|
||||
* Wait for all previously submitted work to complete before returning.
|
||||
*
|
||||
* Can be used as a barrier between two sets of tasks executed on a thread
|
||||
* pool without destroying it or in a performance sensitive path where the
|
||||
* caller just wants to wait for all tasks to complete while deferring the
|
||||
* pool free operation for later, less performance sensitive time.
|
||||
*/
|
||||
void thread_pool_wait(ThreadPool *pool);
|
||||
|
||||
/* Set the maximum number of threads in the pool. */
|
||||
bool thread_pool_set_max_threads(ThreadPool *pool, int max_threads);
|
||||
|
||||
/*
|
||||
* Adjust the maximum number of threads in the pool to give each task its
|
||||
* own thread (exactly one thread per task).
|
||||
*/
|
||||
bool thread_pool_adjust_max_threads_to_work(ThreadPool *pool);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* QEMU block throttling group infrastructure
|
||||
*
|
||||
* Copyright (C) Nodalink, EURL. 2014
|
||||
* Copyright (C) Igalia, S.L. 2015
|
||||
*
|
||||
* Authors:
|
||||
* Benoît Canet <[email protected]>
|
||||
* Alberto Garcia <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 or
|
||||
* (at your option) version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef THROTTLE_GROUPS_H
|
||||
#define THROTTLE_GROUPS_H
|
||||
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/throttle.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
/* The ThrottleGroupMember structure indicates membership in a ThrottleGroup
|
||||
* and holds related data.
|
||||
*/
|
||||
|
||||
typedef struct ThrottleGroupMember {
|
||||
AioContext *aio_context;
|
||||
/* Protected by ThrottleGroup.lock */
|
||||
CoQueue throttled_reqs[THROTTLE_MAX];
|
||||
|
||||
/* Nonzero if the I/O limits are currently being ignored; generally
|
||||
* it is zero. Accessed with atomic operations.
|
||||
*/
|
||||
unsigned int io_limits_disabled;
|
||||
|
||||
/* Number of pending throttle_group_restart_queue_entry() coroutines.
|
||||
* Accessed with atomic operations.
|
||||
*/
|
||||
unsigned int restart_pending;
|
||||
|
||||
/* The following fields are protected by the ThrottleGroup lock.
|
||||
* See the ThrottleGroup documentation for details.
|
||||
* throttle_state tells us if I/O limits are configured. */
|
||||
ThrottleState *throttle_state;
|
||||
ThrottleTimers throttle_timers;
|
||||
unsigned pending_reqs[THROTTLE_MAX];
|
||||
QLIST_ENTRY(ThrottleGroupMember) round_robin;
|
||||
|
||||
} ThrottleGroupMember;
|
||||
|
||||
#define TYPE_THROTTLE_GROUP "throttle-group"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ThrottleGroup, THROTTLE_GROUP)
|
||||
|
||||
const char *throttle_group_get_name(ThrottleGroupMember *tgm);
|
||||
|
||||
ThrottleState *throttle_group_incref(const char *name);
|
||||
void throttle_group_unref(ThrottleState *ts);
|
||||
|
||||
void throttle_group_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
|
||||
void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
|
||||
|
||||
void throttle_group_register_tgm(ThrottleGroupMember *tgm,
|
||||
const char *groupname,
|
||||
AioContext *ctx);
|
||||
void throttle_group_unregister_tgm(ThrottleGroupMember *tgm);
|
||||
void throttle_group_restart_tgm(ThrottleGroupMember *tgm);
|
||||
|
||||
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
|
||||
int64_t bytes,
|
||||
ThrottleDirection direction);
|
||||
void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
|
||||
AioContext *new_context);
|
||||
void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
|
||||
/*
|
||||
* throttle_group_exists() must be called under the global
|
||||
* mutex.
|
||||
*/
|
||||
bool throttle_group_exists(const char *name);
|
||||
|
||||
#endif
|
||||
+1374
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* QEMU System Emulator block write threshold notification
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2014
|
||||
*
|
||||
* Authors:
|
||||
* Francesco Romani <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_WRITE_THRESHOLD_H
|
||||
#define BLOCK_WRITE_THRESHOLD_H
|
||||
|
||||
/*
|
||||
* bdrv_write_threshold_set:
|
||||
*
|
||||
* Set the write threshold for block devices, in bytes.
|
||||
* Notify when a write exceeds the threshold, meaning the device
|
||||
* is becoming full, so it can be transparently resized.
|
||||
* To be used with thin-provisioned block devices.
|
||||
*
|
||||
* Use threshold_bytes == 0 to disable.
|
||||
*/
|
||||
void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes);
|
||||
|
||||
/*
|
||||
* bdrv_write_threshold_get
|
||||
*
|
||||
* Get the configured write threshold, in bytes.
|
||||
* Zero means no threshold configured.
|
||||
*/
|
||||
uint64_t bdrv_write_threshold_get(const BlockDriverState *bs);
|
||||
|
||||
/*
|
||||
* bdrv_write_threshold_check_write
|
||||
*
|
||||
* Check whether the specified request exceeds the write threshold.
|
||||
* If so, send a corresponding event and disable write threshold checking.
|
||||
*/
|
||||
void bdrv_write_threshold_check_write(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user