]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/test_seastore_cache.cc
import quincy beta 17.1.0
[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;
20effc67
TL
24 ExtentReaderRef reader;
25 CacheRef cache;
26 paddr_t current;
f67539c2
TL
27 journal_seq_t seq;
28
20effc67 29 cache_test_t() = default;
f67539c2 30
20effc67 31 seastar::future<paddr_t> submit_transaction(
f67539c2 32 TransactionRef t) {
20effc67 33 auto record = cache->prepare_record(*t);
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
TL
85 segment_manager = segment_manager::create_test_ephemeral();
86 reader.reset(new ExtentReader());
87 cache.reset(new Cache(*reader));
88 current = paddr_t::make_seg_paddr(segment_id_t(segment_manager->get_device_id(), 0), 0);
89 reader->add_segment_manager(segment_manager.get());
f67539c2 90 return segment_manager->init(
20effc67
TL
91 ).safe_then([this] {
92 return seastar::do_with(
93 get_transaction(),
94 [this](auto &ref_t) {
95 cache->init();
96 return with_trans_intr(*ref_t, [&](auto &t) {
97 return cache->mkfs(t);
98 }).safe_then([this, &ref_t] {
99 return submit_transaction(std::move(ref_t)
100 ).then([](auto p) {});
101 });
102 });
103 }).handle_error(
104 crimson::ct_error::all_same_way([](auto e) {
105 ASSERT_FALSE("failed to submit");
106 })
107 );
f67539c2
TL
108 }
109
110 seastar::future<> tear_down_fut() final {
20effc67
TL
111 return cache->close(
112 ).safe_then([this] {
113 segment_manager.reset();
114 reader.reset();
115 cache.reset();
116 }).handle_error(
117 Cache::close_ertr::assert_all{}
118 );
f67539c2
TL
119 }
120};
121
122TEST_F(cache_test_t, test_addr_fixup)
123{
124 run_async([this] {
125 paddr_t addr;
126 int csum = 0;
127 {
128 auto t = get_transaction();
20effc67 129 auto extent = cache->alloc_new_extent<TestBlockPhysical>(
f67539c2
TL
130 *t,
131 TestBlockPhysical::SIZE);
132 extent->set_contents('c');
133 csum = extent->get_crc32c();
20effc67 134 submit_transaction(std::move(t)).get0();
f67539c2
TL
135 addr = extent->get_paddr();
136 }
137 {
138 auto t = get_transaction();
20effc67 139 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
140 *t,
141 addr,
142 TestBlockPhysical::SIZE).unsafe_get0();
143 ASSERT_EQ(extent->get_paddr(), addr);
144 ASSERT_EQ(extent->get_crc32c(), csum);
145 }
146 });
147}
148
149TEST_F(cache_test_t, test_dirty_extent)
150{
151 run_async([this] {
152 paddr_t addr;
153 int csum = 0;
154 int csum2 = 0;
155 {
156 // write out initial test block
157 auto t = get_transaction();
20effc67 158 auto extent = cache->alloc_new_extent<TestBlockPhysical>(
f67539c2
TL
159 *t,
160 TestBlockPhysical::SIZE);
161 extent->set_contents('c');
162 csum = extent->get_crc32c();
163 auto reladdr = extent->get_paddr();
164 ASSERT_TRUE(reladdr.is_relative());
165 {
166 // test that read with same transaction sees new block though
167 // uncommitted
20effc67 168 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
169 *t,
170 reladdr,
171 TestBlockPhysical::SIZE).unsafe_get0();
172 ASSERT_TRUE(extent->is_clean());
173 ASSERT_TRUE(extent->is_pending());
174 ASSERT_TRUE(extent->get_paddr().is_relative());
175 ASSERT_EQ(extent->get_version(), 0);
176 ASSERT_EQ(csum, extent->get_crc32c());
177 }
20effc67 178 submit_transaction(std::move(t)).get0();
f67539c2
TL
179 addr = extent->get_paddr();
180 }
181 {
182 // test that consecutive reads on the same extent get the same ref
183 auto t = get_transaction();
20effc67 184 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
185 *t,
186 addr,
187 TestBlockPhysical::SIZE).unsafe_get0();
188 auto t2 = get_transaction();
20effc67 189 auto extent2 = get_extent<TestBlockPhysical>(
f67539c2
TL
190 *t2,
191 addr,
192 TestBlockPhysical::SIZE).unsafe_get0();
193 ASSERT_EQ(&*extent, &*extent2);
194 }
195 {
196 // read back test block
197 auto t = get_transaction();
20effc67 198 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
199 *t,
200 addr,
201 TestBlockPhysical::SIZE).unsafe_get0();
202 // duplicate and reset contents
20effc67 203 extent = cache->duplicate_for_write(*t, extent)->cast<TestBlockPhysical>();
f67539c2
TL
204 extent->set_contents('c');
205 csum2 = extent->get_crc32c();
206 ASSERT_EQ(extent->get_paddr(), addr);
207 {
208 // test that concurrent read with fresh transaction sees old
209 // block
210 auto t2 = get_transaction();
20effc67 211 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
212 *t2,
213 addr,
214 TestBlockPhysical::SIZE).unsafe_get0();
215 ASSERT_TRUE(extent->is_clean());
216 ASSERT_FALSE(extent->is_pending());
217 ASSERT_EQ(addr, extent->get_paddr());
218 ASSERT_EQ(extent->get_version(), 0);
219 ASSERT_EQ(csum, extent->get_crc32c());
220 }
221 {
222 // test that read with same transaction sees new block
20effc67 223 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
224 *t,
225 addr,
226 TestBlockPhysical::SIZE).unsafe_get0();
227 ASSERT_TRUE(extent->is_dirty());
228 ASSERT_TRUE(extent->is_pending());
229 ASSERT_EQ(addr, extent->get_paddr());
230 ASSERT_EQ(extent->get_version(), 1);
231 ASSERT_EQ(csum2, extent->get_crc32c());
232 }
233 // submit transaction
20effc67 234 submit_transaction(std::move(t)).get0();
f67539c2
TL
235 ASSERT_TRUE(extent->is_dirty());
236 ASSERT_EQ(addr, extent->get_paddr());
237 ASSERT_EQ(extent->get_version(), 1);
238 ASSERT_EQ(extent->get_crc32c(), csum2);
239 }
240 {
241 // test that fresh transaction now sees newly dirty block
242 auto t = get_transaction();
20effc67 243 auto extent = get_extent<TestBlockPhysical>(
f67539c2
TL
244 *t,
245 addr,
246 TestBlockPhysical::SIZE).unsafe_get0();
247 ASSERT_TRUE(extent->is_dirty());
248 ASSERT_EQ(addr, extent->get_paddr());
249 ASSERT_EQ(extent->get_version(), 1);
250 ASSERT_EQ(csum2, extent->get_crc32c());
251 }
252 });
253}