]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/test_extent_allocator.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / crimson / seastore / test_extent_allocator.cc
CommitLineData
1e59de90
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include <random>
5
6#include <boost/iterator/counting_iterator.hpp>
7
8#include "test/crimson/gtest_seastar.h"
9#include "crimson/os/seastore/random_block_manager.h"
10#include "crimson/os/seastore/random_block_manager/extent_allocator.h"
11#include "crimson/os/seastore/random_block_manager/avlallocator.h"
12#include "include/interval_set.h"
13
14
15using namespace crimson;
16using namespace crimson::os;
17using namespace crimson::os::seastore;
18
19namespace {
20 [[maybe_unused]] seastar::logger& logger() {
21 return crimson::get_logger(ceph_subsys_test);
22 }
23}
24
25struct allocator_test_t :
26 public seastar_test_suite_t,
27 ::testing::WithParamInterface<const char*> {
28 std::random_device rd;
29 std::mt19937 gen;
30 ExtentAllocatorRef allocator;
31
32 allocator_test_t()
33 : gen(rd()) {}
34
35 seastar::future<> set_up_fut() final {
36 std::string a_type = GetParam();
37 if (a_type == "avl") {
38 allocator.reset(new AvlAllocator(false));
39 return seastar::now();
40 }
41 ceph_assert(0 == "no support");
42 }
43 seastar::future<> tear_down_fut() final {
44 if (allocator) {
45 allocator->close();
46 }
47 return seastar::now();
48 }
49 void init_alloc(uint64_t block_size, uint64_t total_size) {
50 assert(allocator);
51 allocator->init(0, total_size, block_size);
52 }
53 void close() {
54 assert(allocator);
55 allocator->close();
56 }
57 auto allocate(size_t size) {
58 return allocator->alloc_extent(size);
59 }
60 void free(uint64_t start, uint64_t length) {
61 allocator->free_extent(start, length);
62 }
63 rbm_abs_addr get_random_addr(size_t block_size, size_t capacity) {
64 return block_size *
65 std::uniform_int_distribution<>(0, (capacity / block_size) - 1)(gen);
66 }
67};
68
69TEST_P(allocator_test_t, test_alloc_init)
70{
71 init_alloc(4096, 4096 * 64);
72 ASSERT_EQ((4096 * 64), allocator->get_available_size());
73 close();
74 init_alloc(8192, 8192 * 32);
75 allocate(8192);
76 ASSERT_EQ(8192 * 32 - 8192, allocator->get_available_size());
77 close();
78 init_alloc(4096, 4096 * 128);
79 allocate(8192);
80 ASSERT_EQ(4096 * 128 - 8192, allocator->get_available_size());
81}
82
83TEST_P(allocator_test_t, test_init_alloc_free)
84{
85 uint64_t block_size = 4096;
86 uint64_t capacity = 4 * 1024 * block_size;
87
88 {
89 init_alloc(block_size, capacity);
90
91 auto free_length = allocator->get_available_size();
92 allocate(allocator->get_max_alloc_size());
93 ASSERT_EQ(free_length - allocator->get_max_alloc_size(),
94 allocator->get_available_size());
95
96 free(0, allocator->get_max_alloc_size());
97 ASSERT_EQ(free_length, allocator->get_available_size());
98 }
99}
100
101TEST_P(allocator_test_t, test_alloc_failure)
102{
103 uint64_t block_size = 8192;
104 uint64_t capacity = 1024 * block_size;
105
106 {
107 init_alloc(block_size, capacity);
108 allocator->mark_extent_used(0, block_size * 256);
109 allocator->mark_extent_used(block_size * 512, block_size * 256);
110
111 auto result = allocate(block_size * 512);
112 ASSERT_EQ(false, result.has_value());
113
114 free(0, block_size * 256);
115 allocator->mark_extent_used(0, block_size * 512);
116
117 result = allocate(block_size * 512);
118 ASSERT_EQ(false, result.has_value());
119 }
120}
121
122TEST_P(allocator_test_t, test_random_alloc_verify)
123{
124 uint64_t block_size = 4096;
125 uint64_t capacity = 64 * 1024 * block_size;
126 uint64_t avail = capacity;
127 interval_set<rbm_abs_addr> alloc_map;
128 init_alloc(block_size, capacity);
129
130 {
131 for (int i = 0; i < 256; i++) {
132 auto addr = get_random_addr(block_size, capacity);
133 auto size = get_random_addr(block_size, capacity) % (4 << 20);
134 if (addr + size > capacity || size == 0 ||
135 alloc_map.intersects(addr, size) ) continue;
136 allocator->mark_extent_used(addr, size);
137 alloc_map.insert(addr, size);
138 avail -= size;
139 }
140 ASSERT_EQ(avail, allocator->get_available_size());
141
142 for (auto p : alloc_map) {
143 free(p.first, p.second);
144 avail += p.second;
145 alloc_map.erase(p.first, p.second);
146 ASSERT_EQ(avail, allocator->get_available_size());
147 }
148 ASSERT_EQ(capacity, allocator->get_available_size());
149
150 for (int i = 0; i < 100; i++) {
151 auto addr = get_random_addr(block_size, capacity);
152 auto size = get_random_addr(block_size, capacity) % (4 << 20);
153 if (addr + size > capacity || size == 0 ||
154 alloc_map.intersects(addr, size) ) continue;
155 allocator->mark_extent_used(addr, size);
156 alloc_map.insert(addr, size);
157 avail -= size;
158 }
159
160 for (int i = 0; i < 50; i++) {
161 free((*alloc_map.begin()).first, (*alloc_map.begin()).second);
162 avail += (*alloc_map.begin()).second;
163 alloc_map.erase((*alloc_map.begin()).first, (*alloc_map.begin()).second);
164 ASSERT_EQ(avail, allocator->get_available_size());
165
166 auto addr = get_random_addr(block_size, capacity);
167 auto size = get_random_addr(block_size, capacity) % (4 << 20);
168 if (addr + size > capacity || size == 0 ||
169 alloc_map.intersects(addr, size) ) continue;
170 allocator->mark_extent_used(addr, size);
171 alloc_map.insert(addr, size);
172 avail -= size;
173 }
174 ASSERT_EQ(avail, allocator->get_available_size());
175 }
176}
177
178INSTANTIATE_TEST_SUITE_P(
179 allocator_test,
180 allocator_test_t,
181 ::testing::Values("avl"));