From 849c2d25e981ca25f7e3bf6588b6b70ce255ebab Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 4 Sep 2013 21:29:11 -0700 Subject: common/crc32c_intel_fast: avoid reading partial trailing word The optimized intel code reads in word-sized chunks, knowing that the allocator will only hand out memory in word-sized increments. This makes valgrind unhappy. Whitelisting doesn't work because for some reason there is no caller context (probably because of some interaction with yasm?). Instead, just use the baseline code for the last few bytes. This should not be significant. Signed-off-by: Sage Weil --- src/common/crc32c_intel_fast.c | 18 +++++++++++++++++- src/test/common/test_crc32c.cc | 9 +++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) 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 #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); -- cgit v1.2.1