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,
int nb_sectors, bool is_write)
static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *qiov, bool is_write)
{
QEMUIOVector qiov;
struct iovec iov = {
.iov_base = (void *)buf,
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
};
Coroutine *co;
RwCo rwco = {
.bs = bs,
.sector_num = sector_num,
.nb_sectors = nb_sectors,
.qiov = &qiov,
.nb_sectors = qiov->size >> BDRV_SECTOR_BITS,
.qiov = qiov,
.is_write = is_write,
.ret = NOT_DONE,
};
qemu_iovec_init_external(&qiov, &iov, 1);
assert((qiov->size & (BDRV_SECTOR_SIZE - 1)) == 0);
/**
* 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;
}
/*
* 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 */
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
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);
}
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,
void *buf, int count1)
{
@ -2255,15 +2270,15 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
return count1;
}
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf, int count1)
int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
{
uint8_t tmp_buf[BDRV_SECTOR_SIZE];
int len, nb_sectors, count;
int64_t sector_num;
int ret;
count = count1;
count = qiov->size;
/* first write to align to sector start */
len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
if (len > count)
@ -2272,24 +2287,32 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
if (len > 0) {
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
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)
return ret;
count -= len;
if (count == 0)
return count1;
return qiov->size;
sector_num++;
buf += len;
}
/* write the sectors "in place" */
nb_sectors = count >> BDRV_SECTOR_BITS;
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;
}
sector_num += nb_sectors;
len = nb_sectors << BDRV_SECTOR_BITS;
buf += len;
count -= len;
}
@ -2297,11 +2320,24 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
if (count > 0) {
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
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)
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,
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;
if (!drv)
if (!drv) {
return -ENOMEDIUM;
if (drv->bdrv_save_vmstate)
return drv->bdrv_save_vmstate(bs, buf, pos, size);
if (bs->file)
return bdrv_save_vmstate(bs->file, buf, pos, size);
} else if (drv->bdrv_save_vmstate) {
return drv->bdrv_save_vmstate(bs, qiov, pos);
} else if (bs->file) {
return bdrv_writev_vmstate(bs->file, qiov, pos);
}
return -ENOTSUP;
}

View File

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

View File

@ -1652,8 +1652,8 @@ static void dump_refcounts(BlockDriverState *bs)
}
#endif
static int qcow2_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size)
static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos)
{
BDRVQcowState *s = bs->opaque;
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);
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;
return ret;

View File

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

View File

@ -2054,12 +2054,19 @@ cleanup:
return ret;
}
static int sd_save_vmstate(BlockDriverState *bs, const uint8_t *data,
int64_t pos, int size)
static int sd_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos)
{
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,

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=""
gtkabi="2.0"
tpm="no"
libssh2=""
# parse CC options first
for opt do
@ -922,6 +923,10 @@ for opt do
;;
--enable-tpm) tpm="yes"
;;
--disable-libssh2) libssh2="no"
;;
--enable-libssh2) libssh2="yes"
;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
@ -1182,6 +1187,8 @@ echo " --disable-glusterfs disable GlusterFS backend"
echo " --enable-gcov enable test coverage analysis with gcov"
echo " --gcov=GCOV use specified gcov [$gcov_tool]"
echo " --enable-tpm enable TPM support"
echo " --disable-libssh2 disable ssh block device support"
echo " --enable-libssh2 enable ssh block device support"
echo ""
echo "NOTE: The object files are built at the place where configure is launched"
exit 1
@ -2313,6 +2320,67 @@ EOF
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
@ -3435,6 +3503,7 @@ echo "virtio-blk-data-plane $virtio_blk_data_plane"
echo "gcov $gcov_tool"
echo "gcov enabled $gcov"
echo "TPM support $tpm"
echo "libssh2 support $libssh2"
if test "$sdl_too_old" = "yes"; then
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
fi
if test "$libssh2" = "yes" ; then
echo "CONFIG_LIBSSH2=y" >> $config_host_mak
fi
if test "$virtio_blk_data_plane" = "yes" ; then
echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak
fi

View File

@ -1262,6 +1262,10 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
lba48 = 1;
/* fall through */
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_set_sector(s, s->nb_sectors - 1);
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);
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
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,
void *buf, int count);
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf, int count);
int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov);
int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
const void *buf, int count);
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 *filename);
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size);

View File

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

View File

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

View File

@ -423,6 +423,7 @@ snapshots.
* disk_images_sheepdog:: Sheepdog disk images
* disk_images_iscsi:: iSCSI LUNs
* disk_images_gluster:: GlusterFS disk images
* disk_images_ssh:: Secure Shell (ssh) disk images
@end menu
@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
@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
@section Network emulation

View File

@ -2107,6 +2107,18 @@ Example for Unix Domain Sockets
qemu-system-i386 --drive file=nbd:unix:/tmp/nbd-socket
@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
Sheepdog is a distributed storage system for QEMU.
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();
}
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;
ssize_t len;
@ -457,6 +458,21 @@ fail:
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,
int64_t pos, int size)
{
@ -480,8 +496,9 @@ static const QEMUFileOps bdrv_read_ops = {
};
static const QEMUFileOps bdrv_write_ops = {
.put_buffer = block_put_buffer,
.close = bdrv_fclose
.put_buffer = block_put_buffer,
.writev_buffer = block_writev_buffer,
.close = bdrv_fclose
};
static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
@ -535,7 +552,7 @@ static void qemu_fflush(QEMUFile *f)
if (f->ops->writev_buffer) {
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 {
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 "unaligned pwrite"
$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 "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 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
echo "*** done"

View File

@ -16,8 +16,34 @@ read 134217728/134217728 bytes at offset 0
unaligned pwrite
wrote 42/42 bytes at offset 66
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
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
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

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
-sheepdog test sheepdog
-nbd test nbd
-ssh test ssh
-xdiff graphical mode diff
-nocache use O_DIRECT on backing file
-misalign misalign memory allocations
@ -206,6 +207,10 @@ testlist options
IMGPROTO=nbd
xpand=false
;;
-ssh)
IMGPROTO=ssh
xpand=false
;;
-nocache)
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
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)/"
}
# replace occurrences of QEMU_PROG with "qemu"
_filter_qemu()
{
sed -e "s#$(basename $QEMU_PROG)#QEMU_PROG#g"
}
# make sure this script returns success
/bin/true

View File

@ -52,6 +52,9 @@ if [ "$IMGPROTO" = "file" ]; then
elif [ "$IMGPROTO" = "nbd" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
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
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
fi

View File

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