diff --git a/block-cache/copier.cc b/block-cache/copier.cc index c130e14..a1e9a5f 100644 --- a/block-cache/copier.cc +++ b/block-cache/copier.cc @@ -37,6 +37,7 @@ copier::issue(copy_op const &op) job.op.read_complete = job.op.write_complete = false; unsigned key = genkey(); // used as context for the io_engine + cerr << "data = " << &(*data) << "\n"; engine_.issue_io(src_handle_, io_engine::READ, to_sector(op.src_b), diff --git a/block-cache/copier.h b/block-cache/copier.h index 28fdd8a..24e1b38 100644 --- a/block-cache/copier.h +++ b/block-cache/copier.h @@ -19,6 +19,17 @@ namespace bcache { write_complete(false) { } + + copy_op(block_address src_b_, + block_address src_e_, + block_address dest_b_) + : src_b(src_b_), + src_e(src_e_), + dest_b(dest_b_), + read_complete(false), + write_complete(false) { + } + block_address src_b, src_e; block_address dest_b; diff --git a/block-cache/mem_pool.cc b/block-cache/mem_pool.cc index f655fd0..db5cc9e 100644 --- a/block-cache/mem_pool.cc +++ b/block-cache/mem_pool.cc @@ -1,18 +1,19 @@ #include "block-cache/mem_pool.h" +#include +#include #include using namespace bcache; using namespace boost; using namespace mempool_detail; - -#define PAGE_SIZE 4096 +using namespace std; //---------------------------------------------------------------- -mempool::mempool(size_t block_size, size_t total_mem) +mempool::mempool(size_t block_size, size_t total_mem, size_t alignment) { - mem_ = alloc_aligned(total_mem, PAGE_SIZE); + mem_ = alloc_aligned(total_mem, alignment); unsigned nr_blocks = total_mem / block_size; for (auto i = 0u; i < nr_blocks; i++) @@ -21,6 +22,7 @@ mempool::mempool(size_t block_size, size_t total_mem) mempool::~mempool() { + free_.clear(); ::free(mem_); } @@ -47,8 +49,11 @@ mempool::alloc_aligned(size_t len, size_t alignment) { void *result = NULL; int r = posix_memalign(&result, alignment, len); - if (r) - return NULL; + if (r) { + ostringstream out; + out << "posix_memalign failed: len = " << len << ", alignment = " << alignment << ", r = " << r << "\n"; + throw runtime_error(out.str()); + } return result; } diff --git a/block-cache/mem_pool.h b/block-cache/mem_pool.h index 61c1812..50328d3 100644 --- a/block-cache/mem_pool.h +++ b/block-cache/mem_pool.h @@ -13,13 +13,14 @@ namespace bcache { // FIXME: move to base? namespace mempool_detail { - struct alloc_block : public bi::list_base_hook<> { + struct alloc_block : public bi::list_base_hook> { }; }; class mempool { public: - mempool(size_t block_size, size_t total_mem); + // alignment must be a power of 2 + mempool(size_t block_size, size_t total_mem, size_t alignment = 8); ~mempool(); boost::optional alloc(); diff --git a/unit-tests/Makefile.in b/unit-tests/Makefile.in index 38f3d04..8746456 100644 --- a/unit-tests/Makefile.in +++ b/unit-tests/Makefile.in @@ -55,9 +55,11 @@ TEST_SOURCE=\ unit-tests/btree_counter_t.cc \ unit-tests/btree_damage_visitor_t.cc \ unit-tests/cache_superblock_t.cc \ + unit-tests/copier_t.cc \ unit-tests/damage_tracker_t.cc \ unit-tests/endian_t.cc \ unit-tests/error_state_t.cc \ + unit-tests/mem_pool_t.cc \ unit-tests/rmap_visitor_t.cc \ unit-tests/rolling_hash_t.cc \ unit-tests/run_set_t.cc \ diff --git a/unit-tests/copier_t.cc b/unit-tests/copier_t.cc new file mode 100644 index 0000000..b366ff8 --- /dev/null +++ b/unit-tests/copier_t.cc @@ -0,0 +1,103 @@ +// Copyright (C) 2016 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#include "gmock/gmock.h" +#include "block-cache/copier.h" +#include "test_utils.h" + + +#include + +using namespace boost; +using namespace std; +using namespace test; +using namespace testing; + +//---------------------------------------------------------------- + +namespace { + class temp_file { + public: + temp_file(string const &name_base, unsigned meg_size) + : path_(gen_path(name_base)) { + + int fd = ::open(path_.c_str(), O_CREAT | O_RDWR, 0666); + if (fd < 0) + throw runtime_error("couldn't open file"); + + if (::fallocate(fd, 0, 0, 1024 * 1024 * meg_size)) + throw runtime_error("couldn't fallocate"); + + ::close(fd); + } + + ~temp_file() { + ::unlink(path_.c_str()); + } + + string const &get_path() const { + return path_; + } + + private: + static string gen_path(string const &base) { + return string("./") + base + string(".tmp"); + } + + string path_; + }; + + class CopierTests : public Test { + public: + CopierTests() + : src_file_("copy_src", 32), + dest_file_("copy_dest", 32), + copier_(src_file_.get_path(), + dest_file_.get_path(), + 64, 1 * 1024 * 1024) { + } + + copier &get_copier() { + return copier_; + } + + private: + temp_file src_file_; + temp_file dest_file_; + + copier copier_; + }; +} + +//---------------------------------------------------------------- + +TEST_F(CopierTests, empty_test) +{ + // Copy first block + copy_op op1(0, 1, 0); + get_copier().issue(op1); + auto mop = get_copier().wait(); + + if (mop) { + cerr << "op completed\n"; + } else { + cerr << "no op completed\n"; + } +} + +//---------------------------------------------------------------- diff --git a/unit-tests/mem_pool_t.cc b/unit-tests/mem_pool_t.cc new file mode 100644 index 0000000..b385f74 --- /dev/null +++ b/unit-tests/mem_pool_t.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2016 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#include "gmock/gmock.h" +#include "block-cache/mem_pool.h" +#include "test_utils.h" + +#include + +using namespace boost; +using namespace std; +using namespace test; +using namespace testing; + +//---------------------------------------------------------------- + +namespace { + class MempoolTests : public Test { + public: + bool aligned(void *data, size_t alignment) { + return (reinterpret_cast(data) % alignment) == 0; + } + + private: + + }; +} + +//---------------------------------------------------------------- + +TEST_F(MempoolTests, empty_test) +{ +} + +TEST_F(MempoolTests, create_destroy_cycle) +{ + for (size_t bs = 64; bs <= 512; bs *= 2) { + mempool mp(bs, 4 * 1024 * 1024, bs); + } +} + +TEST_F(MempoolTests, alignments_observed) +{ + for (size_t bs = 64; bs <= 512; bs *= 2) { + mempool mp(bs, 512 * 1024, bs); + + for (unsigned i = 0; i < 100; i++) { + auto md = mp.alloc(); + + if (!md) + throw runtime_error("couldn't alloc"); + + ASSERT_THAT(aligned(*md, bs), Eq(true)); + } + } +} + +TEST_F(MempoolTests, alloc_free_cycle) +{ + mempool mp(512, 512 * 1024, 512); + + for (unsigned i = 0; i < 10000; i++) { + auto md = mp.alloc(); + mp.free(*md); + } +} + +TEST_F(MempoolTests, exhaust_pool) +{ + mempool mp(512, 100 * 512, 512); + + for (unsigned i = 0; i < 100; i++) { + auto md = mp.alloc(); + + ASSERT_THAT(*md, NEq(0)); + } + + auto md = mp.alloc(); + ASSERT(*md, Eq(0)); +} + +//----------------------------------------------------------------