Commit 93531372 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

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



# By Paolo Bonzini (17) and others
# Via Stefan Hajnoczi
* stefanha/block: (48 commits)
  qemu-iotests: filter QEMU monitor \r\n
  aio: make aio_poll(ctx, true) block with no fds
  block: clean up bdrv_drain_all() throttling comments
  qcow2: use start_of_cluster() and offset_into_cluster() everywhere
  qemu-img: decrease progress update interval on convert
  qemu-img: round down request length to an aligned sector
  qemu-img: dynamically adjust iobuffer size during convert
  block/iscsi: set bs->bl.opt_transfer_length
  block: add opt_transfer_length to BlockLimits
  block/iscsi: set bdi->cluster_size
  qemu-img: fix usage instruction for qemu-img convert
  qemu-img: add support for skipping zeroes in input during convert
  qemu-nbd: add doc for option -f
  qemu-iotests: add test for snapshot in qemu-img convert
  qemu-img: add -l for snapshot in convert
  qemu-iotests: add 058 internal snapshot export with qemu-nbd case
  qemu-nbd: support internal snapshot export
  snapshot: distinguish id and name in load_tmp
  qemu-iotests: Split qcow2 only cases in 048
  qemu-iotests: Clean up spaces in usage output
  ...

Message-id: 1386347807-27359-1-git-send-email-stefanha@redhat.com
Signed-off-by: default avatarAnthony Liguori <aliguori@amazon.com>
parents 0c0cb6a2 ac9524dc
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -217,11 +217,6 @@ bool aio_poll(AioContext *ctx, bool blocking)

    ctx->walking_handlers--;

    /* early return if we only have the aio_notify() fd */
    if (ctx->pollfds->len == 1) {
        return progress;
    }

    /* wait until next event */
    ret = qemu_poll_ns((GPollFD *)ctx->pollfds->data,
                         ctx->pollfds->len,
+0 −5
Original line number Diff line number Diff line
@@ -161,11 +161,6 @@ bool aio_poll(AioContext *ctx, bool blocking)

    ctx->walking_handlers--;

    /* early return if we only have the aio_notify() fd */
    if (count == 1) {
        return progress;
    }

    /* wait until next event */
    while (count > 0) {
        int ret;
+92 −68
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
                                               int64_t sector_num,
                                               QEMUIOVector *qiov,
                                               int nb_sectors,
                                               BdrvRequestFlags flags,
                                               BlockDriverCompletionFunc *cb,
                                               void *opaque,
                                               bool is_write);
@@ -1556,13 +1557,8 @@ void bdrv_drain_all(void)
    BlockDriverState *bs;

    while (busy) {
        /* FIXME: We do not have timer support here, so this is effectively
         * a busy wait.
         */
        QTAILQ_FOREACH(bs, &bdrv_states, list) {
            if (bdrv_start_throttled_reqs(bs)) {
                busy = true;
            }
            bdrv_start_throttled_reqs(bs);
        }

        busy = bdrv_requests_pending_all();
@@ -2770,14 +2766,21 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
    while (nb_sectors > 0 && !ret) {
        int num = nb_sectors;

        /* align request */
        if (bs->bl.write_zeroes_alignment &&
            num >= bs->bl.write_zeroes_alignment &&
            sector_num % bs->bl.write_zeroes_alignment) {
            if (num > bs->bl.write_zeroes_alignment) {
        /* Align request.  Block drivers can expect the "bulk" of the request
         * to be aligned.
         */
        if (bs->bl.write_zeroes_alignment
            && num > bs->bl.write_zeroes_alignment) {
            if (sector_num % bs->bl.write_zeroes_alignment != 0) {
                /* Make a small request up to the first aligned sector.  */
                num = bs->bl.write_zeroes_alignment;
            }
                num -= sector_num % bs->bl.write_zeroes_alignment;
            } else if ((sector_num + num) % bs->bl.write_zeroes_alignment != 0) {
                /* Shorten the request to the last aligned sector.  num cannot
                 * underflow because num > bs->bl.write_zeroes_alignment.
                 */
                num -= (sector_num + num) % bs->bl.write_zeroes_alignment;
            }
        }

        /* limit request size */
@@ -2795,16 +2798,20 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
            /* Fall back to bounce buffer if write zeroes is unsupported */
            iov.iov_len = num * BDRV_SECTOR_SIZE;
            if (iov.iov_base == NULL) {
                /* allocate bounce buffer only once and ensure that it
                 * is big enough for this and all future requests.
                 */
                size_t bufsize = num <= nb_sectors ? num : max_write_zeroes;
                iov.iov_base = qemu_blockalign(bs, bufsize * BDRV_SECTOR_SIZE);
                memset(iov.iov_base, 0, bufsize * BDRV_SECTOR_SIZE);
                iov.iov_base = qemu_blockalign(bs, num * BDRV_SECTOR_SIZE);
                memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE);
            }
            qemu_iovec_init_external(&qiov, &iov, 1);

            ret = drv->bdrv_co_writev(bs, sector_num, num, &qiov);

            /* Keep bounce buffer around if it is big enough for all
             * all future requests.
             */
            if (num < max_write_zeroes) {
                qemu_vfree(iov.iov_base);
                iov.iov_base = NULL;
            }
        }

        sector_num += num;
@@ -2887,7 +2894,7 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
                                      int64_t sector_num, int nb_sectors,
                                      BdrvRequestFlags flags)
{
    trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
    trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);

    if (!(bs->open_flags & BDRV_O_UNMAP)) {
        flags &= ~BDRV_REQ_MAY_UNMAP;
@@ -3669,7 +3676,7 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
{
    trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque);

    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors,
    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,
                                 cb, opaque, false);
}

@@ -3679,7 +3686,18 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
{
    trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);

    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors,
    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,
                                 cb, opaque, true);
}

BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
        int64_t sector_num, int nb_sectors, BdrvRequestFlags flags,
        BlockDriverCompletionFunc *cb, void *opaque)
{
    trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque);

    return bdrv_co_aio_rw_vector(bs, sector_num, NULL, nb_sectors,
                                 BDRV_REQ_ZERO_WRITE | flags,
                                 cb, opaque, true);
}

@@ -3851,8 +3869,10 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
    /* Run the aio requests. */
    mcb->num_requests = num_reqs;
    for (i = 0; i < num_reqs; i++) {
        bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
            reqs[i].nb_sectors, multiwrite_cb, mcb);
        bdrv_co_aio_rw_vector(bs, reqs[i].sector, reqs[i].qiov,
                              reqs[i].nb_sectors, reqs[i].flags,
                              multiwrite_cb, mcb,
                              true);
    }

    return 0;
@@ -3994,10 +4014,10 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)

    if (!acb->is_write) {
        acb->req.error = bdrv_co_do_readv(bs, acb->req.sector,
            acb->req.nb_sectors, acb->req.qiov, 0);
            acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
    } else {
        acb->req.error = bdrv_co_do_writev(bs, acb->req.sector,
            acb->req.nb_sectors, acb->req.qiov, 0);
            acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
    }

    acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
@@ -4008,6 +4028,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
                                               int64_t sector_num,
                                               QEMUIOVector *qiov,
                                               int nb_sectors,
                                               BdrvRequestFlags flags,
                                               BlockDriverCompletionFunc *cb,
                                               void *opaque,
                                               bool is_write)
@@ -4019,6 +4040,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
    acb->req.sector = sector_num;
    acb->req.nb_sectors = nb_sectors;
    acb->req.qiov = qiov;
    acb->req.flags = flags;
    acb->is_write = is_write;
    acb->done = NULL;

@@ -4302,6 +4324,8 @@ static void coroutine_fn bdrv_discard_co_entry(void *opaque)
int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
                                 int nb_sectors)
{
    int max_discard;

    if (!bs->drv) {
        return -ENOMEDIUM;
    } else if (bdrv_check_request(bs, sector_num, nb_sectors)) {
@@ -4317,10 +4341,11 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
        return 0;
    }

    if (bs->drv->bdrv_co_discard) {
        int max_discard = bs->bl.max_discard ?
                          bs->bl.max_discard : MAX_DISCARD_DEFAULT;
    if (!bs->drv->bdrv_co_discard && !bs->drv->bdrv_aio_discard) {
        return 0;
    }

    max_discard = bs->bl.max_discard ?  bs->bl.max_discard : MAX_DISCARD_DEFAULT;
    while (nb_sectors > 0) {
        int ret;
        int num = nb_sectors;
@@ -4340,16 +4365,9 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
            num = max_discard;
        }

        if (bs->drv->bdrv_co_discard) {
            ret = bs->drv->bdrv_co_discard(bs, sector_num, num);
            if (ret) {
                return ret;
            }

            sector_num += num;
            nb_sectors -= num;
        }
        return 0;
    } else if (bs->drv->bdrv_aio_discard) {
        } else {
            BlockDriverAIOCB *acb;
            CoroutineIOCompletion co = {
                .coroutine = qemu_coroutine_self(),
@@ -4361,11 +4379,17 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
                return -EIO;
            } else {
                qemu_coroutine_yield();
            return co.ret;
                ret = co.ret;
            }
    } else {
        return 0;
        }
        if (ret && ret != -ENOTSUP) {
            return ret;
        }

        sector_num += num;
        nb_sectors -= num;
    }
    return 0;
}

int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
@@ -4684,7 +4708,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
{
    QEMUOptionParameter *param = NULL, *create_options = NULL;
    QEMUOptionParameter *backing_fmt, *backing_file, *size;
    BlockDriverState *bs = NULL;
    BlockDriver *drv, *proto_drv;
    BlockDriver *backing_drv = NULL;
    Error *local_err = NULL;
@@ -4763,6 +4786,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
    size = get_option_parameter(param, BLOCK_OPT_SIZE);
    if (size && size->value.n == -1) {
        if (backing_file && backing_file->value.s) {
            BlockDriverState *bs;
            uint64_t size;
            char buf[32];
            int back_flags;
@@ -4781,6 +4805,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
                                 error_get_pretty(local_err));
                error_free(local_err);
                local_err = NULL;
                bdrv_unref(bs);
                goto out;
            }
            bdrv_get_geometry(bs, &size);
@@ -4788,6 +4813,8 @@ void bdrv_img_create(const char *filename, const char *fmt,

            snprintf(buf, sizeof(buf), "%" PRId64, size);
            set_option_parameter(param, BLOCK_OPT_SIZE, buf);

            bdrv_unref(bs);
        } else {
            error_setg(errp, "Image creation needs a size parameter");
            goto out;
@@ -4818,9 +4845,6 @@ out:
    free_option_parameters(create_options);
    free_option_parameters(param);

    if (bs) {
        bdrv_unref(bs);
    }
    if (error_is_set(&local_err)) {
        error_propagate(errp, local_err);
    }
+28 −9
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 * QEMU Block driver for iSCSI images
 *
 * Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
 * Copyright (c) 2012-2013 Peter Lieven <pl@kamp.de>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
@@ -54,6 +55,7 @@ typedef struct IscsiLun {
    QEMUTimer *nop_timer;
    uint8_t lbpme;
    uint8_t lbprz;
    uint8_t has_write_same;
    struct scsi_inquiry_logical_block_provisioning lbp;
    struct scsi_inquiry_block_limits bl;
    unsigned char *zeroblock;
@@ -975,8 +977,13 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
        return -EINVAL;
    }

    if (!iscsilun->lbp.lbpws) {
        /* WRITE SAME is not supported by the target */
    if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
        /* WRITE SAME without UNMAP is not supported by the target */
        return -ENOTSUP;
    }

    if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
        /* WRITE SAME with UNMAP is not supported by the target */
        return -ENOTSUP;
    }

@@ -1011,6 +1018,14 @@ retry:
    }

    if (iTask.status != SCSI_STATUS_GOOD) {
        if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
            iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
            iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
            /* WRITE SAME is not supported by the target */
            iscsilun->has_write_same = false;
            return -ENOTSUP;
        }

        return -EIO;
    }

@@ -1374,6 +1389,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
    }

    iscsilun->type = inq->periperal_device_type;
    iscsilun->has_write_same = true;

    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
        goto out;
@@ -1441,6 +1457,9 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
        }
        bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
                                                        iscsilun);

        bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
                                                     iscsilun);
    }

#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
@@ -1505,11 +1524,6 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
    return 0;
}

static int iscsi_has_zero_init(BlockDriverState *bs)
{
    return 0;
}

static int iscsi_create(const char *filename, QEMUOptionParameter *options,
                        Error **errp)
{
@@ -1569,6 +1583,13 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
    IscsiLun *iscsilun = bs->opaque;
    bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
    bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
    /* Guess the internal cluster (page) size of the iscsi target by the means
     * of opt_unmap_gran. Transfer the unmap granularity only if it has a
     * reasonable size for bdi->cluster_size */
    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 64 * 1024 &&
        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
        bdi->cluster_size = iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
    }
    return 0;
}

@@ -1608,8 +1629,6 @@ static BlockDriver bdrv_iscsi = {
    .bdrv_aio_writev = iscsi_aio_writev,
    .bdrv_aio_flush  = iscsi_aio_flush,

    .bdrv_has_zero_init = iscsi_has_zero_init,

#ifdef __linux__
    .bdrv_ioctl       = iscsi_ioctl,
    .bdrv_aio_ioctl   = iscsi_aio_ioctl,
+1 −1
Original line number Diff line number Diff line
@@ -1401,7 +1401,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,

    /* Round start up and end down */
    offset = align_offset(offset, s->cluster_size);
    end_offset &= ~(s->cluster_size - 1);
    end_offset = start_of_cluster(s, end_offset);

    if (offset > end_offset) {
        return 0;
Loading