X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=block%2Fqed.h;h=42c115d8220cc61a74ff50dede211ea033d421da;hb=c4107e8208d0222f9b328691b519aaee4101db87;hp=1d1421fee1230e3c7f0262939cd878cae779cac6;hpb=aa348082d8e89d2ab021caadbcc97c93038fffb2;p=mirror_qemu.git diff --git a/block/qed.h b/block/qed.h index 1d1421fee1..42c115d822 100644 --- a/block/qed.h +++ b/block/qed.h @@ -15,7 +15,8 @@ #ifndef BLOCK_QED_H #define BLOCK_QED_H -#include "block_int.h" +#include "block/block_int.h" +#include "qemu/cutils.h" /* The layout of a QED file is as follows: * @@ -43,7 +44,7 @@ * * All fields are little-endian on disk. */ - +#define QED_DEFAULT_CLUSTER_SIZE 65536 enum { QED_MAGIC = 'Q' | 'E' << 8 | 'D' << 16 | '\0' << 24, @@ -69,7 +70,6 @@ enum { */ QED_MIN_CLUSTER_SIZE = 4 * 1024, /* in bytes */ QED_MAX_CLUSTER_SIZE = 64 * 1024 * 1024, - QED_DEFAULT_CLUSTER_SIZE = 64 * 1024, /* Allocated clusters are tracked using a 2-level pagetable. Table size is * a multiple of clusters so large maximum image sizes can be supported @@ -78,6 +78,9 @@ enum { QED_MIN_TABLE_SIZE = 1, /* in clusters */ QED_MAX_TABLE_SIZE = 16, QED_DEFAULT_TABLE_SIZE = 4, + + /* Delay to flush and clean image after last allocating write completes */ + QED_NEED_CHECK_TIMEOUT = 5, /* in seconds */ }; typedef struct { @@ -97,7 +100,7 @@ typedef struct { /* if (features & QED_F_BACKING_FILE) */ uint32_t backing_filename_offset; /* in bytes from start of header */ uint32_t backing_filename_size; /* in bytes */ -} QEDHeader; +} QEMU_PACKED QEDHeader; typedef struct { uint64_t offsets[0]; /* in bytes */ @@ -120,13 +123,15 @@ typedef struct QEDRequest { CachedL2Table *l2_table; } QEDRequest; +enum { + QED_AIOCB_WRITE = 0x0001, /* read or write? */ + QED_AIOCB_ZERO = 0x0002, /* zero write, used with QED_AIOCB_WRITE */ +}; + typedef struct QEDAIOCB { - BlockDriverAIOCB common; - QEMUBH *bh; - int bh_ret; /* final return status for completion bh */ + BlockDriverState *bs; QSIMPLEQ_ENTRY(QEDAIOCB) next; /* next request */ - bool is_write; /* false - read, true - write */ - bool *finished; /* signal for cancel completion */ + int flags; /* QED_AIOCB_* bits ORed together */ uint64_t end_pos; /* request end on block device, in bytes */ /* User scatter-gather list */ @@ -135,6 +140,7 @@ typedef struct QEDAIOCB { /* Current cluster scatter-gather list */ QEMUIOVector cur_qiov; + QEMUIOVector *backing_qiov; uint64_t cur_pos; /* position on block device, in bytes */ uint64_t cur_cluster; /* cluster offset in image file */ unsigned int cur_nclusters; /* number of clusters being accessed */ @@ -145,18 +151,29 @@ typedef struct QEDAIOCB { typedef struct { BlockDriverState *bs; /* device */ - uint64_t file_size; /* length of image file, in bytes */ + /* Written only by an allocating write or the timer handler (the latter + * while allocating reqs are plugged). + */ QEDHeader header; /* always cpu-endian */ + + /* Protected by table_lock. */ + CoMutex table_lock; QEDTable *l1_table; L2TableCache l2_cache; /* l2 table cache */ uint32_t table_nelems; uint32_t l1_shift; uint32_t l2_shift; uint32_t l2_mask; + uint64_t file_size; /* length of image file, in bytes */ /* Allocating write request queue */ - QSIMPLEQ_HEAD(, QEDAIOCB) allocating_write_reqs; + QEDAIOCB *allocating_acb; + CoQueue allocating_write_reqs; + bool allocating_write_reqs_plugged; + + /* Periodic flush and clear need check flag */ + QEMUTimer *need_check_timer; } BDRVQEDState; enum { @@ -167,36 +184,9 @@ enum { }; /** - * qed_find_cluster() completion callback - * - * @opaque: User data for completion callback - * @ret: QED_CLUSTER_FOUND Success - * QED_CLUSTER_L2 Data cluster unallocated in L2 - * QED_CLUSTER_L1 L2 unallocated in L1 - * -errno POSIX error occurred - * @offset: Data cluster offset - * @len: Contiguous bytes starting from cluster offset - * - * This function is invoked when qed_find_cluster() completes. - * - * On success ret is QED_CLUSTER_FOUND and offset/len are a contiguous range - * in the image file. - * - * On failure ret is QED_CLUSTER_L2 or QED_CLUSTER_L1 for missing L2 or L1 - * table offset, respectively. len is number of contiguous unallocated bytes. + * Header functions */ -typedef void QEDFindClusterFunc(void *opaque, int ret, uint64_t offset, size_t len); - -/** - * Generic callback for chaining async callbacks - */ -typedef struct { - BlockDriverCompletionFunc *cb; - void *opaque; -} GenericCB; - -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque); -void gencb_complete(void *opaque, int ret); +int qed_write_header_sync(BDRVQEDState *s); /** * L2 cache functions @@ -211,31 +201,33 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table); /** * Table I/O functions */ -int qed_read_l1_table_sync(BDRVQEDState *s); -void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n, - BlockDriverCompletionFunc *cb, void *opaque); -int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, - unsigned int n); -int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - uint64_t offset); -void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset, - BlockDriverCompletionFunc *cb, void *opaque); -void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque); -int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, bool flush); +int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s); +int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index, + unsigned int n); +int coroutine_fn qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, + unsigned int n); +int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, + uint64_t offset); +int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, + uint64_t offset); +int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, + unsigned int index, unsigned int n, + bool flush); +int coroutine_fn qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, + unsigned int index, unsigned int n, + bool flush); /** * Cluster functions */ -void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos, - size_t len, QEDFindClusterFunc *cb, void *opaque); +int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request, + uint64_t pos, size_t *len, + uint64_t *img_offset); /** * Consistency check */ -int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix); +int coroutine_fn qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix); QEDTable *qed_alloc_table(BDRVQEDState *s);