From patchwork Sun Oct 7 05:32:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wenchao xia X-Patchwork-Id: 189790 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 E775D2C0269 for ; Sun, 7 Oct 2012 17:04:09 +1100 (EST) Received: from localhost ([::1]:55950 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TKjXE-0004Zs-UI for incoming@patchwork.ozlabs.org; Sun, 07 Oct 2012 01:36:16 -0400 Received: from eggs.gnu.org ([208.118.235.92]:42259) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TKjWq-0004JR-Cu for qemu-devel@nongnu.org; Sun, 07 Oct 2012 01:35:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TKjWn-0005r1-Su for qemu-devel@nongnu.org; Sun, 07 Oct 2012 01:35:52 -0400 Received: from m12-18.163.com ([220.181.12.18]:59273) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TKjWm-0005qe-DN for qemu-devel@nongnu.org; Sun, 07 Oct 2012 01:35:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=Received:From:To:Cc:Subject:Date:Message-Id: In-Reply-To:References; bh=UR5Evcea9l9vpS6cNdze27wKTM5zLEm4o00yi kl/Dsw=; b=Awr0x3gHteeTM0TgnR1vngRP+xyx8PYs7Gw01F4bxzF/i0Yt5GGLw 8MxvAS+QTKlp2WOznVUVod1sgt3Ix5Iv/SQD2GDxeLUj3mRovcdOsgyLr+bgNzbQ sebaShua8W3jdxk4aGmJxRs2BbX51iXFtQM97D6nIt9JE4NIoqNKvw= Received: from RedHat62GAWSWenchao.localdomain (unknown [113.246.196.44]) by smtp14 (Coremail) with SMTP id EsCowECJe0X2E3FQiZD7Aw--.30209S20; Sun, 07 Oct 2012 13:35:27 +0800 (CST) From: Wenchao Xia To: qemu-devel@nongnu.org Date: Sun, 7 Oct 2012 13:32:36 +0800 Message-Id: <1349587956-21436-6-git-send-email-xiaxia347os@163.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1349587956-21436-1-git-send-email-xiaxia347os@163.com> References: <1349587956-21436-1-git-send-email-xiaxia347os@163.com> X-CM-TRANSID: EsCowECJe0X2E3FQiZD7Aw--.30209S20 X-Coremail-Antispam: 1Uf129KBjvJXoW3KFWrWr4DXFyxCryDJryUAwb_yoWkCFW3pF Z5Cr18Aa15AF1xuw4fZas7Zr909w1DJry3WayDZ3W0yr15XryDXwn5KFyYv3s7Z3ykXr90 va1UAFW8GF45tFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jS2NZUUUUU= X-CM-SenderInfo: x0ld5xzdtul0rv6rljoofrz/xtbB0ARBX09o5rAnsgAAsu X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 220.181.12.18 Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@gmail.com, blauwirbel@gmail.com, pbonzini@redhat.com, xiawenc@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH V6 5/5] libqblock test example 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 From: Wenchao Xia In this example, at first it will create some qcow2 images, then get information including backing file relationship. Then it will do sync IO on the image. Signed-off-by: Wenchao Xia --- tests/libqblock/libqblock-qcow2.c | 392 ++++++++++++++++++++++++++++++++++++- 1 files changed, 390 insertions(+), 2 deletions(-) diff --git a/tests/libqblock/libqblock-qcow2.c b/tests/libqblock/libqblock-qcow2.c index 58fe692..15e81b8 100644 --- a/tests/libqblock/libqblock-qcow2.c +++ b/tests/libqblock/libqblock-qcow2.c @@ -1,4 +1,392 @@ -int main(void) +/* + * QEMU block layer library test + * + * 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. + * + * Limitation: + * 1 filename do not support relative path, to save trouble in creating + * backing files. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "libqblock.h" +#include "libqtest.h" + +#define LIBQB_TEST_ENV_DIR "LIBQBLOCK_TEST_DIR" +#define LIBQB_TEST_DEFAULT_DIR "/tmp" +#define LIBQB_TEST_DEFAULT_FILENAME "libqblock_qcow2_test_img" + +typedef struct LibqbTestSettings { + const char *image_filename; + uint64_t image_size; + unsigned int num_backings; + unsigned int io_buf_size; + uint64_t io_offset; + int print_flag; +} LibqbTestSettings; + +LibqbTestSettings libqb_test_settings; + +static void print_loc(const QBlockLocationInfo *loc) { - return 0; + if (loc == NULL) { + printf("loc is NULL."); + return; + } + switch (loc->prot_type) { + case QB_PROTO_NONE: + printf("protocol type [none]."); + break; + case QB_PROTO_FILE: + printf("protocol type [file], filename [%s].", + loc->o_file.filename); + break; + default: + printf("protocol type not supported."); + break; + } +} + +static void print_info_image_static(QBlockStaticInfo *info) +{ + const uint64_t *virt_size = qb_get_virt_size(info); + const QBlockLocationInfo *backing_loc = qb_get_backing_loc(info); + g_assert(virt_size != NULL); + + printf("=======image location:\n"); + print_loc(&info->loc); + printf("\nvirtual_size %" PRId64 ", format type %d [%s]", + *(virt_size), + info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type)); + printf("\nbacking image location:\n"); + print_loc(backing_loc); + printf("\n"); +} + +static char *generate_backing_filename(const char *filename, int index) +{ + char *backing_filename = NULL; + + backing_filename = g_strdup_printf("%s_backing_%d", filename, index); + return backing_filename; +} + +/* get filename in a full path */ +static const char *get_filename(const char *path) +{ + const char *filename; + filename = strrchr(path, '/'); + if (filename == NULL) { + filename = path; + } else { + filename++; + } + return filename; +} + +/* create a chain of files, num_backings must >= 0. */ +static void files_create_qcow2(const char *filename, + int num_backings, + uint64_t virt_size) +{ + QBlockContext *context = NULL; + QBlockState *qbs = NULL; + QBlockLocationInfo *loc_info = NULL; + QBlockFormatInfo *fmt_info = NULL; + int ret; + int index; + int flag; + char *backing_filename = NULL, *new_filename = NULL; + const char *relative_filename = NULL; + + ret = qb_context_new(&context); + g_assert(ret == 0); + + ret = qb_state_new(context, &qbs); + g_assert(ret == 0); + + ret = qb_loc_info_new(context, &loc_info); + g_assert(ret == 0); + + ret = qb_fmt_info_new(context, &fmt_info); + g_assert(ret == 0); + + loc_info->prot_type = QB_PROTO_FILE; + fmt_info->fmt_type = QB_FMT_QCOW2; + fmt_info->o_qcow2.virt_size = virt_size; + flag = 0; + + index = 0; + while (index < num_backings) { + new_filename = generate_backing_filename(filename, index); + loc_info->o_file.filename = new_filename; + if (backing_filename != NULL) { + fmt_info->o_qcow2.backing_loc.prot_type = QB_PROTO_FILE; + relative_filename = get_filename(backing_filename); + fmt_info->o_qcow2.backing_loc.o_file.filename = + relative_filename; + } + ret = qb_create(context, qbs, loc_info, fmt_info, flag); + g_assert(ret == 0); + free(backing_filename); + backing_filename = new_filename; + new_filename = NULL; + index++; + } + + loc_info->o_file.filename = filename; + if (backing_filename != NULL) { + fmt_info->o_qcow2.backing_loc.prot_type = QB_PROTO_FILE; + relative_filename = get_filename(backing_filename); + fmt_info->o_qcow2.backing_loc.o_file.filename = + relative_filename; + } + ret = qb_create(context, qbs, loc_info, fmt_info, flag); + g_assert(ret == 0); + free(backing_filename); + + qb_fmt_info_delete(context, &fmt_info); + qb_loc_info_delete(context, &loc_info); + qb_state_delete(context, &qbs); + qb_context_delete(&context); + return; +} + +static void files_delete(const char *filename, + int num_backings, + uint64_t virt_size) +{ + char *new_filename = NULL; + int index = 0; + while (index < num_backings) { + new_filename = generate_backing_filename(filename, index); + unlink(new_filename); + free(new_filename); + index++; + } + unlink(filename); +} + +static void testcase_info_image_static(void) +{ + const char *filename = libqb_test_settings.image_filename; + uint64_t image_size = libqb_test_settings.image_size; + int num_backings = libqb_test_settings.num_backings; + QBlockContext *context = NULL; + QBlockState *qbs = NULL; + QBlockLocationInfo *loc_info = NULL; + int ret, flag; + QBlockStaticInfo *info_st = NULL; + int i; + char *backing_filename = NULL; + const uint64_t *virt_size = NULL; + const QBlockLocationInfo *backing_loc = NULL; + + ret = qb_context_new(&context); + g_assert(ret == 0); + + ret = qb_state_new(context, &qbs); + g_assert(ret == 0); + + ret = qb_loc_info_new(context, &loc_info); + g_assert(ret == 0); + + loc_info->prot_type = QB_PROTO_FILE; + loc_info->o_file.filename = filename; + flag = LIBQBLOCK_O_NO_BACKING; + ret = qb_open(context, qbs, loc_info, NULL, flag); + g_assert(ret == 0); + + i = num_backings - 1; + while (1) { + ret = qb_info_image_static_get(context, qbs, &info_st); + g_assert(ret == 0); + if (libqb_test_settings.print_flag > 0) { + print_info_image_static(info_st); + } + qb_close(context, qbs); + + /* checking the information */ + g_assert(info_st->loc.prot_type == loc_info->prot_type); + ret = strcmp(info_st->loc.o_file.filename, + loc_info->o_file.filename); + + g_assert(ret == 0); + g_assert(info_st->fmt.fmt_type == QB_FMT_QCOW2); + virt_size = qb_get_virt_size(info_st); + g_assert(virt_size != NULL); + g_assert(*virt_size == image_size); + backing_loc = qb_get_backing_loc(info_st); + /* qcow2 have always backing file property */ + g_assert(backing_loc != NULL); + if (i >= 0) { + /* it should have backing file */ + g_assert(backing_loc->prot_type == QB_PROTO_FILE); + backing_filename = generate_backing_filename(filename, i); + ret = strcmp(backing_filename, backing_loc->o_file.filename); + g_assert(ret == 0); + g_free(backing_filename); + } else { + g_assert(backing_loc->prot_type == QB_FMT_NONE); + } + i--; + /* see if there is backing file need to check. */ + if (backing_loc->prot_type == QB_FMT_NONE) { + g_assert(i < 0); + break; + } + qb_loc_info_delete(context, &loc_info); + loc_info = qb_loc_info_dup(backing_loc); + ret = qb_open(context, qbs, loc_info, NULL, flag); + g_assert(ret == 0); + qb_info_image_static_delete(context, &info_st); + } + qb_info_image_static_delete(context, &info_st); + + qb_loc_info_delete(context, &loc_info); + qb_state_delete(context, &qbs); + qb_context_delete(&context); + return; +} + +/* assuming the image is new created */ +static void testcase_sync_io(void) +{ + const char *filename = libqb_test_settings.image_filename; + uint64_t io_buf_size = libqb_test_settings.io_buf_size; + uint64_t io_offset = libqb_test_settings.io_offset;; + unsigned char *buf_r, *buf_w; + uint64_t i; + unsigned int rand_value; + + buf_r = g_malloc0(io_buf_size); + buf_w = g_malloc0(io_buf_size); + for (i = 0; i < io_buf_size; i++) { + rand_value = g_test_rand_int_range(0, 255); + buf_w[i] = (unsigned char)rand_value; + } + + QBlockContext *context = NULL; + QBlockState *qbs = NULL; + QBlockLocationInfo *loc_info = NULL; + int ret, flag; + + ret = qb_context_new(&context); + g_assert(ret == 0); + + ret = qb_state_new(context, &qbs); + g_assert(ret == 0); + + ret = qb_loc_info_new(context, &loc_info); + g_assert(ret == 0); + + + loc_info->prot_type = QB_PROTO_FILE; + loc_info->o_file.filename = filename; + flag = LIBQBLOCK_O_RDWR; + ret = qb_open(context, qbs, loc_info, NULL, flag); + g_assert(ret == 0); + + int status; + int64_t len; + ret = qb_check_allocation(context, qbs, io_offset, io_buf_size, + &status, &len); + g_assert(ret == 0); + g_assert(status == 0); + g_assert(len == io_buf_size); + + ret = qb_write(context, qbs, buf_w, io_buf_size, io_offset); + g_assert(ret == io_buf_size); + + ret = qb_read(context, qbs, buf_r, io_buf_size, io_offset); + g_assert(ret == io_buf_size); + + int cmp = memcmp(buf_r, buf_w, io_buf_size); + g_assert(cmp == 0); + + ret = qb_check_allocation(context, qbs, io_offset, io_buf_size, + &status, &len); + g_assert(ret == 0); + g_assert(status == 1); + g_assert(len == io_buf_size); + + qb_close(context, qbs); + + qb_loc_info_delete(context, &loc_info); + qb_state_delete(context, &qbs); + qb_context_delete(&context); + g_free(buf_r); + g_free(buf_w); + return; +} + +int main(int argc, char **argv) +{ + const char *root_dir; + const char *name = LIBQB_TEST_DEFAULT_FILENAME; + int ret; + int dir_created = 0; + char *filename; + + root_dir = getenv(LIBQB_TEST_ENV_DIR); + if (root_dir == NULL) { + root_dir = LIBQB_TEST_DEFAULT_DIR; + } + + ret = access(root_dir, F_OK); + if (ret != 0) { + /*try mkdir */ + ret = mkdir(root_dir, 0755); + g_assert(ret == 0); + dir_created = 1; + } + + filename = g_strdup_printf("%s/%s", root_dir, name); + + g_test_init(&argc, &argv, NULL); + g_test_rand_int(); + + libqb_test_settings.image_filename = filename; + libqb_test_settings.image_size = + 1024 * 1024 * g_test_rand_int_range(1, 1024); + libqb_test_settings.num_backings = g_test_rand_int_range(0, 10); + libqb_test_settings.io_buf_size = g_test_rand_int_range(1, 1024 * 1024); + libqb_test_settings.io_offset = g_test_rand_int_range(0, + libqb_test_settings.image_size - libqb_test_settings.io_buf_size); + + files_create_qcow2(libqb_test_settings.image_filename, + libqb_test_settings.num_backings, + libqb_test_settings.image_size); + + g_test_add_func("/libqblock/sync_info_image_static", + testcase_info_image_static); + g_test_add_func("/libqblock/sync_io", testcase_sync_io); + + ret = g_test_run(); + files_delete(libqb_test_settings.image_filename, + libqb_test_settings.num_backings, + libqb_test_settings.image_size); + + g_free(filename); + if (dir_created) { + ret = rmdir(root_dir); + g_assert(ret == 0); + } + return ret; }