Changeset 21856 in vbox
- Timestamp:
- Jul 28, 2009 6:28:01 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 50492
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/src/VBox/VMM/Makefile.kmk ¶
r21496 r21856 107 107 PGMPool.cpp \ 108 108 SELM.cpp \ 109 SSM .cpp \109 SSM$(if-expr defined(VBOX_WITH_NEW_SSM),-new,).cpp \ 110 110 STAM.cpp \ 111 111 TM.cpp \ -
TabularUnified trunk/src/VBox/VMM/SSM-new.cpp ¶
r21799 r21856 99 99 * - type 1: Terminator with CRC-32 and unit size. 100 100 * - 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. 103 108 * - bit 4: Important (set), can be skipped (clear). 104 109 * - bit 5: Undefined flag, must be zero. … … 109 114 * encoded in UTF-8 style. 110 115 * 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.) 116 119 * 117 120 * … … 141 144 #include <VBox/version.h> 142 145 146 #include <iprt/alloc.h> 143 147 #include <iprt/assert.h> 148 #include <iprt/crc32.h> 144 149 #include <iprt/file.h> 145 #include <iprt/alloc.h> 150 #include <iprt/param.h> 151 #include <iprt/thread.h> 152 #include <iprt/string.h> 146 153 #include <iprt/uuid.h> 147 154 #include <iprt/zip.h> 148 #include <iprt/crc32.h>149 #include <iprt/thread.h>150 #include <iprt/string.h>151 155 152 156 … … 199 203 /** Raw data. The data follows the size field without further ado. */ 200 204 #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 201 209 /** Named data items. 202 210 * A length prefix zero terminated string (i.e. max 255) followed by the data. */ 203 #define SSM_REC_TYPE_NAMED 3211 #define SSM_REC_TYPE_NAMED 4 204 212 /** Macro for validating the record type. 205 213 * This can be used with the flags+type byte, no need to mask out the type first. */ … … 321 329 struct 322 330 { 323 /** The compressor of the current data unit. */324 PRTZIPCOMP pZipComp;325 331 /** Offset into the databuffer. */ 326 332 uint32_t offDataBuffer; … … 334 340 struct 335 341 { 336 /** The decompressor of the current data unit. */337 PRTZIPDECOMP pZipDecomp ;342 /** V1: The decompressor of the current data unit. */ 343 PRTZIPDECOMP pZipDecompV1; 338 344 /** The major format version number. */ 339 345 uint32_t uFmtVerMajor; … … 380 386 /** @} */ 381 387 382 /** V2: Data buffer. */ 388 /** V2: Data buffer. 389 * @remarks Be extremely careful when changing the size of this buffer! */ 383 390 uint8_t abDataBuffer[4096]; 391 392 /** V2: Decompression buffer. 393 * @todo removed this when we start buffering the stream. */ 394 uint8_t abComprBuffer[4096]; 384 395 } Read; 385 396 } u; … … 417 428 /** Flags, see SSMFILEHDR_FLAGS_XXX. */ 418 429 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; 421 432 /** The checksum of this header. 422 433 * This field is set to zero when calculating the checksum. */ … … 1530 1541 Handle.fChecksummed = true; 1531 1542 Handle.u32StreamCRC = RTCrc32Start(); 1532 Handle.u.Write.pZipComp = NULL;1533 1543 Handle.u.Write.offDataBuffer = 0; 1534 1544 … … 1563 1573 u.FileHdr.cUnits = pVM->ssm.s.cUnits; 1564 1574 u.FileHdr.fFlags = SSMFILEHDR_FLAGS_STREAM_CRC32; 1565 u.FileHdr. u32Reserved = 0;1575 u.FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer); 1566 1576 u.FileHdr.u32CRC = 0; 1567 1577 u.FileHdr.u32CRC = RTCrc32(&u.FileHdr, sizeof(u.FileHdr)); … … 1829 1839 rc2 = RTFileDelete(pszFilename); 1830 1840 AssertRC(rc2); 1831 if (Handle.u.Write.pZipComp)1832 RTZipCompDestroy(Handle.u.Write.pZipComp);1833 1841 1834 1842 return rc; … … 1949 1957 /* validate the header. */ 1950 1958 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) 1953 1960 { 1954 LogRel(("SSM: Reserved header field s 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)); 1955 1962 return VERR_SSM_INTEGRITY; 1956 1963 } … … 1958 1965 { 1959 1966 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)); 1960 1974 return VERR_SSM_INTEGRITY; 1961 1975 } … … 2193 2207 pSSM->u32StreamCRC = 0; 2194 2208 2195 pSSM->u.Read.pZipDecomp 2209 pSSM->u.Read.pZipDecompV1 = NULL; 2196 2210 pSSM->u.Read.uFmtVerMajor = UINT32_MAX; 2197 2211 pSSM->u.Read.uFmtVerMinor = UINT32_MAX; … … 2839 2853 int rc = RTFileClose(pSSM->hFile); 2840 2854 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; 2845 2859 } 2846 2860 RTMemFree(pSSM); … … 3070 3084 * Reset the state. 3071 3085 */ 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; 3076 3090 } 3077 3091 pSSM->cbUnitLeftV1 = 0; … … 3101 3115 int rc = ssmR3DataFlushBuffer(pSSM); 3102 3116 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; 3119 3118 3120 3119 if (RT_SUCCESS(pSSM->rc)) … … 3126 3125 3127 3126 /** 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 * 3131 3131 * @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.3147 3132 */ 3148 3133 static void ssmR3DataWriteBegin(PSSMHANDLE pSSM) 3149 3134 { 3150 Assert(!pSSM->u.Write.pZipComp);3151 3152 pSSM->u.Write.pZipComp = NULL;3153 3135 pSSM->offUnit = 0; 3154 3136 if (pSSM->fUnitChecksummed) 3155 3137 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;3162 3138 } 3163 3139 … … 3173 3149 static int ssmR3DataWriteRaw(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf) 3174 3150 { 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 ? "..." : "")); 3176 3153 3177 3154 /* … … 3193 3170 { 3194 3171 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); 3196 3173 if (RT_FAILURE(rc)) 3197 3174 return rc; … … 3204 3181 return VINF_SUCCESS; 3205 3182 } 3183 3206 3184 3207 3185 /** … … 3266 3244 AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), pSSM->rc = VERR_INTERNAL_ERROR); 3267 3245 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)); 3270 3248 3271 3249 return ssmR3DataWriteRaw(pSSM, &abHdr[0], cbHdr); … … 3345 3323 pbHdr[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW; 3346 3324 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) )); 3349 3327 3350 3328 /* … … 3370 3348 if (RT_SUCCESS(rc)) 3371 3349 { 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 } 3375 3403 } 3376 3404 return rc; 3377 3405 } 3406 3378 3407 3379 3408 /** … … 3887 3916 static void ssmR3DataReadFinishV1(PSSMHANDLE pSSM) 3888 3917 { 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); 3892 3921 AssertRC(rc); 3893 pSSM->u.Read.pZipDecomp = NULL;3922 pSSM->u.Read.pZipDecompV1 = NULL; 3894 3923 } 3895 3924 } … … 3946 3975 * Open the decompressor on the first read. 3947 3976 */ 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); 3951 3980 if (RT_FAILURE(pSSM->rc)) 3952 3981 return pSSM->rc; … … 3956 3985 * Do the requested read. 3957 3986 */ 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); 3959 3988 if (RT_SUCCESS(rc)) 3960 3989 { … … 3969 3998 3970 3999 /** 3971 * Callback for reading compressed data into the input buffer of the3972 * 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 /**4000 4000 * Creates the decompressor for the data unit. 4001 4001 * … … 4006 4006 static void ssmR3DataReadBeginV2(PSSMHANDLE pSSM) 4007 4007 { 4008 Assert(!pSSM->u.Read.pZipDecomp);4009 4008 Assert(!pSSM->u.Read.cbDataBuffer || pSSM->u.Read.cbDataBuffer == pSSM->u.Read.offDataBuffer); 4010 4009 Assert(!pSSM->u.Read.cbRecLeft); 4011 4010 4012 4011 pSSM->offUnit = 0; 4013 pSSM->u.Read.pZipDecomp = NULL;4014 4012 pSSM->u.Read.cbRecLeft = 0; 4015 4013 pSSM->u.Read.cbDataBuffer = 0; … … 4017 4015 pSSM->u.Read.fEndOfData = false; 4018 4016 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;4023 4017 } 4024 4018 … … 4033 4027 static void ssmR3DataReadFinishV2(PSSMHANDLE pSSM) 4034 4028 { 4035 if (RT_UNLIKELY(!pSSM->u.Read.pZipDecomp))4036 {4037 Assert(RT_FAILURE_NP(pSSM->rc));4038 return;4039 }4040 4041 4029 /* 4042 4030 * If we haven't encountered the end of the record, it must be the next one. … … 4051 4039 pSSM->rc = rc; 4052 4040 } 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;4065 4041 } 4066 4042 … … 4079 4055 DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead) 4080 4056 { 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 */ 4083 DECLINLINE(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); 4082 4095 if (RT_FAILURE(rc)) 4083 4096 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; 4087 4106 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 */ 4119 static 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; 4088 4139 } 4089 4140 … … 4144 4195 } 4145 4196 4146 Log3(("ssmR3DataReadRecHdrV2: %08llx : TERM\n", pSSM->offUnit));4197 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx: TERM\n", ssmR3StrmTell(pSSM) - sizeof(SSMRECTERM), pSSM->offUnit)); 4147 4198 return VINF_SUCCESS; 4148 4199 } … … 4178 4229 if (RT_FAILURE(rc)) 4179 4230 return rc; 4180 Log(("ssmR3DataReadRecHdrV2: cb=%u %.*Rhxs\n", cb, cb + 1, abHdr));4181 4231 4182 4232 /* … … 4247 4297 } 4248 4298 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, 4251 4301 pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK, 4252 4302 !!(pSSM->u.Read.u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), … … 4274 4324 uint32_t off = pSSM->u.Read.offDataBuffer; 4275 4325 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)); 4277 4327 if (cbInBuffer > 0) 4278 4328 { … … 4305 4355 * Read data from the current record. 4306 4356 */ 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 4312 4401 cbBuf -= cbToRead; 4313 4402 pvBuf = (uint8_t *)pvBuf + cbToRead; 4314 4403 } while (cbBuf > 0); 4315 4404 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 ? "..." : "")); 4318 4407 return VINF_SUCCESS; 4319 4408 } … … 4337 4426 uint32_t off = pSSM->u.Read.offDataBuffer; 4338 4427 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)); 4340 4429 if (cbInBuffer > 0) 4341 4430 { … … 4369 4458 * LATER: optimize by reading directly into the output buffer for some cases. 4370 4459 */ 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 } 4377 4491 /*pSSM->u.Read.offDataBuffer = 0;*/ 4378 4492 … … 4387 4501 } while (cbBuf > 0); 4388 4502 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, 4391 4505 cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : "")); 4392 4506 return VINF_SUCCESS; … … 4426 4540 pSSM->u.Read.offDataBuffer = off + cbBuf; 4427 4541 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, 4431 4545 cbBuf, RT_MIN(SSM_LOG_BYTES, cbBuf), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : "")); 4432 4546
Note:
See TracChangeset
for help on using the changeset viewer.