static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
{
    BDRVQcowState *s = bs->opaque;
    int len, i, ret = 0;
    QCowHeader header;
    QemuOpts *opts;
    Error *local_err = NULL;
    uint64_t ext_end;
    uint64_t l1_vm_state_index;
    ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
    if (ret < 0) {
    be32_to_cpus(&header.magic);
    be32_to_cpus(&header.version);
    be64_to_cpus(&header.backing_file_offset);
    be32_to_cpus(&header.backing_file_size);
    be64_to_cpus(&header.size);
    be32_to_cpus(&header.cluster_bits);
    be32_to_cpus(&header.crypt_method);
    be64_to_cpus(&header.l1_table_offset);
    be32_to_cpus(&header.l1_size);
    be64_to_cpus(&header.refcount_table_offset);
    be32_to_cpus(&header.refcount_table_clusters);
    be64_to_cpus(&header.snapshots_offset);
    be32_to_cpus(&header.nb_snapshots);
    if (header.magic != QCOW_MAGIC) {
        ret = -EMEDIUMTYPE;
    if (header.version < 2 || header.version > 3) {
        report_unsupported(bs, "QCOW version %d", header.version);
        ret = -ENOTSUP;
    s->qcow_version = header.version;
    /* Initialise version 3 header fields */
    if (header.version == 2) {
        header.incompatible_features    = 0;
        header.compatible_features      = 0;
        header.autoclear_features       = 0;
        header.refcount_order           = 4;
        header.header_length            = 72;
    } else {
        be64_to_cpus(&header.incompatible_features);
        be64_to_cpus(&header.compatible_features);
        be64_to_cpus(&header.autoclear_features);
        be32_to_cpus(&header.refcount_order);
        be32_to_cpus(&header.header_length);
    if (header.header_length > sizeof(header)) {
        s->unknown_header_fields_size = header.header_length - sizeof(header);
        s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
        ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,
                         s->unknown_header_fields_size);
        if (ret < 0) {
    if (header.backing_file_offset) {
        ext_end = header.backing_file_offset;
    } else {
        ext_end = 1 << header.cluster_bits;
    /* Handle feature bits */
    s->incompatible_features    = header.incompatible_features;
    s->compatible_features      = header.compatible_features;
    s->autoclear_features       = header.autoclear_features;
    if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
        void *feature_table = NULL;
        qcow2_read_extensions(bs, header.header_length, ext_end,
                              &feature_table);
        report_unsupported_feature(bs, feature_table,
                                   s->incompatible_features &
                                   ~QCOW2_INCOMPAT_MASK);
        ret = -ENOTSUP;
    /* Check support for various header values */
    if (header.refcount_order != 4) {
        report_unsupported(bs, "%d bit reference counts",
                           1 << header.refcount_order);
        ret = -ENOTSUP;
    if (header.cluster_bits < MIN_CLUSTER_BITS ||
        header.cluster_bits > MAX_CLUSTER_BITS) {
        ret = -EINVAL;
    if (header.crypt_method > QCOW_CRYPT_AES) {
        ret = -EINVAL;
    s->crypt_method_header = header.crypt_method;
    if (s->crypt_method_header) {
        bs->encrypted = 1;
    s->cluster_bits = header.cluster_bits;
    s->cluster_size = 1 << s->cluster_bits;
    s->cluster_sectors = 1 << (s->cluster_bits - 9);
    s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
    s->l2_size = 1 << s->l2_bits;
    bs->total_sectors = header.size / 512;
    s->csize_shift = (62 - (s->cluster_bits - 8));
    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
    s->refcount_table_offset = header.refcount_table_offset;
    s->refcount_table_size =
        header.refcount_table_clusters << (s->cluster_bits - 3);
    s->snapshots_offset = header.snapshots_offset;
    s->nb_snapshots = header.nb_snapshots;
    /* read the level 1 table */
    s->l1_size = header.l1_size;
    l1_vm_state_index = size_to_l1(s, header.size);
    if (l1_vm_state_index > INT_MAX) {
        ret = -EFBIG;
    s->l1_vm_state_index = l1_vm_state_index;
    /* the L1 table must contain at least enough entries to put
       header.size bytes */
    if (s->l1_size < s->l1_vm_state_index) {
        ret = -EINVAL;
    s->l1_table_offset = header.l1_table_offset;
    if (s->l1_size > 0) {
        s->l1_table = g_malloc0(
            align_offset(s->l1_size * sizeof(uint64_t), 512));
        ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
                         s->l1_size * sizeof(uint64_t));
        if (ret < 0) {
        for(i = 0;i < s->l1_size; i++) {
            be64_to_cpus(&s->l1_table[i]);
    /* alloc L2 table/refcount block cache */
    s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);
    s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);
    s->cluster_cache = g_malloc(s->cluster_size);
    /* one more sector for decompressed data alignment */
    s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
                                  + 512);
    s->cluster_cache_offset = -1;
    s->flags = flags;
    ret = qcow2_refcount_init(bs);
    if (ret != 0) {
    QLIST_INIT(&s->cluster_allocs);
    QTAILQ_INIT(&s->discards);
    /* read qcow2 extensions */
    if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) {
        ret = -EINVAL;
    /* read the backing file name */
    if (header.backing_file_offset != 0) {
        len = header.backing_file_size;
        if (len > 1023) {
            len = 1023;
        ret = bdrv_pread(bs->file, header.backing_file_offset,
                         bs->backing_file, len);
        if (ret < 0) {
        bs->backing_file[len] = '\0';
    ret = qcow2_read_snapshots(bs);
    if (ret < 0) {
    /* Clear unknown autoclear feature bits */
    if (!bs->read_only && s->autoclear_features != 0) {
        s->autoclear_features = 0;
        ret = qcow2_update_header(bs);
        if (ret < 0) {
    /* Initialise locks */
    qemu_co_mutex_init(&s->lock);
    /* Repair image if dirty */
    if (!(flags & BDRV_O_CHECK) && !bs->read_only &&
        (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
        BdrvCheckResult result = {0};
        ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS);
        if (ret < 0) {
    /* Enable lazy_refcounts according to image and command line options */
    opts = qemu_opts_create_nofail(&qcow2_runtime_opts);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        ret = -EINVAL;
    s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
        (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
    s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
    s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
    s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
                          flags & BDRV_O_UNMAP);
    s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
    s->discard_passthrough[QCOW2_DISCARD_OTHER] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
    qemu_opts_del(opts);
    if (s->use_lazy_refcounts && s->qcow_version < 3) {
        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require "
            "a qcow2 image with at least qemu 1.1 compatibility level");
        ret = -EINVAL;
#ifdef DEBUG_ALLOC
    {
        BdrvCheckResult result = {0};
        qcow2_check_refcounts(bs, &result, 0);
#endif
    return ret;
 fail:
    g_free(s->unknown_header_fields);
    cleanup_unknown_header_ext(bs);
    qcow2_free_snapshots(bs);
    qcow2_refcount_close(bs);
    g_free(s->l1_table);
    if (s->l2_table_cache) {
        qcow2_cache_destroy(bs, s->l2_table_cache);
    g_free(s->cluster_cache);
    qemu_vfree(s->cluster_data);
    return ret;
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
{
    BDRVQcowState *s = bs->opaque;
    int len, i, ret = 0;
    QCowHeader header;
    QemuOpts *opts;
    Error *local_err = NULL;
    uint64_t ext_end;
    uint64_t l1_vm_state_index;
    ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
    if (ret < 0) {
    be32_to_cpus(&header.magic);
    be32_to_cpus(&header.version);
    be64_to_cpus(&header.backing_file_offset);
    be32_to_cpus(&header.backing_file_size);
    be64_to_cpus(&header.size);
    be32_to_cpus(&header.cluster_bits);
    be32_to_cpus(&header.crypt_method);
    be64_to_cpus(&header.l1_table_offset);
    be32_to_cpus(&header.l1_size);
    be64_to_cpus(&header.refcount_table_offset);
    be32_to_cpus(&header.refcount_table_clusters);
    be64_to_cpus(&header.snapshots_offset);
    be32_to_cpus(&header.nb_snapshots);
    if (header.magic != QCOW_MAGIC) {
        ret = -EMEDIUMTYPE;
    if (header.version < 2 || header.version > 3) {
        report_unsupported(bs, "QCOW version %d", header.version);
        ret = -ENOTSUP;
    s->qcow_version = header.version;
    
    if (header.version == 2) {
        header.incompatible_features    = 0;
        header.compatible_features      = 0;
        header.autoclear_features       = 0;
        header.refcount_order           = 4;
        header.header_length            = 72;
    } else {
        be64_to_cpus(&header.incompatible_features);
        be64_to_cpus(&header.compatible_features);
        be64_to_cpus(&header.autoclear_features);
        be32_to_cpus(&header.refcount_order);
        be32_to_cpus(&header.header_length);
    if (header.header_length > sizeof(header)) {
        s->unknown_header_fields_size = header.header_length - sizeof(header);
        s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
        ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,
                         s->unknown_header_fields_size);
        if (ret < 0) {
    if (header.backing_file_offset) {
        ext_end = header.backing_file_offset;
    } else {
        ext_end = 1 << header.cluster_bits;
    
    s->incompatible_features    = header.incompatible_features;
    s->compatible_features      = header.compatible_features;
    s->autoclear_features       = header.autoclear_features;
    if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
        void *feature_table = NULL;
        qcow2_read_extensions(bs, header.header_length, ext_end,
                              &feature_table);
        report_unsupported_feature(bs, feature_table,
                                   s->incompatible_features &
                                   ~QCOW2_INCOMPAT_MASK);
        ret = -ENOTSUP;
    
    if (header.refcount_order != 4) {
        report_unsupported(bs, "%d bit reference counts",
                           1 << header.refcount_order);
        ret = -ENOTSUP;
    if (header.cluster_bits < MIN_CLUSTER_BITS ||
        header.cluster_bits > MAX_CLUSTER_BITS) {
        ret = -EINVAL;
    if (header.crypt_method > QCOW_CRYPT_AES) {
        ret = -EINVAL;
    s->crypt_method_header = header.crypt_method;
    if (s->crypt_method_header) {
        bs->encrypted = 1;
    s->cluster_bits = header.cluster_bits;
    s->cluster_size = 1 << s->cluster_bits;
    s->cluster_sectors = 1 << (s->cluster_bits - 9);
    s->l2_bits = s->cluster_bits - 3; 
    s->l2_size = 1 << s->l2_bits;
    bs->total_sectors = header.size / 512;
    s->csize_shift = (62 - (s->cluster_bits - 8));
    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
    s->refcount_table_offset = header.refcount_table_offset;
    s->refcount_table_size =
        header.refcount_table_clusters << (s->cluster_bits - 3);
    s->snapshots_offset = header.snapshots_offset;
    s->nb_snapshots = header.nb_snapshots;
    
    s->l1_size = header.l1_size;
    l1_vm_state_index = size_to_l1(s, header.size);
    if (l1_vm_state_index > INT_MAX) {
        ret = -EFBIG;
    s->l1_vm_state_index = l1_vm_state_index;
    

    if (s->l1_size < s->l1_vm_state_index) {
        ret = -EINVAL;
    s->l1_table_offset = header.l1_table_offset;
    if (s->l1_size > 0) {
        s->l1_table = g_malloc0(
            align_offset(s->l1_size * sizeof(uint64_t), 512));
        ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
                         s->l1_size * sizeof(uint64_t));
        if (ret < 0) {
        for(i = 0;i < s->l1_size; i++) {
            be64_to_cpus(&s->l1_table[i]);
    
    s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);
    s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);
    s->cluster_cache = g_malloc(s->cluster_size);
    
    s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
                                  + 512);
    s->cluster_cache_offset = -1;
    s->flags = flags;
    ret = qcow2_refcount_init(bs);
    if (ret != 0) {
    QLIST_INIT(&s->cluster_allocs);
    QTAILQ_INIT(&s->discards);
    
    if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) {
        ret = -EINVAL;
    
    if (header.backing_file_offset != 0) {
        len = header.backing_file_size;
        if (len > 1023) {
            len = 1023;
        ret = bdrv_pread(bs->file, header.backing_file_offset,
                         bs->backing_file, len);
        if (ret < 0) {
        bs->backing_file[len] = '\0';
    ret = qcow2_read_snapshots(bs);
    if (ret < 0) {
    
    if (!bs->read_only && s->autoclear_features != 0) {
        s->autoclear_features = 0;
        ret = qcow2_update_header(bs);
        if (ret < 0) {
    
    qemu_co_mutex_init(&s->lock);
    
    if (!(flags & BDRV_O_CHECK) && !bs->read_only &&
        (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
        BdrvCheckResult result = {0};
        ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS);
        if (ret < 0) {
    
    opts = qemu_opts_create_nofail(&qcow2_runtime_opts);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        ret = -EINVAL;
    s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
        (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
    s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
    s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
    s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
                          flags & BDRV_O_UNMAP);
    s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
    s->discard_passthrough[QCOW2_DISCARD_OTHER] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
    qemu_opts_del(opts);
    if (s->use_lazy_refcounts && s->qcow_version < 3) {
        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require "
            "a qcow2 image with at least qemu 1.1 compatibility level");
        ret = -EINVAL;
#ifdef DEBUG_ALLOC
    {
        BdrvCheckResult result = {0};
        qcow2_check_refcounts(bs, &result, 0);
#endif
    return ret;
 fail:
    g_free(s->unknown_header_fields);
    cleanup_unknown_header_ext(bs);
    qcow2_free_snapshots(bs);
    qcow2_refcount_close(bs);
    g_free(s->l1_table);
    if (s->l2_table_cache) {
        qcow2_cache_destroy(bs, s->l2_table_cache);
    g_free(s->cluster_cache);
    qemu_vfree(s->cluster_data);
    return ret;
static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2)
{
    BDRVQcowState *s = VAR_0->opaque;
    int VAR_3, VAR_4, VAR_5 = 0;
    QCowHeader header;
    QemuOpts *opts;
    Error *local_err = NULL;
    uint64_t ext_end;
    uint64_t l1_vm_state_index;
    VAR_5 = bdrv_pread(VAR_0->file, 0, &header, sizeof(header));
    if (VAR_5 < 0) {
    be32_to_cpus(&header.magic);
    be32_to_cpus(&header.version);
    be64_to_cpus(&header.backing_file_offset);
    be32_to_cpus(&header.backing_file_size);
    be64_to_cpus(&header.size);
    be32_to_cpus(&header.cluster_bits);
    be32_to_cpus(&header.crypt_method);
    be64_to_cpus(&header.l1_table_offset);
    be32_to_cpus(&header.l1_size);
    be64_to_cpus(&header.refcount_table_offset);
    be32_to_cpus(&header.refcount_table_clusters);
    be64_to_cpus(&header.snapshots_offset);
    be32_to_cpus(&header.nb_snapshots);
    if (header.magic != QCOW_MAGIC) {
        VAR_5 = -EMEDIUMTYPE;
    if (header.version < 2 || header.version > 3) {
        report_unsupported(VAR_0, "QCOW version %d", header.version);
        VAR_5 = -ENOTSUP;
    s->qcow_version = header.version;
    
    if (header.version == 2) {
        header.incompatible_features    = 0;
        header.compatible_features      = 0;
        header.autoclear_features       = 0;
        header.refcount_order           = 4;
        header.header_length            = 72;
    } else {
        be64_to_cpus(&header.incompatible_features);
        be64_to_cpus(&header.compatible_features);
        be64_to_cpus(&header.autoclear_features);
        be32_to_cpus(&header.refcount_order);
        be32_to_cpus(&header.header_length);
    if (header.header_length > sizeof(header)) {
        s->unknown_header_fields_size = header.header_length - sizeof(header);
        s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
        VAR_5 = bdrv_pread(VAR_0->file, sizeof(header), s->unknown_header_fields,
                         s->unknown_header_fields_size);
        if (VAR_5 < 0) {
    if (header.backing_file_offset) {
        ext_end = header.backing_file_offset;
    } else {
        ext_end = 1 << header.cluster_bits;
    
    s->incompatible_features    = header.incompatible_features;
    s->compatible_features      = header.compatible_features;
    s->autoclear_features       = header.autoclear_features;
    if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
        void *VAR_6 = NULL;
        qcow2_read_extensions(VAR_0, header.header_length, ext_end,
                              &VAR_6);
        report_unsupported_feature(VAR_0, VAR_6,
                                   s->incompatible_features &
                                   ~QCOW2_INCOMPAT_MASK);
        VAR_5 = -ENOTSUP;
    
    if (header.refcount_order != 4) {
        report_unsupported(VAR_0, "%d bit reference counts",
                           1 << header.refcount_order);
        VAR_5 = -ENOTSUP;
    if (header.cluster_bits < MIN_CLUSTER_BITS ||
        header.cluster_bits > MAX_CLUSTER_BITS) {
        VAR_5 = -EINVAL;
    if (header.crypt_method > QCOW_CRYPT_AES) {
        VAR_5 = -EINVAL;
    s->crypt_method_header = header.crypt_method;
    if (s->crypt_method_header) {
        VAR_0->encrypted = 1;
    s->cluster_bits = header.cluster_bits;
    s->cluster_size = 1 << s->cluster_bits;
    s->cluster_sectors = 1 << (s->cluster_bits - 9);
    s->l2_bits = s->cluster_bits - 3; 
    s->l2_size = 1 << s->l2_bits;
    VAR_0->total_sectors = header.size / 512;
    s->csize_shift = (62 - (s->cluster_bits - 8));
    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
    s->refcount_table_offset = header.refcount_table_offset;
    s->refcount_table_size =
        header.refcount_table_clusters << (s->cluster_bits - 3);
    s->snapshots_offset = header.snapshots_offset;
    s->nb_snapshots = header.nb_snapshots;
    
    s->l1_size = header.l1_size;
    l1_vm_state_index = size_to_l1(s, header.size);
    if (l1_vm_state_index > INT_MAX) {
        VAR_5 = -EFBIG;
    s->l1_vm_state_index = l1_vm_state_index;
    

    if (s->l1_size < s->l1_vm_state_index) {
        VAR_5 = -EINVAL;
    s->l1_table_offset = header.l1_table_offset;
    if (s->l1_size > 0) {
        s->l1_table = g_malloc0(
            align_offset(s->l1_size * sizeof(uint64_t), 512));
        VAR_5 = bdrv_pread(VAR_0->file, s->l1_table_offset, s->l1_table,
                         s->l1_size * sizeof(uint64_t));
        if (VAR_5 < 0) {
        for(VAR_4 = 0;VAR_4 < s->l1_size; VAR_4++) {
            be64_to_cpus(&s->l1_table[VAR_4]);
    
    s->l2_table_cache = qcow2_cache_create(VAR_0, L2_CACHE_SIZE);
    s->refcount_block_cache = qcow2_cache_create(VAR_0, REFCOUNT_CACHE_SIZE);
    s->cluster_cache = g_malloc(s->cluster_size);
    
    s->cluster_data = qemu_blockalign(VAR_0, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
                                  + 512);
    s->cluster_cache_offset = -1;
    s->VAR_2 = VAR_2;
    VAR_5 = qcow2_refcount_init(VAR_0);
    if (VAR_5 != 0) {
    QLIST_INIT(&s->cluster_allocs);
    QTAILQ_INIT(&s->discards);
    
    if (qcow2_read_extensions(VAR_0, header.header_length, ext_end, NULL)) {
        VAR_5 = -EINVAL;
    
    if (header.backing_file_offset != 0) {
        VAR_3 = header.backing_file_size;
        if (VAR_3 > 1023) {
            VAR_3 = 1023;
        VAR_5 = bdrv_pread(VAR_0->file, header.backing_file_offset,
                         VAR_0->backing_file, VAR_3);
        if (VAR_5 < 0) {
        VAR_0->backing_file[VAR_3] = '\0';
    VAR_5 = qcow2_read_snapshots(VAR_0);
    if (VAR_5 < 0) {
    
    if (!VAR_0->read_only && s->autoclear_features != 0) {
        s->autoclear_features = 0;
        VAR_5 = qcow2_update_header(VAR_0);
        if (VAR_5 < 0) {
    
    qemu_co_mutex_init(&s->lock);
    
    if (!(VAR_2 & BDRV_O_CHECK) && !VAR_0->read_only &&
        (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
        BdrvCheckResult result = {0};
        VAR_5 = qcow2_check(VAR_0, &result, BDRV_FIX_ERRORS);
        if (VAR_5 < 0) {
    
    opts = qemu_opts_create_nofail(&qcow2_runtime_opts);
    qemu_opts_absorb_qdict(opts, VAR_1, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        VAR_5 = -EINVAL;
    s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
        (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
    s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
    s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
    s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
                          VAR_2 & BDRV_O_UNMAP);
    s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
    s->discard_passthrough[QCOW2_DISCARD_OTHER] =
        qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
    qemu_opts_del(opts);
    if (s->use_lazy_refcounts && s->qcow_version < 3) {
        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require "
            "a qcow2 image with at least qemu 1.1 compatibility level");
        VAR_5 = -EINVAL;
#ifdef DEBUG_ALLOC
    {
        BdrvCheckResult result = {0};
        qcow2_check_refcounts(VAR_0, &result, 0);
#endif
    return VAR_5;
 fail:
    g_free(s->unknown_header_fields);
    cleanup_unknown_header_ext(VAR_0);
    qcow2_free_snapshots(VAR_0);
    qcow2_refcount_close(VAR_0);
    g_free(s->l1_table);
    if (s->l2_table_cache) {
        qcow2_cache_destroy(VAR_0, s->l2_table_cache);
    g_free(s->cluster_cache);
    qemu_vfree(s->cluster_data);
    return VAR_5;
static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2)
{ BDRVQcowState *s = VAR_0->opaque; int VAR_3, VAR_4, VAR_5 = 0; QCowHeader header; QemuOpts *opts; Error *local_err = NULL; uint64_t ext_end; uint64_t l1_vm_state_index; VAR_5 = bdrv_pread(VAR_0->file, 0, &header, sizeof(header)); if (VAR_5 < 0) { be32_to_cpus(&header.magic); be32_to_cpus(&header.version); be64_to_cpus(&header.backing_file_offset); be32_to_cpus(&header.backing_file_size); be64_to_cpus(&header.size); be32_to_cpus(&header.cluster_bits); be32_to_cpus(&header.crypt_method); be64_to_cpus(&header.l1_table_offset); be32_to_cpus(&header.l1_size); be64_to_cpus(&header.refcount_table_offset); be32_to_cpus(&header.refcount_table_clusters); be64_to_cpus(&header.snapshots_offset); be32_to_cpus(&header.nb_snapshots); if (header.magic != QCOW_MAGIC) { VAR_5 = -EMEDIUMTYPE; if (header.version < 2 || header.version > 3) { report_unsupported(VAR_0, "QCOW version %d", header.version); VAR_5 = -ENOTSUP; s->qcow_version = header.version; if (header.version == 2) { header.incompatible_features    = 0; header.compatible_features      = 0; header.autoclear_features       = 0; header.refcount_order           = 4; header.header_length            = 72; } else { be64_to_cpus(&header.incompatible_features); be64_to_cpus(&header.compatible_features); be64_to_cpus(&header.autoclear_features); be32_to_cpus(&header.refcount_order); be32_to_cpus(&header.header_length); if (header.header_length > sizeof(header)) { s->unknown_header_fields_size = header.header_length - sizeof(header); s->unknown_header_fields = g_malloc(s->unknown_header_fields_size); VAR_5 = bdrv_pread(VAR_0->file, sizeof(header), s->unknown_header_fields,
s->unknown_header_fields_size); if (VAR_5 < 0) { if (header.backing_file_offset) { ext_end = header.backing_file_offset; } else { ext_end = 1 << header.cluster_bits; s->incompatible_features    = header.incompatible_features; s->compatible_features      = header.compatible_features; s->autoclear_features       = header.autoclear_features; if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) { void *VAR_6 = NULL; qcow2_read_extensions(VAR_0, header.header_length, ext_end,
&VAR_6); report_unsupported_feature(VAR_0, VAR_6,
s->incompatible_features &
~QCOW2_INCOMPAT_MASK); VAR_5 = -ENOTSUP; if (header.refcount_order != 4) { report_unsupported(VAR_0, "%d bit reference counts",
1 << header.refcount_order); VAR_5 = -ENOTSUP; if (header.cluster_bits < MIN_CLUSTER_BITS ||
header.cluster_bits > MAX_CLUSTER_BITS) { VAR_5 = -EINVAL; if (header.crypt_method > QCOW_CRYPT_AES) { VAR_5 = -EINVAL; s->crypt_method_header = header.crypt_method; if (s->crypt_method_header) { VAR_0->encrypted = 1; s->cluster_bits = header.cluster_bits; s->cluster_size = 1 << s->cluster_bits; s->cluster_sectors = 1 << (s->cluster_bits - 9); s->l2_bits = s->cluster_bits - 3; s->l2_size = 1 << s->l2_bits; VAR_0->total_sectors = header.size / 512; s->csize_shift = (62 - (s->cluster_bits - 8)); s->csize_mask = (1 << (s->cluster_bits - 8)) - 1; s->cluster_offset_mask = (1LL << s->csize_shift) - 1; s->refcount_table_offset = header.refcount_table_offset; s->refcount_table_size =
header.refcount_table_clusters << (s->cluster_bits - 3); s->snapshots_offset = header.snapshots_offset; s->nb_snapshots = header.nb_snapshots; s->l1_size = header.l1_size; l1_vm_state_index = size_to_l1(s, header.size); if (l1_vm_state_index > INT_MAX) { VAR_5 = -EFBIG; s->l1_vm_state_index = l1_vm_state_index; if (s->l1_size < s->l1_vm_state_index) { VAR_5 = -EINVAL; s->l1_table_offset = header.l1_table_offset; if (s->l1_size > 0) { s->l1_table = g_malloc0(
align_offset(s->l1_size * sizeof(uint64_t), 512)); VAR_5 = bdrv_pread(VAR_0->file, s->l1_table_offset, s->l1_table,
s->l1_size * sizeof(uint64_t)); if (VAR_5 < 0) { for(VAR_4 = 0;VAR_4 < s->l1_size; VAR_4++) { be64_to_cpus(&s->l1_table[VAR_4]); s->l2_table_cache = qcow2_cache_create(VAR_0, L2_CACHE_SIZE); s->refcount_block_cache = qcow2_cache_create(VAR_0, REFCOUNT_CACHE_SIZE); s->cluster_cache = g_malloc(s->cluster_size); s->cluster_data = qemu_blockalign(VAR_0, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
+ 512); s->cluster_cache_offset = -1; s->VAR_2 = VAR_2; VAR_5 = qcow2_refcount_init(VAR_0); if (VAR_5 != 0) { QLIST_INIT(&s->cluster_allocs); QTAILQ_INIT(&s->discards); if (qcow2_read_extensions(VAR_0, header.header_length, ext_end, NULL)) { VAR_5 = -EINVAL; if (header.backing_file_offset != 0) { VAR_3 = header.backing_file_size; if (VAR_3 > 1023) { VAR_3 = 1023; VAR_5 = bdrv_pread(VAR_0->file, header.backing_file_offset,
VAR_0->backing_file, VAR_3); if (VAR_5 < 0) { VAR_0->backing_file[VAR_3] = '\0'; VAR_5 = qcow2_read_snapshots(VAR_0); if (VAR_5 < 0) { if (!VAR_0->read_only && s->autoclear_features != 0) { s->autoclear_features = 0; VAR_5 = qcow2_update_header(VAR_0); if (VAR_5 < 0) { qemu_co_mutex_init(&s->lock); if (!(VAR_2 & BDRV_O_CHECK) && !VAR_0->read_only &&
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { BdrvCheckResult result = {0}; VAR_5 = qcow2_check(VAR_0, &result, BDRV_FIX_ERRORS); if (VAR_5 < 0) { opts = qemu_opts_create_nofail(&qcow2_runtime_opts); qemu_opts_absorb_qdict(opts, VAR_1, &local_err); if (error_is_set(&local_err)) { qerror_report_err(local_err); error_free(local_err); VAR_5 = -EINVAL; s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS)); s->discard_passthrough[QCOW2_DISCARD_NEVER] = false; s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true; s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
VAR_2 & BDRV_O_UNMAP); s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true); s->discard_passthrough[QCOW2_DISCARD_OTHER] =
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); qemu_opts_del(opts); if (s->use_lazy_refcounts && s->qcow_version < 3) { qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require "
"a qcow2 image with at least qemu 1.1 compatibility level"); VAR_5 = -EINVAL; #ifdef DEBUG_ALLOC
{ BdrvCheckResult result = {0}; qcow2_check_refcounts(VAR_0, &result, 0); #endif
return VAR_5; fail:
g_free(s->unknown_header_fields); cleanup_unknown_header_ext(VAR_0); qcow2_free_snapshots(VAR_0); qcow2_refcount_close(VAR_0); g_free(s->l1_table); if (s->l2_table_cache) { qcow2_cache_destroy(VAR_0, s->l2_table_cache); g_free(s->cluster_cache); qemu_vfree(s->cluster_data); return VAR_5;