From patchwork Wed Aug 29 11:03:19 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wayne Xia X-Patchwork-Id: 180681 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 916312C033A for ; Wed, 29 Aug 2012 21:04:36 +1000 (EST) Received: from localhost ([::1]:55152 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T6g4Y-00050d-MI for incoming@patchwork.ozlabs.org; Wed, 29 Aug 2012 07:04:34 -0400 Received: from eggs.gnu.org ([208.118.235.92]:59977) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T6g4B-0004A9-V1 for qemu-devel@nongnu.org; Wed, 29 Aug 2012 07:04:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T6g46-0006t1-LT for qemu-devel@nongnu.org; Wed, 29 Aug 2012 07:04:11 -0400 Received: from e28smtp09.in.ibm.com ([122.248.162.9]:47173) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T6g45-0006sI-Mx for qemu-devel@nongnu.org; Wed, 29 Aug 2012 07:04:06 -0400 Received: from /spool/local by e28smtp09.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 29 Aug 2012 16:33:59 +0530 Received: from d28relay02.in.ibm.com (9.184.220.59) by e28smtp09.in.ibm.com (192.168.1.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 29 Aug 2012 16:33:58 +0530 Received: from d28av02.in.ibm.com (d28av02.in.ibm.com [9.184.220.64]) by d28relay02.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q7TB3vZ762980122 for ; Wed, 29 Aug 2012 16:33:57 +0530 Received: from d28av02.in.ibm.com (loopback [127.0.0.1]) by d28av02.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q7TB3ur8008246 for ; Wed, 29 Aug 2012 21:03:57 +1000 Received: from RedHat62GAWSWenchao (wenchaox.cn.ibm.com [9.115.122.69]) by d28av02.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q7TB3HNj005404; Wed, 29 Aug 2012 21:03:54 +1000 From: Wenchao Xia To: qemu-devel@nongnu.org Date: Wed, 29 Aug 2012 19:03:19 +0800 Message-Id: <1346238199-24425-1-git-send-email-xiawenc@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1 x-cbid: 12082911-2674-0000-0000-000005C66D68 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 122.248.162.9 Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@gmail.com, Wenchao Xia , blauwirbel@gmail.com, pbonzini@redhat.com, eblake@redhat.com, afaerber@suse.de Subject: [Qemu-devel] [PATCH v3 1/5] [RFC] libqblock, API design X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Important APIs: 1 QBroker. These structure was used to retrieve errors, every thread must create one first, Later maybe thread related staff could be added into it. 2 AIO. This library does an encapsulation on qemu aio. AIO api r/w API would be called and return without blocking, and then it runs the checking API, in which the registered call back function in previous r/w API call, would be executed if that request have completed. It is actually the "bottom half" in qemu code. Executing sequence of submitted request may be not the same as submit order. 3 Image Information. Now it is not folded with location and format structure, because it would cause caller more codes to find one member. For example, if backing_file is embbed in struture and union loc, user may have "switch" code to find the real sub memebr embbed depends on formats. Foldered structure may represent some formats have not this property, but user is harder to use. A nother solution is a series of small APIs, but it seems function is duplicated. Signed-off-by: Wenchao Xia --- libqblock/libqblock.h | 550 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 550 insertions(+), 0 deletions(-) create mode 100644 libqblock/libqblock.h diff --git a/libqblock/libqblock.h b/libqblock/libqblock.h new file mode 100644 index 0000000..33381d1 --- /dev/null +++ b/libqblock/libqblock.h @@ -0,0 +1,550 @@ +/* + * QEMU block layer library + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * 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 LIBQBLOCK_H +#define LIBQBLOCK_H + +#include +#include +#include +#include + +#define QB_ERR_MEM_ERR (-1) +#define QB_ERR_INTERNAL_ERR (-2) +#define QB_ERR_INVALID_PARAM (-3) + +/* this library is designed around this core struct. */ +struct QBlockState; + +/* every thread would have a broker. */ +struct QBroker; + +/** + * libqblock_init: Initialize the library + */ +void libqblock_init(void); + +/** + * qb_broker_new: allocate a new broker + * + * Broker is used to pass operation to libqblock, and got feed back from it. + * + * Returns 0 on success, negative value on fail. + * + * @broker: used to receive the created struct. + */ +int qb_broker_new(struct QBroker **broker); + +/** + * qb_broker_delete: delete broker + * + * Broker will be freed and set to NULL. + * + * @broker: operation broker to be deleted. + */ +void qb_broker_delete(struct QBroker **broker); + +/** + * qb_state_new: allocate a new QBloctState struct + * + * Following qblock action were based on this struct + * + * Returns 0 if succeed, negative value on fail. + * + * @broker: operation broker. + * @qbs: used to receive the created struct. + */ +int qb_state_new(struct QBroker *broker, + struct QBlockState **qbs); + +/** + * qb_state_delete: free a QBloctState struct + * + * if it is opened, a qb_close must be called before free. + * + * @broker: operation broker. + * @qbs: pointer to the struct's pointer. + */ +void qb_state_delete(struct QBroker *broker, + struct QBlockState **qbs); + + +/* flag used in open and create */ +#define LIBQBLOCK_O_RDWR 0x0002 +/* do not use the host page cache */ +#define LIBQBLOCK_O_NOCACHE 0x0020 +/* use write-back caching */ +#define LIBQBLOCK_O_CACHE_WB 0x0040 +/* don't open the backing file */ +#define LIBQBLOCK_O_NO_BACKING 0x0100 +/* disable flushing on this disk */ +#define LIBQBLOCK_O_NO_FLUSH 0x0200 + +#define LIBQBLOCK_O_CACHE_MASK \ + (LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | LIBQBLOCK_O_NO_FLUSH) + +#define LIBQBLOCK_O_VALID_MASK \ + (LIBQBLOCK_O_RDWR | LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | \ + LIBQBLOCK_O_NO_BACKING | LIBQBLOCK_O_NO_FLUSH) + +enum QBlockProtocol { + QB_PROTO_NONE = 0, + QB_PROTO_FILE, + QB_PROTO_MAX +}; + +enum QBlockFormat { + QB_FMT_NONE = 0, + QB_FMT_COW, + QB_FMT_QED, + QB_FMT_QCOW, + QB_FMT_QCOW2, + QB_FMT_RAW, + QB_FMT_RBD, + QB_FMT_SHEEPDOG, + QB_FMT_VDI, + QB_FMT_VMDK, + QB_FMT_VPC, + QB_FMT_MAX +}; + +struct QBlockOption_prot_file { + char *filename; +}; + +union QBlockOption_prot { + struct QBlockOption_prot_file o_file; +}; + +/** + * struct QBlockOptionLoc: contains information about how to find the image + * + * @prot_type: protocol type, now only support FILE. + * @prot_op: protocol related options. + */ +struct QBlockOptionLoc { + enum QBlockProtocol prot_type; + union QBlockOption_prot prot_op; + uint8_t reserved[512]; +}; + +/** + * qb_ol_new: create a new struct QBlockOptionLoc. + * + * return 0 on success, negative on fail. + * + * @broker: operation broker. + * @op: pointer to receive the new created one. + */ +int qb_ol_new(struct QBroker *broker, + struct QBlockOptionLoc **op); + +/** + * qb_ol_delete: free a struct QBlockOptionLoc. + * + * @broker: operation broker. + * @op: pointer to the object, *op would be set to NULL. + */ +void qb_ol_delete(struct QBroker *broker, + struct QBlockOptionLoc **op); + + +/* format related options */ +struct QBlockOption_fmt_cow { + size_t virt_size; + struct QBlockOptionLoc backing_loc; +}; + +struct QBlockOption_fmt_qed { + size_t virt_size; + struct QBlockOptionLoc backing_loc; + enum QBlockFormat backing_fmt; + size_t cluster_size; /* unit is bytes */ + size_t table_size; /* unit is clusters */ +}; + +struct QBlockOption_fmt_qcow { + size_t virt_size; + struct QBlockOptionLoc backing_loc; + bool encrypt; +}; + +/* "Compatibility level (0.10 or 1.1)" */ +enum QBlockOption_fmt_qcow2_cpt { + QBO_FMT_QCOW2_CPT_NONE = 0, + QBO_FMT_QCOW2_CPT_V010, + QBO_FMT_QCOW2_CPT_V110, +}; + +/* off or metadata */ +enum QBlockOption_fmt_qcow2_prealloc { + QBO_FMT_QCOW2_PREALLOC_NONE = 0, + QBO_FMT_QCOW2_PREALLOC_OFF, + QBO_FMT_QCOW2_PREALLOC_METADATA, +}; + +struct QBlockOption_fmt_qcow2 { + size_t virt_size; + struct QBlockOptionLoc backing_loc; + enum QBlockFormat backing_fmt; + bool encrypt; + size_t cluster_size; /* unit is bytes */ + enum QBlockOption_fmt_qcow2_cpt cpt_lv; + enum QBlockOption_fmt_qcow2_prealloc pre_mode; +}; + +struct QBlockOption_fmt_raw { + size_t virt_size; +}; + +struct QBlockOption_fmt_rbd { + size_t virt_size; + size_t cluster_size; +}; + +/* off or full */ +enum QBlockOption_fmt_sheepdog_prealloc { + QBO_FMT_SD_PREALLOC_NONE = 0, + QBO_FMT_SD_PREALLOC_OFF, + QBO_FMT_SD_PREALLOC_FULL, +}; + +struct QBlockOption_fmt_sheepdog { + size_t virt_size; + struct QBlockOptionLoc backing_loc; + enum QBlockOption_fmt_sheepdog_prealloc pre_mode; +}; + +enum QBlockOption_fmt_vdi_prealloc { + QBO_FMT_VDI_PREALLOC_NONE = 0, + QBO_FMT_VDI_PREALLOC_FALSE, + QBO_FMT_VDI_PREALLOC_TRUE, +}; + +struct QBlockOption_fmt_vdi { + size_t virt_size; + size_t cluster_size; + enum QBlockOption_fmt_vdi_prealloc pre_mode; +}; + +/* whether compact to vmdk verion 6 */ +enum QBlockOption_fmt_vmdk_cpt { + QBO_FMT_VMDK_CPT_NONE = 0, + QBO_FMT_VMDK_CPT_VMDKV6_FALSE, + QBO_FMT_VMDK_CPT_VMDKV6_TRUE, +}; + +/* vmdk flat extent format, values: +"{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | +twoGbMaxExtentFlat | streamOptimized} */ +enum QBlockOption_fmt_vmdk_subfmt { + QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE = 0, + QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE, + QBO_FMT_VMDK_SUBFMT_MONOLITHIC_FLAT, + QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_SPARSE, + QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_FLAT, + QBO_FMT_VMDK_SUBFMT_STREAM_OPTIMIZED, +}; + +struct QBlockOption_fmt_vmdk { + size_t virt_size; + struct QBlockOptionLoc backing_loc; + enum QBlockOption_fmt_vmdk_cpt cpt_lv; + enum QBlockOption_fmt_vmdk_subfmt subfmt; +}; + +/* "{dynamic (default) | fixed} " */ +enum QBlockOption_fmt_vpc_subfmt { + QBO_FMT_VPC_SUBFMT_NONE = 0, + QBO_FMT_VPC_SUBFMT_DYNAMIC, + QBO_FMT_VPC_SUBFMT_FIXED, +}; + +struct QBlockOption_fmt_vpc { + size_t virt_size; + enum QBlockOption_fmt_vpc_subfmt subfmt; +}; + +union QBlockOption_fmt { + struct QBlockOption_fmt_cow o_cow; + struct QBlockOption_fmt_qed o_qed; + struct QBlockOption_fmt_qcow o_qcow; + struct QBlockOption_fmt_qcow2 o_qcow2; + struct QBlockOption_fmt_raw o_raw; + struct QBlockOption_fmt_rbd o_rbd; + struct QBlockOption_fmt_sheepdog o_sheepdog; + struct QBlockOption_fmt_vdi o_vdi; + struct QBlockOption_fmt_vmdk o_vmdk; + struct QBlockOption_fmt_vpc o_vpc; +}; + +struct QBlockOptionFormat { + enum QBlockFormat fmt_type; + union QBlockOption_fmt fmt_op; + uint8_t reserved[512]; +}; + +/** + * qb_of_new: create a new QBlockOptionFormat structure. + * + * return 0 on success, negative on fail. + * + * @broker: operation broker. + * @op: pointer that will receive created struct. + */ +int qb_of_new(struct QBroker *broker, + struct QBlockOptionFormat **op); + +/** + * qb_of_delete: free QBlockOptionFormat structure. + * + * @broker: operation broker. + * @op: pointer to the struct, *op would be set to NULL. + */ +void qb_of_delete(struct QBroker *broker, + struct QBlockOptionFormat **op); + + +/** + * qb_open: open a block object. + * + * return 0 on success, negative on fail. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @loc: location options for open, how to find the image. + * @fmt: format options, how to extract the data, only valid member now is + fmt->fmt_type, set NULL if you want auto discovery the format. + * @flag: behavior control flags. + */ +int qb_open(struct QBroker *broker, + struct QBlockState *qbs, + struct QBlockOptionLoc *loc, + struct QBlockOptionFormat *fmt, + int flag); + +/** + * qb_close: close a block object. + * + * qb_flush is automaticlly done inside. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + */ +void qb_close(struct QBroker *broker, + struct QBlockState *qbs); + +/** + * qb_create: create a block image or object. + * + * Note: Create operation would not open the image automatically. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @loc: location options for open, how to find the image. + * @fmt: format options, how to extract the data. + * @flag: behavior control flags. + */ +int qb_create(struct QBroker *broker, + struct QBlockState *qbs, + struct QBlockOptionLoc *loc, + struct QBlockOptionFormat *fmt, + int flag); + + +/* sync access */ +/** + * qb_read: block sync read. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @buf: buffer that receive the content. + * @len: length to read. + * @offset: offset in the block data. + */ +int qb_read(struct QBroker *broker, + struct QBlockState *qbs, + const void *buf, + size_t len, + off_t offset); +/** + * qb_write: block sync write. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @buf: buffer that receive the content. + * @len: length to write. + * @offset: offset in the block data. + */ +int qb_write(struct QBroker *broker, + struct QBlockState *qbs, + const void *buf, + size_t len, + off_t offset); + +/** + * qb_flush: block sync flush. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + */ +int qb_flush(struct QBroker *broker, + struct QBlockState *qbs); + +/* AIO */ +/** + * QBAioReq: represent the AIO request fired. + */ +struct QBAioReq; + +/** + * QBAioCompFunc: call back function which would be automatically called in + * qb_aio_check if a IO complete or cancelled. + * + * @opaque: opaque data registed. + * @ret: io execution result. + */ +typedef void QBAioCompFunc(void *opaque, int ret); + +/** + * qb_aio_write: block async write. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @buf: buffer that receive the content. + * @len: length to write. + * @offset: offset in the block data. + * @cb: call back function after io complete, can be NULL. + * @cb_opaque: call back opaque data. + * @req: pointer to receive new created request, can be NULL. + */ +int qb_aio_write(struct QBroker *broker, + struct QBlockState *qbs, + void *buf, + size_t len, + off_t offset, + QBAioCompFunc *cb, + void *cb_opaque, + struct QBAioReq **req); + +/** + * qb_aio_read: block async read. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @buf: buffer that receive the content. + * @len: length to write. + * @offset: offset in the block data. + * @cb: call back function after io complete, can be NULL. + * @cb_opaque: call back opaque data. + * @req: pointer to receive new created request, can be NULL. + */ +int qb_aio_read(struct QBroker *broker, + struct QBlockState *qbs, + void *buf, + size_t len, + off_t offset, + QBAioCompFunc *cb, + void *cb_opaque, + struct QBAioReq **req); + +/** + * qb_aio_check: check if there is aio request completed, if there is, execute + * the registered QBAioCompFunc call back function. + * + * return true if there is aio request remains, false if no aio request left, + * It never fail. Note the execution sequence of submitted request is not + * guarrentted. + */ +bool qb_aio_check(struct QBroker *broker); + +/* image information */ +/** + * QBlockInfoImageStatic: information about the block image. + * + * @loc: location info. + * @fmt_type: format type. + * @virt_size: virtual size in bytes. + * @backing_loc: backing file location, its type is QB_PROT_NONE if not exist. + * @allocated_size: allocated size in bytes, negative if not available. + * @encrypt: encrypt flag. + */ +struct QBlockInfoImageStatic { + struct QBlockOptionLoc loc; + enum QBlockFormat fmt_type; + size_t virt_size; + /* advance info */ + struct QBlockOptionLoc backing_loc; + size_t allocated_size; + bool encrypt; +}; + + +/** + * qb_get_image_info: get image info. + * + * return negative on fail, 0 on success. + * + * @broker: operation broker. + * @qbs: pointer to struct QBlockState. + * @info: pointer that would receive the information. + */ +int qb_info_image_static_get(struct QBroker *broker, + struct QBlockState *qbs, + struct QBlockInfoImageStatic **info); + +/** + * qb_delete_image_info: free image info. + * + * @broker: operation broker. + * @info: pointer to the information struct. + */ +void qb_info_image_static_delete(struct QBroker *broker, + struct QBlockInfoImageStatic **info); + + +/* error handling */ +/** + * qb_error_get_human_str: get human readable erro string. + * + * return a human readable string. + * + * @broker: operation broker, must be valid. + * @buf: buf to receive the string. + * @buf_size: the size of the string buf. + */ +void qb_error_get_human_str(struct QBroker *broker, + char *buf, int buf_size); + +/** + * qb_error_get_errno: get error number, only valid when err_ret is + * QB_ERR_INTERNAL_ERR. + * + * return negative errno or 0 if last error is not QB_ERR_INTERNAL_ERR. + * + * @broker: operation broker. + */ +int qb_error_get_errno(struct QBroker *broker); +#endif