Merge remote-tracking branch 'stefanha/block' into staging

* stefanha/block:
  rbd: add an asynchronous flush
  iotests: Add 'check -ssh' option to test Secure Shell block device.
  block: ssh: Use libssh2_sftp_fsync (if supported by libssh2) to flush to disk.
  block: Add support for Secure Shell (ssh) block device.
  ide: refuse WIN_READ_NATIVE_MAX on empty device
  qemu-iotests: filter QEMU_PROG in 051.out
  qemu-iotests: Add test for -drive options
  qemu-iotests: A few more bdrv_pread/pwrite tests
  block: Introduce bdrv_pwritev() for qcow2_save_vmstate
  savevm: Implement block_writev_buffer()
  block: Introduce bdrv_writev_vmstate

Conflicts:
	savevm.c

aliguori: add f->pos parameter to writev_buffer().

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-04-15 08:02:41 -05:00
commit db08dc213b
22 changed files with 1722 additions and 44 deletions

105
block.c
View File

@ -2131,27 +2131,21 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque)
} }
/* /*
* Process a synchronous request using coroutines * Process a vectored synchronous request using coroutines
*/ */
static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, bool is_write) QEMUIOVector *qiov, bool is_write)
{ {
QEMUIOVector qiov;
struct iovec iov = {
.iov_base = (void *)buf,
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
};
Coroutine *co; Coroutine *co;
RwCo rwco = { RwCo rwco = {
.bs = bs, .bs = bs,
.sector_num = sector_num, .sector_num = sector_num,
.nb_sectors = nb_sectors, .nb_sectors = qiov->size >> BDRV_SECTOR_BITS,
.qiov = &qiov, .qiov = qiov,
.is_write = is_write, .is_write = is_write,
.ret = NOT_DONE, .ret = NOT_DONE,
}; };
assert((qiov->size & (BDRV_SECTOR_SIZE - 1)) == 0);
qemu_iovec_init_external(&qiov, &iov, 1);
/** /**
* In sync call context, when the vcpu is blocked, this throttling timer * In sync call context, when the vcpu is blocked, this throttling timer
@ -2177,6 +2171,22 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
return rwco.ret; return rwco.ret;
} }
/*
* Process a synchronous request using coroutines
*/
static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
int nb_sectors, bool is_write)
{
QEMUIOVector qiov;
struct iovec iov = {
.iov_base = (void *)buf,
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
};
qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_rwv_co(bs, sector_num, &qiov, is_write);
}
/* return < 0 if error. See bdrv_write() for the return codes */ /* return < 0 if error. See bdrv_write() for the return codes */
int bdrv_read(BlockDriverState *bs, int64_t sector_num, int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors) uint8_t *buf, int nb_sectors)
@ -2210,6 +2220,11 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true); return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true);
} }
int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov)
{
return bdrv_rwv_co(bs, sector_num, qiov, true);
}
int bdrv_pread(BlockDriverState *bs, int64_t offset, int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf, int count1) void *buf, int count1)
{ {
@ -2255,15 +2270,15 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
return count1; return count1;
} }
int bdrv_pwrite(BlockDriverState *bs, int64_t offset, int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
const void *buf, int count1)
{ {
uint8_t tmp_buf[BDRV_SECTOR_SIZE]; uint8_t tmp_buf[BDRV_SECTOR_SIZE];
int len, nb_sectors, count; int len, nb_sectors, count;
int64_t sector_num; int64_t sector_num;
int ret; int ret;
count = count1; count = qiov->size;
/* first write to align to sector start */ /* first write to align to sector start */
len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1); len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
if (len > count) if (len > count)
@ -2272,24 +2287,32 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
if (len > 0) { if (len > 0) {
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0) if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
return ret; return ret;
memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len); qemu_iovec_to_buf(qiov, 0, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)),
len);
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0) if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
return ret; return ret;
count -= len; count -= len;
if (count == 0) if (count == 0)
return count1; return qiov->size;
sector_num++; sector_num++;
buf += len;
} }
/* write the sectors "in place" */ /* write the sectors "in place" */
nb_sectors = count >> BDRV_SECTOR_BITS; nb_sectors = count >> BDRV_SECTOR_BITS;
if (nb_sectors > 0) { if (nb_sectors > 0) {
if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0) QEMUIOVector qiov_inplace;
qemu_iovec_init(&qiov_inplace, qiov->niov);
qemu_iovec_concat(&qiov_inplace, qiov, len,
nb_sectors << BDRV_SECTOR_BITS);
ret = bdrv_writev(bs, sector_num, &qiov_inplace);
qemu_iovec_destroy(&qiov_inplace);
if (ret < 0) {
return ret; return ret;
}
sector_num += nb_sectors; sector_num += nb_sectors;
len = nb_sectors << BDRV_SECTOR_BITS; len = nb_sectors << BDRV_SECTOR_BITS;
buf += len;
count -= len; count -= len;
} }
@ -2297,11 +2320,24 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
if (count > 0) { if (count > 0) {
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0) if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
return ret; return ret;
memcpy(tmp_buf, buf, count); qemu_iovec_to_buf(qiov, qiov->size - count, tmp_buf, count);
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0) if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
return ret; return ret;
} }
return count1; return qiov->size;
}
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf, int count1)
{
QEMUIOVector qiov;
struct iovec iov = {
.iov_base = (void *) buf,
.iov_len = count1,
};
qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_pwritev(bs, offset, &qiov);
} }
/* /*
@ -3183,14 +3219,29 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size) int64_t pos, int size)
{
QEMUIOVector qiov;
struct iovec iov = {
.iov_base = (void *) buf,
.iov_len = size,
};
qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_writev_vmstate(bs, &qiov, pos);
}
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
if (!drv)
if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;
if (drv->bdrv_save_vmstate) } else if (drv->bdrv_save_vmstate) {
return drv->bdrv_save_vmstate(bs, buf, pos, size); return drv->bdrv_save_vmstate(bs, qiov, pos);
if (bs->file) } else if (bs->file) {
return bdrv_save_vmstate(bs->file, buf, pos, size); return bdrv_writev_vmstate(bs->file, qiov, pos);
}
return -ENOTSUP; return -ENOTSUP;
} }

View File

@ -13,6 +13,7 @@ block-obj-$(CONFIG_LIBISCSI) += iscsi.o
block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_CURL) += curl.o
block-obj-$(CONFIG_RBD) += rbd.o block-obj-$(CONFIG_RBD) += rbd.o
block-obj-$(CONFIG_GLUSTERFS) += gluster.o block-obj-$(CONFIG_GLUSTERFS) += gluster.o
block-obj-$(CONFIG_LIBSSH2) += ssh.o
endif endif
common-obj-y += stream.o common-obj-y += stream.o

View File

@ -1652,8 +1652,8 @@ static void dump_refcounts(BlockDriverState *bs)
} }
#endif #endif
static int qcow2_save_vmstate(BlockDriverState *bs, const uint8_t *buf, static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos, int size) int64_t pos)
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
int growable = bs->growable; int growable = bs->growable;
@ -1661,7 +1661,7 @@ static int qcow2_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE); BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
bs->growable = 1; bs->growable = 1;
ret = bdrv_pwrite(bs, qcow2_vm_state_offset(s) + pos, buf, size); ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov);
bs->growable = growable; bs->growable = growable;
return ret; return ret;

View File

@ -63,7 +63,8 @@
typedef enum { typedef enum {
RBD_AIO_READ, RBD_AIO_READ,
RBD_AIO_WRITE, RBD_AIO_WRITE,
RBD_AIO_DISCARD RBD_AIO_DISCARD,
RBD_AIO_FLUSH
} RBDAIOCmd; } RBDAIOCmd;
typedef struct RBDAIOCB { typedef struct RBDAIOCB {
@ -379,8 +380,7 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
r = rcb->ret; r = rcb->ret;
if (acb->cmd == RBD_AIO_WRITE || if (acb->cmd != RBD_AIO_READ) {
acb->cmd == RBD_AIO_DISCARD) {
if (r < 0) { if (r < 0) {
acb->ret = r; acb->ret = r;
acb->error = 1; acb->error = 1;
@ -659,6 +659,16 @@ static int rbd_aio_discard_wrapper(rbd_image_t image,
#endif #endif
} }
static int rbd_aio_flush_wrapper(rbd_image_t image,
rbd_completion_t comp)
{
#ifdef LIBRBD_SUPPORTS_AIO_FLUSH
return rbd_aio_flush(image, comp);
#else
return -ENOTSUP;
#endif
}
static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs, static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
int64_t sector_num, int64_t sector_num,
QEMUIOVector *qiov, QEMUIOVector *qiov,
@ -679,7 +689,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
acb = qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque); acb = qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque);
acb->cmd = cmd; acb->cmd = cmd;
acb->qiov = qiov; acb->qiov = qiov;
if (cmd == RBD_AIO_DISCARD) { if (cmd == RBD_AIO_DISCARD || cmd == RBD_AIO_FLUSH) {
acb->bounce = NULL; acb->bounce = NULL;
} else { } else {
acb->bounce = qemu_blockalign(bs, qiov->size); acb->bounce = qemu_blockalign(bs, qiov->size);
@ -723,6 +733,9 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
case RBD_AIO_DISCARD: case RBD_AIO_DISCARD:
r = rbd_aio_discard_wrapper(s->image, off, size, c); r = rbd_aio_discard_wrapper(s->image, off, size, c);
break; break;
case RBD_AIO_FLUSH:
r = rbd_aio_flush_wrapper(s->image, c);
break;
default: default:
r = -EINVAL; r = -EINVAL;
} }
@ -762,6 +775,16 @@ static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
RBD_AIO_WRITE); RBD_AIO_WRITE);
} }
#ifdef LIBRBD_SUPPORTS_AIO_FLUSH
static BlockDriverAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs,
BlockDriverCompletionFunc *cb,
void *opaque)
{
return rbd_start_aio(bs, 0, NULL, 0, cb, opaque, RBD_AIO_FLUSH);
}
#else
static int qemu_rbd_co_flush(BlockDriverState *bs) static int qemu_rbd_co_flush(BlockDriverState *bs)
{ {
#if LIBRBD_VERSION_CODE >= LIBRBD_VERSION(0, 1, 1) #if LIBRBD_VERSION_CODE >= LIBRBD_VERSION(0, 1, 1)
@ -772,6 +795,7 @@ static int qemu_rbd_co_flush(BlockDriverState *bs)
return 0; return 0;
#endif #endif
} }
#endif
static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi) static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
@ -949,7 +973,12 @@ static BlockDriver bdrv_rbd = {
.bdrv_aio_readv = qemu_rbd_aio_readv, .bdrv_aio_readv = qemu_rbd_aio_readv,
.bdrv_aio_writev = qemu_rbd_aio_writev, .bdrv_aio_writev = qemu_rbd_aio_writev,
#ifdef LIBRBD_SUPPORTS_AIO_FLUSH
.bdrv_aio_flush = qemu_rbd_aio_flush,
#else
.bdrv_co_flush_to_disk = qemu_rbd_co_flush, .bdrv_co_flush_to_disk = qemu_rbd_co_flush,
#endif
#ifdef LIBRBD_SUPPORTS_DISCARD #ifdef LIBRBD_SUPPORTS_DISCARD
.bdrv_aio_discard = qemu_rbd_aio_discard, .bdrv_aio_discard = qemu_rbd_aio_discard,

View File

@ -2054,12 +2054,19 @@ cleanup:
return ret; return ret;
} }
static int sd_save_vmstate(BlockDriverState *bs, const uint8_t *data, static int sd_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos, int size) int64_t pos)
{ {
BDRVSheepdogState *s = bs->opaque; BDRVSheepdogState *s = bs->opaque;
void *buf;
int ret;
return do_load_save_vmstate(s, (uint8_t *)data, pos, size, 0); buf = qemu_blockalign(bs, qiov->size);
qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
ret = do_load_save_vmstate(s, (uint8_t *) buf, pos, qiov->size, 0);
qemu_vfree(buf);
return ret;
} }
static int sd_load_vmstate(BlockDriverState *bs, uint8_t *data, static int sd_load_vmstate(BlockDriverState *bs, uint8_t *data,

1063
block/ssh.c Normal file

File diff suppressed because it is too large Load Diff

73
configure vendored
View File

@ -239,6 +239,7 @@ virtio_blk_data_plane=""
gtk="" gtk=""
gtkabi="2.0" gtkabi="2.0"
tpm="no" tpm="no"
libssh2=""
# parse CC options first # parse CC options first
for opt do for opt do
@ -922,6 +923,10 @@ for opt do
;; ;;
--enable-tpm) tpm="yes" --enable-tpm) tpm="yes"
;; ;;
--disable-libssh2) libssh2="no"
;;
--enable-libssh2) libssh2="yes"
;;
*) echo "ERROR: unknown option $opt"; show_help="yes" *) echo "ERROR: unknown option $opt"; show_help="yes"
;; ;;
esac esac
@ -1182,6 +1187,8 @@ echo " --disable-glusterfs disable GlusterFS backend"
echo " --enable-gcov enable test coverage analysis with gcov" echo " --enable-gcov enable test coverage analysis with gcov"
echo " --gcov=GCOV use specified gcov [$gcov_tool]" echo " --gcov=GCOV use specified gcov [$gcov_tool]"
echo " --enable-tpm enable TPM support" echo " --enable-tpm enable TPM support"
echo " --disable-libssh2 disable ssh block device support"
echo " --enable-libssh2 enable ssh block device support"
echo "" echo ""
echo "NOTE: The object files are built at the place where configure is launched" echo "NOTE: The object files are built at the place where configure is launched"
exit 1 exit 1
@ -2313,6 +2320,67 @@ EOF
fi fi
fi fi
##########################################
# libssh2 probe
if test "$libssh2" != "no" ; then
cat > $TMPC <<EOF
#include <stdio.h>
#include <libssh2.h>
#include <libssh2_sftp.h>
int main(void) {
LIBSSH2_SESSION *session;
session = libssh2_session_init ();
(void) libssh2_sftp_init (session);
return 0;
}
EOF
if $pkg_config libssh2 --modversion >/dev/null 2>&1; then
libssh2_cflags=`$pkg_config libssh2 --cflags`
libssh2_libs=`$pkg_config libssh2 --libs`
else
libssh2_cflags=
libssh2_libs="-lssh2"
fi
if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then
libssh2=yes
libs_tools="$libssh2_libs $libs_tools"
libs_softmmu="$libssh2_libs $libs_softmmu"
QEMU_CFLAGS="$QEMU_CFLAGS $libssh2_cflags"
else
if test "$libssh2" = "yes" ; then
feature_not_found "libssh2"
fi
libssh2=no
fi
fi
##########################################
# libssh2_sftp_fsync probe
if test "$libssh2" = "yes"; then
cat > $TMPC <<EOF
#include <stdio.h>
#include <libssh2.h>
#include <libssh2_sftp.h>
int main(void) {
LIBSSH2_SESSION *session;
LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *sftp_handle;
session = libssh2_session_init ();
sftp = libssh2_sftp_init (session);
sftp_handle = libssh2_sftp_open (sftp, "/", 0, 0);
libssh2_sftp_fsync (sftp_handle);
return 0;
}
EOF
# libssh2_cflags/libssh2_libs defined in previous test.
if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then
QEMU_CFLAGS="-DHAS_LIBSSH2_SFTP_FSYNC $QEMU_CFLAGS"
fi
fi
########################################## ##########################################
# linux-aio probe # linux-aio probe
@ -3435,6 +3503,7 @@ echo "virtio-blk-data-plane $virtio_blk_data_plane"
echo "gcov $gcov_tool" echo "gcov $gcov_tool"
echo "gcov enabled $gcov" echo "gcov enabled $gcov"
echo "TPM support $tpm" echo "TPM support $tpm"
echo "libssh2 support $libssh2"
if test "$sdl_too_old" = "yes"; then if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support" echo "-> Your SDL version is too old - please upgrade to have SDL support"
@ -3793,6 +3862,10 @@ if test "$glusterfs" = "yes" ; then
echo "CONFIG_GLUSTERFS=y" >> $config_host_mak echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
fi fi
if test "$libssh2" = "yes" ; then
echo "CONFIG_LIBSSH2=y" >> $config_host_mak
fi
if test "$virtio_blk_data_plane" = "yes" ; then if test "$virtio_blk_data_plane" = "yes" ; then
echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak
fi fi

View File

@ -1262,6 +1262,10 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
lba48 = 1; lba48 = 1;
/* fall through */ /* fall through */
case WIN_READ_NATIVE_MAX: case WIN_READ_NATIVE_MAX:
/* Refuse if no sectors are addressable (e.g. medium not inserted) */
if (s->nb_sectors == 0) {
goto abort_cmd;
}
ide_cmd_lba48_transform(s, lba48); ide_cmd_lba48_transform(s, lba48);
ide_set_sector(s, s->nb_sectors - 1); ide_set_sector(s, s->nb_sectors - 1);
s->status = READY_STAT | SEEK_STAT; s->status = READY_STAT | SEEK_STAT;

View File

@ -166,10 +166,12 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors); uint8_t *buf, int nb_sectors);
int bdrv_write(BlockDriverState *bs, int64_t sector_num, int bdrv_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors); const uint8_t *buf, int nb_sectors);
int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov);
int bdrv_pread(BlockDriverState *bs, int64_t offset, int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf, int count); void *buf, int count);
int bdrv_pwrite(BlockDriverState *bs, int64_t offset, int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf, int count); const void *buf, int count);
int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov);
int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
const void *buf, int count); const void *buf, int count);
int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
@ -348,6 +350,7 @@ void path_combine(char *dest, int dest_size,
const char *base_path, const char *base_path,
const char *filename); const char *filename);
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size); int64_t pos, int size);

View File

@ -164,8 +164,8 @@ struct BlockDriver {
const char *snapshot_name); const char *snapshot_name);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
int (*bdrv_save_vmstate)(BlockDriverState *bs, const uint8_t *buf, int (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos, int size); int64_t pos);
int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf, int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size); int64_t pos, int size);

View File

@ -55,7 +55,7 @@ typedef int (QEMUFileGetFD)(void *opaque);
* This function writes an iovec to file. * This function writes an iovec to file.
*/ */
typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov, typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
int iovcnt); int iovcnt, int64_t pos);
typedef struct QEMUFileOps { typedef struct QEMUFileOps {
QEMUFilePutBufferFunc *put_buffer; QEMUFilePutBufferFunc *put_buffer;

View File

@ -423,6 +423,7 @@ snapshots.
* disk_images_sheepdog:: Sheepdog disk images * disk_images_sheepdog:: Sheepdog disk images
* disk_images_iscsi:: iSCSI LUNs * disk_images_iscsi:: iSCSI LUNs
* disk_images_gluster:: GlusterFS disk images * disk_images_gluster:: GlusterFS disk images
* disk_images_ssh:: Secure Shell (ssh) disk images
@end menu @end menu
@node disk_images_quickstart @node disk_images_quickstart
@ -1038,6 +1039,59 @@ qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glu
qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img
@end example @end example
@node disk_images_ssh
@subsection Secure Shell (ssh) disk images
You can access disk images located on a remote ssh server
by using the ssh protocol:
@example
qemu-system-x86_64 -drive file=ssh://[@var{user}@@]@var{server}[:@var{port}]/@var{path}[?host_key_check=@var{host_key_check}]
@end example
Alternative syntax using properties:
@example
qemu-system-x86_64 -drive file.driver=ssh[,file.user=@var{user}],file.host=@var{server}[,file.port=@var{port}],file.path=@var{path}[,file.host_key_check=@var{host_key_check}]
@end example
@var{ssh} is the protocol.
@var{user} is the remote user. If not specified, then the local
username is tried.
@var{server} specifies the remote ssh server. Any ssh server can be
used, but it must implement the sftp-server protocol. Most Unix/Linux
systems should work without requiring any extra configuration.
@var{port} is the port number on which sshd is listening. By default
the standard ssh port (22) is used.
@var{path} is the path to the disk image.
The optional @var{host_key_check} parameter controls how the remote
host's key is checked. The default is @code{yes} which means to use
the local @file{.ssh/known_hosts} file. Setting this to @code{no}
turns off known-hosts checking. Or you can check that the host key
matches a specific fingerprint:
@code{host_key_check=md5:78:45:8e:14:57:4f:d5:45:83:0a:0e:f3:49:82:c9:c8}
(@code{sha1:} can also be used as a prefix, but note that OpenSSH
tools only use MD5 to print fingerprints).
Currently authentication must be done using ssh-agent. Other
authentication methods may be supported in future.
Note: Many ssh servers do not support an @code{fsync}-style operation.
The ssh driver cannot guarantee that disk flush requests are
obeyed, and this causes a risk of disk corruption if the remote
server or network goes down during writes. The driver will
print a warning when @code{fsync} is not supported:
warning: ssh server @code{ssh.example.com:22} does not support fsync
With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is
supported.
@node pcsys_network @node pcsys_network
@section Network emulation @section Network emulation

View File

@ -2107,6 +2107,18 @@ Example for Unix Domain Sockets
qemu-system-i386 --drive file=nbd:unix:/tmp/nbd-socket qemu-system-i386 --drive file=nbd:unix:/tmp/nbd-socket
@end example @end example
@item SSH
QEMU supports SSH (Secure Shell) access to remote disks.
Examples:
@example
qemu-system-i386 -drive file=ssh://user@@host/path/to/disk.img
qemu-system-i386 -drive file.driver=ssh,file.user=user,file.host=host,file.port=22,file.path=/path/to/disk.img
@end example
Currently authentication must be done using ssh-agent. Other
authentication methods may be supported in future.
@item Sheepdog @item Sheepdog
Sheepdog is a distributed storage system for QEMU. Sheepdog is a distributed storage system for QEMU.
QEMU supports using either local sheepdog devices or remote networked QEMU supports using either local sheepdog devices or remote networked

View File

@ -175,7 +175,8 @@ static void coroutine_fn yield_until_fd_readable(int fd)
qemu_coroutine_yield(); qemu_coroutine_yield();
} }
static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt) static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
int64_t pos)
{ {
QEMUFileSocket *s = opaque; QEMUFileSocket *s = opaque;
ssize_t len; ssize_t len;
@ -457,6 +458,21 @@ fail:
return NULL; return NULL;
} }
static ssize_t block_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
int64_t pos)
{
int ret;
QEMUIOVector qiov;
qemu_iovec_init_external(&qiov, iov, iovcnt);
ret = bdrv_writev_vmstate(opaque, &qiov, pos);
if (ret < 0) {
return ret;
}
return qiov.size;
}
static int block_put_buffer(void *opaque, const uint8_t *buf, static int block_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size) int64_t pos, int size)
{ {
@ -481,6 +497,7 @@ static const QEMUFileOps bdrv_read_ops = {
static const QEMUFileOps bdrv_write_ops = { static const QEMUFileOps bdrv_write_ops = {
.put_buffer = block_put_buffer, .put_buffer = block_put_buffer,
.writev_buffer = block_writev_buffer,
.close = bdrv_fclose .close = bdrv_fclose
}; };
@ -535,7 +552,7 @@ static void qemu_fflush(QEMUFile *f)
if (f->ops->writev_buffer) { if (f->ops->writev_buffer) {
if (f->iovcnt > 0) { if (f->iovcnt > 0) {
ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt); ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
} }
} else { } else {
if (f->buf_index > 0) { if (f->buf_index > 0) {

View File

@ -61,10 +61,23 @@ $QEMU_IO -c "read -pP 0xa 0 $size" $TEST_IMG | _filter_qemu_io
echo echo
echo "unaligned pwrite" echo "unaligned pwrite"
$QEMU_IO -c 'write -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io $QEMU_IO -c 'write -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write -pP 0xac 512 288' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write -pP 0xad 800 224' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write -pP 0xae 66000 128k' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write -pP 0xaf 256k 42' $TEST_IMG | _filter_qemu_io
echo echo
echo "verify pattern" echo "verify pattern"
$QEMU_IO -c 'read -pP 0xa 0 66' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io $QEMU_IO -c 'read -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xa 108 404' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xac 512 288' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xad 800 224' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xa 1k 64976' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xae 66000 128k' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xa 197072 65072' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xaf 256k 42' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'read -pP 0xa 262186 470' $TEST_IMG | _filter_qemu_io
# success, all done # success, all done
echo "*** done" echo "*** done"

View File

@ -16,8 +16,34 @@ read 134217728/134217728 bytes at offset 0
unaligned pwrite unaligned pwrite
wrote 42/42 bytes at offset 66 wrote 42/42 bytes at offset 66
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 288/288 bytes at offset 512
288 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 224/224 bytes at offset 800
224 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 66000
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 42/42 bytes at offset 262144
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
verify pattern verify pattern
read 66/66 bytes at offset 0
66 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 42/42 bytes at offset 66 read 42/42 bytes at offset 66
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 404/404 bytes at offset 108
404 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 288/288 bytes at offset 512
288 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 224/224 bytes at offset 800
224 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 64976/64976 bytes at offset 1024
63.453 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 131072/131072 bytes at offset 66000
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 65072/65072 bytes at offset 197072
63.547 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 42/42 bytes at offset 262144
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 470/470 bytes at offset 262186
470 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done *** done

148
tests/qemu-iotests/051 Executable file
View File

@ -0,0 +1,148 @@
#!/bin/bash
#
# Test command line configuration of block devices and driver-specific options
#
# Copyright (C) 2013 Red Hat, Inc.
#
# 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 <http://www.gnu.org/licenses/>.
#
# creator
owner=kwolf@redhat.com
seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
function do_run_qemu()
{
echo Testing: "$@"
echo quit | $QEMU -nographic -monitor stdio -serial none "$@"
echo
}
function run_qemu()
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu
}
size=128M
_make_test_img $size
echo
echo === Unknown option ===
echo
run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=
run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=on
run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=1234
run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=foo
echo
echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
echo
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=on
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=off
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=42
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=foo
echo
echo === With version 2 images enabling lazy refcounts must fail ===
echo
_make_test_img -ocompat=0.10 $size
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=on
run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=off
echo
echo === No medium ===
echo
run_qemu -drive if=floppy
run_qemu -drive if=ide,media=cdrom
run_qemu -drive if=scsi,media=cdrom
run_qemu -drive if=ide
run_qemu -drive if=virtio
run_qemu -drive if=scsi
run_qemu -drive if=none,id=disk -device ide-cd,drive=disk
run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
run_qemu -drive if=none,id=disk -device ide-drive,drive=disk
run_qemu -drive if=none,id=disk -device ide-hd,drive=disk
run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
echo
echo === Read-only ===
echo
run_qemu -drive file=$TEST_IMG,if=floppy,readonly=on
run_qemu -drive file=$TEST_IMG,if=ide,media=cdrom,readonly=on
run_qemu -drive file=$TEST_IMG,if=scsi,media=cdrom,readonly=on
run_qemu -drive file=$TEST_IMG,if=ide,readonly=on
run_qemu -drive file=$TEST_IMG,if=virtio,readonly=on
run_qemu -drive file=$TEST_IMG,if=scsi,readonly=on
run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-cd,drive=disk
run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-drive,drive=disk
run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-hd,drive=disk
run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
echo
echo === Cache modes ===
echo
# Cannot use the test image because cache=none might not work on the host FS
# Use cdrom so that we won't get errors about missing media
run_qemu -drive media=cdrom,cache=none
run_qemu -drive media=cdrom,cache=directsync
run_qemu -drive media=cdrom,cache=writeback
run_qemu -drive media=cdrom,cache=writethrough
run_qemu -drive media=cdrom,cache=unsafe
run_qemu -drive media=cdrom,cache=invalid_value
# success, all done
echo "*** done"
rm -f $seq.full
status=0

162
tests/qemu-iotests/051.out Normal file
View File

@ -0,0 +1,162 @@
QA output created by 051
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
=== Unknown option ===
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: could not open disk image TEST_DIR/t.qcow2: Invalid argument
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: could not open disk image TEST_DIR/t.qcow2: Invalid argument
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: Parameter 'lazy_refcounts' expects 'on' or 'off'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: could not open disk image TEST_DIR/t.qcow2: Invalid argument
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42: Parameter 'lazy_refcounts' expects 'on' or 'off'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42: could not open disk image TEST_DIR/t.qcow2: Invalid argument
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo: Parameter 'lazy_refcounts' expects 'on' or 'off'
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument
=== With version 2 images enabling lazy refcounts must fail ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off
qququiquit
=== No medium ===
Testing: -drive if=floppy
qququiquit
Testing: -drive if=ide,media=cdrom
qququiquit
Testing: -drive if=scsi,media=cdrom
qququiquit
Testing: -drive if=ide
QEMU_PROG: Device needs media, but drive is empty
QEMU_PROG: Initialization of device ide-hd failed
Testing: -drive if=virtio
QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized
Testing: -drive if=scsi
QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty
QEMU_PROG: Initialization of device lsi53c895a failed
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
qququiquit
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
qququiquit
Testing: -drive if=none,id=disk -device ide-drive,drive=disk
QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized
Testing: -drive if=none,id=disk -device ide-hd,drive=disk
QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized
=== Read-only ===
Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: readonly not supported by this bus type
Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
qququiquit
=== Cache modes ===
Testing: -drive media=cdrom,cache=none
qququiquit
Testing: -drive media=cdrom,cache=directsync
qququiquit
Testing: -drive media=cdrom,cache=writeback
qququiquit
Testing: -drive media=cdrom,cache=writethrough
qququiquit
Testing: -drive media=cdrom,cache=unsafe
qququiquit
Testing: -drive media=cdrom,cache=invalid_value
QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option
*** done

View File

@ -137,6 +137,7 @@ check options
-rbd test rbd -rbd test rbd
-sheepdog test sheepdog -sheepdog test sheepdog
-nbd test nbd -nbd test nbd
-ssh test ssh
-xdiff graphical mode diff -xdiff graphical mode diff
-nocache use O_DIRECT on backing file -nocache use O_DIRECT on backing file
-misalign misalign memory allocations -misalign misalign memory allocations
@ -206,6 +207,10 @@ testlist options
IMGPROTO=nbd IMGPROTO=nbd
xpand=false xpand=false
;; ;;
-ssh)
IMGPROTO=ssh
xpand=false
;;
-nocache) -nocache)
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache" QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
xpand=false xpand=false

View File

@ -152,5 +152,11 @@ _filter_qemu_io()
_filter_win32 | sed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/" _filter_win32 | sed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/"
} }
# replace occurrences of QEMU_PROG with "qemu"
_filter_qemu()
{
sed -e "s#$(basename $QEMU_PROG)#QEMU_PROG#g"
}
# make sure this script returns success # make sure this script returns success
/bin/true /bin/true

View File

@ -52,6 +52,9 @@ if [ "$IMGPROTO" = "file" ]; then
elif [ "$IMGPROTO" = "nbd" ]; then elif [ "$IMGPROTO" = "nbd" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
TEST_IMG="nbd:127.0.0.1:10810" TEST_IMG="nbd:127.0.0.1:10810"
elif [ "$IMGPROTO" = "ssh" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
else else
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
fi fi

View File

@ -57,4 +57,5 @@
048 img auto quick 048 img auto quick
049 rw auto 049 rw auto
050 rw auto backing quick 050 rw auto backing quick
051 rw auto
052 rw auto backing 052 rw auto backing