[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] HLFS driver for QEMU
From: |
harryxiyou |
Subject: |
[Qemu-devel] [PATCH] HLFS driver for QEMU |
Date: |
Mon, 18 Mar 2013 14:39:29 +0800 |
From: Harry Wei <address@hidden>
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 <address@hidden>
---
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 <address@hidden>
+ * Copyright (c) 2013, Wang Sen <address@hidden>
+ * Copyright (c) 2013, Harry Wei <address@hidden>
+ *
+ * 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 <<EOF
+#include <stdio.h>
+#include <api/hlfs.h>
+ 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
--
1.7.9.5
- [Qemu-devel] [PATCH] HLFS driver for QEMU, harryxiyou, 2013/03/16
- [Qemu-devel] [PATCH] HLFS driver for QEMU,
harryxiyou <=
- [Qemu-devel] [PATCH] HLFS driver for QEMU, harryxiyou, 2013/03/18
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, Stefan Hajnoczi, 2013/03/18
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, harryxiyou, 2013/03/18
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, Stefan Hajnoczi, 2013/03/18
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, harryxiyou, 2013/03/20
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, Stefan Hajnoczi, 2013/03/20
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, harryxiyou, 2013/03/20
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, harryxiyou, 2013/03/28
- Re: [Qemu-devel] [PATCH] HLFS driver for QEMU, Stefan Hajnoczi, 2013/03/28