From 9a05feabd537615b7f3d9d899686e513e71fdc12 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Feb 2014 18:28:03 +0100 Subject: [PATCH 1/9] qemu-iotests: add more tests to the "quick" group None of these needs QEMU_PROG, and they all take but a few seconds. We need to point the launching script to qemu-nbd, though. Signed-off-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests-quick.sh | 1 + tests/qemu-iotests/group | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/tests/qemu-iotests-quick.sh b/tests/qemu-iotests-quick.sh index cf90de0b8b..c449e8ab4a 100755 --- a/tests/qemu-iotests-quick.sh +++ b/tests/qemu-iotests-quick.sh @@ -8,6 +8,7 @@ export QEMU_PROG="this_should_be_unused" export QEMU_IMG_PROG="$(pwd)/qemu-img" export QEMU_IO_PROG="$(pwd)/qemu-io" +export QEMU_NBD_PROG="$(pwd)/qemu-nbd" cd $SRC_PATH/tests/qemu-iotests diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index db127d924d..8dd8553035 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -58,30 +58,30 @@ 049 rw auto 050 rw auto backing quick 051 rw auto -052 rw auto backing -053 rw auto -054 rw auto +052 rw auto backing quick +053 rw auto quick +054 rw auto quick 055 rw auto 056 rw auto backing 057 rw auto -058 rw auto -059 rw auto -060 rw auto -061 rw auto -062 rw auto -063 rw auto -064 rw auto +058 rw auto quick +059 rw auto quick +060 rw auto quick +061 rw auto quick +062 rw auto quick +063 rw auto quick +064 rw auto quick 065 rw auto -066 rw auto +066 rw auto quick 067 rw auto 068 rw auto -069 rw auto -070 rw auto +069 rw auto quick +070 rw auto quick 071 rw auto -072 rw auto -073 rw auto -074 rw auto -077 rw auto +072 rw auto quick +073 rw auto quick +074 rw auto quick +077 rw auto quick 079 rw auto 081 rw auto 082 rw auto quick From 1b37b3442f78a77844fdaf7f53e5f04e4ce8f1d6 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Mon, 17 Feb 2014 11:11:11 -0500 Subject: [PATCH 2/9] block: gluster - code movements, state storage changes In preparation for supporting reopen on gluster, move flag parsing out to a function. Also, add a NULL check in the gconf cleanup. Signed-off-by: Jeff Cody Signed-off-by: Stefan Hajnoczi --- block/gluster.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/block/gluster.c b/block/gluster.c index 14d390b4c7..d09824d750 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -45,11 +45,13 @@ typedef struct GlusterConf { static void qemu_gluster_gconf_free(GlusterConf *gconf) { - g_free(gconf->server); - g_free(gconf->volname); - g_free(gconf->image); - g_free(gconf->transport); - g_free(gconf); + if (gconf) { + g_free(gconf->server); + g_free(gconf->volname); + g_free(gconf->image); + g_free(gconf->transport); + g_free(gconf); + } } static int parse_volume_options(GlusterConf *gconf, char *path) @@ -272,11 +274,28 @@ static QemuOptsList runtime_opts = { }, }; +static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags) +{ + assert(open_flags != NULL); + + *open_flags |= O_BINARY; + + if (bdrv_flags & BDRV_O_RDWR) { + *open_flags |= O_RDWR; + } else { + *open_flags |= O_RDONLY; + } + + if ((bdrv_flags & BDRV_O_NOCACHE)) { + *open_flags |= O_DIRECT; + } +} + static int qemu_gluster_open(BlockDriverState *bs, QDict *options, int bdrv_flags, Error **errp) { BDRVGlusterState *s = bs->opaque; - int open_flags = O_BINARY; + int open_flags = 0; int ret = 0; GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); QemuOpts *opts; @@ -299,15 +318,7 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options, goto out; } - if (bdrv_flags & BDRV_O_RDWR) { - open_flags |= O_RDWR; - } else { - open_flags |= O_RDONLY; - } - - if ((bdrv_flags & BDRV_O_NOCACHE)) { - open_flags |= O_DIRECT; - } + qemu_gluster_parse_flags(bdrv_flags, &open_flags); s->fd = glfs_open(s->glfs, gconf->image, open_flags); if (!s->fd) { From adccfbcd6020e928db93b2b4faf0dbd05ffbe016 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Mon, 17 Feb 2014 11:11:12 -0500 Subject: [PATCH 3/9] block: gluster - add reopen support. Gluster does parse open flags in its .bdrv_open() implementation, and the .bdrv_reopen_* implementations need to do the same. A new gluster connection to the image file to be created is established in the .bdrv_reopen_prepare(), and the image file opened with the new flags. If this is successful, then the old image file is closed, and the old connection torn down. The relevant structure pointers in the gluster state structure are updated to the new connection. If it is not successful, then the new file handle and connection is abandoned (if it exists), while the old connection is not modified at all. With reopen supported, block-commit (and offline commit) is now also supported for image files whose base image uses the native gluster protocol driver. Signed-off-by: Jeff Cody Signed-off-by: Stefan Hajnoczi --- block/gluster.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/block/gluster.c b/block/gluster.c index d09824d750..54ee9b7d93 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -340,6 +340,96 @@ out: return ret; } +typedef struct BDRVGlusterReopenState { + struct glfs *glfs; + struct glfs_fd *fd; +} BDRVGlusterReopenState; + + +static int qemu_gluster_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + int ret = 0; + BDRVGlusterReopenState *reop_s; + GlusterConf *gconf = NULL; + int open_flags = 0; + + assert(state != NULL); + assert(state->bs != NULL); + + state->opaque = g_malloc0(sizeof(BDRVGlusterReopenState)); + reop_s = state->opaque; + + qemu_gluster_parse_flags(state->flags, &open_flags); + + gconf = g_malloc0(sizeof(GlusterConf)); + + reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename); + if (reop_s->glfs == NULL) { + ret = -errno; + goto exit; + } + + reop_s->fd = glfs_open(reop_s->glfs, gconf->image, open_flags); + if (reop_s->fd == NULL) { + /* reops->glfs will be cleaned up in _abort */ + ret = -errno; + goto exit; + } + +exit: + /* state->opaque will be freed in either the _abort or _commit */ + qemu_gluster_gconf_free(gconf); + return ret; +} + +static void qemu_gluster_reopen_commit(BDRVReopenState *state) +{ + BDRVGlusterReopenState *reop_s = state->opaque; + BDRVGlusterState *s = state->bs->opaque; + + + /* close the old */ + if (s->fd) { + glfs_close(s->fd); + } + if (s->glfs) { + glfs_fini(s->glfs); + } + + /* use the newly opened image / connection */ + s->fd = reop_s->fd; + s->glfs = reop_s->glfs; + + g_free(state->opaque); + state->opaque = NULL; + + return; +} + + +static void qemu_gluster_reopen_abort(BDRVReopenState *state) +{ + BDRVGlusterReopenState *reop_s = state->opaque; + + if (reop_s == NULL) { + return; + } + + if (reop_s->fd) { + glfs_close(reop_s->fd); + } + + if (reop_s->glfs) { + glfs_fini(reop_s->glfs); + } + + g_free(state->opaque); + state->opaque = NULL; + + return; +} + #ifdef CONFIG_GLUSTERFS_ZEROFILL static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags) @@ -630,6 +720,9 @@ static BlockDriver bdrv_gluster = { .instance_size = sizeof(BDRVGlusterState), .bdrv_needs_filename = true, .bdrv_file_open = qemu_gluster_open, + .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, + .bdrv_reopen_commit = qemu_gluster_reopen_commit, + .bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_close = qemu_gluster_close, .bdrv_create = qemu_gluster_create, .bdrv_getlength = qemu_gluster_getlength, @@ -654,6 +747,9 @@ static BlockDriver bdrv_gluster_tcp = { .instance_size = sizeof(BDRVGlusterState), .bdrv_needs_filename = true, .bdrv_file_open = qemu_gluster_open, + .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, + .bdrv_reopen_commit = qemu_gluster_reopen_commit, + .bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_close = qemu_gluster_close, .bdrv_create = qemu_gluster_create, .bdrv_getlength = qemu_gluster_getlength, @@ -678,6 +774,9 @@ static BlockDriver bdrv_gluster_unix = { .instance_size = sizeof(BDRVGlusterState), .bdrv_needs_filename = true, .bdrv_file_open = qemu_gluster_open, + .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, + .bdrv_reopen_commit = qemu_gluster_reopen_commit, + .bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_close = qemu_gluster_close, .bdrv_create = qemu_gluster_create, .bdrv_getlength = qemu_gluster_getlength, @@ -702,6 +801,9 @@ static BlockDriver bdrv_gluster_rdma = { .instance_size = sizeof(BDRVGlusterState), .bdrv_needs_filename = true, .bdrv_file_open = qemu_gluster_open, + .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, + .bdrv_reopen_commit = qemu_gluster_reopen_commit, + .bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_close = qemu_gluster_close, .bdrv_create = qemu_gluster_create, .bdrv_getlength = qemu_gluster_getlength, From a9e6a0cbe2c12c7b5708451d2211d9b00922d605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Canet?= Date: Sat, 22 Feb 2014 18:43:40 +0100 Subject: [PATCH 4/9] qmp: Fix BlockdevOptionQuorum. Fix some nits before QEMU 2.0 freeze. Signed-off-by: Benoit Canet Reviewed-by: Eric Blake Signed-off-by: Stefan Hajnoczi --- qapi-schema.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index ac8ad24966..c3592f6c11 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4436,10 +4436,11 @@ # Driver specific block device options for Quorum # # @blkverify: #optional true if the driver must print content mismatch +# set to false by default # -# @children: the children block device to use +# @children: the children block devices to use # -# @vote_threshold: the vote limit under which a read will fail +# @vote-threshold: the vote limit under which a read will fail # # Since: 2.0 ## From 0c762736df0cce743b4017c41435632dcb866413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Canet?= Date: Sat, 22 Feb 2014 18:43:41 +0100 Subject: [PATCH 5/9] qmp: Make Quorum error events more palatable. Insert quorum QMP events documentation alphabetically. Also change the "ret" errno value by an optional "error" being an strerror(-ret) in the QUORUM_REPORT_BAD qmp event. Signed-off-by: Benoit Canet Reviewed-by: Eric Blake Signed-off-by: Stefan Hajnoczi --- block/quorum.c | 9 +++-- docs/qmp/qmp-events.txt | 75 ++++++++++++++++++++------------------ tests/qemu-iotests/081.out | 2 +- 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/block/quorum.c b/block/quorum.c index 6c28239718..bd997b7322 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -200,11 +200,14 @@ static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret) { QObject *data; assert(node_name); - data = qobject_from_jsonf("{ 'ret': %d" - ", 'node-name': %s" + data = qobject_from_jsonf("{ 'node-name': %s" ", 'sector-num': %" PRId64 ", 'sectors-count': %d }", - ret, node_name, acb->sector_num, acb->nb_sectors); + node_name, acb->sector_num, acb->nb_sectors); + if (ret < 0) { + QDict *dict = qobject_to_qdict(data); + qdict_put(dict, "error", qstring_from_str(strerror(-ret))); + } monitor_protocol_event(QEVENT_QUORUM_REPORT_BAD, data); qobject_decref(data); } diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt index 00f95154dd..145402e078 100644 --- a/docs/qmp/qmp-events.txt +++ b/docs/qmp/qmp-events.txt @@ -225,6 +225,45 @@ Data: "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } } +QUORUM_FAILURE +-------------- + +Emitted by the Quorum block driver if it fails to establish a quorum. + +Data: + +- "reference": device name if defined else node name. +- "sector-num": Number of the first sector of the failed read operation. +- "sector-count": Failed read operation sector count. + +Example: + +{ "event": "QUORUM_FAILURE", + "data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 }, + "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } + +QUORUM_REPORT_BAD +----------------- + +Emitted to report a corruption of a Quorum file. + +Data: + +- "error": Error message (json-string, optional) + Only present on failure. This field contains a human-readable + error message. There are no semantics other than that the + block layer reported an error and clients should not try to + interpret the error string. +- "node-name": The graph node name of the block driver state. +- "sector-num": Number of the first sector of the failed read operation. +- "sector-count": Failed read operation sector count. + +Example: + +{ "event": "QUORUM_REPORT_BAD", + "data": { "node-name": "1.raw", "sector-num": 345435, "sector-count": 5 }, + "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } + RESET ----- @@ -500,39 +539,3 @@ Example: Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is followed respectively by the RESET, SHUTDOWN, or STOP events. - -QUORUM_FAILURE --------------- - -Emitted by the Quorum block driver if it fails to establish a quorum. - -Data: - -- "reference": device name if defined else node name. -- "sector-num": Number of the first sector of the failed read operation. -- "sector-count": Failed read operation sector count. - -Example: - -{ "event": "QUORUM_FAILURE", - "data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 }, - "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } - -QUORUM_REPORT_BAD ------------------ - -Emitted to report a corruption of a Quorum file. - -Data: - -- "ret": The IO return code. -- "node-name": The graph node name of the block driver state. -- "sector-num": Number of the first sector of the failed read operation. -- "sector-count": Failed read operation sector count. - -Example: - -{ "event": "QUORUM_REPORT_BAD", - "data": { "ret": 0, "node-name": "1.raw", "sector-num": 345435, - "sector-count": 5 }, - "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out index 4fe2f95f63..84aeb0c730 100644 --- a/tests/qemu-iotests/081.out +++ b/tests/qemu-iotests/081.out @@ -30,7 +30,7 @@ Testing: -drive file=TEST_DIR/2.IMGFMT,format=IMGFMT,if=none,id=drive2 QMP_VERSION {"return": {}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "", "ret": 0, "sectors-count": 20480, "sector-num": 0}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "", "sectors-count": 20480, "sector-num": 0}} read 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} From 4b350f1de1685d7763b3b856eccdedbd691932b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Canet?= Date: Sat, 22 Feb 2014 18:43:42 +0100 Subject: [PATCH 6/9] qemu-io-test: Disable Quorum test when not compiled in. Quorum is not compiled by default: make the quorum 081 test aware of this. Signed-off-by: Benoit Canet Reviewed-by: Fam Zheng Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/081 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081 index f053f11942..b512d00cc8 100755 --- a/tests/qemu-iotests/081 +++ b/tests/qemu-iotests/081 @@ -56,6 +56,9 @@ function run_qemu() do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu_io } +test_quorum=$($QEMU_IMG --help|grep quorum) +[ "$test_quorum" = "" ] && _supported_fmt quorum + quorum="file.driver=quorum,file.children.0.file.filename=$TEST_DIR/1.raw" quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw" quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw,file.vote-threshold=2" From 69bef7931e8880c709556f8444938d8bb9a16118 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Wed, 26 Feb 2014 15:12:37 +0530 Subject: [PATCH 7/9] block: use /var/tmp instead of /tmp for -snapshot If TMPDIR is not specified, the default was to use /tmp for the working copy of the block devices. Update this to /var/tmp instead, so systems using tmp-on-tmpfs don't end up inadvertently using RAM for the block device. Signed-off-by: Amit Shah Signed-off-by: Stefan Hajnoczi --- block.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 2fd5482572..38bbdf3083 100644 --- a/block.c +++ b/block.c @@ -547,8 +547,9 @@ int get_tmp_filename(char *filename, int size) int fd; const char *tmpdir; tmpdir = getenv("TMPDIR"); - if (!tmpdir) - tmpdir = "/tmp"; + if (!tmpdir) { + tmpdir = "/var/tmp"; + } if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) { return -EOVERFLOW; } From 9147d019f3315d5be97e349aead3ced93ef46c6a Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Wed, 8 Jan 2014 21:05:38 +0100 Subject: [PATCH 8/9] discard rbd error output when not relevant in qemu-iotests Suppress rbd progress messages with --no-progress so they are not confused with an error output when comparing test results ( progress is displayed on stderr ). Signed-off-by: Loic Dachary Reviewed-by: Josh Durgin Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/common.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 71e9a7462d..881079bdb9 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -203,7 +203,7 @@ _cleanup_test_img() ;; rbd) - rbd rm "$TEST_DIR/t.$IMGFMT" > /dev/null + rbd --no-progress rm "$TEST_DIR/t.$IMGFMT" > /dev/null ;; sheepdog) From 3eba13ec25341ce473591ff338eab3196890a4eb Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Wed, 26 Feb 2014 10:47:57 +0100 Subject: [PATCH 9/9] block/vmdk: do not report file offset for compressed extents Signed-off-by: Peter Lieven Reviewed-by: Fam Zheng Signed-off-by: Stefan Hajnoczi --- block/vmdk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/vmdk.c b/block/vmdk.c index 83839f9b7a..b69988d169 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1184,7 +1184,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs, break; case VMDK_OK: ret = BDRV_BLOCK_DATA; - if (extent->file == bs->file) { + if (extent->file == bs->file && !extent->compressed) { ret |= BDRV_BLOCK_OFFSET_VALID | offset; }