]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[ldm] Fix bug in overflow correction with large job size (#1678)
authorNick Terrell <terrelln@fb.com>
Fri, 12 Jul 2019 22:45:18 +0000 (18:45 -0400)
committerGitHub <noreply@github.com>
Fri, 12 Jul 2019 22:45:18 +0000 (18:45 -0400)
* [ldm] Fix bug in overflow correction with large job size

* [zstdmt] Respect ZSTDMT_JOBSIZE_MAX (1G in 64-bit mode)

* [test] Add test that exposes the bug

Sadly the test fails on our CI because it uses too much memory, so
I had to comment it out.

lib/compress/zstd_ldm.c
lib/compress/zstdmt_compress.c
lib/compress/zstdmt_compress.h
tests/playTests.sh

index 784d20f3ab71642631f230c77daaa7007a6d0864..3dcf86e6e8a32ac75399fc3bbe2442f86d76f980 100644 (file)
@@ -447,7 +447,7 @@ size_t ZSTD_ldm_generateSequences(
         if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) {
             U32 const ldmHSize = 1U << params->hashLog;
             U32 const correction = ZSTD_window_correctOverflow(
-                &ldmState->window, /* cycleLog */ 0, maxDist, src);
+                &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
             ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction);
         }
         /* 2. We enforce the maximum offset allowed.
index 5557b478e6f8ebea1ffbdf9dc719613debba3bd8..9e537b884853e1e582e4f84a65c0781be9ecee5c 100644 (file)
@@ -1153,12 +1153,16 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
 
 static unsigned ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params)
 {
-    if (params.ldmParams.enableLdm)
+    unsigned jobLog;
+    if (params.ldmParams.enableLdm) {
         /* In Long Range Mode, the windowLog is typically oversized.
          * In which case, it's preferable to determine the jobSize
          * based on chainLog instead. */
-        return MAX(21, params.cParams.chainLog + 4);
-    return MAX(20, params.cParams.windowLog + 2);
+        jobLog = MAX(21, params.cParams.chainLog + 4);
+    } else {
+        jobLog = MAX(20, params.cParams.windowLog + 2);
+    }
+    return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX);
 }
 
 static int ZSTDMT_overlapLog_default(ZSTD_strategy strat)
@@ -1396,7 +1400,7 @@ size_t ZSTDMT_initCStream_internal(
         FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) );
 
     if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
-    if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
+    if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;
 
     mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN);  /* do not trigger multi-threading when srcSize is too small */
     if (mtctx->singleBlockingThread) {
@@ -1437,6 +1441,8 @@ size_t ZSTDMT_initCStream_internal(
     if (mtctx->targetSectionSize == 0) {
         mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(params);
     }
+    assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX);
+
     if (params.rsyncable) {
         /* Aim for the targetsectionSize as the average job size. */
         U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
index 12e6bcb3a3389345f813b6c11161a031cb60c205..12a526087db4ee6b8e922d4af8872ecd2d573fd9 100644 (file)
@@ -50,6 +50,7 @@
 #ifndef ZSTDMT_JOBSIZE_MIN
 #  define ZSTDMT_JOBSIZE_MIN (1 MB)
 #endif
+#define ZSTDMT_JOBLOG_MAX   (MEM_32bits() ? 29 : 30)
 #define ZSTDMT_JOBSIZE_MAX  (MEM_32bits() ? (512 MB) : (1024 MB))
 
 
index 2b8843f9784839c56d950d521d30df27a9c540e3..69387321f92fac4fbc17b3a8ab9873eadd702c82 100755 (executable)
@@ -974,6 +974,10 @@ then
     roundTripTest -g500000000 -P97 "1 -T999" " "
     fileRoundTripTest -g4103M -P98 " -T0" " "
     roundTripTest -g400000000 -P97 "1 --long=24 -T2" " "
+    # Exposes the bug in https://github.com/facebook/zstd/pull/1678
+    # This test fails on 4 different travis builds at the time of writing
+    # because it needs to allocate 8 GB of memory.
+    # roundTripTest -g10G -P99 "1 -T1 --long=31 --zstd=clog=27 --fast=1000"
 else
     println "\n**** no multithreading, skipping zstdmt tests **** "
 fi