Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-reques…
Browse files Browse the repository at this point in the history
…t' 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>
  • Loading branch information
pm215 committed Jun 25, 2015
2 parents 355df30 + 1204854 commit 58e8b33
Show file tree
Hide file tree
Showing 17 changed files with 210 additions and 86 deletions.
8 changes: 4 additions & 4 deletions block.c
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions block/block-backend.c
Expand Up @@ -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();
Expand Down
45 changes: 28 additions & 17 deletions block/io.c
Expand Up @@ -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
*
Expand All @@ -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);
}
}

Expand All @@ -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);
Expand All @@ -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);
}
}
Expand All @@ -312,6 +320,7 @@ void bdrv_drain_all(void)
}
aio_context_release(aio_context);
}
g_slist_free(aio_ctxs);
}

/**
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}
4 changes: 0 additions & 4 deletions block/iscsi.c
Expand Up @@ -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;
}
Expand Down
91 changes: 53 additions & 38 deletions block/raw-posix.c
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1020,15 +1025,17 @@ 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;
fl.l_start = offset;
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;
Expand All @@ -1037,15 +1044,17 @@ 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;
fl.l_start = offset;
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
9 changes: 7 additions & 2 deletions block/throttle-groups.c
Expand Up @@ -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);
}

Expand Down

0 comments on commit 58e8b33

Please sign in to comment.