From c3adb58fe0b2db4942f5b2f5d19bc51a29b93a89 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 14 Mar 2014 09:22:48 +0100 Subject: blockdev: Refuse to open encrypted image unless paused Opening an encrypted image takes an additional step: setting the key. Between open and the key set, the image must not be used. We have some protection against accidental use in place: you can't unpause a guest while we're missing keys. You can, however, hot-plug block devices lacking keys into a running guest just fine, or insert media lacking keys. In the latter case, notifying the guest of the insert is delayed until the key is set, which may suffice to protect at least some guests in common usage. This patch makes the protection apply in more cases, in a rather heavy-handed way: it doesn't let you open encrypted images unless we're in a paused state. It doesn't extend the protection to users other than the guest (block jobs?). Use of runstate_check() from block.c is disgusting. Best I can do right now. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- block.c | 9 ++++++++- stubs/Makefile.objs | 1 + stubs/runstate-check.c | 6 ++++++ tests/qemu-iotests/087 | 17 +++++++++++++++++ tests/qemu-iotests/087.out | 11 ++++++++++- 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 stubs/runstate-check.c diff --git a/block.c b/block.c index fae50c95b5..53f5b44fbb 100644 --- a/block.c +++ b/block.c @@ -1388,12 +1388,19 @@ done: ret = -EINVAL; goto close_and_fail; } - QDECREF(options); if (!bdrv_key_required(bs)) { bdrv_dev_change_media_cb(bs, true); + } else if (!runstate_check(RUN_STATE_PRELAUNCH) + && !runstate_check(RUN_STATE_INMIGRATE) + && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ + error_setg(errp, + "Guest must be stopped for opening of encrypted image"); + ret = -EBUSY; + goto close_and_fail; } + QDECREF(options); *pbs = bs; return 0; diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 59c5a54239..5ed1d38d70 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -20,6 +20,7 @@ stub-obj-y += mon-set-error.o stub-obj-y += pci-drive-hot-add.o stub-obj-y += qtest.o stub-obj-y += reset.o +stub-obj-y += runstate-check.o stub-obj-y += set-fd-handler.o stub-obj-y += slirp.o stub-obj-y += sysbus.o diff --git a/stubs/runstate-check.c b/stubs/runstate-check.c new file mode 100644 index 0000000000..bd2e3757ae --- /dev/null +++ b/stubs/runstate-check.c @@ -0,0 +1,6 @@ +#include "sysemu/sysemu.h" + +bool runstate_check(RunState state) +{ + return state == RUN_STATE_PRELAUNCH; +} diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087 index 53b6c43bff..a38bb702b3 100755 --- a/tests/qemu-iotests/087 +++ b/tests/qemu-iotests/087 @@ -99,6 +99,23 @@ echo === Encrypted image === echo _make_test_img -o encryption=on $size +run_qemu -S < Date: Fri, 14 Mar 2014 06:50:37 -0400 Subject: block: Explicitly specify 'unsigned long long' for VHDX 64-bit constants On 32-bit hosts, some compilers will warn on too large integer constants for constants that are 64-bit in length. Explicitly put a 'ULL' suffix on those defines. Reported-by: Alexander Graf Signed-off-by: Jeff Cody Signed-off-by: Stefan Hajnoczi --- block/vhdx.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/vhdx.h b/block/vhdx.h index 2acd7c2d19..8103d4c446 100644 --- a/block/vhdx.h +++ b/block/vhdx.h @@ -61,7 +61,7 @@ /* These structures are ones that are defined in the VHDX specification * document */ -#define VHDX_FILE_SIGNATURE 0x656C696678646876 /* "vhdxfile" in ASCII */ +#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL /* "vhdxfile" in ASCII */ typedef struct VHDXFileIdentifier { uint64_t signature; /* "vhdxfile" in ASCII */ uint16_t creator[256]; /* optional; utf-16 string to identify @@ -238,7 +238,7 @@ typedef struct QEMU_PACKED VHDXLogDataSector { /* upper 44 bits are the file offset in 1MB units lower 3 bits are the state other bits are reserved */ #define VHDX_BAT_STATE_BIT_MASK 0x07 -#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000 /* upper 44 bits */ +#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000ULL /* upper 44 bits */ typedef uint64_t VHDXBatEntry; /* ---- METADATA REGION STRUCTURES ---- */ @@ -247,7 +247,7 @@ typedef uint64_t VHDXBatEntry; #define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */ #define VHDX_METADATA_TABLE_MAX_SIZE \ (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1)) -#define VHDX_METADATA_SIGNATURE 0x617461646174656D /* "metadata" in ASCII */ +#define VHDX_METADATA_SIGNATURE 0x617461646174656DULL /* "metadata" in ASCII */ typedef struct QEMU_PACKED VHDXMetadataTableHeader { uint64_t signature; /* "metadata" in ASCII */ uint16_t reserved; -- cgit v1.2.1 From 4a41a2d68a684241aca96dba066e0699941b730d Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Feb 2014 15:30:18 +0100 Subject: nbd: close socket if connection breaks nbd_receive_reply() is called by the event loop whenever data is available or the socket has been closed by the remote side. This patch closes the socket when an error occurs to prevent the nbd_receive_reply() handler from being called indefinitely after the connection has failed. Note that we were already correctly returning EIO for pending requests but leaving the nbd_receive_reply() handler registered resulted in high CPU consumption and a flood of error messages. Reuse nbd_teardown_connection() to close the socket. Reported-by: Zhifeng Cai Signed-off-by: Stefan Hajnoczi --- block/nbd-client.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 0922b78292..7d698cb619 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -43,6 +43,17 @@ static void nbd_recv_coroutines_enter_all(NbdClientSession *s) } } +static void nbd_teardown_connection(NbdClientSession *client) +{ + /* finish any pending coroutines */ + shutdown(client->sock, 2); + nbd_recv_coroutines_enter_all(client); + + qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL); + closesocket(client->sock); + client->sock = -1; +} + static void nbd_reply_ready(void *opaque) { NbdClientSession *s = opaque; @@ -78,7 +89,7 @@ static void nbd_reply_ready(void *opaque) } fail: - nbd_recv_coroutines_enter_all(s); + nbd_teardown_connection(s); } static void nbd_restart_write(void *opaque) @@ -324,7 +335,7 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num, } -static void nbd_teardown_connection(NbdClientSession *client) +void nbd_client_session_close(NbdClientSession *client) { struct nbd_request request = { .type = NBD_CMD_DISC, @@ -332,22 +343,14 @@ static void nbd_teardown_connection(NbdClientSession *client) .len = 0 }; - nbd_send_request(client->sock, &request); - - /* finish any pending coroutines */ - shutdown(client->sock, 2); - nbd_recv_coroutines_enter_all(client); - - qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL); - closesocket(client->sock); - client->sock = -1; -} - -void nbd_client_session_close(NbdClientSession *client) -{ if (!client->bs) { return; } + if (client->sock == -1) { + return; + } + + nbd_send_request(client->sock, &request); nbd_teardown_connection(client); client->bs = NULL; -- cgit v1.2.1 From 1e8ece0db3e8604d3a17bbd2bd1277161851a44a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Feb 2014 15:30:19 +0100 Subject: tests: add nbd-fault-injector.py utility The nbd-fault-injector.py script is a special kind of NBD server. It throws away all writes and produces zeroes for reads. Given a list of fault injection rules, it can simulate NBD protocol errors and is useful for testing NBD client error handling code paths. See the patch for documentation. This scripts is modelled after Kevin Wolf 's blkdebug block driver. Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/nbd-fault-injector.py | 264 +++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100755 tests/qemu-iotests/nbd-fault-injector.py diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py new file mode 100755 index 0000000000..6c07191a5a --- /dev/null +++ b/tests/qemu-iotests/nbd-fault-injector.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python +# NBD server - fault injection utility +# +# Configuration file syntax: +# [inject-error "disconnect-neg1"] +# event=neg1 +# io=readwrite +# when=before +# +# Note that Python's ConfigParser squashes together all sections with the same +# name, so give each [inject-error] a unique name. +# +# inject-error options: +# event - name of the trigger event +# "neg1" - first part of negotiation struct +# "export" - export struct +# "neg2" - second part of negotiation struct +# "request" - NBD request struct +# "reply" - NBD reply struct +# "data" - request/reply data +# io - I/O direction that triggers this rule: +# "read", "write", or "readwrite" +# default: readwrite +# when - after how many bytes to inject the fault +# -1 - inject error after I/O +# 0 - inject error before I/O +# integer - inject error after integer bytes +# "before" - alias for 0 +# "after" - alias for -1 +# default: before +# +# Currently the only error injection action is to terminate the server process. +# This resets the TCP connection and thus forces the client to handle +# unexpected connection termination. +# +# Other error injection actions could be added in the future. +# +# Copyright Red Hat, Inc. 2014 +# +# Authors: +# Stefan Hajnoczi +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +import sys +import socket +import struct +import collections +import ConfigParser + +FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB + +# Protocol constants +NBD_CMD_READ = 0 +NBD_CMD_WRITE = 1 +NBD_CMD_DISC = 2 +NBD_REQUEST_MAGIC = 0x25609513 +NBD_REPLY_MAGIC = 0x67446698 +NBD_PASSWD = 0x4e42444d41474943 +NBD_OPTS_MAGIC = 0x49484156454F5054 +NBD_CLIENT_MAGIC = 0x0000420281861253 +NBD_OPT_EXPORT_NAME = 1 << 0 + +# Protocol structs +neg_classic_struct = struct.Struct('>QQQI124x') +neg1_struct = struct.Struct('>QQH') +export_tuple = collections.namedtuple('Export', 'reserved magic opt len') +export_struct = struct.Struct('>IQII') +neg2_struct = struct.Struct('>QH124x') +request_tuple = collections.namedtuple('Request', 'magic type handle from_ len') +request_struct = struct.Struct('>IIQQI') +reply_struct = struct.Struct('>IIQ') + +def err(msg): + sys.stderr.write(msg + '\n') + sys.exit(1) + +def recvall(sock, bufsize): + received = 0 + chunks = [] + while received < bufsize: + chunk = sock.recv(bufsize - received) + if len(chunk) == 0: + raise Exception('unexpected disconnect') + chunks.append(chunk) + received += len(chunk) + return ''.join(chunks) + +class Rule(object): + def __init__(self, name, event, io, when): + self.name = name + self.event = event + self.io = io + self.when = when + + def match(self, event, io): + if event != self.event: + return False + if io != self.io and self.io != 'readwrite': + return False + return True + +class FaultInjectionSocket(object): + def __init__(self, sock, rules): + self.sock = sock + self.rules = rules + + def check(self, event, io, bufsize=None): + for rule in self.rules: + if rule.match(event, io): + if rule.when == 0 or bufsize is None: + print 'Closing connection on rule match %s' % rule.name + sys.exit(0) + if rule.when != -1: + return rule.when + return bufsize + + def send(self, buf, event): + bufsize = self.check(event, 'write', bufsize=len(buf)) + self.sock.sendall(buf[:bufsize]) + self.check(event, 'write') + + def recv(self, bufsize, event): + bufsize = self.check(event, 'read', bufsize=bufsize) + data = recvall(self.sock, bufsize) + self.check(event, 'read') + return data + + def close(self): + self.sock.close() + +def negotiate_classic(conn): + buf = neg_classic_struct.pack(NBD_PASSWD, NBD_CLIENT_MAGIC, + FAKE_DISK_SIZE, 0) + conn.send(buf, event='neg-classic') + +def negotiate_export(conn): + # Send negotiation part 1 + buf = neg1_struct.pack(NBD_PASSWD, NBD_OPTS_MAGIC, 0) + conn.send(buf, event='neg1') + + # Receive export option + buf = conn.recv(export_struct.size, event='export') + export = export_tuple._make(export_struct.unpack(buf)) + assert export.magic == NBD_OPTS_MAGIC + assert export.opt == NBD_OPT_EXPORT_NAME + name = conn.recv(export.len, event='export-name') + + # Send negotiation part 2 + buf = neg2_struct.pack(FAKE_DISK_SIZE, 0) + conn.send(buf, event='neg2') + +def negotiate(conn, use_export): + '''Negotiate export with client''' + if use_export: + negotiate_export(conn) + else: + negotiate_classic(conn) + +def read_request(conn): + '''Parse NBD request from client''' + buf = conn.recv(request_struct.size, event='request') + req = request_tuple._make(request_struct.unpack(buf)) + assert req.magic == NBD_REQUEST_MAGIC + return req + +def write_reply(conn, error, handle): + buf = reply_struct.pack(NBD_REPLY_MAGIC, error, handle) + conn.send(buf, event='reply') + +def handle_connection(conn, use_export): + negotiate(conn, use_export) + while True: + req = read_request(conn) + if req.type == NBD_CMD_READ: + write_reply(conn, 0, req.handle) + conn.send('\0' * req.len, event='data') + elif req.type == NBD_CMD_WRITE: + _ = conn.recv(req.len, event='data') + write_reply(conn, 0, req.handle) + elif req.type == NBD_CMD_DISC: + break + else: + print 'unrecognized command type %#02x' % req.type + break + conn.close() + +def run_server(sock, rules, use_export): + while True: + conn, _ = sock.accept() + handle_connection(FaultInjectionSocket(conn, rules), use_export) + +def parse_inject_error(name, options): + if 'event' not in options: + err('missing \"event\" option in %s' % name) + event = options['event'] + if event not in ('neg-classic', 'neg1', 'export', 'neg2', 'request', 'reply', 'data'): + err('invalid \"event\" option value \"%s\" in %s' % (event, name)) + io = options.get('io', 'readwrite') + if io not in ('read', 'write', 'readwrite'): + err('invalid \"io\" option value \"%s\" in %s' % (io, name)) + when = options.get('when', 'before') + try: + when = int(when) + except ValueError: + if when == 'before': + when = 0 + elif when == 'after': + when = -1 + else: + err('invalid \"when\" option value \"%s\" in %s' % (when, name)) + return Rule(name, event, io, when) + +def parse_config(config): + rules = [] + for name in config.sections(): + if name.startswith('inject-error'): + options = dict(config.items(name)) + rules.append(parse_inject_error(name, options)) + else: + err('invalid config section name: %s' % name) + return rules + +def load_rules(filename): + config = ConfigParser.RawConfigParser() + with open(filename, 'rt') as f: + config.readfp(f, filename) + return parse_config(config) + +def open_socket(path): + '''Open a TCP or UNIX domain listen socket''' + if ':' in path: + host, port = path.split(':', 1) + sock = socket.socket() + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((host, int(port))) + else: + sock = socket.socket(socket.AF_UNIX) + sock.bind(path) + sock.listen(0) + print 'Listening on %s' % path + return sock + +def usage(args): + sys.stderr.write('usage: %s [--classic-negotiation] | \n' % args[0]) + sys.stderr.write('Run an fault injector NBD server with rules defined in a config file.\n') + sys.exit(1) + +def main(args): + if len(args) != 3 and len(args) != 4: + usage(args) + use_export = True + if args[1] == '--classic-negotiation': + use_export = False + elif len(args) == 4: + usage(args) + sock = open_socket(args[1 if use_export else 2]) + rules = load_rules(args[2 if use_export else 3]) + run_server(sock, rules, use_export) + return 0 + +if __name__ == '__main__': + sys.exit(main(sys.argv)) -- cgit v1.2.1 From dc668ded1009f88da5e31bc5a143cf3e9070d49b Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Feb 2014 15:30:20 +0100 Subject: qemu-iotests: add 083 NBD client disconnect tests This new test case uses nbd-fault-injector.py to simulate broken TCP connections at each stage in the NBD protocol. This way we can exercise block/nbd-client.c's socket error handling code paths. In particular, this serves as a regression test to make sure nbd-client.c doesn't cause an infinite loop by leaving its nbd_receive_reply() fd handler registered after the connection has been closed. This bug was fixed in an earlier patch. Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/083 | 129 +++++++++++++++++++++++++++++++++++ tests/qemu-iotests/083.out | 163 +++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 293 insertions(+) create mode 100755 tests/qemu-iotests/083 create mode 100644 tests/qemu-iotests/083.out diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083 new file mode 100755 index 0000000000..f764534782 --- /dev/null +++ b/tests/qemu-iotests/083 @@ -0,0 +1,129 @@ +#!/bin/bash +# +# Test NBD client unexpected disconnect +# +# Copyright Red Hat, Inc. 2014 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=stefanha@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt generic +_supported_proto nbd +_supported_os Linux + +# Pick a TCP port based on our pid. This way multiple instances of this test +# can run in parallel without conflicting. +choose_tcp_port() { + echo $((($$ % 31744) + 1024)) # 1024 <= port < 32768 +} + +wait_for_tcp_port() { + while ! (netstat --tcp --listening --numeric | \ + grep "$1.*0.0.0.0:\*.*LISTEN") 2>&1 >/dev/null; do + sleep 0.1 + done +} + +filter_nbd() { + # nbd.c error messages contain function names and line numbers that are prone + # to change. Message ordering depends on timing between send and receive + # callbacks sometimes, making them unreliable. + # + # Filter out the TCP port number since this changes between runs. + sed -e 's#^nbd.c:.*##g' \ + -e 's#nbd:127.0.0.1:[^:]*:#nbd:127.0.0.1:PORT:#g' +} + +check_disconnect() { + event=$1 + when=$2 + negotiation=$3 + echo "=== Check disconnect $when $event ===" + echo + + port=$(choose_tcp_port) + + cat > "$TEST_DIR/nbd-fault-injector.conf" <&1 >/dev/null & + wait_for_tcp_port "127.0.0.1:$port" + $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | filter_nbd + + echo +} + +for event in neg1 "export" neg2 request reply data; do + for when in before after; do + check_disconnect "$event" "$when" + done + + # Also inject short replies from the NBD server + case "$event" in + neg1) + for when in 8 16; do + check_disconnect "$event" "$when" + done + ;; + "export") + for when in 4 12 16; do + check_disconnect "$event" "$when" + done + ;; + neg2) + for when in 8 10; do + check_disconnect "$event" "$when" + done + ;; + reply) + for when in 4 8; do + check_disconnect "$event" "$when" + done + ;; + esac +done + +# Also check classic negotiation without export information +for when in before 8 16 24 28 after; do + check_disconnect "neg-classic" "$when" --classic-negotiation +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out new file mode 100644 index 0000000000..85ee8d6dd7 --- /dev/null +++ b/tests/qemu-iotests/083.out @@ -0,0 +1,163 @@ +QA output created by 083 +=== Check disconnect before neg1 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect after neg1 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 8 neg1 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 16 neg1 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect before export === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect after export === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 4 export === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 12 export === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 16 export === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect before neg2 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect after neg2 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect 8 neg2 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 10 neg2 === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect before request === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect after request === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect before reply === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect after reply === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect 4 reply === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect 8 reply === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect before data === + + +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +=== Check disconnect after data === + + +read failed: Input/output error + +=== Check disconnect before neg-classic === + + +qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 8 neg-classic === + + +qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 16 neg-classic === + + +qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 24 neg-classic === + + +qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect 28 neg-classic === + + +qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +no file open, try 'help open' + +=== Check disconnect after neg-classic === + + +qemu-io: can't open device nbd:127.0.0.1:PORT: Could not read image for determining its format: Input/output error +no file open, try 'help open' + +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index e96eafdf43..40cd3b3fa7 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -85,6 +85,7 @@ 079 rw auto 081 rw auto 082 rw auto quick +083 rw auto 085 rw auto quick 086 rw auto quick 087 rw auto quick -- cgit v1.2.1 From 46dea4160d587add2f3670306c41ad9ad4064af5 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 13 Mar 2014 10:28:01 +0100 Subject: qemu-iotests: remove 085 and 087 from 'quick' group The 'quick' group in qemu-iotests are not allowed to run QEMU since we don't know which targets are available. In other words, they may only use qemu-img, qemu-io, and qemu-nbd. Drop 085 and 087 from the 'quick' group since they run QEMU. This makes "make check-block" pass again. Reported-by: Markus Armbruster Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/group | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 40cd3b3fa7..ee09ebc98e 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -86,6 +86,6 @@ 081 rw auto 082 rw auto quick 083 rw auto -085 rw auto quick +085 rw auto 086 rw auto quick -087 rw auto quick +087 rw auto -- cgit v1.2.1