From e32f8395a291bbec93232487357abc66aaf05f2e Mon Sep 17 00:00:00 2001 From: Igor Fedotov Date: Wed, 29 Apr 2020 19:56:41 +0300 Subject: [PATCH] tests/objectstore: introduce unittest_bdev Currently reproduces https://tracker.ceph.com/issues/45337 only. To be extended with more block device UTs. Signed-off-by: Igor Fedotov (cherry picked from commit d6fcc9c1b1b9301797899204241e53ff66b39187) --- src/test/objectstore/CMakeLists.txt | 8 ++ src/test/objectstore/test_bdev.cc | 111 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100755 src/test/objectstore/test_bdev.cc diff --git a/src/test/objectstore/CMakeLists.txt b/src/test/objectstore/CMakeLists.txt index 506f3f6e5e38f..be9951d6ef908 100644 --- a/src/test/objectstore/CMakeLists.txt +++ b/src/test/objectstore/CMakeLists.txt @@ -118,6 +118,14 @@ if(WITH_BLUESTORE) ) add_ceph_unittest(unittest_bluestore_types) target_link_libraries(unittest_bluestore_types os global) + + # unittest_bdev + add_executable(unittest_bdev + test_bdev.cc + ) + add_ceph_unittest(unittest_bdev) + target_link_libraries(unittest_bdev os global) + endif(WITH_BLUESTORE) # unittest_transaction diff --git a/src/test/objectstore/test_bdev.cc b/src/test/objectstore/test_bdev.cc new file mode 100755 index 0000000000000..09a5226ebcd56 --- /dev/null +++ b/src/test/objectstore/test_bdev.cc @@ -0,0 +1,111 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +#include +#include +#include +#include "global/global_init.h" +#include "global/global_context.h" +#include "common/ceph_context.h" +#include "common/ceph_argparse.h" +#include "include/stringify.h" +#include "common/errno.h" + +#include "os/bluestore/BlockDevice.h" + +class TempBdev { +public: + TempBdev(uint64_t size) + : path{get_temp_bdev(size)} + {} + ~TempBdev() { + rm_temp_bdev(path); + } + const std::string path; +private: + static string get_temp_bdev(uint64_t size) + { + static int n = 0; + string fn = "ceph_test_bluefs.tmp.block." + stringify(getpid()) + + "." + stringify(++n); + int fd = ::open(fn.c_str(), O_CREAT|O_RDWR|O_TRUNC, 0644); + ceph_assert(fd >= 0); + int r = ::ftruncate(fd, size); + ceph_assert(r >= 0); + ::close(fd); + return fn; + } + static void rm_temp_bdev(string f) + { + ::unlink(f.c_str()); + } +}; + +TEST(KernelDevice, Ticket45337) { + // Large (>=2 GB) writes are incomplete when bluefs_buffered_io = true + + uint64_t size = 1048576ull * 8192; + TempBdev bdev{ size }; + + const bool buffered = true; + + std::unique_ptr b( + BlockDevice::create(g_ceph_context, bdev.path, NULL, NULL, + [](void* handle, void* aio) {}, NULL)); + bufferlist bl; + // writing a bit less than 4GB + for (auto i = 0; i < 4000; i++) { + string s(1048576, 'a' + (i % 28)); + bl.append(s); + } + uint64_t magic_offs = bl.length(); + string s(4086, 'z'); + s += "0123456789"; + bl.append(s); + + { + int r = b->open(bdev.path); + if (r < 0) { + std::cerr << "open " << bdev.path << " failed" << std::endl; + return; + } + } + std::unique_ptr ioc(new IOContext(g_ceph_context, NULL)); + + auto r = b->aio_write(0, bl, ioc.get(), buffered); + ASSERT_EQ(r, 0); + + if (ioc->has_pending_aios()) { + b->aio_submit(ioc.get()); + ioc->aio_wait(); + } + + char outbuf[0x1000]; + r = b->read_random(magic_offs, sizeof(outbuf), outbuf, buffered); + ASSERT_EQ(r, 0); + ASSERT_EQ(memcmp(s.c_str(), outbuf, sizeof(outbuf)), 0); + + b->close(); +} + +int main(int argc, char **argv) { + vector args; + argv_to_vec(argc, (const char **)argv, args); + + map defaults = { + { "debug_bdev", "1/20" } + }; + + auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + common_init_finish(g_ceph_context); + g_ceph_context->_conf.set_val( + "enable_experimental_unrecoverable_data_corrupting_features", + "*"); + g_ceph_context->_conf.apply_changes(nullptr); + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- 2.39.5