Uploaded image for project: 'Couchbase Server'
  1. Couchbase Server
  2. MB-63243

Magma does not allocate aligned buffers correctly

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Blocker
    • Morpheus
    • None
    • storage-engine
    • Untriaged
    • 0
    • Unknown

    Description

      Since we moved to using cb_aligned_alloc in https://review.couchbase.org/c/magma/+/206686, we have a bug as the allocation size provided does not meet the requirements of the API.

      This is reported by clang-15.

      ==311003==ERROR: AddressSanitizer: invalid alignment requested in aligned_alloc: 4096, alignment must be a power of two and the requested size 0x47dabd must be a multiple of alignment (thread T5211 (mg:flusher:2))
          #0 0x7b5f40 in aligned_alloc /tmp/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:113:3
          #1 0x434d212 in cb::SystemArenaMalloc::aligned_alloc(unsigned long, unsigned long) /home/trond/compile/asan/platform/src/system_arena_malloc.cc:148:16
          #2 0x14bf419 in cb::_ArenaMalloc<cb::SystemArenaMalloc>::aligned_alloc(unsigned long, unsigned long) /home/trond/compile/asan/platform/include/platform/cb_arena_malloc.h:242:16
          #3 0x14bf419 in cb_aligned_alloc /home/trond/compile/asan/platform/src/cb_malloc_arena.cc:58:17
          #4 0x473cf2b in magma::Buffer::resize(unsigned long, unsigned long, double) /home/trond/compile/asan/magma/util/buffer.cc:95:24
          #5 0x473d454 in magma::Buffer::Reserve(unsigned long, unsigned long, double, bool) /home/trond/compile/asan/magma/util/buffer.cc
          #6 0x473ddfe in magma::Buffer::Allocate(unsigned long, bool) /home/trond/compile/asan/magma/util/buffer.cc:159:9
          #7 0x471972a in magma::BufferedFileWriter::Write(char const*, unsigned long, bool) /home/trond/compile/asan/magma/util/rw_file.cc:554:23
          #8 0x471afb6 in magma::BufferedFileWriter::Write(folly::IOBuf const&, bool) /home/trond/compile/asan/magma/util/rw_file.cc:528:18
          #9 0x45c1bea in magma::SSTableWriter::writeBlock(folly::IOBuf const&, magma::BlockType, magma::BlockPointer*) /home/trond/compile/asan/magma/lsm/sstable/sstable_writer.cc:362:17
          #10 0x45c0ee0 in magma::SSTableWriter::writeDataBlock(magma::BlockBuilder&) /home/trond/compile/asan/magma/lsm/sstable/sstable_writer.cc:140:14
          #11 0x45c3fa0 in magma::SSTableWriter::AddKV(magma::Slice const&, folly::IOBuf const&, bool) /home/trond/compile/asan/magma/lsm/sstable/sstable_writer.cc:202:17
          #12 0x4620253 in magma::LSMTree::gcOutputCallback::addKV(magma::LSMTree::gcOutputCallback::gcSSTableWriter&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation) /home/trond/compile/asan/magma/lsm/lsm_tree.cc:835:30
          #13 0x4620610 in magma::LSMTree::gcOutputCallback::operator()(std::pair<magma::Slice, folly::IOBuf>&, magma::Operation) /home/trond/compile/asan/magma/lsm/lsm_tree.cc:861:18
          #14 0x46791a6 in magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18::operator()(std::pair<magma::Slice, folly::IOBuf>&, magma::Operation) const /home/trond/compile/asan/magma/lsm/lsm_tree.cc:817:16
          #15 0x46791a6 in magma::Status std::__invoke_impl<magma::Status, magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation>(std::__invoke_other, magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation&&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:60:14
          #16 0x46791a6 in std::enable_if<is_invocable_r_v<magma::Status, magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation>, magma::Status>::type std::__invoke_r<magma::Status, magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation>(magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation&&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:113:9
          #17 0x46791a6 in std::_Function_handler<magma::Status (std::pair<magma::Slice, folly::IOBuf>&, magma::Operation), magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool)::$_18>::_M_invoke(std::_Any_data const&, std::pair<magma::Slice, folly::IOBuf>&, magma::Operation&&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/std_function.h:291:9
          #18 0x45740cf in std::function<magma::Status (std::pair<magma::Slice, folly::IOBuf>&, magma::Operation)>::operator()(std::pair<magma::Slice, folly::IOBuf>&, magma::Operation) const /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/std_function.h:622:14
          #19 0x4563317 in magma::ItemGCFilter::Process(magma::KVReader::KVStream&, std::function<magma::Status (std::pair<magma::Slice, folly::IOBuf>&, magma::Operation)>, bool) /home/trond/compile/asan/magma/lsm/mvcc.cc:223:22
          #20 0x4620008 in magma::LSMTree::addKVs(magma::KVReader&, magma::LSMTree::gcOutputCallback&, magma::ItemGCFilter&, bool) /home/trond/compile/asan/magma/lsm/lsm_tree.cc:819:15
          #21 0x461f41a in magma::LSMTree::writeSSTable(magma::SSTableWriter&, magma::Iterator*, long, std::function<bool (magma::Slice const&)>) /home/trond/compile/asan/magma/lsm/lsm_tree.cc:887:18
          #22 0x461e4e0 in magma::LSMTree::writeSSTable(bool, magma::Iterator*, unsigned long, long, bool, std::function<bool (magma::Slice const&)>) /home/trond/compile/asan/magma/lsm/lsm_tree.cc:762:17
          #23 0x461b5c0 in magma::LSMTree::writeMemtable(magma::Memtable*, bool)::$_14::operator()(magma::Iterator*) const /home/trond/compile/asan/magma/lsm/lsm_tree.cc:537:17
          #24 0x4619dd4 in magma::LSMTree::writeMemtable(magma::Memtable*, bool) /home/trond/compile/asan/magma/lsm/lsm_tree.cc:570:22
          #25 0x461bfcf in magma::LSMTree::doMemtableFlushWork() /home/trond/compile/asan/magma/lsm/lsm_tree.cc:614:18
          #26 0x4679528 in magma::LSMTree::newFlush()::$_23::operator()() const /home/trond/compile/asan/magma/lsm/lsm_tree.cc:1175:34
          #27 0x4679528 in std::tuple<magma::Status, magma::CheckpointTransaction> std::__invoke_impl<std::tuple<magma::Status, magma::CheckpointTransaction>, magma::LSMTree::newFlush()::$_23&>(std::__invoke_other, magma::LSMTree::newFlush()::$_23&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:60:14
          #28 0x4679528 in std::enable_if<is_invocable_r_v<std::tuple<magma::Status, magma::CheckpointTransaction>, magma::LSMTree::newFlush()::$_23&>, std::tuple<magma::Status, magma::CheckpointTransaction>>::type std::__invoke_r<std::tuple<magma::Status, magma::CheckpointTransaction>, magma::LSMTree::newFlush()::$_23&>(magma::LSMTree::newFlush()::$_23&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:113:9
          #29 0x4679528 in std::_Function_handler<std::tuple<magma::Status, magma::CheckpointTransaction> (), magma::LSMTree::newFlush()::$_23>::_M_invoke(std::_Any_data const&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/std_function.h:291:9
          #30 0x46907d1 in std::function<std::tuple<magma::Status, magma::CheckpointTransaction> ()>::operator()() const /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/std_function.h:622:14
          #31 0x4618634 in magma::FlushWork::Execute() /home/trond/compile/asan/magma/lsm/flush_work.cc:70:29
          #32 0x465493a in magma::KVStore::executeFlush(std::shared_ptr<magma::FlushWork>, std::shared_ptr<magma::FlushWork>, std::shared_ptr<magma::FlushWork>, magma::KVStore::bulkLoadArgs) /home/trond/compile/asan/magma/magma/kvstore/kvstore.cc:661:23
          #33 0x4655e4e in magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55::operator()() /home/trond/compile/asan/magma/magma/kvstore/kvstore.cc:845:19
          #34 0x46815b1 in magma::Status std::__invoke_impl<magma::Status, magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55&>(std::__invoke_other, magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:60:14
          #35 0x46815b1 in std::enable_if<is_invocable_r_v<void, magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55&>, void>::type std::__invoke_r<void, magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55&>(magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:110:2
          #36 0x46815b1 in std::_Function_handler<void (), magma::KVStore::flushMemTables(magma::WAL*, magma::WALOffset, magma::KVStore::FlushMode, magma::BlockingMode, magma::KVStore::bulkLoadArgs)::$_55>::_M_invoke(std::_Any_data const&) /opt/gcc-10.2.0/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/std_function.h:291:9
          #37 0x46e0844 in magma::TimedTask::Complete(bool) /home/trond/compile/asan/magma/util/worker.cc
          #38 0x46e0b8d in magma::TaskWorker::loop(void*) /home/trond/compile/asan/magma/util/worker.cc:180:19 

      Additionally,

      the cb_* allocation functions do not throw bad_alloc (unlike the new operators do), so we must explicitly check for nullptr before proceeding to use them.

      if (alignBoundary > 1) {
              Expects(alignBoundary % 2 == 0);
              newOwnership = cb_aligned_alloc(alignBoundary, newCap);
              isAligned = true;
          } else {
              newOwnership = cb_malloc(newCap);
              isAligned = false;
          }
       
          if (preserve) {
              std::copy(data, data + preserve, (char*)newOwnership);
          } 

      Thanks to Trond Norbye for reporting the bug.

      Attachments

        Issue Links

          Activity

            People

              rohan.suri Rohan Suri
              rohan.suri Rohan Suri
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                PagerDuty