-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1
 
 iQEcBAABAgAGBQJVisx5AAoJEJykq7OBq3PIbasIALJC/7BEyCSEubcjH25CIzao
 D20ufmo8/Et6KGuD1r2zdGRXQ79q/SDCGStQK8QEEfvRxPMehngfCUb5aJXkcGbu
 /bRIaHh7DFxSiPGJI1/1wwR1MC7tjjR6ZrpSd2OTF0VOZvuXlP3noWpX1eiRAcvu
 ekK2vvYtDi03/Xzhbx8MIRSuYPAdh/tXZ3mrDfUQNrtO47QYAxh0C9ABzZVrHJCa
 RFCFXPoqZroOcrVe20ZHLt82AUL0H3cfHvF74Z+LbOlPJ7JbP/5+PzLisAqX7VeE
 VYvK78mQih41Ww+qYYx4lwhUMUW1fYYnN/MHpdU2LBHcF/tPqxz5kyvQ6GJhD5w=
 =rdVl
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging

# gpg: Signature made Wed Jun 24 16:27:53 2015 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/block-pull-request:
  virito-blk: drop duplicate check
  qemu-iotests: fix 051.out after qdev error message change
  iov: don't touch iov in iov_send_recv()
  raw-posix: Introduce hdev_is_sg()
  raw-posix: Use DPRINTF for DEBUG_FLOPPY
  raw-posix: DPRINTF instead of DEBUG_BLOCK_PRINT
  Fix migration in case of scsi-generic
  block: Use bdrv_is_sg() everywhere
  nvme: Fix memleak in nvme_dma_read_prp
  vvfat: add a label option
  util/hbitmap: Add an API to reset all set bits in hbitmap
  virtio-blk: Use blk_drain() to drain IO requests
  block-backend: Introduce blk_drain()
  throttle: Check current timers before updating any_timer_armed[]
  block: Let bdrv_drain_all() to call aio_poll() for each AioContext

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-06-25 11:19:46 +01:00
commit 58e8b33518
17 changed files with 210 additions and 86 deletions

View File

@ -585,7 +585,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename,
int ret = 0;
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) {
if (bdrv_is_sg(bs) || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) {
*pdrv = &bdrv_raw;
return ret;
}
@ -617,7 +617,7 @@ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
BlockDriver *drv = bs->drv;
/* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
if (bs->sg)
if (bdrv_is_sg(bs))
return 0;
/* query actual device if possible, otherwise just trust the hint */
@ -948,7 +948,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
assert(bdrv_opt_mem_align(bs) != 0);
assert(bdrv_min_mem_align(bs) != 0);
assert((bs->request_alignment != 0) || bs->sg);
assert((bs->request_alignment != 0) || bdrv_is_sg(bs));
qemu_opts_del(opts);
return 0;
@ -3513,7 +3513,7 @@ void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap)
{
assert(bdrv_dirty_bitmap_enabled(bitmap));
hbitmap_reset(bitmap->bitmap, 0, bitmap->size);
hbitmap_reset_all(bitmap->bitmap);
}
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,

View File

@ -700,6 +700,11 @@ int blk_flush_all(void)
return bdrv_flush_all();
}
void blk_drain(BlockBackend *blk)
{
bdrv_drain(blk->bs);
}
void blk_drain_all(void)
{
bdrv_drain_all();

View File

@ -233,17 +233,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
return false;
}
static bool bdrv_drain_one(BlockDriverState *bs)
{
bool bs_busy;
bdrv_flush_io_queue(bs);
bdrv_start_throttled_reqs(bs);
bs_busy = bdrv_requests_pending(bs);
bs_busy |= aio_poll(bdrv_get_aio_context(bs), bs_busy);
return bs_busy;
}
/*
* Wait for pending requests to complete on a single BlockDriverState subtree
*
@ -256,8 +245,13 @@ static bool bdrv_drain_one(BlockDriverState *bs)
*/
void bdrv_drain(BlockDriverState *bs)
{
while (bdrv_drain_one(bs)) {
bool busy = true;
while (busy) {
/* Keep iterating */
bdrv_flush_io_queue(bs);
busy = bdrv_requests_pending(bs);
busy |= aio_poll(bdrv_get_aio_context(bs), busy);
}
}
@ -278,6 +272,7 @@ void bdrv_drain_all(void)
/* Always run first iteration so any pending completion BHs run */
bool busy = true;
BlockDriverState *bs = NULL;
GSList *aio_ctxs = NULL, *ctx;
while ((bs = bdrv_next(bs))) {
AioContext *aio_context = bdrv_get_aio_context(bs);
@ -287,17 +282,30 @@ void bdrv_drain_all(void)
block_job_pause(bs->job);
}
aio_context_release(aio_context);
if (!aio_ctxs || !g_slist_find(aio_ctxs, aio_context)) {
aio_ctxs = g_slist_prepend(aio_ctxs, aio_context);
}
}
while (busy) {
busy = false;
bs = NULL;
while ((bs = bdrv_next(bs))) {
AioContext *aio_context = bdrv_get_aio_context(bs);
for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) {
AioContext *aio_context = ctx->data;
bs = NULL;
aio_context_acquire(aio_context);
busy |= bdrv_drain_one(bs);
while ((bs = bdrv_next(bs))) {
if (aio_context == bdrv_get_aio_context(bs)) {
bdrv_flush_io_queue(bs);
if (bdrv_requests_pending(bs)) {
busy = true;
aio_poll(aio_context, busy);
}
}
}
busy |= aio_poll(aio_context, false);
aio_context_release(aio_context);
}
}
@ -312,6 +320,7 @@ void bdrv_drain_all(void)
}
aio_context_release(aio_context);
}
g_slist_free(aio_ctxs);
}
/**
@ -2256,7 +2265,8 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
{
int ret;
if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
bdrv_is_sg(bs)) {
return 0;
}
@ -2562,4 +2572,5 @@ void bdrv_flush_io_queue(BlockDriverState *bs)
} else if (bs->file) {
bdrv_flush_io_queue(bs->file);
}
bdrv_start_throttled_reqs(bs);
}

View File

@ -628,10 +628,6 @@ static int coroutine_fn iscsi_co_flush(BlockDriverState *bs)
IscsiLun *iscsilun = bs->opaque;
struct IscsiTask iTask;
if (bs->sg) {
return 0;
}
if (!iscsilun->force_next_flush) {
return 0;
}

View File

@ -59,6 +59,7 @@
#include <linux/fd.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <scsi/sg.h>
#ifdef __s390__
#include <asm/dasd.h>
#endif
@ -96,15 +97,19 @@
#include <xfs/xfs.h>
#endif
//#define DEBUG_FLOPPY
//#define DEBUG_BLOCK
#if defined(DEBUG_BLOCK)
#define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
{ qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
#ifdef DEBUG_BLOCK
# define DEBUG_BLOCK_PRINT 1
#else
#define DEBUG_BLOCK_PRINT(formatCstr, ...)
# define DEBUG_BLOCK_PRINT 0
#endif
#define DPRINTF(fmt, ...) \
do { \
if (DEBUG_BLOCK_PRINT) { \
printf(fmt, ## __VA_ARGS__); \
} \
} while (0)
/* OS X does not have O_DSYNC */
#ifndef O_DSYNC
@ -305,9 +310,9 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
char *buf;
size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize());
/* For /dev/sg devices the alignment is not really used.
/* For SCSI generic devices the alignment is not really used.
With buffered I/O, we don't have any restrictions. */
if (bs->sg || !s->needs_alignment) {
if (bdrv_is_sg(bs) || !s->needs_alignment) {
bs->request_alignment = 1;
s->buf_align = 1;
return;
@ -1020,6 +1025,7 @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
{
struct xfs_flock64 fl;
int err;
memset(&fl, 0, sizeof(fl));
fl.l_whence = SEEK_SET;
@ -1027,8 +1033,9 @@ static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
fl.l_len = bytes;
if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) {
DEBUG_BLOCK_PRINT("cannot write zero range (%s)\n", strerror(errno));
return -errno;
err = errno;
DPRINTF("cannot write zero range (%s)\n", strerror(errno));
return -err;
}
return 0;
@ -1037,6 +1044,7 @@ static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
{
struct xfs_flock64 fl;
int err;
memset(&fl, 0, sizeof(fl));
fl.l_whence = SEEK_SET;
@ -1044,8 +1052,9 @@ static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
fl.l_len = bytes;
if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
return -errno;
err = errno;
DPRINTF("cannot punch hole (%s)\n", strerror(errno));
return -err;
}
return 0;
@ -2078,15 +2087,38 @@ static void hdev_parse_filename(const char *filename, QDict *options,
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
}
static bool hdev_is_sg(BlockDriverState *bs)
{
#if defined(__linux__)
struct stat st;
struct sg_scsi_id scsiid;
int sg_version;
if (stat(bs->filename, &st) >= 0 && S_ISCHR(st.st_mode) &&
!bdrv_ioctl(bs, SG_GET_VERSION_NUM, &sg_version) &&
!bdrv_ioctl(bs, SG_GET_SCSI_ID, &scsiid)) {
DPRINTF("SG device found: type=%d, version=%d\n",
scsiid.scsi_type, sg_version);
return true;
}
#endif
return false;
}
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVRawState *s = bs->opaque;
Error *local_err = NULL;
int ret;
const char *filename = qdict_get_str(options, "filename");
#if defined(__APPLE__) && defined(__MACH__)
const char *filename = qdict_get_str(options, "filename");
if (strstart(filename, "/dev/cdrom", NULL)) {
kern_return_t kernResult;
io_iterator_t mediaIterator;
@ -2115,16 +2147,6 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
#endif
s->type = FTYPE_FILE;
#if defined(__linux__)
{
char resolved_path[ MAXPATHLEN ], *temp;
temp = realpath(filename, resolved_path);
if (temp && strstart(temp, "/dev/sg", NULL)) {
bs->sg = 1;
}
}
#endif
ret = raw_open_common(bs, options, flags, 0, &local_err);
if (ret < 0) {
@ -2134,6 +2156,9 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
/* Since this does ioctl the device must be already opened */
bs->sg = hdev_is_sg(bs);
if (flags & BDRV_O_RDWR) {
ret = check_hdev_writable(s);
if (ret < 0) {
@ -2162,16 +2187,12 @@ static int fd_open(BlockDriverState *bs)
(qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
qemu_close(s->fd);
s->fd = -1;
#ifdef DEBUG_FLOPPY
printf("Floppy closed\n");
#endif
DPRINTF("Floppy closed\n");
}
if (s->fd < 0) {
if (s->fd_got_error &&
(qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
#ifdef DEBUG_FLOPPY
printf("No floppy (open delayed)\n");
#endif
DPRINTF("No floppy (open delayed)\n");
return -EIO;
}
s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK);
@ -2180,14 +2201,10 @@ static int fd_open(BlockDriverState *bs)
s->fd_got_error = 1;
if (last_media_present)
s->fd_media_changed = 1;
#ifdef DEBUG_FLOPPY
printf("No floppy\n");
#endif
DPRINTF("No floppy\n");
return -EIO;
}
#ifdef DEBUG_FLOPPY
printf("Floppy opened\n");
#endif
DPRINTF("Floppy opened\n");
}
if (!last_media_present)
s->fd_media_changed = 1;
@ -2455,9 +2472,7 @@ static int floppy_media_changed(BlockDriverState *bs)
fd_open(bs);
ret = s->fd_media_changed;
s->fd_media_changed = 0;
#ifdef DEBUG_FLOPPY
printf("Floppy changed=%d\n", ret);
#endif
DPRINTF("Floppy changed=%d\n", ret);
return ret;
}

View File

@ -324,9 +324,14 @@ void throttle_group_config(BlockDriverState *bs, ThrottleConfig *cfg)
ThrottleState *ts = bs->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
qemu_mutex_lock(&tg->lock);
throttle_config(ts, tt, cfg);
/* throttle_config() cancels the timers */
tg->any_timer_armed[0] = tg->any_timer_armed[1] = false;
if (timer_pending(tt->timers[0])) {
tg->any_timer_armed[0] = false;
}
if (timer_pending(tt->timers[1])) {
tg->any_timer_armed[1] = false;
}
throttle_config(ts, tt, cfg);
qemu_mutex_unlock(&tg->lock);
}

View File

@ -323,6 +323,7 @@ typedef struct BDRVVVFATState {
int fat_type; /* 16 or 32 */
array_t fat,directory,mapping;
char volume_label[11];
unsigned int cluster_size;
unsigned int sectors_per_cluster;
@ -860,7 +861,7 @@ static int init_directories(BDRVVVFATState* s,
{
direntry_t* entry=array_get_next(&(s->directory));
entry->attributes=0x28; /* archive | volume label */
memcpy(entry->name, "QEMU VVFAT ", sizeof(entry->name));
memcpy(entry->name, s->volume_label, sizeof(entry->name));
}
/* Now build FAT, and write back information into directory */
@ -969,7 +970,8 @@ static int init_directories(BDRVVVFATState* s,
bootsector->u.fat16.signature=0x29;
bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
memcpy(bootsector->u.fat16.volume_label,"QEMU VVFAT ",11);
memcpy(bootsector->u.fat16.volume_label, s->volume_label,
sizeof(bootsector->u.fat16.volume_label));
memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12 ":s->fat_type==16?"FAT16 ":"FAT32 "),8);
bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
@ -1008,6 +1010,11 @@ static QemuOptsList runtime_opts = {
.type = QEMU_OPT_BOOL,
.help = "Create a floppy rather than a hard disk image",
},
{
.name = "label",
.type = QEMU_OPT_STRING,
.help = "Use a volume label other than QEMU VVFAT",
},
{
.name = "rw",
.type = QEMU_OPT_BOOL,
@ -1070,7 +1077,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
BDRVVVFATState *s = bs->opaque;
int cyls, heads, secs;
bool floppy;
const char *dirname;
const char *dirname, *label;
QemuOpts *opts;
Error *local_err = NULL;
int ret;
@ -1097,6 +1104,18 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
floppy = qemu_opt_get_bool(opts, "floppy", false);
memset(s->volume_label, ' ', sizeof(s->volume_label));
label = qemu_opt_get(opts, "label");
if (label) {
size_t label_length = strlen(label);
if (label_length > 11) {
error_setg(errp, "vvfat label cannot be longer than 11 bytes");
ret = -EINVAL;
goto fail;
}
memcpy(s->volume_label, label, label_length);
}
if (floppy) {
/* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
if (!s->fat_type) {

View File

@ -154,6 +154,7 @@ static uint16_t nvme_dma_read_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
qemu_sglist_destroy(&qsg);
return NVME_INVALID_FIELD | NVME_DNR;
}
qemu_sglist_destroy(&qsg);
return NVME_SUCCESS;
}

View File

@ -499,8 +499,7 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
iov_discard_front(&iov, &out_num, sizeof(req->out));
if (in_num < 1 ||
in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) {
if (in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) {
error_report("virtio-blk request inhdr too short");
exit(1);
}
@ -651,16 +650,21 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
static void virtio_blk_reset(VirtIODevice *vdev)
{
VirtIOBlock *s = VIRTIO_BLK(vdev);
if (s->dataplane) {
virtio_blk_data_plane_stop(s->dataplane);
}
AioContext *ctx;
/*
* This should cancel pending requests, but can't do nicely until there
* are per-device request lists.
*/
blk_drain_all();
ctx = blk_get_aio_context(s->blk);
aio_context_acquire(ctx);
blk_drain(s->blk);
if (s->dataplane) {
virtio_blk_data_plane_stop(s->dataplane);
}
aio_context_release(ctx);
blk_set_enable_write_cache(s->blk, s->original_wce);
}

View File

@ -131,6 +131,14 @@ void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count);
*/
void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count);
/**
* hbitmap_reset_all:
* @hb: HBitmap to operate on.
*
* Reset all bits in an HBitmap.
*/
void hbitmap_reset_all(HBitmap *hb);
/**
* hbitmap_get:
* @hb: HBitmap to operate on.

View File

@ -75,7 +75,7 @@ size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
* For iov_send_recv() _whole_ area being sent or received
* should be within the iovec, not only beginning of it.
*/
ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
ssize_t iov_send_recv(int sockfd, const struct iovec *iov, unsigned iov_cnt,
size_t offset, size_t bytes, bool do_send);
#define iov_recv(sockfd, iov, iov_cnt, offset, bytes) \
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, false)

View File

@ -118,6 +118,7 @@ int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors);
int blk_co_flush(BlockBackend *blk);
int blk_flush(BlockBackend *blk);
int blk_flush_all(void);
void blk_drain(BlockBackend *blk);
void blk_drain_all(void);
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read);
BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,

View File

@ -1453,13 +1453,17 @@
# @fat-type: #optional FAT type: 12, 16 or 32
# @floppy: #optional whether to export a floppy image (true) or
# partitioned hard disk (false; default)
# @label: #optional set the volume label, limited to 11 bytes. FAT16 and
# FAT32 traditionally have some restrictions on labels, which are
# ignored by most operating systems. Defaults to "QEMU VVFAT".
# (since 2.4)
# @rw: #optional whether to allow write operations (default: false)
#
# Since: 1.7
##
{ 'struct': 'BlockdevOptionsVVFAT',
'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool',
'*rw': 'bool' } }
'*label': 'str', '*rw': 'bool' } }
##
# @BlockdevOptionsGenericFormat

View File

@ -52,7 +52,6 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specif
Testing: -device virtio-scsi-pci -device scsi-hd
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-hd: drive property not set
QEMU_PROG: -device scsi-hd: Device 'scsi-hd' could not be initialized
=== Overriding backing file ===
@ -128,7 +127,6 @@ QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
Testing: -drive if=virtio
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) 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 X.Y.Z monitor - type 'help' for more information
@ -146,23 +144,19 @@ Testing: -drive if=none,id=disk -device ide-drive,drive=disk
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
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 X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
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 X.Y.Z monitor - type 'help' for more information
(qemu) 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 X.Y.Z monitor - type 'help' for more information
(qemu) 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 ===
@ -204,13 +198,11 @@ Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-dr
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
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 X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
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
QEMU X.Y.Z monitor - type 'help' for more information

View File

@ -184,6 +184,23 @@ static void hbitmap_test_reset(TestHBitmapData *data,
}
}
static void hbitmap_test_reset_all(TestHBitmapData *data)
{
size_t n;
hbitmap_reset_all(data->hb);
n = (data->size + BITS_PER_LONG - 1) / BITS_PER_LONG;
if (n == 0) {
n = 1;
}
memset(data->bits, 0, n * sizeof(unsigned long));
if (data->granularity == 0) {
hbitmap_test_check(data, 0);
}
}
static void hbitmap_test_check_get(TestHBitmapData *data)
{
uint64_t count = 0;
@ -364,6 +381,26 @@ static void test_hbitmap_reset(TestHBitmapData *data,
hbitmap_test_set(data, L3 / 2, L3);
}
static void test_hbitmap_reset_all(TestHBitmapData *data,
const void *unused)
{
hbitmap_test_init(data, L3 * 2, 0);
hbitmap_test_set(data, L1 - 1, L1 + 2);
hbitmap_test_reset_all(data);
hbitmap_test_set(data, 0, L1 * 3);
hbitmap_test_reset_all(data);
hbitmap_test_set(data, L2, L1);
hbitmap_test_reset_all(data);
hbitmap_test_set(data, L2, L3 - L2 + 1);
hbitmap_test_reset_all(data);
hbitmap_test_set(data, L3 - 1, 3);
hbitmap_test_reset_all(data);
hbitmap_test_set(data, 0, L3 * 2);
hbitmap_test_reset_all(data);
hbitmap_test_set(data, L3 / 2, L3);
hbitmap_test_reset_all(data);
}
static void test_hbitmap_granularity(TestHBitmapData *data,
const void *unused)
{
@ -627,6 +664,7 @@ int main(int argc, char **argv)
hbitmap_test_add("/hbitmap/set/overlap", test_hbitmap_set_overlap);
hbitmap_test_add("/hbitmap/reset/empty", test_hbitmap_reset_empty);
hbitmap_test_add("/hbitmap/reset/general", test_hbitmap_reset);
hbitmap_test_add("/hbitmap/reset/all", test_hbitmap_reset_all);
hbitmap_test_add("/hbitmap/granularity", test_hbitmap_granularity);
hbitmap_test_add("/hbitmap/truncate/nop", test_hbitmap_truncate_nop);

View File

@ -356,6 +356,19 @@ void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count)
hb_reset_between(hb, HBITMAP_LEVELS - 1, start, last);
}
void hbitmap_reset_all(HBitmap *hb)
{
unsigned int i;
/* Same as hbitmap_alloc() except for memset() instead of malloc() */
for (i = HBITMAP_LEVELS; --i >= 1; ) {
memset(hb->levels[i], 0, hb->sizes[i] * sizeof(unsigned long));
}
hb->levels[0][0] = 1UL << (BITS_PER_LONG - 1);
hb->count = 0;
}
bool hbitmap_get(const HBitmap *hb, uint64_t item)
{
/* Compute position and bit in the last layer. */

View File

@ -133,7 +133,7 @@ do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
#endif
}
ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
ssize_t iov_send_recv(int sockfd, const struct iovec *_iov, unsigned iov_cnt,
size_t offset, size_t bytes,
bool do_send)
{
@ -141,6 +141,16 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
ssize_t ret;
size_t orig_len, tail;
unsigned niov;
struct iovec *local_iov, *iov;
if (bytes <= 0) {
return 0;
}
local_iov = g_new0(struct iovec, iov_cnt);
iov_copy(local_iov, iov_cnt, _iov, iov_cnt, offset, bytes);
offset = 0;
iov = local_iov;
while (bytes > 0) {
/* Find the start position, skipping `offset' bytes:
@ -187,6 +197,7 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
if (ret < 0) {
assert(errno != EINTR);
g_free(local_iov);
if (errno == EAGAIN && total > 0) {
return total;
}
@ -205,6 +216,7 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
bytes -= ret;
}
g_free(local_iov);
return total;
}