Block layer patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJZLDGTAAoJEH8JsnLIjy/WjY0P/jtXF+SQKs9H695Uy+U+EUr5 9w+lYTfjHXTUx9F5AKT4OAMww/uWSG5ywG8FZD8AJZyt1B8piDrSA7sW5YYgWCV4 XD1HMzN6pasVGrchzgfBSW/K9BgUlvBEjqFrLCNVii0osa68J7vX3uJsLyRA+yPo ijFseJaB/b0KnAPG9JqHXc4DVQgU2IhZH3ZsgE6Utb+KUrm8/veiORhWQboBbfCW eyTF+YWee/rI+up4nKn9+Le57EUXWr3Y50BBxFZw1/4wQbv0WEhOIbl/Z4ggxNRR VoyXGMqOIZFlGQ7bGxDawuEwGKfcOFFEHj3rhPrs7RPnod/6X8Vxm0rAr2GNZoOW 9tLMQKe4HLo3kVwX65AhzWd/WMukAd0MC/0oaULOjiAEdlWjflyEhx9H9uYefl5x kn77ZqQqIEL4aCYRBLJn9oJV3CIZbSd6cuKC9UPuXAwD8XDWTXUzT/aDMJUnfij7 vhS1qks1Wyk37wIjTuuERwrr0K6y8e3De30NeU6LqQuzXvJ1MYSp49BA1FCgHfmT x5RWbTSjLdjZiIo7biE2dSwdOtsxsnuxX19utqfGqOmegNU7LykRtu6mFh9kJhNe 5ladt1Mu//puZLQ/q4RH/J0pwkuS/OVrS3LBobcggPGHhUIiHhdNUI73bb7BK0+9 ME5DGLm4/c/REB3Lidr9 =kkU0 -----END PGP SIGNATURE----- Merge remote-tracking branch 'kwolf/tags/for-upstream' into staging Block layer patches # gpg: Signature made Mon 29 May 2017 03:34:59 PM BST # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * kwolf/tags/for-upstream: block/file-*: *_parse_filename() and colons block: Fix backing paths for filenames with colons block: Tweak error message related to qemu-img amend qemu-img: Fix leakage of options on error qemu-img: copy *key-secret opts when opening newly created files qemu-img: introduce --target-image-opts for 'convert' command qemu-img: fix --image-opts usage with dd command qemu-img: add support for --object with 'dd' command qemu-img: Fix documentation of convert qcow2: remove extra local_error variable mirror: Drop permissions on s->target on completion nvme: Add support for Controller Memory Buffers iotests: 147: Don't test inet6 if not available qemu-iotests: Test streaming with missing job ID stream: fix crash in stream_start() when block_job_create() fails Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
		
						commit
						0748b3526e
					
				
							
								
								
									
										50
									
								
								block.c
								
								
								
								
							
							
						
						
									
										50
									
								
								block.c
								
								
								
								
							| 
						 | 
				
			
			@ -163,11 +163,16 @@ void path_combine(char *dest, int dest_size,
 | 
			
		|||
    if (path_is_absolute(filename)) {
 | 
			
		||||
        pstrcpy(dest, dest_size, filename);
 | 
			
		||||
    } else {
 | 
			
		||||
        p = strchr(base_path, ':');
 | 
			
		||||
        if (p)
 | 
			
		||||
            p++;
 | 
			
		||||
        else
 | 
			
		||||
            p = base_path;
 | 
			
		||||
        const char *protocol_stripped = NULL;
 | 
			
		||||
 | 
			
		||||
        if (path_has_protocol(base_path)) {
 | 
			
		||||
            protocol_stripped = strchr(base_path, ':');
 | 
			
		||||
            if (protocol_stripped) {
 | 
			
		||||
                protocol_stripped++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        p = protocol_stripped ?: base_path;
 | 
			
		||||
 | 
			
		||||
        p1 = strrchr(base_path, '/');
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -192,6 +197,41 @@ void path_combine(char *dest, int dest_size,
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Helper function for bdrv_parse_filename() implementations to remove optional
 | 
			
		||||
 * protocol prefixes (especially "file:") from a filename and for putting the
 | 
			
		||||
 * stripped filename into the options QDict if there is such a prefix.
 | 
			
		||||
 */
 | 
			
		||||
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
 | 
			
		||||
                                      QDict *options)
 | 
			
		||||
{
 | 
			
		||||
    if (strstart(filename, prefix, &filename)) {
 | 
			
		||||
        /* Stripping the explicit protocol prefix may result in a protocol
 | 
			
		||||
         * prefix being (wrongly) detected (if the filename contains a colon) */
 | 
			
		||||
        if (path_has_protocol(filename)) {
 | 
			
		||||
            QString *fat_filename;
 | 
			
		||||
 | 
			
		||||
            /* This means there is some colon before the first slash; therefore,
 | 
			
		||||
             * this cannot be an absolute path */
 | 
			
		||||
            assert(!path_is_absolute(filename));
 | 
			
		||||
 | 
			
		||||
            /* And we can thus fix the protocol detection issue by prefixing it
 | 
			
		||||
             * by "./" */
 | 
			
		||||
            fat_filename = qstring_from_str("./");
 | 
			
		||||
            qstring_append(fat_filename, filename);
 | 
			
		||||
 | 
			
		||||
            assert(!path_has_protocol(qstring_get_str(fat_filename)));
 | 
			
		||||
 | 
			
		||||
            qdict_put(options, "filename", fat_filename);
 | 
			
		||||
        } else {
 | 
			
		||||
            /* If no protocol prefix was detected, we can use the shortened
 | 
			
		||||
             * filename as-is */
 | 
			
		||||
            qdict_put_str(options, "filename", filename);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Returns whether the image file is opened as read-only. Note that this can
 | 
			
		||||
 * return false and writing to the image file is still not possible because the
 | 
			
		||||
 * image is inactivated. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -381,12 +381,7 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
 | 
			
		|||
static void raw_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                               Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The filename does not have to be prefixed by the protocol name, since
 | 
			
		||||
     * "file" is the default protocol; therefore, the return value of this
 | 
			
		||||
     * function call can be ignored. */
 | 
			
		||||
    strstart(filename, "file:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_str(options, "filename", filename);
 | 
			
		||||
    bdrv_parse_filename_strip_prefix(filename, "file:", options);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QemuOptsList raw_runtime_opts = {
 | 
			
		||||
| 
						 | 
				
			
			@ -2395,10 +2390,7 @@ static int check_hdev_writable(BDRVRawState *s)
 | 
			
		|||
static void hdev_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                                Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The prefix is optional, just as for "file". */
 | 
			
		||||
    strstart(filename, "host_device:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_str(options, "filename", filename);
 | 
			
		||||
    bdrv_parse_filename_strip_prefix(filename, "host_device:", options);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool hdev_is_sg(BlockDriverState *bs)
 | 
			
		||||
| 
						 | 
				
			
			@ -2697,10 +2689,7 @@ static BlockDriver bdrv_host_device = {
 | 
			
		|||
static void cdrom_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                                 Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The prefix is optional, just as for "file". */
 | 
			
		||||
    strstart(filename, "host_cdrom:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_str(options, "filename", filename);
 | 
			
		||||
    bdrv_parse_filename_strip_prefix(filename, "host_cdrom:", options);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,12 +276,7 @@ static void raw_parse_flags(int flags, bool use_aio, int *access_flags,
 | 
			
		|||
static void raw_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                               Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The filename does not have to be prefixed by the protocol name, since
 | 
			
		||||
     * "file" is the default protocol; therefore, the return value of this
 | 
			
		||||
     * function call can be ignored. */
 | 
			
		||||
    strstart(filename, "file:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_str(options, "filename", filename);
 | 
			
		||||
    bdrv_parse_filename_strip_prefix(filename, "file:", options);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QemuOptsList raw_runtime_opts = {
 | 
			
		||||
| 
						 | 
				
			
			@ -671,10 +666,7 @@ static int hdev_probe_device(const char *filename)
 | 
			
		|||
static void hdev_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                                Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The prefix is optional, just as for "file". */
 | 
			
		||||
    strstart(filename, "host_device:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_str(options, "filename", filename);
 | 
			
		||||
    bdrv_parse_filename_strip_prefix(filename, "host_device:", options);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -514,7 +514,12 @@ static void mirror_exit(BlockJob *job, void *opaque)
 | 
			
		|||
 | 
			
		||||
    /* Remove target parent that still uses BLK_PERM_WRITE/RESIZE before
 | 
			
		||||
     * inserting target_bs at s->to_replace, where we might not be able to get
 | 
			
		||||
     * these permissions. */
 | 
			
		||||
     * these permissions.
 | 
			
		||||
     *
 | 
			
		||||
     * Note that blk_unref() alone doesn't necessarily drop permissions because
 | 
			
		||||
     * we might be running nested inside mirror_drain(), which takes an extra
 | 
			
		||||
     * reference, so use an explicit blk_set_perm() first. */
 | 
			
		||||
    blk_set_perm(s->target, 0, BLK_PERM_ALL, &error_abort);
 | 
			
		||||
    blk_unref(s->target);
 | 
			
		||||
    s->target = NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1797,7 +1797,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            if (offset_into_cluster(s, offset)) {
 | 
			
		||||
                qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset "
 | 
			
		||||
                qcow2_signal_corruption(bs, true, -1, -1,
 | 
			
		||||
                                        "Cluster allocation offset "
 | 
			
		||||
                                        "%#" PRIx64 " unaligned (L2 offset: %#"
 | 
			
		||||
                                        PRIx64 ", L2 index: %#x)", offset,
 | 
			
		||||
                                        l2_offset, j);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3222,7 +3222,6 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
 | 
			
		|||
 | 
			
		||||
    if (s->refcount_bits != refcount_bits) {
 | 
			
		||||
        int refcount_order = ctz32(refcount_bits);
 | 
			
		||||
        Error *local_error = NULL;
 | 
			
		||||
 | 
			
		||||
        if (new_version < 3 && refcount_bits != 16) {
 | 
			
		||||
            error_report("Different refcount widths than 16 bits require "
 | 
			
		||||
| 
						 | 
				
			
			@ -3234,9 +3233,9 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
 | 
			
		|||
        helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER;
 | 
			
		||||
        ret = qcow2_change_refcount_order(bs, refcount_order,
 | 
			
		||||
                                          &qcow2_amend_helper_cb,
 | 
			
		||||
                                          &helper_cb_info, &local_error);
 | 
			
		||||
                                          &helper_cb_info, &local_err);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            error_report_err(local_error);
 | 
			
		||||
            error_report_err(local_err);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -280,6 +280,6 @@ void stream_start(const char *job_id, BlockDriverState *bs,
 | 
			
		|||
 | 
			
		||||
fail:
 | 
			
		||||
    if (orig_bs_flags != bdrv_get_flags(bs)) {
 | 
			
		||||
        bdrv_reopen(bs, s->bs_flags, NULL);
 | 
			
		||||
        bdrv_reopen(bs, orig_bs_flags, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reference Specs: http://www.nvmexpress.org, 1.1, 1.0e
 | 
			
		||||
 * Reference Specs: http://www.nvmexpress.org, 1.2, 1.1, 1.0e
 | 
			
		||||
 *
 | 
			
		||||
 *  http://www.nvmexpress.org/resources/
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,11 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Usage: add options:
 | 
			
		||||
 *      -drive file=<file>,if=none,id=<drive_id>
 | 
			
		||||
 *      -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>
 | 
			
		||||
 *      -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
 | 
			
		||||
 *              cmb_size_mb=<cmb_size_mb[optional]>
 | 
			
		||||
 *
 | 
			
		||||
 * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
 | 
			
		||||
 * offset 0 in BAR2 and supports SQS only for now.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +38,16 @@
 | 
			
		|||
 | 
			
		||||
static void nvme_process_sq(void *opaque);
 | 
			
		||||
 | 
			
		||||
static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
 | 
			
		||||
{
 | 
			
		||||
    if (n->cmbsz && addr >= n->ctrl_mem.addr &&
 | 
			
		||||
                addr < (n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size))) {
 | 
			
		||||
        memcpy(buf, (void *)&n->cmbuf[addr - n->ctrl_mem.addr], size);
 | 
			
		||||
    } else {
 | 
			
		||||
        pci_dma_read(&n->parent_obj, addr, buf, size);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nvme_check_sqid(NvmeCtrl *n, uint16_t sqid)
 | 
			
		||||
{
 | 
			
		||||
    return sqid < n->num_queues && n->sq[sqid] != NULL ? 0 : -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -637,7 +651,7 @@ static void nvme_process_sq(void *opaque)
 | 
			
		|||
 | 
			
		||||
    while (!(nvme_sq_empty(sq) || QTAILQ_EMPTY(&sq->req_list))) {
 | 
			
		||||
        addr = sq->dma_addr + sq->head * n->sqe_size;
 | 
			
		||||
        pci_dma_read(&n->parent_obj, addr, (void *)&cmd, sizeof(cmd));
 | 
			
		||||
        nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd));
 | 
			
		||||
        nvme_inc_sq_head(sq);
 | 
			
		||||
 | 
			
		||||
        req = QTAILQ_FIRST(&sq->req_list);
 | 
			
		||||
| 
						 | 
				
			
			@ -852,6 +866,32 @@ static const MemoryRegionOps nvme_mmio_ops = {
 | 
			
		|||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data,
 | 
			
		||||
    unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    NvmeCtrl *n = (NvmeCtrl *)opaque;
 | 
			
		||||
    memcpy(&n->cmbuf[addr], &data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t val;
 | 
			
		||||
    NvmeCtrl *n = (NvmeCtrl *)opaque;
 | 
			
		||||
 | 
			
		||||
    memcpy(&val, &n->cmbuf[addr], size);
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const MemoryRegionOps nvme_cmb_ops = {
 | 
			
		||||
    .read = nvme_cmb_read,
 | 
			
		||||
    .write = nvme_cmb_write,
 | 
			
		||||
    .endianness = DEVICE_LITTLE_ENDIAN,
 | 
			
		||||
    .impl = {
 | 
			
		||||
        .min_access_size = 2,
 | 
			
		||||
        .max_access_size = 8,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int nvme_init(PCIDevice *pci_dev)
 | 
			
		||||
{
 | 
			
		||||
    NvmeCtrl *n = NVME(pci_dev);
 | 
			
		||||
| 
						 | 
				
			
			@ -936,9 +976,31 @@ static int nvme_init(PCIDevice *pci_dev)
 | 
			
		|||
    NVME_CAP_SET_CSS(n->bar.cap, 1);
 | 
			
		||||
    NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
 | 
			
		||||
 | 
			
		||||
    n->bar.vs = 0x00010100;
 | 
			
		||||
    n->bar.vs = 0x00010200;
 | 
			
		||||
    n->bar.intmc = n->bar.intms = 0;
 | 
			
		||||
 | 
			
		||||
    if (n->cmb_size_mb) {
 | 
			
		||||
 | 
			
		||||
        NVME_CMBLOC_SET_BIR(n->bar.cmbloc, 2);
 | 
			
		||||
        NVME_CMBLOC_SET_OFST(n->bar.cmbloc, 0);
 | 
			
		||||
 | 
			
		||||
        NVME_CMBSZ_SET_SQS(n->bar.cmbsz, 1);
 | 
			
		||||
        NVME_CMBSZ_SET_CQS(n->bar.cmbsz, 0);
 | 
			
		||||
        NVME_CMBSZ_SET_LISTS(n->bar.cmbsz, 0);
 | 
			
		||||
        NVME_CMBSZ_SET_RDS(n->bar.cmbsz, 0);
 | 
			
		||||
        NVME_CMBSZ_SET_WDS(n->bar.cmbsz, 0);
 | 
			
		||||
        NVME_CMBSZ_SET_SZU(n->bar.cmbsz, 2); /* MBs */
 | 
			
		||||
        NVME_CMBSZ_SET_SZ(n->bar.cmbsz, n->cmb_size_mb);
 | 
			
		||||
 | 
			
		||||
        n->cmbuf = g_malloc0(NVME_CMBSZ_GETSIZE(n->bar.cmbsz));
 | 
			
		||||
        memory_region_init_io(&n->ctrl_mem, OBJECT(n), &nvme_cmb_ops, n,
 | 
			
		||||
                              "nvme-cmb", NVME_CMBSZ_GETSIZE(n->bar.cmbsz));
 | 
			
		||||
        pci_register_bar(&n->parent_obj, NVME_CMBLOC_BIR(n->bar.cmbloc),
 | 
			
		||||
            PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
 | 
			
		||||
            PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < n->num_namespaces; i++) {
 | 
			
		||||
        NvmeNamespace *ns = &n->namespaces[i];
 | 
			
		||||
        NvmeIdNs *id_ns = &ns->id_ns;
 | 
			
		||||
| 
						 | 
				
			
			@ -964,12 +1026,17 @@ static void nvme_exit(PCIDevice *pci_dev)
 | 
			
		|||
    g_free(n->namespaces);
 | 
			
		||||
    g_free(n->cq);
 | 
			
		||||
    g_free(n->sq);
 | 
			
		||||
    if (n->cmbsz) {
 | 
			
		||||
        memory_region_unref(&n->ctrl_mem);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    msix_uninit_exclusive_bar(pci_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property nvme_props[] = {
 | 
			
		||||
    DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
 | 
			
		||||
    DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
 | 
			
		||||
    DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ typedef struct NvmeBar {
 | 
			
		|||
    uint32_t    aqa;
 | 
			
		||||
    uint64_t    asq;
 | 
			
		||||
    uint64_t    acq;
 | 
			
		||||
    uint32_t    cmbloc;
 | 
			
		||||
    uint32_t    cmbsz;
 | 
			
		||||
} NvmeBar;
 | 
			
		||||
 | 
			
		||||
enum NvmeCapShift {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,6 +140,72 @@ enum NvmeAqaMask {
 | 
			
		|||
#define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK)
 | 
			
		||||
#define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK)
 | 
			
		||||
 | 
			
		||||
enum NvmeCmblocShift {
 | 
			
		||||
    CMBLOC_BIR_SHIFT  = 0,
 | 
			
		||||
    CMBLOC_OFST_SHIFT = 12,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum NvmeCmblocMask {
 | 
			
		||||
    CMBLOC_BIR_MASK  = 0x7,
 | 
			
		||||
    CMBLOC_OFST_MASK = 0xfffff,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define NVME_CMBLOC_BIR(cmbloc) ((cmbloc >> CMBLOC_BIR_SHIFT)  & \
 | 
			
		||||
                                 CMBLOC_BIR_MASK)
 | 
			
		||||
#define NVME_CMBLOC_OFST(cmbloc)((cmbloc >> CMBLOC_OFST_SHIFT) & \
 | 
			
		||||
                                 CMBLOC_OFST_MASK)
 | 
			
		||||
 | 
			
		||||
#define NVME_CMBLOC_SET_BIR(cmbloc, val)  \
 | 
			
		||||
    (cmbloc |= (uint64_t)(val & CMBLOC_BIR_MASK) << CMBLOC_BIR_SHIFT)
 | 
			
		||||
#define NVME_CMBLOC_SET_OFST(cmbloc, val) \
 | 
			
		||||
    (cmbloc |= (uint64_t)(val & CMBLOC_OFST_MASK) << CMBLOC_OFST_SHIFT)
 | 
			
		||||
 | 
			
		||||
enum NvmeCmbszShift {
 | 
			
		||||
    CMBSZ_SQS_SHIFT   = 0,
 | 
			
		||||
    CMBSZ_CQS_SHIFT   = 1,
 | 
			
		||||
    CMBSZ_LISTS_SHIFT = 2,
 | 
			
		||||
    CMBSZ_RDS_SHIFT   = 3,
 | 
			
		||||
    CMBSZ_WDS_SHIFT   = 4,
 | 
			
		||||
    CMBSZ_SZU_SHIFT   = 8,
 | 
			
		||||
    CMBSZ_SZ_SHIFT    = 12,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum NvmeCmbszMask {
 | 
			
		||||
    CMBSZ_SQS_MASK   = 0x1,
 | 
			
		||||
    CMBSZ_CQS_MASK   = 0x1,
 | 
			
		||||
    CMBSZ_LISTS_MASK = 0x1,
 | 
			
		||||
    CMBSZ_RDS_MASK   = 0x1,
 | 
			
		||||
    CMBSZ_WDS_MASK   = 0x1,
 | 
			
		||||
    CMBSZ_SZU_MASK   = 0xf,
 | 
			
		||||
    CMBSZ_SZ_MASK    = 0xfffff,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define NVME_CMBSZ_SQS(cmbsz)  ((cmbsz >> CMBSZ_SQS_SHIFT)   & CMBSZ_SQS_MASK)
 | 
			
		||||
#define NVME_CMBSZ_CQS(cmbsz)  ((cmbsz >> CMBSZ_CQS_SHIFT)   & CMBSZ_CQS_MASK)
 | 
			
		||||
#define NVME_CMBSZ_LISTS(cmbsz)((cmbsz >> CMBSZ_LISTS_SHIFT) & CMBSZ_LISTS_MASK)
 | 
			
		||||
#define NVME_CMBSZ_RDS(cmbsz)  ((cmbsz >> CMBSZ_RDS_SHIFT)   & CMBSZ_RDS_MASK)
 | 
			
		||||
#define NVME_CMBSZ_WDS(cmbsz)  ((cmbsz >> CMBSZ_WDS_SHIFT)   & CMBSZ_WDS_MASK)
 | 
			
		||||
#define NVME_CMBSZ_SZU(cmbsz)  ((cmbsz >> CMBSZ_SZU_SHIFT)   & CMBSZ_SZU_MASK)
 | 
			
		||||
#define NVME_CMBSZ_SZ(cmbsz)   ((cmbsz >> CMBSZ_SZ_SHIFT)    & CMBSZ_SZ_MASK)
 | 
			
		||||
 | 
			
		||||
#define NVME_CMBSZ_SET_SQS(cmbsz, val)   \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val &  CMBSZ_SQS_MASK)  << CMBSZ_SQS_SHIFT)
 | 
			
		||||
#define NVME_CMBSZ_SET_CQS(cmbsz, val)   \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val & CMBSZ_CQS_MASK) << CMBSZ_CQS_SHIFT)
 | 
			
		||||
#define NVME_CMBSZ_SET_LISTS(cmbsz, val) \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val & CMBSZ_LISTS_MASK) << CMBSZ_LISTS_SHIFT)
 | 
			
		||||
#define NVME_CMBSZ_SET_RDS(cmbsz, val)   \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val & CMBSZ_RDS_MASK) << CMBSZ_RDS_SHIFT)
 | 
			
		||||
#define NVME_CMBSZ_SET_WDS(cmbsz, val)   \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val & CMBSZ_WDS_MASK) << CMBSZ_WDS_SHIFT)
 | 
			
		||||
#define NVME_CMBSZ_SET_SZU(cmbsz, val)   \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val & CMBSZ_SZU_MASK) << CMBSZ_SZU_SHIFT)
 | 
			
		||||
#define NVME_CMBSZ_SET_SZ(cmbsz, val)    \
 | 
			
		||||
    (cmbsz |= (uint64_t)(val & CMBSZ_SZ_MASK) << CMBSZ_SZ_SHIFT)
 | 
			
		||||
 | 
			
		||||
#define NVME_CMBSZ_GETSIZE(cmbsz) \
 | 
			
		||||
    (NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
 | 
			
		||||
 | 
			
		||||
typedef struct NvmeCmd {
 | 
			
		||||
    uint8_t     opcode;
 | 
			
		||||
    uint8_t     fuse;
 | 
			
		||||
| 
						 | 
				
			
			@ -688,6 +756,7 @@ typedef struct NvmeNamespace {
 | 
			
		|||
typedef struct NvmeCtrl {
 | 
			
		||||
    PCIDevice    parent_obj;
 | 
			
		||||
    MemoryRegion iomem;
 | 
			
		||||
    MemoryRegion ctrl_mem;
 | 
			
		||||
    NvmeBar      bar;
 | 
			
		||||
    BlockConf    conf;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -701,6 +770,10 @@ typedef struct NvmeCtrl {
 | 
			
		|||
    uint32_t    num_queues;
 | 
			
		||||
    uint32_t    max_q_ents;
 | 
			
		||||
    uint64_t    ns_size;
 | 
			
		||||
    uint32_t    cmb_size_mb;
 | 
			
		||||
    uint32_t    cmbsz;
 | 
			
		||||
    uint32_t    cmbloc;
 | 
			
		||||
    uint8_t     *cmbuf;
 | 
			
		||||
 | 
			
		||||
    char            *serial;
 | 
			
		||||
    NvmeNamespace   *namespaces;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -682,6 +682,9 @@ int get_tmp_filename(char *filename, int size);
 | 
			
		|||
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
 | 
			
		||||
                            const char *filename);
 | 
			
		||||
 | 
			
		||||
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
 | 
			
		||||
                                      QDict *options);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bdrv_add_before_write_notifier:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,9 +40,9 @@ STEXI
 | 
			
		|||
ETEXI
 | 
			
		||||
 | 
			
		||||
DEF("convert", img_convert,
 | 
			
		||||
    "convert [--object objectdef] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
 | 
			
		||||
    "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
 | 
			
		||||
STEXI
 | 
			
		||||
@item convert [--object @var{objectdef}] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
 | 
			
		||||
@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
 | 
			
		||||
ETEXI
 | 
			
		||||
 | 
			
		||||
DEF("dd", img_dd,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										150
									
								
								qemu-img.c
								
								
								
								
							
							
						
						
									
										150
									
								
								qemu-img.c
								
								
								
								
							| 
						 | 
				
			
			@ -60,6 +60,7 @@ enum {
 | 
			
		|||
    OPTION_PATTERN = 260,
 | 
			
		||||
    OPTION_FLUSH_INTERVAL = 261,
 | 
			
		||||
    OPTION_NO_DRAIN = 262,
 | 
			
		||||
    OPTION_TARGET_IMAGE_OPTS = 263,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum OutputFormat {
 | 
			
		||||
| 
						 | 
				
			
			@ -294,6 +295,7 @@ static BlockBackend *img_open_opts(const char *optstr,
 | 
			
		|||
        if (qdict_haskey(options, BDRV_OPT_FORCE_SHARE)
 | 
			
		||||
            && !qdict_get_bool(options, BDRV_OPT_FORCE_SHARE)) {
 | 
			
		||||
            error_report("--force-share/-U conflicts with image options");
 | 
			
		||||
            QDECREF(options);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
        qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -313,14 +315,17 @@ static BlockBackend *img_open_opts(const char *optstr,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static BlockBackend *img_open_file(const char *filename,
 | 
			
		||||
                                   QDict *options,
 | 
			
		||||
                                   const char *fmt, int flags,
 | 
			
		||||
                                   bool writethrough, bool quiet,
 | 
			
		||||
                                   bool force_share)
 | 
			
		||||
{
 | 
			
		||||
    BlockBackend *blk;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
    QDict *options = qdict_new();
 | 
			
		||||
 | 
			
		||||
    if (!options) {
 | 
			
		||||
        options = qdict_new();
 | 
			
		||||
    }
 | 
			
		||||
    if (fmt) {
 | 
			
		||||
        qdict_put_str(options, "driver", fmt);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -343,6 +348,35 @@ static BlockBackend *img_open_file(const char *filename,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int img_add_key_secrets(void *opaque,
 | 
			
		||||
                               const char *name, const char *value,
 | 
			
		||||
                               Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    QDict *options = opaque;
 | 
			
		||||
 | 
			
		||||
    if (g_str_has_suffix(name, "key-secret")) {
 | 
			
		||||
        qdict_put(options, name, qstring_from_str(value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BlockBackend *img_open_new_file(const char *filename,
 | 
			
		||||
                                       QemuOpts *create_opts,
 | 
			
		||||
                                       const char *fmt, int flags,
 | 
			
		||||
                                       bool writethrough, bool quiet,
 | 
			
		||||
                                       bool force_share)
 | 
			
		||||
{
 | 
			
		||||
    QDict *options = NULL;
 | 
			
		||||
 | 
			
		||||
    options = qdict_new();
 | 
			
		||||
    qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort);
 | 
			
		||||
 | 
			
		||||
    return img_open_file(filename, options, fmt, flags, writethrough, quiet,
 | 
			
		||||
                         force_share);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static BlockBackend *img_open(bool image_opts,
 | 
			
		||||
                              const char *filename,
 | 
			
		||||
                              const char *fmt, int flags, bool writethrough,
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +397,7 @@ static BlockBackend *img_open(bool image_opts,
 | 
			
		|||
        blk = img_open_opts(filename, opts, flags, writethrough, quiet,
 | 
			
		||||
                            force_share);
 | 
			
		||||
    } else {
 | 
			
		||||
        blk = img_open_file(filename, fmt, flags, writethrough, quiet,
 | 
			
		||||
        blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet,
 | 
			
		||||
                            force_share);
 | 
			
		||||
    }
 | 
			
		||||
    return blk;
 | 
			
		||||
| 
						 | 
				
			
			@ -1913,10 +1947,10 @@ static int convert_do_copy(ImgConvertState *s)
 | 
			
		|||
static int img_convert(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    int c, bs_i, flags, src_flags = 0;
 | 
			
		||||
    const char *fmt = NULL, *out_fmt = "raw", *cache = "unsafe",
 | 
			
		||||
    const char *fmt = NULL, *out_fmt = NULL, *cache = "unsafe",
 | 
			
		||||
               *src_cache = BDRV_DEFAULT_CACHE, *out_baseimg = NULL,
 | 
			
		||||
               *out_filename, *out_baseimg_param, *snapshot_name = NULL;
 | 
			
		||||
    BlockDriver *drv, *proto_drv;
 | 
			
		||||
    BlockDriver *drv = NULL, *proto_drv = NULL;
 | 
			
		||||
    BlockDriverInfo bdi;
 | 
			
		||||
    BlockDriverState *out_bs;
 | 
			
		||||
    QemuOpts *opts = NULL, *sn_opts = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1924,7 +1958,7 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
    char *options = NULL;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
    bool writethrough, src_writethrough, quiet = false, image_opts = false,
 | 
			
		||||
         skip_create = false, progress = false;
 | 
			
		||||
         skip_create = false, progress = false, tgt_image_opts = false;
 | 
			
		||||
    int64_t ret = -EINVAL;
 | 
			
		||||
    bool force_share = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1942,6 +1976,7 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
            {"object", required_argument, 0, OPTION_OBJECT},
 | 
			
		||||
            {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
 | 
			
		||||
            {"force-share", no_argument, 0, 'U'},
 | 
			
		||||
            {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
 | 
			
		||||
            {0, 0, 0, 0}
 | 
			
		||||
        };
 | 
			
		||||
        c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:WU",
 | 
			
		||||
| 
						 | 
				
			
			@ -2062,9 +2097,16 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
        case OPTION_IMAGE_OPTS:
 | 
			
		||||
            image_opts = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case OPTION_TARGET_IMAGE_OPTS:
 | 
			
		||||
            tgt_image_opts = true;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!out_fmt && !tgt_image_opts) {
 | 
			
		||||
        out_fmt = "raw";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (qemu_opts_foreach(&qemu_object_opts,
 | 
			
		||||
                          user_creatable_add_opts_foreach,
 | 
			
		||||
                          NULL, NULL)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2076,12 +2118,22 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
        goto fail_getopt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tgt_image_opts && !skip_create) {
 | 
			
		||||
        error_report("--target-image-opts requires use of -n flag");
 | 
			
		||||
        goto fail_getopt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s.src_num = argc - optind - 1;
 | 
			
		||||
    out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL;
 | 
			
		||||
 | 
			
		||||
    if (options && has_help_option(options)) {
 | 
			
		||||
        ret = print_block_option_help(out_filename, out_fmt);
 | 
			
		||||
        goto fail_getopt;
 | 
			
		||||
        if (out_fmt) {
 | 
			
		||||
            ret = print_block_option_help(out_filename, out_fmt);
 | 
			
		||||
            goto fail_getopt;
 | 
			
		||||
        } else {
 | 
			
		||||
            error_report("Option help requires a format be specified");
 | 
			
		||||
            goto fail_getopt;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s.src_num < 1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2146,22 +2198,22 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Find driver and parse its options */
 | 
			
		||||
    drv = bdrv_find_format(out_fmt);
 | 
			
		||||
    if (!drv) {
 | 
			
		||||
        error_report("Unknown file format '%s'", out_fmt);
 | 
			
		||||
        ret = -1;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
 | 
			
		||||
    if (!proto_drv) {
 | 
			
		||||
        error_report_err(local_err);
 | 
			
		||||
        ret = -1;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!skip_create) {
 | 
			
		||||
        /* Find driver and parse its options */
 | 
			
		||||
        drv = bdrv_find_format(out_fmt);
 | 
			
		||||
        if (!drv) {
 | 
			
		||||
            error_report("Unknown file format '%s'", out_fmt);
 | 
			
		||||
            ret = -1;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
 | 
			
		||||
        if (!proto_drv) {
 | 
			
		||||
            error_report_err(local_err);
 | 
			
		||||
            ret = -1;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!drv->create_opts) {
 | 
			
		||||
            error_report("Format driver '%s' does not support image creation",
 | 
			
		||||
                         drv->format_name);
 | 
			
		||||
| 
						 | 
				
			
			@ -2218,7 +2270,7 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
        const char *preallocation =
 | 
			
		||||
            qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
 | 
			
		||||
 | 
			
		||||
        if (!drv->bdrv_co_pwritev_compressed) {
 | 
			
		||||
        if (drv && !drv->bdrv_co_pwritev_compressed) {
 | 
			
		||||
            error_report("Compression not supported for this file format");
 | 
			
		||||
            ret = -1;
 | 
			
		||||
            goto out;
 | 
			
		||||
| 
						 | 
				
			
			@ -2258,19 +2310,30 @@ static int img_convert(int argc, char **argv)
 | 
			
		|||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* XXX we should allow --image-opts to trigger use of
 | 
			
		||||
     * img_open() here, but then we have trouble with
 | 
			
		||||
     * the bdrv_create() call which takes different params.
 | 
			
		||||
     * Not critical right now, so fix can wait...
 | 
			
		||||
     */
 | 
			
		||||
    s.target = img_open_file(out_filename, out_fmt, flags, writethrough, quiet,
 | 
			
		||||
                             false);
 | 
			
		||||
    if (skip_create) {
 | 
			
		||||
        s.target = img_open(tgt_image_opts, out_filename, out_fmt,
 | 
			
		||||
                            flags, writethrough, quiet, false);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* TODO ultimately we should allow --target-image-opts
 | 
			
		||||
         * to be used even when -n is not given.
 | 
			
		||||
         * That has to wait for bdrv_create to be improved
 | 
			
		||||
         * to allow filenames in option syntax
 | 
			
		||||
         */
 | 
			
		||||
        s.target = img_open_new_file(out_filename, opts, out_fmt,
 | 
			
		||||
                                     flags, writethrough, quiet, false);
 | 
			
		||||
    }
 | 
			
		||||
    if (!s.target) {
 | 
			
		||||
        ret = -1;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    out_bs = blk_bs(s.target);
 | 
			
		||||
 | 
			
		||||
    if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) {
 | 
			
		||||
        error_report("Compression not supported for this file format");
 | 
			
		||||
        ret = -1;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* increase bufsectors from the default 4096 (2M) if opt_transfer
 | 
			
		||||
     * or discard_alignment of the out_bs is greater. Limit to 32768 (16MB)
 | 
			
		||||
     * as maximum. */
 | 
			
		||||
| 
						 | 
				
			
			@ -4157,6 +4220,7 @@ static int img_dd(int argc, char **argv)
 | 
			
		|||
    };
 | 
			
		||||
    const struct option long_options[] = {
 | 
			
		||||
        { "help", no_argument, 0, 'h'},
 | 
			
		||||
        { "object", required_argument, 0, OPTION_OBJECT},
 | 
			
		||||
        { "image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
 | 
			
		||||
        { "force-share", no_argument, 0, 'U'},
 | 
			
		||||
        { 0, 0, 0, 0 }
 | 
			
		||||
| 
						 | 
				
			
			@ -4185,6 +4249,15 @@ static int img_dd(int argc, char **argv)
 | 
			
		|||
        case 'U':
 | 
			
		||||
            force_share = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case OPTION_OBJECT: {
 | 
			
		||||
            QemuOpts *opts;
 | 
			
		||||
            opts = qemu_opts_parse_noisily(&qemu_object_opts,
 | 
			
		||||
                                           optarg, true);
 | 
			
		||||
            if (!opts) {
 | 
			
		||||
                ret = -1;
 | 
			
		||||
                goto out;
 | 
			
		||||
            }
 | 
			
		||||
        }   break;
 | 
			
		||||
        case OPTION_IMAGE_OPTS:
 | 
			
		||||
            image_opts = true;
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -4229,6 +4302,14 @@ static int img_dd(int argc, char **argv)
 | 
			
		|||
        ret = -1;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (qemu_opts_foreach(&qemu_object_opts,
 | 
			
		||||
                          user_creatable_add_opts_foreach,
 | 
			
		||||
                          NULL, NULL)) {
 | 
			
		||||
        ret = -1;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
 | 
			
		||||
                    force_share);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4297,8 +4378,13 @@ static int img_dd(int argc, char **argv)
 | 
			
		|||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR,
 | 
			
		||||
                    false, false, false);
 | 
			
		||||
    /* TODO, we can't honour --image-opts for the target,
 | 
			
		||||
     * since it needs to be given in a format compatible
 | 
			
		||||
     * with the bdrv_create() call above which does not
 | 
			
		||||
     * support image-opts style.
 | 
			
		||||
     */
 | 
			
		||||
    blk2 = img_open_file(out.filename, NULL, out_fmt, BDRV_O_RDWR,
 | 
			
		||||
                         false, false, false);
 | 
			
		||||
 | 
			
		||||
    if (!blk2) {
 | 
			
		||||
        ret = -1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,9 +45,17 @@ keys.
 | 
			
		|||
 | 
			
		||||
@item --image-opts
 | 
			
		||||
 | 
			
		||||
Indicates that the @var{filename} parameter is to be interpreted as a
 | 
			
		||||
Indicates that the source @var{filename} parameter is to be interpreted as a
 | 
			
		||||
full option string, not a plain filename. This parameter is mutually
 | 
			
		||||
exclusive with the @var{-f} and @var{-F} parameters.
 | 
			
		||||
exclusive with the @var{-f} parameter.
 | 
			
		||||
 | 
			
		||||
@item --target-image-opts
 | 
			
		||||
 | 
			
		||||
Indicates that the @var{output_filename} parameter(s) are to be interpreted as
 | 
			
		||||
a full option string, not a plain filename. This parameter is mutually
 | 
			
		||||
exclusive with the @var{-O} parameters. It is currently required to also use
 | 
			
		||||
the @var{-n} parameter to skip image creation. This restriction may be relaxed
 | 
			
		||||
in a future release.
 | 
			
		||||
 | 
			
		||||
@item fmt
 | 
			
		||||
is the disk image format. It is guessed automatically in most cases. See below
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -147,6 +147,10 @@ class TestSingleDrive(iotests.QMPTestCase):
 | 
			
		|||
        result = self.vm.qmp('block-stream', device='nonexistent')
 | 
			
		||||
        self.assert_qmp(result, 'error/class', 'GenericError')
 | 
			
		||||
 | 
			
		||||
    def test_job_id_missing(self):
 | 
			
		||||
        result = self.vm.qmp('block-stream', device='mid')
 | 
			
		||||
        self.assert_qmp(result, 'error/class', 'GenericError')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestParallelOps(iotests.QMPTestCase):
 | 
			
		||||
    num_ops = 4 # Number of parallel block-stream operations
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
......................
 | 
			
		||||
.......................
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
Ran 22 tests
 | 
			
		||||
Ran 23 tests
 | 
			
		||||
 | 
			
		||||
OK
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -143,7 +143,7 @@ read failed: Input/output error
 | 
			
		|||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 | 
			
		||||
wrote 65536/65536 bytes at offset 0
 | 
			
		||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | 
			
		||||
qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
 | 
			
		||||
qcow2: Marking image as corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
 | 
			
		||||
qemu-img: Error while amending options: Input/output error
 | 
			
		||||
 | 
			
		||||
=== Testing unaligned reftable entry ===
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -147,6 +147,13 @@ class BuiltinNBD(NBDBlockdevAddBase):
 | 
			
		|||
        self._server_down()
 | 
			
		||||
 | 
			
		||||
    def test_inet6(self):
 | 
			
		||||
        try:
 | 
			
		||||
            socket.getaddrinfo("::0", "0", socket.AF_INET6,
 | 
			
		||||
                               socket.SOCK_STREAM, socket.IPPROTO_TCP,
 | 
			
		||||
                               socket.AI_ADDRCONFIG | socket.AI_CANONNAME)
 | 
			
		||||
        except socket.gaierror:
 | 
			
		||||
            # IPv6 not available, skip
 | 
			
		||||
            return
 | 
			
		||||
        address = { 'type': 'inet',
 | 
			
		||||
                    'data': {
 | 
			
		||||
                        'host': '::1',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue