Commit 3521f767 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging



Block patches for 2.3-rc0

# gpg: Signature made Mon Mar 16 16:11:55 2015 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream:
  block/vpc: remove disabled code from get_sector_offset
  block/vpc: rename footer->size -> footer->current_size
  block/vpc: make calculate_geometry spec conform
  vpc: Ignore geometry for large images
  block/vpc: optimize vpc_co_get_block_status
  block: Drop bdrv_find
  blockdev: Convert bdrv_find to blk_by_name
  migration: Convert bdrv_find to blk_by_name
  monitor: Convert bdrv_find to blk_by_name
  iotests: Test non-self-referential qcow2 refblocks
  iotests: Add tests for refcount table growth
  qcow2: Respect new_block in alloc_refcount_block()
  qemu-img: Avoid qerror_report_err() outside QMP handlers, again
  block: Fix block-set-write-threshold not to use funky error class
  block: Deprecate QCOW/QCOW2 encryption
  qemu-img: Fix convert, amend error messages for unknown options
  iotests: Update 051's reference output

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 17b11a14 47aced50
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -1065,6 +1065,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
        goto free_and_fail;
    }

    if (bs->encrypted) {
        error_report("Encrypted images are deprecated");
        error_printf("Support for them will be removed in a future release.\n"
                     "You can use 'qemu-img convert' to convert your image"
                     " to an unencrypted one.\n");
    }

    ret = refresh_total_sectors(bs, bs->total_sectors);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Could not refresh total sector count");
@@ -3814,15 +3821,6 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
    g_free(formats);
}

/* This function is to find block backend bs */
/* TODO convert callers to blk_by_name(), then remove */
BlockDriverState *bdrv_find(const char *name)
{
    BlockBackend *blk = blk_by_name(name);

    return blk ? blk_bs(blk) : NULL;
}

/* This function is to find a node in the bs graph */
BlockDriverState *bdrv_find_node(const char *node_name)
{
+14 −2
Original line number Diff line number Diff line
@@ -466,8 +466,20 @@ static int alloc_refcount_block(BlockDriverState *bs,
     */
    BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW);

    /* Calculate the number of refcount blocks needed so far */
    uint64_t blocks_used = DIV_ROUND_UP(cluster_index, s->refcount_block_size);
    /* Calculate the number of refcount blocks needed so far; this will be the
     * basis for calculating the index of the first cluster used for the
     * self-describing refcount structures which we are about to create.
     *
     * Because we reached this point, there cannot be any refcount entries for
     * cluster_index or higher indices yet. However, because new_block has been
     * allocated to describe that cluster (and it will assume this role later
     * on), we cannot use that index; also, new_block may actually have a higher
     * cluster index than cluster_index, so it needs to be taken into account
     * here (and 1 needs to be added to its value because that cluster is used).
     */
    uint64_t blocks_used = DIV_ROUND_UP(MAX(cluster_index + 1,
                                            (new_block >> s->cluster_bits) + 1),
                                        s->refcount_block_size);

    if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {
        return -EFBIG;
+37 −69
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ enum vhd_type {
#define VHD_TIMESTAMP_BASE 946684800

#define VHD_MAX_SECTORS       (65535LL * 255 * 255)
#define VHD_MAX_GEOMETRY      (65535LL *  16 * 255)

// always big-endian
typedef struct vhd_footer {
@@ -65,7 +66,7 @@ typedef struct vhd_footer {
    char        creator_os[4]; // "Wi2k"

    uint64_t    orig_size;
    uint64_t    size;
    uint64_t    current_size;

    uint16_t    cyls;
    uint8_t     heads;
@@ -215,13 +216,12 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
    bs->total_sectors = (int64_t)
        be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;

    /* images created with disk2vhd report a far higher virtual size
     * than expected with the cyls * heads * sectors_per_cyl formula.
     * use the footer->size instead if the image was created with
     * disk2vhd.
     */
    if (!strncmp(footer->creator_app, "d2v", 4)) {
        bs->total_sectors = be64_to_cpu(footer->size) / BDRV_SECTOR_SIZE;
    /* Images that have exactly the maximum geometry are probably bigger and
     * would be truncated if we adhered to the geometry for them. Rely on
     * footer->current_size for them. */
    if (bs->total_sectors == VHD_MAX_GEOMETRY) {
        bs->total_sectors = be64_to_cpu(footer->current_size) /
                            BDRV_SECTOR_SIZE;
    }

    /* Allow a maximum disk size of approximately 2 TB */
@@ -376,38 +376,6 @@ static inline int64_t get_sector_offset(BlockDriverState *bs,
        bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
    }

//    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
//	sector_num, pagetable_index, pageentry_index,
//	bitmap_offset, block_offset);

// disabled by reason
#if 0
#ifdef CACHE
    if (bitmap_offset != s->last_bitmap)
    {
	lseek(s->fd, bitmap_offset, SEEK_SET);

	s->last_bitmap = bitmap_offset;

	// Scary! Bitmap is stored as big endian 32bit entries,
	// while we used to look it up byte by byte
	read(s->fd, s->pageentry_u8, 512);
	for (i = 0; i < 128; i++)
	    be32_to_cpus(&s->pageentry_u32[i]);
    }

    if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)
	return -1;
#else
    lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);

    read(s->fd, &bitmap_entry, 1);

    if ((bitmap_entry >> (pageentry_index % 8)) & 1)
	return -1; // not allocated
#endif
#endif

    return block_offset;
}

@@ -602,7 +570,7 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
{
    BDRVVPCState *s = bs->opaque;
    VHDFooter *footer = (VHDFooter*) s->footer_buf;
    int64_t start, offset, next;
    int64_t start, offset;
    bool allocated;
    int n;

@@ -626,21 +594,19 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
        *pnum += n;
        sector_num += n;
        nb_sectors -= n;
        next = start + (*pnum * BDRV_SECTOR_SIZE);

        /* *pnum can't be greater than one block for allocated
         * sectors since there is always a bitmap in between. */
        if (allocated) {
            return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
        }
        if (nb_sectors == 0) {
            break;
        }

        offset = get_sector_offset(bs, sector_num, 0);
    } while ((allocated && offset == next) || (!allocated && offset == -1));
    } while (offset == -1);

    if (allocated) {
        return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
    } else {
    return 0;
}
}

/*
 * Calculates the number of cylinders, heads and sectors per cylinder
@@ -659,26 +625,20 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
{
    uint32_t cyls_times_heads;

    /* Allow a maximum disk size of approximately 2 TB */
    if (total_sectors > 65535LL * 255 * 255) {
        return -EFBIG;
    }
    total_sectors = MIN(total_sectors, VHD_MAX_GEOMETRY);

    if (total_sectors > 65535 * 16 * 63) {
    if (total_sectors >= 65535LL * 16 * 63) {
        *secs_per_cyl = 255;
        if (total_sectors > 65535 * 16 * 255) {
            *heads = 255;
        } else {
        *heads = 16;
        }
        cyls_times_heads = total_sectors / *secs_per_cyl;
    } else {
        *secs_per_cyl = 17;
        cyls_times_heads = total_sectors / *secs_per_cyl;
        *heads = (cyls_times_heads + 1023) / 1024;

        if (*heads < 4)
        if (*heads < 4) {
            *heads = 4;
        }

        if (cyls_times_heads >= (*heads * 1024) || *heads > 16) {
            *secs_per_cyl = 31;
@@ -834,19 +794,27 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
     * Calculate matching total_size and geometry. Increase the number of
     * sectors requested until we get enough (or fail). This ensures that
     * qemu-img convert doesn't truncate images, but rather rounds up.
     *
     * If the image size can't be represented by a spec conform CHS geometry,
     * we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use
     * the image size from the VHD footer to calculate total_sectors.
     */
    total_sectors = total_size / BDRV_SECTOR_SIZE;
    total_sectors = MIN(VHD_MAX_GEOMETRY, total_size / BDRV_SECTOR_SIZE);
    for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
        if (calculate_geometry(total_sectors + i, &cyls, &heads,
                               &secs_per_cyl))
        {
        calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl);
    }

    if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) {
        total_sectors = total_size / BDRV_SECTOR_SIZE;
        /* Allow a maximum disk size of approximately 2 TB */
        if (total_sectors > VHD_MAX_SECTORS) {
            ret = -EFBIG;
            goto out;
        }
    }

    } else {
        total_sectors = (int64_t)cyls * heads * secs_per_cyl;
        total_size = total_sectors * BDRV_SECTOR_SIZE;
    }

    /* Prepare the Hard Disk Footer */
    memset(buf, 0, 1024);
@@ -869,7 +837,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
    footer->major = cpu_to_be16(0x0005);
    footer->minor = cpu_to_be16(0x0003);
    footer->orig_size = cpu_to_be64(total_size);
    footer->size = cpu_to_be64(total_size);
    footer->current_size = cpu_to_be64(total_size);
    footer->cyls = cpu_to_be16(cyls);
    footer->heads = heads;
    footer->secs_per_cyl = secs_per_cyl;
+1 −1
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ void qmp_block_set_write_threshold(const char *node_name,

    bs = bdrv_find_node(node_name);
    if (!bs) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, node_name);
        error_setg(errp, "Device '%s' not found", node_name);
        return;
    }

+59 −33
Original line number Diff line number Diff line
@@ -1016,18 +1016,18 @@ fail:
void hmp_commit(Monitor *mon, const QDict *qdict)
{
    const char *device = qdict_get_str(qdict, "device");
    BlockDriverState *bs;
    BlockBackend *blk;
    int ret;

    if (!strcmp(device, "all")) {
        ret = bdrv_commit_all();
    } else {
        bs = bdrv_find(device);
        if (!bs) {
        blk = blk_by_name(device);
        if (!blk) {
            monitor_printf(mon, "Device '%s' not found\n", device);
            return;
        }
        ret = bdrv_commit(bs);
        ret = bdrv_commit(blk_bs(blk));
    }
    if (ret < 0) {
        monitor_printf(mon, "'commit' error for '%s': %s\n", device,
@@ -1092,17 +1092,20 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
                                                         const char *name,
                                                         Error **errp)
{
    BlockDriverState *bs = bdrv_find(device);
    BlockDriverState *bs;
    BlockBackend *blk;
    AioContext *aio_context;
    QEMUSnapshotInfo sn;
    Error *local_err = NULL;
    SnapshotInfo *info = NULL;
    int ret;

    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return NULL;
    }
    bs = blk_bs(blk);

    if (!has_id) {
        id = NULL;
@@ -1205,6 +1208,7 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
    Error *local_err = NULL;
    const char *device;
    const char *name;
    BlockBackend *blk;
    BlockDriverState *bs;
    QEMUSnapshotInfo old_sn, *sn;
    bool ret;
@@ -1223,11 +1227,12 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
    name = internal->name;

    /* 2. check for validation */
    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    /* AioContext is released in .clean() */
    state->aio_context = bdrv_get_aio_context(bs);
@@ -1494,17 +1499,19 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
{
    DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
    BlockDriverState *bs;
    BlockBackend *blk;
    DriveBackup *backup;
    Error *local_err = NULL;

    assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
    backup = common->action->drive_backup;

    bs = bdrv_find(backup->device);
    if (!bs) {
    blk = blk_by_name(backup->device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
        return;
    }
    bs = blk_bs(blk);

    /* AioContext is released in .clean() */
    state->aio_context = bdrv_get_aio_context(bs);
@@ -1559,22 +1566,25 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp)
    BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
    BlockdevBackup *backup;
    BlockDriverState *bs, *target;
    BlockBackend *blk;
    Error *local_err = NULL;

    assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
    backup = common->action->blockdev_backup;

    bs = bdrv_find(backup->device);
    if (!bs) {
    blk = blk_by_name(backup->device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
        return;
    }
    bs = blk_bs(blk);

    target = bdrv_find(backup->target);
    if (!target) {
    blk = blk_by_name(backup->target);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, backup->target);
        return;
    }
    target = blk_bs(blk);

    /* AioContext is released in .clean() */
    state->aio_context = bdrv_get_aio_context(bs);
@@ -1881,13 +1891,15 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
{
    ThrottleConfig cfg;
    BlockDriverState *bs;
    BlockBackend *blk;
    AioContext *aio_context;

    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    memset(&cfg, 0, sizeof(cfg));
    cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
@@ -2091,6 +2103,7 @@ void qmp_block_stream(const char *device,
                      bool has_on_error, BlockdevOnError on_error,
                      Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs;
    BlockDriverState *base_bs = NULL;
    AioContext *aio_context;
@@ -2101,11 +2114,12 @@ void qmp_block_stream(const char *device,
        on_error = BLOCKDEV_ON_ERROR_REPORT;
    }

    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);
@@ -2155,6 +2169,7 @@ void qmp_block_commit(const char *device,
                      bool has_speed, int64_t speed,
                      Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs;
    BlockDriverState *base_bs, *top_bs;
    AioContext *aio_context;
@@ -2173,11 +2188,12 @@ void qmp_block_commit(const char *device,
     *  live commit feature versions; for this to work, we must make sure to
     *  perform the device lookup before any generic errors that may occur in a
     *  scenario in which all optional arguments are omitted. */
    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);
@@ -2258,6 +2274,7 @@ void qmp_drive_backup(const char *device, const char *target,
                      bool has_on_target_error, BlockdevOnError on_target_error,
                      Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs;
    BlockDriverState *target_bs;
    BlockDriverState *source = NULL;
@@ -2281,11 +2298,12 @@ void qmp_drive_backup(const char *device, const char *target,
        mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
    }

    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);
@@ -2385,6 +2403,7 @@ void qmp_blockdev_backup(const char *device, const char *target,
                         BlockdevOnError on_target_error,
                         Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs;
    BlockDriverState *target_bs;
    Error *local_err = NULL;
@@ -2400,20 +2419,22 @@ void qmp_blockdev_backup(const char *device, const char *target,
        on_target_error = BLOCKDEV_ON_ERROR_REPORT;
    }

    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);

    target_bs = bdrv_find(target);
    if (!target_bs) {
    blk = blk_by_name(target);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, target);
        goto out;
    }
    target_bs = blk_bs(blk);

    bdrv_ref(target_bs);
    bdrv_set_aio_context(target_bs, aio_context);
@@ -2442,6 +2463,7 @@ void qmp_drive_mirror(const char *device, const char *target,
                      bool has_on_target_error, BlockdevOnError on_target_error,
                      Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs;
    BlockDriverState *source, *target_bs;
    AioContext *aio_context;
@@ -2481,11 +2503,12 @@ void qmp_drive_mirror(const char *device, const char *target,
        return;
    }

    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);
@@ -2623,12 +2646,14 @@ out:
static BlockJob *find_block_job(const char *device, AioContext **aio_context,
                                Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs;

    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        goto notfound;
    }
    bs = blk_bs(blk);

    *aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(*aio_context);
@@ -2733,6 +2758,7 @@ void qmp_change_backing_file(const char *device,
                             const char *backing_file,
                             Error **errp)
{
    BlockBackend *blk;
    BlockDriverState *bs = NULL;
    AioContext *aio_context;
    BlockDriverState *image_bs = NULL;
@@ -2741,12 +2767,12 @@ void qmp_change_backing_file(const char *device,
    int open_flags;
    int ret;

    /* find the top layer BDS of the chain */
    bs = bdrv_find(device);
    if (!bs) {
    blk = blk_by_name(device);
    if (!blk) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);
Loading