]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/test_seastore_cache.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / crimson / seastore / test_seastore_cache.cc
CommitLineData
f67539c2
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 "test/crimson/gtest_seastar.h"
5
6#include "crimson/common/log.h"
7#include "crimson/os/seastore/cache.h"
8#include "crimson/os/seastore/segment_manager/ephemeral.h"
9
10#include "test/crimson/seastore/test_block.h"
11
12using namespace crimson;
13using namespace crimson::os;
14using namespace crimson::os::seastore;
15
16namespace {
17 [[maybe_unused]] seastar::logger& logger() {
18 return crimson::get_logger(ceph_subsys_test);
19 }
20}
21
22struct cache_test_t : public seastar_test_suite_t {
23 segment_manager::EphemeralSegmentManagerRef segment_manager;
1e59de90 24 ExtentPlacementManagerRef epm;
20effc67
TL
25 CacheRef cache;
26 paddr_t current;
1e59de90 27 journal_seq_t seq = JOURNAL_SEQ_MIN;
f67539c2 28
20effc67 29 cache_test_t() = default;
f67539c2 30
20effc67 31 seastar::future<paddr_t> submit_transaction(
f67539c2 32 TransactionRef t) {
1e59de90 33 auto record = cache->prepare_record(*t, JOURNAL_SEQ_NULL, JOURNAL_SEQ_NULL);
f67539c2
TL
34
35 bufferlist bl;
20effc67 36 for (auto &&block : record.extents) {
f67539c2
TL
37 bl.append(block.bl);
38 }
39
40 ceph_assert((segment_off_t)bl.length() <
41 segment_manager->get_segment_size());
20effc67 42 if (current.as_seg_paddr().get_segment_off() + (segment_off_t)bl.length() >
f67539c2 43 segment_manager->get_segment_size())
20effc67
TL
44 current = paddr_t::make_seg_paddr(
45 segment_id_t(
46 current.as_seg_paddr().get_segment_id().device_id(),
47 current.as_seg_paddr().get_segment_id().device_segment_id() + 1),
48 0);
f67539c2
TL
49
50 auto prev = current;
20effc67
TL
51 current.as_seg_paddr().set_segment_off(
52 current.as_seg_paddr().get_segment_off()
53 + bl.length());
f67539c2
TL
54 return segment_manager->segment_write(
55 prev,
56 std::move(bl),
57 true
58 ).safe_then(
59 [this, prev, t=std::move(t)]() mutable {
20effc67
TL
60 cache->complete_commit(*t, prev, seq /* TODO */);
61 return prev;
f67539c2
TL
62 },
63 crimson::ct_error::all_same_way([](auto e) {
64 ASSERT_FALSE("failed to submit");
65 })
66 );
67 }
68
69 auto get_transaction() {
20effc67
TL
70 return cache->create_transaction(
71 Transaction::src_t::MUTATE, "test_cache", false);
72 }
73
74 template <typename T, typename... Args>
75 auto get_extent(Transaction &t, Args&&... args) {
76 return with_trans_intr(
77 t,
78 [this](auto &&... args) {
79 return cache->get_extent<T>(args...);
80 },
81 std::forward<Args>(args)...);
f67539c2
TL
82 }
83
84 seastar::future<> set_up_fut() final {
20effc67 85 segment_manager = segment_manager::create_test_ephemeral();
f67539c2 86 return segment_manager->init(
20effc67 87 ).safe_then([this] {
1e59de90
TL
88 return segment_manager->mkfs(
89 segment_manager::get_ephemeral_device_config(0, 1, 0));
90 }).safe_then([this] {
91 epm.reset(new ExtentPlacementManager());
92 cache.reset(new Cache(*epm));
93 current = paddr_t::make_seg_paddr(segment_id_t(segment_manager->get_device_id(), 0), 0);
94 epm->test_init_no_background(segment_manager.get());
20effc67
TL
95 return seastar::do_with(
96 get_transaction(),
97 [this](auto &ref_t) {
98 cache->init();
99 return with_trans_intr(*ref_t, [&](auto &t) {
100 return cache->mkfs(t);
101 }).safe_then([this, &ref_t] {
102 return submit_transaction(std::move(ref_t)
103 ).then([](auto p) {});
104 });
105 });
106 }).handle_error(
107 crimson::ct_error::all_same_way([](auto e) {
108 ASSERT_FALSE("failed to submit");
109 })
110 );
f67539c2
TL
111 }
112
113 seastar::future<> tear_down_fut() final {
20effc67
TL
114 return cache->close(
115 ).safe_then([this] {
116 segment_manager.reset();
1e59de90 117 epm.reset();
20effc67
TL
118 cache.reset();
119 }).handle_error(
120 Cache::close_ertr::assert_all{}
121 );
f67539c2
TL
122 }
123};
124
125TEST_F(cache_test_t, test_addr_fixup)
126{
127 run_async([this] {
128 paddr_t addr;
129 int csum = 0;
130 {
131 auto t = get_transaction();
20effc67 132 auto extent = cache->alloc_new_extent<TestBlockPhysical>(
f67539c2 133 *t,
1e59de90
TL
134 TestBlockPhysical::SIZE,
135 placement_hint_t::HOT,
136 0);
f67539c2
TL
137 extent->set_contents('c');
138 csum = extent->get_crc32c();
20effc67 139 submit_transaction(std::move(t)).get0();
f67539c2
TL
140 addr = extent->get_paddr();
141 }
142 {
143 auto t = get_transaction();
20effc67 144 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
145 *t,
146 addr,
147 TestBlockPhysical::SIZE).unsafe_get0();
148 ASSERT_EQ(extent->get_paddr(), addr);
149 ASSERT_EQ(extent->get_crc32c(), csum);
150 }
151 });
152}
153
154TEST_F(cache_test_t, test_dirty_extent)
155{
156 run_async([this] {
157 paddr_t addr;
158 int csum = 0;
159 int csum2 = 0;
160 {
161 // write out initial test block
162 auto t = get_transaction();
20effc67 163 auto extent = cache->alloc_new_extent<TestBlockPhysical>(
f67539c2 164 *t,
1e59de90
TL
165 TestBlockPhysical::SIZE,
166 placement_hint_t::HOT,
167 0);
f67539c2
TL
168 extent->set_contents('c');
169 csum = extent->get_crc32c();
170 auto reladdr = extent->get_paddr();
171 ASSERT_TRUE(reladdr.is_relative());
172 {
173 // test that read with same transaction sees new block though
174 // uncommitted
20effc67 175 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
176 *t,
177 reladdr,
178 TestBlockPhysical::SIZE).unsafe_get0();
179 ASSERT_TRUE(extent->is_clean());
180 ASSERT_TRUE(extent->is_pending());
181 ASSERT_TRUE(extent->get_paddr().is_relative());
182 ASSERT_EQ(extent->get_version(), 0);
183 ASSERT_EQ(csum, extent->get_crc32c());
184 }
20effc67 185 submit_transaction(std::move(t)).get0();
f67539c2
TL
186 addr = extent->get_paddr();
187 }
188 {
189 // test that consecutive reads on the same extent get the same ref
190 auto t = get_transaction();
20effc67 191 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
192 *t,
193 addr,
194 TestBlockPhysical::SIZE).unsafe_get0();
195 auto t2 = get_transaction();
20effc67 196 auto extent2 = get_extent<TestBlockPhysical>(
f67539c2
TL
197 *t2,
198 addr,
199 TestBlockPhysical::SIZE).unsafe_get0();
200 ASSERT_EQ(&*extent, &*extent2);
201 }
202 {
203 // read back test block
204 auto t = get_transaction();
20effc67 205 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
206 *t,
207 addr,
208 TestBlockPhysical::SIZE).unsafe_get0();
209 // duplicate and reset contents
20effc67 210 extent = cache->duplicate_for_write(*t, extent)->cast<TestBlockPhysical>();
f67539c2
TL
211 extent->set_contents('c');
212 csum2 = extent->get_crc32c();
213 ASSERT_EQ(extent->get_paddr(), addr);
214 {
215 // test that concurrent read with fresh transaction sees old
216 // block
217 auto t2 = get_transaction();
20effc67 218 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
219 *t2,
220 addr,
221 TestBlockPhysical::SIZE).unsafe_get0();
222 ASSERT_TRUE(extent->is_clean());
223 ASSERT_FALSE(extent->is_pending());
224 ASSERT_EQ(addr, extent->get_paddr());
225 ASSERT_EQ(extent->get_version(), 0);
226 ASSERT_EQ(csum, extent->get_crc32c());
227 }
228 {
229 // test that read with same transaction sees new block
20effc67 230 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
231 *t,
232 addr,
233 TestBlockPhysical::SIZE).unsafe_get0();
234 ASSERT_TRUE(extent->is_dirty());
235 ASSERT_TRUE(extent->is_pending());
236 ASSERT_EQ(addr, extent->get_paddr());
237 ASSERT_EQ(extent->get_version(), 1);
238 ASSERT_EQ(csum2, extent->get_crc32c());
239 }
240 // submit transaction
20effc67 241 submit_transaction(std::move(t)).get0();
f67539c2
TL
242 ASSERT_TRUE(extent->is_dirty());
243 ASSERT_EQ(addr, extent->get_paddr());
244 ASSERT_EQ(extent->get_version(), 1);
245 ASSERT_EQ(extent->get_crc32c(), csum2);
246 }
247 {
248 // test that fresh transaction now sees newly dirty block
249 auto t = get_transaction();
20effc67 250 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
251 *t,
252 addr,
253 TestBlockPhysical::SIZE).unsafe_get0();
254 ASSERT_TRUE(extent->is_dirty());
255 ASSERT_EQ(addr, extent->get_paddr());
256 ASSERT_EQ(extent->get_version(), 1);
257 ASSERT_EQ(csum2, extent->get_crc32c());
258 }
259 });
260}