]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/test_ObjectMap.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / test / librbd / test_ObjectMap.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3#include "test/librbd/test_fixture.h"
4#include "test/librbd/test_support.h"
5#include "librbd/ExclusiveLock.h"
6#include "librbd/ImageCtx.h"
1adf2230 7#include "librbd/ImageState.h"
7c673cae
FG
8#include "librbd/ImageWatcher.h"
9#include "librbd/internal.h"
10#include "librbd/ObjectMap.h"
11fdf7f2
TL
11#include "common/Cond.h"
12#include "common/Throttle.h"
7c673cae 13#include "cls/rbd/cls_rbd_client.h"
11fdf7f2 14#include "cls/rbd/cls_rbd_types.h"
7c673cae 15#include <list>
11fdf7f2
TL
16#include <boost/accumulators/accumulators.hpp>
17#include <boost/accumulators/statistics/stats.hpp>
18#include <boost/accumulators/statistics/rolling_sum.hpp>
7c673cae
FG
19
20void register_test_object_map() {
21}
22
23class TestObjectMap : public TestFixture {
24public:
25
26 int when_open_object_map(librbd::ImageCtx *ictx) {
27 C_SaferCond ctx;
9f95a23c
TL
28 librbd::ObjectMap<> *object_map = new librbd::ObjectMap<>(*ictx, ictx->snap_id);
29 object_map->open(&ctx);
30 int r = ctx.wait();
31 object_map->put();
32
33 return r;
7c673cae
FG
34 }
35};
36
37TEST_F(TestObjectMap, RefreshInvalidatesWhenCorrupt) {
38 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
39
40 librbd::ImageCtx *ictx;
41 ASSERT_EQ(0, open_image(m_image_name, &ictx));
31f18b77 42 bool flags_set;
91327a77
AA
43 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
44 &flags_set));
31f18b77 45 ASSERT_FALSE(flags_set);
7c673cae
FG
46
47 C_SaferCond lock_ctx;
48 {
9f95a23c 49 std::unique_lock owner_locker{ictx->owner_lock};
7c673cae
FG
50 ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
51 }
52 ASSERT_EQ(0, lock_ctx.wait());
53
54 std::string oid = librbd::ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP);
55 bufferlist bl;
56 bl.append("corrupt");
57 ASSERT_EQ(0, ictx->md_ctx.write_full(oid, bl));
58
59 ASSERT_EQ(0, when_open_object_map(ictx));
91327a77
AA
60 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
61 &flags_set));
31f18b77 62 ASSERT_TRUE(flags_set);
7c673cae
FG
63}
64
65TEST_F(TestObjectMap, RefreshInvalidatesWhenTooSmall) {
66 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
67
68 librbd::ImageCtx *ictx;
69 ASSERT_EQ(0, open_image(m_image_name, &ictx));
31f18b77 70 bool flags_set;
91327a77
AA
71 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
72 &flags_set));
31f18b77 73 ASSERT_FALSE(flags_set);
7c673cae
FG
74
75 C_SaferCond lock_ctx;
76 {
9f95a23c 77 std::unique_lock owner_locker{ictx->owner_lock};
7c673cae
FG
78 ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
79 }
80 ASSERT_EQ(0, lock_ctx.wait());
81
82 librados::ObjectWriteOperation op;
83 librbd::cls_client::object_map_resize(&op, 0, OBJECT_NONEXISTENT);
84
85 std::string oid = librbd::ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP);
86 ASSERT_EQ(0, ictx->md_ctx.operate(oid, &op));
87
88 ASSERT_EQ(0, when_open_object_map(ictx));
91327a77
AA
89 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
90 &flags_set));
31f18b77 91 ASSERT_TRUE(flags_set);
7c673cae
FG
92}
93
94TEST_F(TestObjectMap, InvalidateFlagOnDisk) {
95 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
96
97 librbd::ImageCtx *ictx;
98 ASSERT_EQ(0, open_image(m_image_name, &ictx));
31f18b77 99 bool flags_set;
91327a77
AA
100 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
101 &flags_set));
31f18b77 102 ASSERT_FALSE(flags_set);
7c673cae
FG
103
104 C_SaferCond lock_ctx;
105 {
9f95a23c 106 std::unique_lock owner_locker{ictx->owner_lock};
7c673cae
FG
107 ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
108 }
109 ASSERT_EQ(0, lock_ctx.wait());
110
111 std::string oid = librbd::ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP);
112 bufferlist bl;
113 bl.append("corrupt");
114 ASSERT_EQ(0, ictx->md_ctx.write_full(oid, bl));
115
116 ASSERT_EQ(0, when_open_object_map(ictx));
91327a77
AA
117 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
118 &flags_set));
31f18b77 119 ASSERT_TRUE(flags_set);
7c673cae
FG
120
121 ASSERT_EQ(0, open_image(m_image_name, &ictx));
91327a77
AA
122 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
123 &flags_set));
31f18b77 124 ASSERT_TRUE(flags_set);
7c673cae
FG
125}
126
1adf2230 127TEST_F(TestObjectMap, AcquireLockInvalidatesWhenTooSmall) {
7c673cae
FG
128 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
129
130 librbd::ImageCtx *ictx;
131 ASSERT_EQ(0, open_image(m_image_name, &ictx));
31f18b77 132 bool flags_set;
91327a77
AA
133 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
134 &flags_set));
31f18b77 135 ASSERT_FALSE(flags_set);
7c673cae 136
1adf2230
AA
137 librados::ObjectWriteOperation op;
138 librbd::cls_client::object_map_resize(&op, 0, OBJECT_NONEXISTENT);
139
7c673cae 140 std::string oid = librbd::ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP);
1adf2230 141 ASSERT_EQ(0, ictx->md_ctx.operate(oid, &op));
7c673cae 142
1adf2230
AA
143 C_SaferCond lock_ctx;
144 {
9f95a23c 145 std::unique_lock owner_locker{ictx->owner_lock};
1adf2230
AA
146 ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
147 }
148 ASSERT_EQ(0, lock_ctx.wait());
7c673cae 149
91327a77
AA
150 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
151 &flags_set));
31f18b77 152 ASSERT_TRUE(flags_set);
7c673cae 153
1adf2230
AA
154 // Test the flag is stored on disk
155 ASSERT_EQ(0, ictx->state->refresh());
91327a77 156 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
1adf2230
AA
157 &flags_set));
158 ASSERT_TRUE(flags_set);
7c673cae 159}
11fdf7f2
TL
160
161TEST_F(TestObjectMap, DISABLED_StressTest) {
162 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
163
164 uint64_t object_count = cls::rbd::MAX_OBJECT_MAP_OBJECT_COUNT;
165 librbd::ImageCtx *ictx;
166 ASSERT_EQ(0, open_image(m_image_name, &ictx));
167 ASSERT_EQ(0, resize(ictx, ictx->layout.object_size * object_count));
168
169 bool flags_set;
170 ASSERT_EQ(0, ictx->test_flags(CEPH_NOSNAP, RBD_FLAG_OBJECT_MAP_INVALID,
171 &flags_set));
172 ASSERT_FALSE(flags_set);
173
174 srand(time(NULL) % (unsigned long) -1);
175
176 coarse_mono_time start = coarse_mono_clock::now();
177 chrono::duration<double> last = chrono::duration<double>::zero();
178
179 const int WINDOW_SIZE = 5;
180 typedef boost::accumulators::accumulator_set<
181 double, boost::accumulators::stats<
182 boost::accumulators::tag::rolling_sum> > RollingSum;
183
184 RollingSum time_acc(
185 boost::accumulators::tag::rolling_window::window_size = WINDOW_SIZE);
186 RollingSum ios_acc(
187 boost::accumulators::tag::rolling_window::window_size = WINDOW_SIZE);
188
189 uint32_t io_threads = 16;
190 uint64_t cur_ios = 0;
191 SimpleThrottle throttle(io_threads, false);
192 for (uint64_t ios = 0; ios < 100000;) {
193 if (throttle.pending_error()) {
194 break;
195 }
196
197 throttle.start_op();
198 uint64_t object_no = (rand() % object_count);
9f95a23c 199 auto ctx = new LambdaContext([&throttle, object_no](int r) {
11fdf7f2
TL
200 ASSERT_EQ(0, r) << "object_no=" << object_no;
201 throttle.end_op(r);
202 });
203
9f95a23c
TL
204 std::shared_lock owner_locker{ictx->owner_lock};
205 std::shared_lock image_locker{ictx->image_lock};
11fdf7f2
TL
206 ASSERT_TRUE(ictx->object_map != nullptr);
207
208 if (!ictx->object_map->aio_update<
209 Context, &Context::complete>(CEPH_NOSNAP, object_no,
210 OBJECT_EXISTS, {}, {}, true,
211 ctx)) {
212 ctx->complete(0);
213 } else {
214 ++cur_ios;
215 ++ios;
216 }
217
218 coarse_mono_time now = coarse_mono_clock::now();
219 chrono::duration<double> elapsed = now - start;
220 if (last == chrono::duration<double>::zero()) {
221 last = elapsed;
222 } else if ((int)elapsed.count() != (int)last.count()) {
223 time_acc((elapsed - last).count());
224 ios_acc(static_cast<double>(cur_ios));
225 cur_ios = 0;
226
227 double time_sum = boost::accumulators::rolling_sum(time_acc);
228 std::cerr << std::setw(5) << (int)elapsed.count() << "\t"
229 << std::setw(8) << (int)ios << "\t"
230 << std::fixed << std::setw(8) << std::setprecision(2)
231 << boost::accumulators::rolling_sum(ios_acc) / time_sum
232 << std::endl;
233 last = elapsed;
234 }
235 }
236
237 ASSERT_EQ(0, throttle.wait_for_ret());
238}