From patchwork Sat Mar 16 14:04:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: harryxiyou@gmail.com X-Patchwork-Id: 228214 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 F344B2C00B6 for ; Sun, 17 Mar 2013 01:04:59 +1100 (EST) Received: from localhost ([::1]:36365 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UGrjF-0005Cy-VL for incoming@patchwork.ozlabs.org; Sat, 16 Mar 2013 10:04:57 -0400 Received: from eggs.gnu.org ([208.118.235.92]:37018) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UGriw-0005Bi-My for qemu-devel@nongnu.org; Sat, 16 Mar 2013 10:04:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UGrin-0008TH-90 for qemu-devel@nongnu.org; Sat, 16 Mar 2013 10:04:38 -0400 Received: from mail-pb0-f53.google.com ([209.85.160.53]:37610) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UGrim-0008T0-Rv for qemu-devel@nongnu.org; Sat, 16 Mar 2013 10:04:29 -0400 Received: by mail-pb0-f53.google.com with SMTP id un1so4989389pbc.26 for ; Sat, 16 Mar 2013 07:04:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:qemu; bh=+TkhRqAmA/q3kZ9ivA2e9mIjBY2exZIYIu/kCDU3/Jc=; b=s9TWeR9sD6RParWiOQqqX0qNYzpQ8VRuUXR/iwIhi6WwYOuaLquh4rqQ4pwB4yy0Su Gp2F/IDUISaYp0IsSYPVtq8Gd/OgieYmPGmd63vTMXq17FsCvw4ldiTIxGqUOt2NDzkC 9mNQOhAjA5ThB303coW4vL4jjdAQuAt31b7DouEzJRZT2gIHV3UEY7XDxNMvPL1IDf0g YRCK9awVc3W19YWpgNRM6jkT0etiYZOemL2DR+9law89x+xpbWpAzbc4oW7axfi08A7A vc+1Wg+mneqZNf8sf5kS/5ffWCweZgxzhZyxc5mf/QgtJj0Rc0TBq3ek3j4rVkrexZSN LfXg== X-Received: by 10.66.8.34 with SMTP id o2mr1450146paa.182.1363442667481; Sat, 16 Mar 2013 07:04:27 -0700 (PDT) Received: from localhost ([113.140.86.66]) by mx.google.com with ESMTPS id ol7sm13657225pbb.14.2013.03.16.07.04.21 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 16 Mar 2013 07:04:26 -0700 (PDT) From: harryxiyou@gmail.com To: qemu-devel@nongnu.org Date: Sat, 16 Mar 2013 22:04:06 +0800 Message-Id: <1363442646-23278-1-git-send-email-harryxiyou@gmail.com> X-Mailer: git-send-email 1.7.9.5 QEMU: HLFS driver for QEMU X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.160.53 Cc: kwolf@redhat.com, cloudxy@googlegroups.com, kanghua151@gmail.com, Harry Wei , stefanha@redhat.com Subject: [Qemu-devel] [PATCH] HLFS driver for QEMU 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: Harry Wei HLFS is HDFS-based(Hadoop Distributed File System) Log-Structured File System. Actually, HLFS, currently, is not a FS but a block-storage system, which we simplify LFS to fit block-level storage. So you could also call HLFS as HLBS (HDFS-based Log-Structured Block-storage System). HLFS has two mode, which are local mode and HDFS mode. HDFS is once write and many read so HLFS realize LBS(Log-Structured Block-storage System) to achieve reading and writing randomly. LBS is based on LFS's basic theories but is different from LFS, which LBS fits block storage better. See http://code.google.com/p/cloudxy/wiki/WHAT_IS_CLOUDXY about HLFS in details. Currently, HLFS support following features: 1, Portions of POSIX --- Just realize some interfaces VM image need. 2, Randomly Read/Write. 3, Large file storage (TB). 4, Support snapshots(Linear snapshots and tree snapshots), Clone, Block compression, Cache, etc. 5, A copy of the data more. 6, Cluster system can dynamic expand. ... Signed-off-by: Harry Wei --- block/Makefile.objs | 2 +- block/hlfs.c | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++ configure | 51 +++++ 3 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 block/hlfs.c diff --git a/block/Makefile.objs b/block/Makefile.objs index c067f38..723c7a5 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -8,7 +8,7 @@ block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o ifeq ($(CONFIG_POSIX),y) -block-obj-y += nbd.o sheepdog.o +block-obj-y += nbd.o sheepdog.o hlfs.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o diff --git a/block/hlfs.c b/block/hlfs.c new file mode 100644 index 0000000..331feae --- /dev/null +++ b/block/hlfs.c @@ -0,0 +1,514 @@ +/* + * Block driver for HLFS(HDFS-based Log-structured File System) + * + * Copyright (c) 2013, Kang Hua + * Copyright (c) 2013, Wang Sen + * Copyright (c) 2013, Harry Wei + * + * This program is free software. You can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Reference: + * http://code.google.com/p/cloudxy + */ + +#include "qemu-common.h" +#include "qemu/error-report.h" +#include "qemu/sockets.h" +#include "block/block_int.h" +#include "qemu/bitops.h" +#include "api/hlfs.h" +#include "storage_helper.h" +#include "comm_define.h" +#include "snapshot_helper.h" +#include "address.h" + +#define DEBUG_HLBS +#undef dprintf +#ifdef DEBUG_HLBS +#define dprintf(fmt, args...) \ + do { \ + fprintf(stdout, "%s %d: " fmt, __func__, __LINE__, ##args); \ + } while (0) +#else +#define dprintf(fmt, args...) +#endif + +#define HLBS_MAX_VDI_SIZE (8192ULL*8192ULL*8192ULL*8192ULL) +#define SECTOR_SIZE 512 + +typedef struct BDRVHLBSState { + struct hlfs_ctrl *hctrl; + char *snapshot; + char *uri; +} BDRVHLBSState; + +/* + * Parse a filename. + * + * file name format must be one of the following: + * 1. [vdiname] + * 2. [vdiname]%[snapshot] + * * vdiname format -- + * * local:///tmp/testenv/testfs + * * hdfs:///tmp/testenv/testfs + * * hdfs://localhost:8020/tmp/testenv/testfs + * * hdfs://localhost/tmp/testenv/testfs + * * hdfs://192.168.0.1:8020/tmp/testenv/testfs + */ + +static int parse_vdiname(BDRVHLBSState *s, const char *filename, char *vdi, + char *snapshot) +{ + if (!filename) { + return -1; + } + + gchar **v = g_strsplit(filename, "%", 2); + if (g_strv_length(v) == 1) { + strcpy(vdi, v[0]); + s->uri = g_strdup(vdi); + } else if (g_strv_length(v) == 2) { + strcpy(vdi, v[0]); + strcpy(snapshot, v[1]); + s->uri = g_strdup(vdi); + s->snapshot = g_strdup(snapshot); + } else { + goto out; + } + + return 0; +out: + g_strfreev(v); + return -1; +} + +static int hlbs_open(BlockDriverState *bs, const char *filename, int flags) +{ + int ret = 0; + BDRVHLBSState *s = bs->opaque; + char vdi[256]; + char snapshot[HLFS_FILE_NAME_MAX]; + + strstart(filename, "hlfs:", (const char **)&filename); + memset(snapshot, 0, sizeof(snapshot)); + memset(vdi, 0, sizeof(vdi)); + + if (parse_vdiname(s, filename, vdi, snapshot) < 0) { + goto out; + } + + HLFS_CTRL *ctrl = init_hlfs(vdi); + if (strlen(snapshot)) { + dprintf("snapshot:%s was open.\n", snapshot); + ret = hlfs_open_by_snapshot(ctrl, snapshot, 1); + } else { + ret = hlfs_open(ctrl, 1); + } + g_assert(ret == 0); + s->hctrl = ctrl; + bs->total_sectors = ctrl->sb.max_fs_size * 1024 * 1024 / SECTOR_SIZE; + return 0; +out: + if (s->hctrl) { + hlfs_close(s->hctrl); + deinit_hlfs(s->hctrl); + } + return -1; +} + +static int hlbs_create(const char *filename, QEMUOptionParameter *options) +{ + int64_t vdi_size = 0; + char *backing_file = NULL; + BDRVHLBSState s; + char vdi[256]; + char snapshot[256]; + const char *vdiname; + int prealloc = 0; + uint32_t is_compress = 0; + strstart(filename, "hlfs:", &vdiname); + + memset(&s, 0, sizeof(s)); + memset(vdi, 0, sizeof(vdi)); + memset(snapshot, 0, sizeof(snapshot)); + + if (parse_vdiname(&s, vdiname, vdi, (char *)&snapshot) < 0) { + error_report("invailid filename"); + return -EINVAL; + } + + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + vdi_size = options->value.n; + } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { + backing_file = options->value.s; + } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { + if (!options->value.s || !strcmp(options->value.s, "off")) { + prealloc = 0; + } else if (!strcmp(options->value.s, "full")) { + prealloc = 1; + } else { + error_report("Invalid preallocation mode: '%s'", + options->value.s); + return -EINVAL; + } + } + options++; + } + + if (vdi_size > HLBS_MAX_VDI_SIZE) { + g_message("vdi_size: %llu Max: %llu", vdi_size, HLBS_MAX_VDI_SIZE); + error_report("too big image size"); + return -EINVAL; + } + + if (backing_file) { + const char *father_uri_with_snapshot; + strstart(backing_file, "hlfs:", &father_uri_with_snapshot); + char *son_uri = vdi; + char *father_uri = NULL; + char *father_snapshot = NULL; + gchar **v = NULL; + v = g_strsplit(father_uri_with_snapshot, "%", 2); + if (g_strv_length(v) != 2) { + g_strfreev(v); + return -1; + } + father_uri = g_strdup(v[0]); + father_snapshot = g_strdup(v[1]); + g_strfreev(v); + if (0 == strcmp(father_uri, son_uri)) { + g_message("father uri can not equal son uri"); + return -1; + } + struct back_storage *father_storage = init_storage_handler(father_uri); + if (!father_storage) { + g_message("can not get storage handler for father_uri:%s", + father_uri); + return -1; + } + struct back_storage *son_storage = init_storage_handler(son_uri); + if (!son_storage) { + g_message("can not get storage handler for son_uri:%s", son_uri); + return -1; + } + /* check son is exist and empty must */ + if ((0 != son_storage->bs_file_is_exist(son_storage, NULL)) || (0 != + son_storage->bs_file_is_exist(son_storage, "superblock"))) { + g_message("hlfs with uri:%s has not exist,please mkfs it first!", + son_uri); + return -1; + } + + uint32_t segno = 0; + uint32_t offset = 0; + if (0 != get_cur_latest_segment_info(son_storage, &segno, &offset)) { + g_message("can not get latest seg info for son "); + } else { + if (segno != 0 || offset != 0) { + g_message("son hlfs must empty"); + return -1; + } + } + /* check son is not clone already */ + char *content = NULL; + uint32_t size = 0; + if (0 != file_get_contents(son_storage, "superblock", + &content, &size)) { + g_message("can not read superblock"); + } + GKeyFile *sb_keyfile = g_key_file_new(); + if (FALSE == g_key_file_load_from_data(sb_keyfile, content, size, + G_KEY_FILE_NONE, NULL)) { + g_message("superblock file format is not key value pairs"); + return -1; + } + gchar *_father_uri = g_key_file_get_string(sb_keyfile, "METADATA", + "father_uri", NULL); + printf("father uri: %s\n", _father_uri); + if (_father_uri != NULL) { + g_message("uri:%s has clone :%s", son_uri, _father_uri); + return -1; + } + g_free(content); + /* read father's snapshot 's inode */ + uint64_t inode_addr; + struct snapshot *ss = NULL; + if (0 > load_snapshot_by_name(father_storage, SNAPSHOT_FILE, &ss, \ + father_snapshot)) { + g_message("load uri:%s ss by name:%s error", father_uri, \ + father_snapshot); + g_free(ss); + return -1; + } + inode_addr = ss->inode_addr; + g_free(ss); + + uint32_t father_seg_size = 0; + uint32_t father_block_size = 0; + uint64_t father_max_fs_size = 0; + + if (0 != read_fs_meta(father_storage, &father_seg_size, + &father_block_size, &father_max_fs_size, &is_compress)) { + g_message("can not read father uri meta"); + return -1; + } + segno = get_segno(inode_addr); + uint32_t son_block_size = g_key_file_get_integer(sb_keyfile, + "METADATA", "block_size", NULL); + uint32_t son_seg_size = g_key_file_get_integer(sb_keyfile, "METADATA", + "segment_size", NULL); + if (son_block_size != father_block_size || father_seg_size != + son_seg_size) { + g_message("sorry , now father segsize and block sizee must same as \ + son!!!"); + return -1; + } + g_key_file_set_uint64(sb_keyfile, "METADATA", "from_segno", segno + 1); + g_key_file_set_string(sb_keyfile, "METADATA", "father_uri", father_uri); + g_key_file_set_integer(sb_keyfile, "METADATA", + "is_compress", is_compress); + g_key_file_set_string(sb_keyfile, "METADATA", "father_ss", + father_snapshot); + g_key_file_set_uint64(sb_keyfile, "METADATA", "snapshot_inode", + inode_addr); + g_key_file_set_uint64(sb_keyfile, "METADATA", "max_fs_size", + father_max_fs_size); + gchar *data = g_key_file_to_data(sb_keyfile, NULL, NULL); + if (0 != son_storage->bs_file_delete(son_storage, "superblock")) { + g_message("can not delete old superblock file"); + return -1; + } + if (0 != file_append_contents(son_storage, "superblock", (char *)data, + strlen(data) + 1)) { + g_message("can not write superblock file"); + return -1; + } + deinit_storage_handler(son_storage); + deinit_storage_handler(father_storage); + } else { + struct back_storage *storage = init_storage_handler(vdi); + if (NULL == storage) { + g_message("can not get storage handler for uri:%s", vdi); + return -1; + } + if ((0 == storage->bs_file_is_exist(storage, NULL)) && (0 == + storage->bs_file_is_exist(storage, "superblock"))) { + g_message("hlfs with uri:%s has exist", vdi); + return 1; + } + if (0 != storage->bs_file_mkdir(storage, NULL)) { + g_message("can not mkdir for our fs %s", vdi); + } + GKeyFile *sb_keyfile = g_key_file_new(); + g_key_file_set_string(sb_keyfile, "METADATA", "uri", vdi); + g_key_file_set_integer(sb_keyfile, "METADATA", "block_size", 8192); + g_key_file_set_integer(sb_keyfile, "METADATA", + "is_compress", is_compress); + g_key_file_set_integer(sb_keyfile, "METADATA", "segment_size", + 67108864); + g_key_file_set_integer(sb_keyfile, "METADATA", "max_fs_size", + vdi_size/(1024 * 1024)); + gchar *data = g_key_file_to_data(sb_keyfile, NULL, NULL); + char *head, *hostname, *dir, *fs_name; + int port; + parse_from_uri(vdi, &head, &hostname, &dir, &fs_name, &port); + char *sb_file_path = g_build_filename(dir, fs_name, "superblock", NULL); + bs_file_t file = storage->bs_file_create(storage, "superblock"); + if (NULL == file) { + g_message("open file :superblock failed"); + g_free(sb_file_path); + return -1; + } + int size = storage->bs_file_append(storage, file, (char *)data, + strlen(data) + 1); + if (size != strlen(data) + 1) { + g_message("can not write superblock file"); + g_free(sb_file_path); + } + storage->bs_file_flush(storage, file); + storage->bs_file_close(storage, file); + deinit_storage_handler(storage); + } + return 0; +} + +static void hlbs_close(BlockDriverState *bs) +{ + BDRVHLBSState *s = bs->opaque; + if (s->hctrl) { + hlfs_close(s->hctrl); + deinit_hlfs(s->hctrl); + } +} + +static int64_t hlbs_getlength(BlockDriverState *bs) +{ + BDRVHLBSState *s = bs->opaque; + return s->hctrl->sb.max_fs_size*1024*1024; +} + +static int64_t hlbs_get_allocated_file_size(BlockDriverState *bs) +{ + BDRVHLBSState *s = bs->opaque; + return s->hctrl->inode.length; +} + +static int hlbs_write(BlockDriverState *bs, int64_t sector_num, const uint8_t + *buf, int nb_sectors) +{ + int ret; + BDRVHLBSState *s = bs->opaque; + uint32_t write_size = nb_sectors * 512; + uint64_t offset = sector_num * 512; + ret = hlfs_write(s->hctrl, (char *)buf, write_size, offset); + if (ret != write_size) { + return -EIO; + } + return 0; +} + +static int hlbs_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, + int nb_sectors) +{ + int ret; + BDRVHLBSState *s = bs->opaque; + uint32_t read_size = nb_sectors * 512; + uint64_t offset = sector_num * 512; + ret = hlfs_read(s->hctrl, (char *)buf, read_size, offset); + if (ret != read_size) { + return -EIO; + } + return 0; +} + +static int hlbs_flush(BlockDriverState *bs) +{ + int ret; + BDRVHLBSState *s = bs->opaque; + ret = hlfs_flush(s->hctrl); + return ret; +} + +static int hlbs_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) +{ + int ret = 0; + BDRVHLBSState *s = bs->opaque; + dprintf("sn_info: name %s id_str %s vm_state_size %llu\n", sn_info->name, + sn_info->id_str, sn_info->vm_state_size); + dprintf("%s %s\n", sn_info->name, sn_info->id_str); + ret = hlfs_take_snapshot(s->hctrl, sn_info->name); + return ret; +} + +static int hlbs_snapshot_goto(BlockDriverState *bs, const char *snapshot) +{ + int ret; + BDRVHLBSState *s = bs->opaque; + char vdi[265]; + + memset(vdi, 0, sizeof(vdi)); + strncpy(vdi, s->hctrl->storage->uri, sizeof(vdi)); + hlfs_close(s->hctrl); + deinit_hlfs(s->hctrl); + HLFS_CTRL *ctrl = init_hlfs(vdi); + s->hctrl = ctrl; + ret = hlfs_open_by_snapshot(ctrl, snapshot, 1); + if (ret != 0) { + goto out; + } + s->hctrl = ctrl; + s->uri = g_strdup(vdi); + s->snapshot = g_strdup(vdi); + bs->total_sectors = ctrl->sb.max_fs_size * 1024 * 1024 / SECTOR_SIZE; + return 0; +out: + if (s->hctrl != NULL) { + hlfs_close(s->hctrl); + deinit_hlfs(s->hctrl); + } + return -1; +} + +static int hlbs_snapshot_delete(BlockDriverState *bs, const char *snapshot) +{ + /* FIXME: Delete specified snapshot id. */ + BDRVHLBSState *s = bs->opaque; + int ret = 0; + ret = hlfs_rm_snapshot(s->hctrl->storage->uri, snapshot); + return ret; +} + +static int hlbs_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) +{ + BDRVHLBSState *s = bs->opaque; + /*Fixed: num_entries must be inited 0*/ + int num_entries = 0; + struct snapshot *snapshots = hlfs_get_all_snapshots(s->hctrl->storage->uri, + &num_entries); + dprintf("snapshot count:%d\n", num_entries); + /*Fixed: snapshots is NULL condition*/ + if (NULL == snapshots) { + dprintf("snapshots is NULL, may be no snapshots, check it please!\n"); + return num_entries; + } + QEMUSnapshotInfo *sn_tab = NULL; + struct snapshot *snapshot = snapshots; + sn_tab = g_malloc0(num_entries * sizeof(*sn_tab)); + int i; + for (i = 0; i < num_entries; i++) { + printf("---snapshot:%s----", snapshot->sname); + sn_tab[i].date_sec = snapshot->timestamp * 1000; + sn_tab[i].date_nsec = 0; + sn_tab[i].vm_state_size = 0; + sn_tab[i].vm_clock_nsec = 0; + snprintf(sn_tab[i].id_str, sizeof(sn_tab[i].id_str), "%u", 0); + strncpy(sn_tab[i].name, snapshot->sname, MIN(sizeof(sn_tab[i].name), + strlen(snapshot->sname))); + snapshot++; + } + *psn_tab = sn_tab; + if (snapshots != NULL) { + g_free(snapshots); + } + return num_entries; +} + +static QEMUOptionParameter hlbs_create_options[] = { + { + .name = BLOCK_OPT_SIZE, + .type = OPT_SIZE, + .help = "Virtual disk size" + }, { + .name = BLOCK_OPT_BACKING_FILE, + .type = OPT_STRING, + .help = "File name of a base image" + }, { + .name = BLOCK_OPT_PREALLOC, + .type = OPT_STRING, + .help = "Preallocation mode (allowed values: off, full)" + }, { NULL } +}; + +static BlockDriver bdrv_hlbs = { + .format_name = "hlfs", + .protocol_name = "hlfs", + .instance_size = sizeof(BDRVHLBSState), + .bdrv_file_open = hlbs_open, + .bdrv_close = hlbs_close, + .bdrv_create = hlbs_create, + .bdrv_getlength = hlbs_getlength, + .bdrv_read = hlbs_read, + .bdrv_write = hlbs_write, + .bdrv_get_allocated_file_size = hlbs_get_allocated_file_size, + .bdrv_snapshot_create = hlbs_snapshot_create, + .bdrv_snapshot_goto = hlbs_snapshot_goto, + .bdrv_snapshot_delete = hlbs_snapshot_delete, + .bdrv_snapshot_list = hlbs_snapshot_list, + .create_options = hlbs_create_options, +}; + +static void bdrv_hlbs_init(void) +{ + if (log4c_init()) { + g_message("log4c_init error!"); + } + bdrv_register(&bdrv_hlbs); +} +block_init(bdrv_hlbs_init); diff --git a/configure b/configure index 46a7594..8afd5ac 100755 --- a/configure +++ b/configure @@ -229,6 +229,7 @@ virtio_blk_data_plane="" gtk="" gtkabi="2.0" tpm="no" +hlfs="" # parse CC options first for opt do @@ -896,6 +897,10 @@ for opt do ;; --enable-glusterfs) glusterfs="yes" ;; + --disable-hlfs) hlfs="no" + ;; + --enable-hlfs) hlfs="yes" + ;; --disable-virtio-blk-data-plane) virtio_blk_data_plane="no" ;; --enable-virtio-blk-data-plane) virtio_blk_data_plane="yes" @@ -1161,6 +1166,8 @@ echo " --with-coroutine=BACKEND coroutine backend. Supported options:" echo " gthread, ucontext, sigaltstack, windows" echo " --enable-glusterfs enable GlusterFS backend" echo " --disable-glusterfs disable GlusterFS backend" +echo " --enable-hlfs enable HLFS backend" +echo " --disable-hlfs disable HLFS backend" echo " --enable-gcov enable test coverage analysis with gcov" echo " --gcov=GCOV use specified gcov [$gcov_tool]" echo " --enable-tpm enable TPM support" @@ -2813,6 +2820,45 @@ if compile_prog "" "" ; then fi ########################################## +# hlfs probe +if test "$hlfs" != "no" ; then + cat > $TMPC < +#include + int main(void) { + return 0; + } +EOF + INC_GLIB_DIR=`pkg-config --cflags glib-2.0` + HLFS_DIR=`echo $HLFS_INSTALL_PATH` + JVM_DIR=`echo $JAVA_HOME` + + if [ `getconf LONG_BIT` -eq "64" ];then + CLIBS="-L$JVM_DIR/jre/lib/amd64/server/ $CLIBS" + fi + if [ `getconf LONG_BIT` -eq "32" ];then + CLIBS="-L$JVM_DIR/jre/lib/i386/server/ $CLIBS" + fi + CLIBS="-L$HLFS_DIR/lib/ $CLIBS" + CFLAGS="-I$HLFS_DIR/include $CFLAGS" + CFLAGS="$INC_GLIB_DIR $CFLAGS" + + hlfs_libs="$CLIBS -lhlfs -llog4c -lglib-2.0 -lgthread-2.0 -lrt -lhdfs -ljvm" + echo "999 CLIBS is $CLIBS\n" + echo "999 CFLAGS is $CFLAGS\n" + if compile_prog "$CFLAGS" "$CLIBS $hlfs_libs"; then + hlfs=yes + libs_tools="$hlfs_libs $libs_tools" + libs_softmmu="$hlfs_libs $libs_softmmu" + else + if test "$hlfs" = "yes"; then + feature_not_found "hlfs block device" + fi + hlfs=no + fi +fi + +########################################## # Do we have libiscsi # We check for iscsi_unmap_sync() to make sure we have a # recent enough version of libiscsi. @@ -3435,6 +3481,7 @@ echo "build guest agent $guest_agent" echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" echo "GlusterFS support $glusterfs" +echo "HLFS support $hlfs" echo "virtio-blk-data-plane $virtio_blk_data_plane" echo "gcov $gcov_tool" echo "gcov enabled $gcov" @@ -4351,6 +4398,10 @@ if test "$gprof" = "yes" ; then fi fi +if test "$hlfs" = "yes" ; then + echo "CONFIG_HLFS=yes" >> $config_target_mak +fi + if test "$tpm" = "yes"; then if test "$target_softmmu" = "yes" ; then echo "CONFIG_TPM=y" >> $config_host_mak