VirtualBox

Changeset 77924 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Mar 27, 2019 6:43:10 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129637
Message:

Storage/QCOW: Add necessary structures and checks to work with v3 images

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/QCOW.cpp

    r77921 r77924  
    3737/** @page pg_storage_qcow   QCOW Storage Backend
    3838 * The QCOW backend implements support for the qemu copy on write format (short QCOW).
    39  * There is no official specification available but the format is described
    40  * at http://people.gnome.org/~markmc/qcow-image-format.html for version 2
    41  * and http://people.gnome.org/~markmc/qcow-image-format-version-1.html for version 1.
     39 *
     40 * The official specification for qcow is available at
     41 * https://github.com/qemu/qemu/blob/master/docs/interop/qcow2.txt version 2 and 3.
     42 * For version 1 there is no official specification available but the format is described
     43 * at http://people.gnome.org/~markmc/qcow-image-format-version-1.html.
    4244 *
    4345 * Missing things to implement:
     
    8688            uint64_t    u64L1TableOffset;
    8789        } v1;
    88         /** Version 2. */
     90        /** Version 2 (and also containing extensions for version 3). */
    8991        struct
    9092        {
     
    111113            /** Offset of the first snapshot header in the image. */
    112114            uint64_t    u64SnapshotsOffset;
     115            /** Version 3 additional data. */
     116            struct
     117            {
     118                /** Incompatible features. */
     119                uint64_t    u64IncompatFeat;
     120                /** Compatible features. */
     121                uint64_t    u64CompatFeat;
     122                /** Autoclear features. */
     123                uint64_t    u64AutoClrFeat;
     124                /** Width in bits of a reference count block. */
     125                uint32_t    u32RefCntWidth;
     126                /** Lenght of the header structure in bytes (for the header extensions). */
     127                uint32_t    u32HdrLenBytes;
     128            } v3;
    113129        } v2;
    114130    } Version;
     
    134150/** The mask for extracting the offset from either the L1 or L2 table. */
    135151#define QCOW_V2_TBL_OFFSET_MASK               UINT64_C(0x00fffffffffffe00)
     152
     153/** Incompatible feature: Dirty bit, reference count may be inconsistent. */
     154#define QCOW_V3_INCOMPAT_FEAT_F_DIRTY         RT_BIT_64(0)
     155/** Incompatible feature: Image is corrupt and needs repair. */
     156#define QCOW_V3_INCOMPAT_FEAT_F_CORRUPT       RT_BIT_64(1)
     157/** Incompatible feature: External data file. */
     158#define QCOW_V3_INCOMPAT_FEAT_F_EXTERNAL_DATA RT_BIT_64(2)
     159/** The incompatible features we support currently. */
     160#define QCOW_V3_INCOMPAT_FEAT_SUPPORTED_MASK  UINT64_C(0x0)
     161
     162/** Compatible feature: Lazy reference counters. */
     163#define QCOW_V3_COMPAT_FEAT_F_LAZY_REF_COUNT  RT_BIT_64(0)
     164/** The compatible features we support currently. */
     165#define QCOW_V3_COMPAT_FEAT_SUPPORTED_MASK    UINT64_C(0x0)
     166
     167/** Auto clear feature: Bitmaps extension. */
     168#define QCOW_V3_AUTOCLR_FEAT_F_BITMAPS        RT_BIT_64(0)
     169/** Auto clear feature: The external data file is raw image which can be accessed standalone. */
     170#define QCOW_V3_AUTOCLR_FEAT_F_EXT_RAW_DATA   RT_BIT_64(1)
     171/** The autoclear features we support currently. */
     172#define QCOW_V3_AUTOCLR_FEAT_SUPPORTED_MASK   UINT64_C(0x0)
    136173
    137174
     
    359396        pHeader->Version.v1.u64L1TableOffset         = RT_BE2H_U64(pHeader->Version.v1.u64L1TableOffset);
    360397    }
    361     else if (pHeader->u32Version == 2)
     398    else if (pHeader->u32Version == 2 || pHeader->u32Version == 3)
    362399    {
    363400        pHeader->Version.v2.u64BackingFileOffset     = RT_BE2H_U64(pHeader->Version.v2.u64BackingFileOffset);
     
    372409        pHeader->Version.v2.u32NbSnapshots           = RT_BE2H_U32(pHeader->Version.v2.u32NbSnapshots);
    373410        pHeader->Version.v2.u64SnapshotsOffset       = RT_BE2H_U64(pHeader->Version.v2.u64SnapshotsOffset);
     411
     412        if (pHeader->u32Version == 3)
     413        {
     414            pHeader->Version.v2.v3.u64IncompatFeat   = RT_BE2H_U64(pHeader->Version.v2.v3.u64IncompatFeat);
     415            pHeader->Version.v2.v3.u64CompatFeat     = RT_BE2H_U64(pHeader->Version.v2.v3.u64CompatFeat);
     416            pHeader->Version.v2.v3.u64AutoClrFeat    = RT_BE2H_U64(pHeader->Version.v2.v3.u64AutoClrFeat);
     417            pHeader->Version.v2.v3.u32RefCntWidth    = RT_BE2H_U32(pHeader->Version.v2.v3.u32RefCntWidth);
     418            pHeader->Version.v2.v3.u32HdrLenBytes    = RT_BE2H_U32(pHeader->Version.v2.v3.u32HdrLenBytes);
     419        }
    374420    }
    375421    else
     
    10311077                             pImage->pszFilename);
    10321078    }
    1033     else if (pHdr->u32Version == 2)
     1079    else if (pHdr->u32Version == 2 || pHdr->u32Version == 3)
    10341080    {
    10351081        /* Check that the backing filename is contained in the file. */
     
    10451091                             N_("QCOW: Cluster size is too small for image  '%s' (%u vs %u)"),
    10461092                             pImage->pszFilename, RT_BIT_32(pHdr->Version.v2.u32ClusterBits), 512);
     1093
     1094        /* Some additional checks for v3 images. */
     1095        if (pHdr->u32Version == 3)
     1096        {
     1097            if (pHdr->Version.v2.v3.u32RefCntWidth > 6)
     1098                return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1099                                 N_("QCOW: Reference count width too big for image  '%s' (%u vs %u)"),
     1100                                 pImage->pszFilename, RT_BIT_32(pHdr->Version.v2.v3.u32RefCntWidth), 6);
     1101        }
    10471102    }
    10481103    else
     
    11141169                                               pImage->pszFilename);
    11151170                        }
    1116                         else if (Header.u32Version == 2)
     1171                        else if (Header.u32Version == 2 || Header.u32Version == 3)
    11171172                        {
    11181173                            if (Header.Version.v2.u32CryptMethod)
     
    11381193                                pImage->cbRefcountTable       = qcowCluster2Byte(pImage, Header.Version.v2.u32RefcountTableClusters);
    11391194                                pImage->cRefcountTableEntries = pImage->cbRefcountTable / sizeof(uint64_t);
     1195
     1196                                if (Header.u32Version == 3)
     1197                                {
     1198                                    if (Header.Version.v2.v3.u64IncompatFeat & ~QCOW_V3_INCOMPAT_FEAT_SUPPORTED_MASK)
     1199                                        rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
     1200                                                       N_("QCow: Image '%s' contains unsupported incompatible features (%llx vs %llx)"),
     1201                                                       pImage->pszFilename, Header.Version.v2.v3.u64IncompatFeat, QCOW_V3_INCOMPAT_FEAT_SUPPORTED_MASK);
     1202
     1203                                    /** @todo Auto clear features need to be reset as soon as write support is added. */
     1204                                }
    11401205                            }
    11411206                        }
     
    11451210                                           pImage->pszFilename, Header.u32Version);
    11461211
    1147                         pImage->cbL1Table = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster);
    1148                         if ((uint64_t)pImage->cbL1Table != RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster))
    1149                             rc = vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
    1150                                            N_("QCOW: L1 table size overflow in image '%s'"),
    1151                                            pImage->pszFilename);
     1212                        if (RT_SUCCESS(rc))
     1213                        {
     1214                            pImage->cbL1Table = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster);
     1215                            if ((uint64_t)pImage->cbL1Table != RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster))
     1216                                rc = vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1217                                               N_("QCOW: L1 table size overflow in image '%s'"),
     1218                                               pImage->pszFilename);
     1219                        }
    11521220                    }
    11531221
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette