diff options
-rw-r--r-- | src/common/crc32c_intel_fast.c | 18 | ||||
-rw-r--r-- | src/test/common/test_crc32c.cc | 9 |
2 files changed, 26 insertions, 1 deletions
diff --git a/src/common/crc32c_intel_fast.c b/src/common/crc32c_intel_fast.c index b446fc1ecc5..49305088aff 100644 --- a/src/common/crc32c_intel_fast.c +++ b/src/common/crc32c_intel_fast.c @@ -1,5 +1,6 @@ #include <inttypes.h> #include "acconfig.h" +#include "common/crc32c_intel_baseline.h" extern unsigned int crc32_iscsi_00(unsigned char const *buffer, int len, unsigned int crc); @@ -7,7 +8,22 @@ extern unsigned int crc32_iscsi_00(unsigned char const *buffer, int len, unsigne uint32_t ceph_crc32c_intel_fast(uint32_t crc, unsigned char const *buffer, unsigned len) { - return crc32_iscsi_00(buffer, len, crc); + uint32_t v; + unsigned left; + + /* + * the crc32_iscsi_00 method reads past buffer+len (because it + * reads full words) which makes valgrind unhappy. don't do + * that. + */ + if (len < 16) + return ceph_crc32c_intel_baseline(crc, buffer, len); + left = ((unsigned long)buffer + len) & 7; + len -= left; + v = crc32_iscsi_00(buffer, len, crc); + if (left) + v = ceph_crc32c_intel_baseline(v, buffer + len, left); + return v; } int ceph_crc32c_intel_fast_exists(void) diff --git a/src/test/common/test_crc32c.cc b/src/test/common/test_crc32c.cc index 19a1dfb7284..5cf88de0a80 100644 --- a/src/test/common/test_crc32c.cc +++ b/src/test/common/test_crc32c.cc @@ -23,6 +23,15 @@ TEST(Crc32c, Small) { ASSERT_EQ(3743019208u, ceph_crc32c(5678, (unsigned char *)b, strlen(b))); } +TEST(Crc32c, PartialWord) { + const char *a = (const char *)malloc(5); + const char *b = (const char *)malloc(35); + memset((void *)a, 1, 5); + memset((void *)b, 1, 35); + ASSERT_EQ(2715569182u, ceph_crc32c(0, (unsigned char *)a, 5)); + ASSERT_EQ(440531800u, ceph_crc32c(0, (unsigned char *)b, 35)); +} + TEST(Crc32c, Big) { int len = 4096000; char *a = (char *)malloc(len); |