VirtualBox

Changeset 21856 in vbox


Ignore:
Timestamp:
Jul 28, 2009 6:28:01 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
50492
Message:

SSM: only compress big stuff that's a page or larger.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/VMM/Makefile.kmk

    r21496 r21856  
    107107        PGMPool.cpp \
    108108        SELM.cpp \
    109         SSM.cpp \
     109        SSM$(if-expr defined(VBOX_WITH_NEW_SSM),-new,).cpp \
    110110        STAM.cpp \
    111111        TM.cpp \
  • TabularUnified trunk/src/VBox/VMM/SSM-new.cpp

    r21799 r21856  
    9999 *       - type 1: Terminator with CRC-32 and unit size.
    100100 *       - type 2: Raw data record.
    101  *       - type 3: Named data - length prefixed name followed by the data.
    102  *       - types 4 thru 15 are current undefined.
     101 *       - type 3: Raw data compressed by LZF. The data is prefixed by a 8-bit
     102 *                 field countining the length of the uncompressed data given as
     103 *                 a page count.
     104 *       - type 4: Named data - length prefixed name followed by the data. This
     105 *                 type is not implemented yet as we're missing the API part, so
     106 *                 the type assignment is tentative.
     107 *       - types 5 thru 15 are current undefined.
    103108 *   - bit 4: Important (set), can be skipped (clear).
    104109 *   - bit 5: Undefined flag, must be zero.
     
    109114 * encoded in UTF-8 style.
    110115 *
    111  * The data part of the unit is compressed using LZF (via RTZip).
    112  *
    113  * (In version 1.2 and earlier the unit header also contained the compressed
    114  * size of the data, i.e.  it was updated after the data was written, and the
    115  * data was not record based.)
     116 * (In version 1.2 and earlier the unit data was compressed and not record
     117 * based. The unit header contained the compressed size of the data, i.e. it
     118 * needed updating after the data was written.)
    116119 *
    117120 *
     
    141144#include <VBox/version.h>
    142145
     146#include <iprt/alloc.h>
    143147#include <iprt/assert.h>
     148#include <iprt/crc32.h>
    144149#include <iprt/file.h>
    145 #include <iprt/alloc.h>
     150#include <iprt/param.h>
     151#include <iprt/thread.h>
     152#include <iprt/string.h>
    146153#include <iprt/uuid.h>
    147154#include <iprt/zip.h>
    148 #include <iprt/crc32.h>
    149 #include <iprt/thread.h>
    150 #include <iprt/string.h>
    151155
    152156
     
    199203/** Raw data. The data follows the size field without further ado. */
    200204#define SSM_REC_TYPE_RAW                        2
     205/** Raw data compressed by LZF.
     206 * The record header is followed by a 8-bit field containing the size of the
     207 * uncompressed data.  The compressed data is after it. */
     208#define SSM_REC_TYPE_RAW_LZF                    3
    201209/** Named data items.
    202210 * A length prefix zero terminated string (i.e. max 255) followed by the data.  */
    203 #define SSM_REC_TYPE_NAMED                      3
     211#define SSM_REC_TYPE_NAMED                      4
    204212/** Macro for validating the record type.
    205213 * This can be used with the flags+type byte, no need to mask out the type first. */
     
    321329        struct
    322330        {
    323             /** The compressor of the current data unit. */
    324             PRTZIPCOMP      pZipComp;
    325331            /** Offset into the databuffer. */
    326332            uint32_t        offDataBuffer;
     
    334340        struct
    335341        {
    336             /** The decompressor of the current data unit. */
    337             PRTZIPDECOMP    pZipDecomp;
     342            /** V1: The decompressor of the current data unit. */
     343            PRTZIPDECOMP    pZipDecompV1;
    338344            /** The major format version number. */
    339345            uint32_t        uFmtVerMajor;
     
    380386            /** @} */
    381387
    382             /** V2: Data buffer. */
     388            /** V2: Data buffer.
     389             * @remarks Be extremely careful when changing the size of this buffer! */
    383390            uint8_t         abDataBuffer[4096];
     391
     392            /** V2: Decompression buffer.
     393             * @todo removed this when we start buffering the stream. */
     394            uint8_t         abComprBuffer[4096];
    384395        } Read;
    385396    } u;
     
    417428    /** Flags, see SSMFILEHDR_FLAGS_XXX.  */
    418429    uint32_t        fFlags;
    419     /** Reserved header space - must be zero. */
    420     uint32_t        u32Reserved;
     430    /** The maximum size of decompressed data. */
     431    uint32_t        cbMaxDecompr;
    421432    /** The checksum of this header.
    422433     * This field is set to zero when calculating the checksum. */
     
    15301541    Handle.fChecksummed     = true;
    15311542    Handle.u32StreamCRC     = RTCrc32Start();
    1532     Handle.u.Write.pZipComp         = NULL;
    15331543    Handle.u.Write.offDataBuffer    = 0;
    15341544
     
    15631573    u.FileHdr.cUnits       = pVM->ssm.s.cUnits;
    15641574    u.FileHdr.fFlags       = SSMFILEHDR_FLAGS_STREAM_CRC32;
    1565     u.FileHdr.u32Reserved  = 0;
     1575    u.FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer);
    15661576    u.FileHdr.u32CRC       = 0;
    15671577    u.FileHdr.u32CRC       = RTCrc32(&u.FileHdr, sizeof(u.FileHdr));
     
    18291839    rc2 = RTFileDelete(pszFilename);
    18301840    AssertRC(rc2);
    1831     if (Handle.u.Write.pZipComp)
    1832         RTZipCompDestroy(Handle.u.Write.pZipComp);
    18331841
    18341842    return rc;
     
    19491957            /* validate the header. */
    19501958            SSM_CHECK_CRC32_RET(&uHdr.v2_0, sizeof(uHdr.v2_0), ("Header CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
    1951             if (    uHdr.v2_0.u8Reserved
    1952                 ||  uHdr.v2_0.u32Reserved)
     1959            if (uHdr.v2_0.u8Reserved)
    19531960            {
    1954                 LogRel(("SSM: Reserved header fields aren't zero: %02x %08x\n", uHdr.v2_0.u8Reserved, uHdr.v2_0.u32Reserved));
     1961                LogRel(("SSM: Reserved header field isn't zero: %02x\n", uHdr.v2_0.u8Reserved));
    19551962                return VERR_SSM_INTEGRITY;
    19561963            }
     
    19581965            {
    19591966                LogRel(("SSM: Unknown header flags: %08x\n", uHdr.v2_0.fFlags));
     1967                return VERR_SSM_INTEGRITY;
     1968            }
     1969            if (    uHdr.v2_0.cbMaxDecompr > sizeof(pSSM->u.Read.abDataBuffer)
     1970                ||  uHdr.v2_0.cbMaxDecompr < PAGE_SIZE
     1971                ||  (uHdr.v2_0.cbMaxDecompr & 0xff) != 0)
     1972            {
     1973                LogRel(("SSM: The cbMaxDecompr header field is out of range: %#x\n", uHdr.v2_0.cbMaxDecompr));
    19601974                return VERR_SSM_INTEGRITY;
    19611975            }
     
    21932207    pSSM->u32StreamCRC     = 0;
    21942208
    2195     pSSM->u.Read.pZipDecomp     = NULL;
     2209    pSSM->u.Read.pZipDecompV1   = NULL;
    21962210    pSSM->u.Read.uFmtVerMajor   = UINT32_MAX;
    21972211    pSSM->u.Read.uFmtVerMinor   = UINT32_MAX;
     
    28392853    int rc = RTFileClose(pSSM->hFile);
    28402854    AssertRC(rc);
    2841     if (pSSM->u.Read.pZipDecomp)
    2842     {
    2843         RTZipDecompDestroy(pSSM->u.Read.pZipDecomp);
    2844         pSSM->u.Read.pZipDecomp = NULL;
     2855    if (pSSM->u.Read.pZipDecompV1)
     2856    {
     2857        RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
     2858        pSSM->u.Read.pZipDecompV1 = NULL;
    28452859    }
    28462860    RTMemFree(pSSM);
     
    30703084     * Reset the state.
    30713085     */
    3072     if (pSSM->u.Read.pZipDecomp)
    3073     {
    3074         RTZipDecompDestroy(pSSM->u.Read.pZipDecomp);
    3075         pSSM->u.Read.pZipDecomp = NULL;
     3086    if (pSSM->u.Read.pZipDecompV1)
     3087    {
     3088        RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
     3089        pSSM->u.Read.pZipDecompV1 = NULL;
    30763090    }
    30773091    pSSM->cbUnitLeftV1  = 0;
     
    31013115    int rc = ssmR3DataFlushBuffer(pSSM);
    31023116    if (RT_SUCCESS(rc))
    3103     {
    3104         if (!pSSM->u.Write.pZipComp)
    3105             return VINF_SUCCESS;
    3106 
    3107         int rc = RTZipCompFinish(pSSM->u.Write.pZipComp);
    3108         if (RT_SUCCESS(rc))
    3109         {
    3110             rc = RTZipCompDestroy(pSSM->u.Write.pZipComp);
    3111             if (RT_SUCCESS(rc))
    3112             {
    3113                 pSSM->u.Write.pZipComp = NULL;
    3114                 //Log2(("ssmR3DataWriteFinish: %#010llx done\n", RTFileTell(pSSM->File)));
    3115                 return VINF_SUCCESS;
    3116             }
    3117         }
    3118     }
     3117        return VINF_SUCCESS;
    31193118
    31203119    if (RT_SUCCESS(pSSM->rc))
     
    31263125
    31273126/**
    3128  * Callback for flusing the output buffer of a compression stream.
    3129  *
    3130  * @returns VBox status.
     3127 * Begins writing the data of a data unit.
     3128 *
     3129 * Errors are signalled via pSSM->rc.
     3130 *
    31313131 * @param   pSSM            The saved state handle.
    3132  * @param   pvBuf           Compressed data.
    3133  * @param   cbBuf           Size of the compressed data.
    3134  */
    3135 static DECLCALLBACK(int) ssmR3WriteOut(void *pvSSM, const void *pvBuf, size_t cbBuf)
    3136 {
    3137     return ssmR3StrmWrite((PSSMHANDLE)pvSSM, pvBuf, cbBuf);
    3138 }
    3139 
    3140 
    3141 /**
    3142  * Begins writing the data of a data unit.
    3143  *
    3144  * Errors are signalled via pSSM->rc.
    3145  *
    3146  * @param   pSSM            The saved state handle.
    31473132 */
    31483133static void ssmR3DataWriteBegin(PSSMHANDLE pSSM)
    31493134{
    3150     Assert(!pSSM->u.Write.pZipComp);
    3151 
    3152     pSSM->u.Write.pZipComp  = NULL;
    31533135    pSSM->offUnit           = 0;
    31543136    if (pSSM->fUnitChecksummed)
    31553137        pSSM->u32UnitCRC    = RTCrc32Start();
    3156 
    3157     //int rc = RTZipCompCreate(&pSSM->u.Write.pZipComp, pSSM, ssmR3WriteOut, RTZIPTYPE_ZLIB, RTZIPLEVEL_FAST);
    3158     int rc = RTZipCompCreate(&pSSM->u.Write.pZipComp, pSSM, ssmR3WriteOut, RTZIPTYPE_LZF, RTZIPLEVEL_FAST);
    3159     //int rc = RTZipCompCreate(&pSSM->u.Write.pZipComp, pSSM, ssmR3WriteOut, RTZIPTYPE_STORE, RTZIPLEVEL_FAST);
    3160     if (RT_FAILURE(rc) && RT_SUCCESS(pSSM->rc))
    3161         pSSM->rc = rc;
    31623138}
    31633139
     
    31733149static int ssmR3DataWriteRaw(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
    31743150{
    3175     Log2(("ssmR3DataWriteRaw: %08llx: pvBuf=%p cbBuf=%#x %.*Rhxs%s\n", pSSM->offUnit, pvBuf, cbBuf, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
     3151    Log2(("ssmR3DataWriteRaw: %08llx|%08llx: pvBuf=%p cbBuf=%#x %.*Rhxs%s\n",
     3152          ssmR3StrmTell(pSSM), pSSM->offUnit, pvBuf, cbBuf, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
    31763153
    31773154    /*
     
    31933170    {
    31943171        size_t cbChunk = RT_MIN(cbBuf, _1M);
    3195         int rc = pSSM->rc = RTZipCompress(pSSM->u.Write.pZipComp, pvBuf, cbChunk);
     3172        int rc = ssmR3StrmWrite(pSSM, pvBuf, cbChunk);
    31963173        if (RT_FAILURE(rc))
    31973174            return rc;
     
    32043181    return VINF_SUCCESS;
    32053182}
     3183
    32063184
    32073185/**
     
    32663244        AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), pSSM->rc = VERR_INTERNAL_ERROR);
    32673245
    3268     Log3(("ssmR3DataWriteRecHdr: %08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
    3269           pSSM->offUnit + cbHdr, cb, u8TypeAndFlags & SSM_REC_TYPE_MASK, !!(u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), cbHdr));
     3246    Log3(("ssmR3DataWriteRecHdr: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
     3247          ssmR3StrmTell(pSSM) + cbHdr, pSSM->offUnit + cbHdr, cb, u8TypeAndFlags & SSM_REC_TYPE_MASK, !!(u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), cbHdr));
    32703248
    32713249    return ssmR3DataWriteRaw(pSSM, &abHdr[0], cbHdr);
     
    33453323    pbHdr[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW;
    33463324
    3347     Log3(("ssmR3DataFlushBuffer: %08llx/%08x: Type=RAW fImportant=true cbHdr=%u\n",
    3348           pSSM->offUnit + (cbTotal - cb), cb, (cbTotal - cb) ));
     3325    Log3(("ssmR3DataFlushBuffer: %08llx|%08llx/%08x: Type=RAW fImportant=true cbHdr=%u\n",
     3326          ssmR3StrmTell(pSSM) + (cbTotal - cb), pSSM->offUnit + (cbTotal - cb), cb, (cbTotal - cb) ));
    33493327
    33503328    /*
     
    33703348    if (RT_SUCCESS(rc))
    33713349    {
    3372         rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
    3373         if (RT_SUCCESS(rc))
    3374             rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf);
     3350        /*
     3351         * Compress it if it's a page or more in size.
     3352         */
     3353        for (;;)
     3354        {
     3355            if (cbBuf >= PAGE_SIZE)
     3356            {
     3357                struct
     3358                {
     3359                    uint8_t     cPages;
     3360                    uint8_t     abCompr[PAGE_SIZE - (PAGE_SIZE / 16)];
     3361                } s;
     3362                AssertCompile(sizeof(s) == PAGE_SIZE - (PAGE_SIZE / 16) + sizeof(uint8_t));
     3363
     3364                size_t cbCompr;
     3365                rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/,
     3366                                        pvBuf, PAGE_SIZE,
     3367                                        &s.abCompr[0], sizeof(s.abCompr), &cbCompr);
     3368                if (RT_SUCCESS(rc))
     3369                {
     3370                    cbCompr += sizeof(s.cPages);
     3371                    s.cPages = 1;
     3372                    rc = ssmR3DataWriteRecHdr(pSSM, cbCompr, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_LZF);
     3373                    if (RT_FAILURE(rc))
     3374                        return rc;
     3375                    rc = ssmR3DataWriteRaw(pSSM, &s, cbCompr);
     3376                    if (RT_FAILURE(rc))
     3377                        return rc;
     3378                }
     3379                else
     3380                {
     3381                    /* Didn't compress very well, store it. */
     3382                    rc = ssmR3DataWriteRecHdr(pSSM, PAGE_SIZE, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
     3383                    if (RT_FAILURE(rc))
     3384                        return rc;
     3385                    rc = ssmR3DataWriteRaw(pSSM, pvBuf, PAGE_SIZE);
     3386                    if (RT_FAILURE(rc))
     3387                        return rc;
     3388                }
     3389                if (cbBuf == PAGE_SIZE)
     3390                    return VINF_SUCCESS;
     3391                cbBuf -= PAGE_SIZE;
     3392                pvBuf = (uint8_t const*)pvBuf + PAGE_SIZE;
     3393            }
     3394            else
     3395            {
     3396                /* Less than one page, just store it. */
     3397                rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
     3398                if (RT_SUCCESS(rc))
     3399                    rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf);
     3400                return rc;
     3401            }
     3402        }
    33753403    }
    33763404    return rc;
    33773405}
     3406
    33783407
    33793408/**
     
    38873916static void ssmR3DataReadFinishV1(PSSMHANDLE pSSM)
    38883917{
    3889     if (pSSM->u.Read.pZipDecomp)
    3890     {
    3891         int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecomp);
     3918    if (pSSM->u.Read.pZipDecompV1)
     3919    {
     3920        int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
    38923921        AssertRC(rc);
    3893         pSSM->u.Read.pZipDecomp = NULL;
     3922        pSSM->u.Read.pZipDecompV1 = NULL;
    38943923    }
    38953924}
     
    39463975     * Open the decompressor on the first read.
    39473976     */
    3948     if (!pSSM->u.Read.pZipDecomp)
    3949     {
    3950         pSSM->rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecomp, pSSM, ssmR3ReadInV1);
     3977    if (!pSSM->u.Read.pZipDecompV1)
     3978    {
     3979        pSSM->rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecompV1, pSSM, ssmR3ReadInV1);
    39513980        if (RT_FAILURE(pSSM->rc))
    39523981            return pSSM->rc;
     
    39563985     * Do the requested read.
    39573986     */
    3958     int rc = pSSM->rc = RTZipDecompress(pSSM->u.Read.pZipDecomp, pvBuf, cbBuf, NULL);
     3987    int rc = pSSM->rc = RTZipDecompress(pSSM->u.Read.pZipDecompV1, pvBuf, cbBuf, NULL);
    39593988    if (RT_SUCCESS(rc))
    39603989    {
     
    39693998
    39703999/**
    3971  * Callback for reading compressed data into the input buffer of the
    3972  * decompressor, for saved file format version 2.
    3973  *
    3974  * @returns VBox status code.
    3975  * @param   pvSSM       The SSM handle.
    3976  * @param   pvBuf       Where to store the compressed data.
    3977  * @param   cbBuf       Size of the buffer.
    3978  * @param   pcbRead     Number of bytes actually stored in the buffer.
    3979  */
    3980 static DECLCALLBACK(int) ssmR3ReadInV2(void *pvSSM, void *pvBuf, size_t cbBuf, size_t *pcbRead)
    3981 {
    3982     PSSMHANDLE  pSSM   = (PSSMHANDLE)pvSSM;
    3983     //Log2(("ssmR3ReadInV2: %#010llx cbBug=%#x cbRead=%#x\n", RTFileTell(pSSM->hFile), cbBuf, cbRead));
    3984     int rc = ssmR3StrmRead(pSSM, pvBuf, cbBuf);
    3985     if (RT_SUCCESS(rc))
    3986     {
    3987         if (pcbRead)
    3988             *pcbRead = cbBuf;
    3989         ssmR3Progress(pSSM, cbBuf);
    3990         return VINF_SUCCESS;
    3991     }
    3992     /** @todo weed out lazy saving */
    3993     if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
    3994         AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
    3995     return VERR_SSM_LOADED_TOO_MUCH;
    3996 }
    3997 
    3998 
    3999 /**
    40004000 * Creates the decompressor for the data unit.
    40014001 *
     
    40064006static void ssmR3DataReadBeginV2(PSSMHANDLE pSSM)
    40074007{
    4008     Assert(!pSSM->u.Read.pZipDecomp);
    40094008    Assert(!pSSM->u.Read.cbDataBuffer || pSSM->u.Read.cbDataBuffer == pSSM->u.Read.offDataBuffer);
    40104009    Assert(!pSSM->u.Read.cbRecLeft);
    40114010
    40124011    pSSM->offUnit = 0;
    4013     pSSM->u.Read.pZipDecomp     = NULL;
    40144012    pSSM->u.Read.cbRecLeft      = 0;
    40154013    pSSM->u.Read.cbDataBuffer   = 0;
     
    40174015    pSSM->u.Read.fEndOfData     = false;
    40184016    pSSM->u.Read.u8TypeAndFlags = 0;
    4019 
    4020     int rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecomp, pSSM, ssmR3ReadInV2);
    4021     if (RT_FAILURE(rc) && RT_SUCCESS(pSSM->rc))
    4022         pSSM->rc = rc;
    40234017}
    40244018
     
    40334027static void ssmR3DataReadFinishV2(PSSMHANDLE pSSM)
    40344028{
    4035     if (RT_UNLIKELY(!pSSM->u.Read.pZipDecomp))
    4036     {
    4037         Assert(RT_FAILURE_NP(pSSM->rc));
    4038         return;
    4039     }
    4040 
    40414029    /*
    40424030     * If we haven't encountered the end of the record, it must be the next one.
     
    40514039        pSSM->rc = rc;
    40524040    }
    4053 
    4054     /*
    4055      * Destroy the decompressor.
    4056      */
    4057     int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecomp);
    4058     if (RT_FAILURE(rc))
    4059     {
    4060         AssertRC(rc);
    4061         if (RT_SUCCESS(pSSM->rc))
    4062             pSSM->rc = rc;
    4063     }
    4064     pSSM->u.Read.pZipDecomp = NULL;
    40654041}
    40664042
     
    40794055DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead)
    40804056{
    4081     int rc = RTZipDecompress(pSSM->u.Read.pZipDecomp, pvBuf, cbToRead, NULL);
     4057    /** @todo buffered reads! (at some level or another) */
     4058    int rc = ssmR3StrmRead(pSSM, pvBuf, cbToRead);
     4059    if (RT_SUCCESS(rc))
     4060    {
     4061        pSSM->offUnit += cbToRead;
     4062        if (pSSM->fUnitChecksummed)
     4063            pSSM->u32UnitCRC = RTCrc32Process(pSSM->u32UnitCRC, pvBuf, cbToRead);
     4064
     4065        ssmR3Progress(pSSM, cbToRead);
     4066        return VINF_SUCCESS;
     4067    }
     4068
     4069    /** @todo weed out lazy saving */
     4070    if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
     4071        AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
     4072    return VERR_SSM_LOADED_TOO_MUCH;
     4073}
     4074
     4075
     4076/**
     4077 * Reads and checks the LZF "header".
     4078 *
     4079 * @returns VBox status code.
     4080 * @param   pSSM            The saved state handle..
     4081 * @param   pcbDecompr      Where to store the size of the decompressed data.
     4082 */
     4083DECLINLINE(int) ssmR3DataReadV2RawLzfHdr(PSSMHANDLE pSSM, size_t *pcbDecompr)
     4084{
     4085    *pcbDecompr = 0; /* shuts up gcc. */
     4086    AssertLogRelMsgReturn(   pSSM->u.Read.cbRecLeft > 1
     4087                          && pSSM->u.Read.cbRecLeft <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abComprBuffer) + 2,
     4088                          ("%#x\n", pSSM->u.Read.cbRecLeft),
     4089                          VERR_SSM_INTEGRITY);
     4090
     4091/** @todo this isn't very efficient, we know we have to read it all, so both
     4092 *        reading the first byte separately.  */
     4093    uint8_t cPages;
     4094    int rc = ssmR3DataReadV2Raw(pSSM, &cPages, 1);
    40824095    if (RT_FAILURE(rc))
    40834096        return rc;
    4084     pSSM->offUnit += cbToRead;
    4085     if (pSSM->fUnitChecksummed)
    4086         pSSM->u32UnitCRC = RTCrc32Process(pSSM->u32UnitCRC, pvBuf, cbToRead);
     4097    pSSM->u.Read.cbRecLeft -= sizeof(cPages);
     4098
     4099    size_t cbDecompr = (size_t)cPages * PAGE_SIZE;
     4100    AssertLogRelMsgReturn(   cbDecompr >= pSSM->u.Read.cbRecLeft
     4101                          && cbDecompr <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
     4102                          ("%#x\n", cbDecompr),
     4103                          VERR_SSM_INTEGRITY);
     4104
     4105    *pcbDecompr = cbDecompr;
    40874106    return VINF_SUCCESS;
     4107}
     4108
     4109
     4110/**
     4111 * Reads an LZF block from the stream and decompresses into the specified
     4112 * buffer.
     4113 *
     4114 * @returns VBox status code.
     4115 * @param   SSM             The saved state handle.
     4116 * @param   pvDst           Pointer to the output buffer.
     4117 * @param   cbDecompr       The size of the decompressed data.
     4118 */
     4119static int ssmR3DataReadV2RawLzf(PSSMHANDLE pSSM, void *pvDst, size_t cbDecompr)
     4120{
     4121    /** @todo optimize this wrt to stream buffering when that is added. */
     4122    uint32_t cbCompr = pSSM->u.Read.cbRecLeft;
     4123    pSSM->u.Read.cbRecLeft = 0;
     4124
     4125    int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
     4126    if (RT_SUCCESS(rc))
     4127    {
     4128        size_t cbDstActual;
     4129        rc = RTZipBlockDecompress(RTZIPTYPE_LZF, 0 /*fFlags*/,
     4130                                  &pSSM->u.Read.abComprBuffer[0], cbCompr, NULL /*pcbSrcActual*/,
     4131                                  pvDst, cbDecompr, &cbDstActual);
     4132        if (RT_SUCCESS(rc))
     4133        {
     4134            AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), VERR_SSM_INTEGRITY);
     4135            return VINF_SUCCESS;
     4136        }
     4137    }
     4138    return rc;
    40884139}
    40894140
     
    41444195        }
    41454196
    4146         Log3(("ssmR3DataReadRecHdrV2: %08llx: TERM\n", pSSM->offUnit));
     4197        Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx: TERM\n", ssmR3StrmTell(pSSM) - sizeof(SSMRECTERM), pSSM->offUnit));
    41474198        return VINF_SUCCESS;
    41484199    }
     
    41784229        if (RT_FAILURE(rc))
    41794230            return rc;
    4180 Log(("ssmR3DataReadRecHdrV2: cb=%u %.*Rhxs\n", cb, cb + 1, abHdr));
    41814231
    41824232        /*
     
    42474297    }
    42484298
    4249     Log3(("ssmR3DataReadRecHdrV2: %08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
    4250           pSSM->offUnit, pSSM->u.Read.cbRecLeft,
     4299    Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
     4300          ssmR3StrmTell(pSSM), pSSM->offUnit, pSSM->u.Read.cbRecLeft,
    42514301          pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK,
    42524302          !!(pSSM->u.Read.u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT),
     
    42744324    uint32_t off        = pSSM->u.Read.offDataBuffer;
    42754325    int32_t  cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
    4276     Log4(("ssmR3DataReadUnbufferedV2: %08llx/%08x/%08x: cbBuf=%#x\n", pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
     4326    Log4(("ssmR3DataReadUnbufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(pSSM), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
    42774327    if (cbInBuffer > 0)
    42784328    {
     
    43054355         * Read data from the current record.
    43064356         */
    4307         size_t cbToRead = RT_MIN(cbBuf, pSSM->u.Read.cbRecLeft);
    4308         int rc = ssmR3DataReadV2Raw(pSSM, pvBuf, cbToRead);
    4309         if (RT_FAILURE(rc))
    4310             return pSSM->rc = rc;
    4311         pSSM->u.Read.cbRecLeft -= cbToRead;
     4357        size_t cbToRead;
     4358        switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
     4359        {
     4360            case SSM_REC_TYPE_RAW:
     4361            {
     4362                cbToRead = RT_MIN(cbBuf, pSSM->u.Read.cbRecLeft);
     4363                int rc = ssmR3DataReadV2Raw(pSSM, pvBuf, cbToRead);
     4364                if (RT_FAILURE(rc))
     4365                    return pSSM->rc = rc;
     4366                pSSM->u.Read.cbRecLeft -= cbToRead;
     4367                break;
     4368            }
     4369
     4370            case SSM_REC_TYPE_RAW_LZF:
     4371            {
     4372                size_t cbDecompr;
     4373                int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbDecompr);
     4374                if (RT_FAILURE(rc))
     4375                    return rc;
     4376                if (cbBuf >= cbDecompr)
     4377                {
     4378                    cbToRead = cbDecompr;
     4379                    rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbDecompr);
     4380                    if (RT_FAILURE(rc))
     4381                        return rc;
     4382                }
     4383                else
     4384                {
     4385                    /* output buffer is too small, use the data buffer. */
     4386                    rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbDecompr);
     4387                    if (RT_FAILURE(rc))
     4388                        return rc;
     4389                    memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbBuf);
     4390                    pSSM->u.Read.cbDataBuffer = cbDecompr;
     4391                    pSSM->u.Read.offDataBuffer = cbBuf;
     4392                    cbToRead = cbBuf;
     4393                }
     4394                break;
     4395            }
     4396
     4397            default:
     4398                AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), VERR_INTERNAL_ERROR_5);
     4399        }
     4400
    43124401        cbBuf -= cbToRead;
    43134402        pvBuf = (uint8_t *)pvBuf + cbToRead;
    43144403    } while (cbBuf > 0);
    43154404
    4316     Log4(("ssmR3DataReadUnBufferedV2: %08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
    4317           pSSM->offUnit, pSSM->u.Read.cbRecLeft, 0, cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
     4405    Log4(("ssmR3DataReadUnBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
     4406          ssmR3StrmTell(pSSM), pSSM->offUnit, pSSM->u.Read.cbRecLeft, 0, cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
    43184407    return VINF_SUCCESS;
    43194408}
     
    43374426    uint32_t off        = pSSM->u.Read.offDataBuffer;
    43384427    int32_t  cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
    4339     Log4(("ssmR3DataReadBufferedV2: %08llx/%08x/%08x: cbBuf=%#x\n", pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
     4428    Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(pSSM), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
    43404429    if (cbInBuffer > 0)
    43414430    {
     
    43694458         * LATER: optimize by reading directly into the output buffer for some cases.
    43704459         */
    4371         size_t cbToRead = RT_MIN(sizeof(pSSM->u.Read.abDataBuffer), pSSM->u.Read.cbRecLeft);
    4372         int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
    4373         if (RT_FAILURE(rc))
    4374             return pSSM->rc = rc;
    4375         pSSM->u.Read.cbRecLeft -= cbToRead;
    4376         pSSM->u.Read.cbDataBuffer = cbToRead;
     4460        size_t cbToRead;
     4461        switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
     4462        {
     4463            case SSM_REC_TYPE_RAW:
     4464            {
     4465                cbToRead = RT_MIN(sizeof(pSSM->u.Read.abDataBuffer), pSSM->u.Read.cbRecLeft);
     4466                int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
     4467                if (RT_FAILURE(rc))
     4468                    return pSSM->rc = rc;
     4469                pSSM->u.Read.cbRecLeft -= cbToRead;
     4470                pSSM->u.Read.cbDataBuffer = cbToRead;
     4471                break;
     4472            }
     4473
     4474            case SSM_REC_TYPE_RAW_LZF:
     4475            {
     4476                size_t cbDecompr;
     4477                int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbDecompr);
     4478                if (RT_FAILURE(rc))
     4479                    return rc;
     4480                cbToRead = cbDecompr;
     4481                rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
     4482                if (RT_FAILURE(rc))
     4483                    return rc;
     4484                pSSM->u.Read.cbDataBuffer = cbToRead;
     4485                break;
     4486            }
     4487
     4488            default:
     4489                AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), VERR_INTERNAL_ERROR_5);
     4490        }
    43774491        /*pSSM->u.Read.offDataBuffer = 0;*/
    43784492
     
    43874501    } while (cbBuf > 0);
    43884502
    4389     Log4(("ssmR3DataReadBufferedV2: %08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
    4390           pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
     4503    Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
     4504          ssmR3StrmTell(pSSM), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
    43914505          cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
    43924506    return VINF_SUCCESS;
     
    44264540    pSSM->u.Read.offDataBuffer = off + cbBuf;
    44274541    Log4((cbBuf
    4428           ? "ssmR3DataRead: %08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n"
    4429           : "ssmR3DataRead: %08llx/%08x/%08x: cbBuf=%#x\n",
    4430           pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
     4542          ? "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n"
     4543          : "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n",
     4544          ssmR3StrmTell(pSSM), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
    44314545          cbBuf, RT_MIN(SSM_LOG_BYTES, cbBuf), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
    44324546
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