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"
7 #include "librbd/ImageWatcher.h"
8 #include "librbd/internal.h"
9 #include "librbd/ObjectMap.h"
10 #include "cls/rbd/cls_rbd_client.h"
13 void register_test_object_map() {
16 class TestObjectMap
: public TestFixture
{
19 int when_open_object_map(librbd::ImageCtx
*ictx
) {
21 librbd::ObjectMap
<> object_map(*ictx
, ictx
->snap_id
);
22 object_map
.open(&ctx
);
27 TEST_F(TestObjectMap
, RefreshInvalidatesWhenCorrupt
) {
28 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
30 librbd::ImageCtx
*ictx
;
31 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
33 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
34 ASSERT_FALSE(flags_set
);
38 RWLock::WLocker
owner_locker(ictx
->owner_lock
);
39 ictx
->exclusive_lock
->try_acquire_lock(&lock_ctx
);
41 ASSERT_EQ(0, lock_ctx
.wait());
43 std::string oid
= librbd::ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
);
46 ASSERT_EQ(0, ictx
->md_ctx
.write_full(oid
, bl
));
48 ASSERT_EQ(0, when_open_object_map(ictx
));
49 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
50 ASSERT_TRUE(flags_set
);
53 TEST_F(TestObjectMap
, RefreshInvalidatesWhenTooSmall
) {
54 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
56 librbd::ImageCtx
*ictx
;
57 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
59 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
60 ASSERT_FALSE(flags_set
);
64 RWLock::WLocker
owner_locker(ictx
->owner_lock
);
65 ictx
->exclusive_lock
->try_acquire_lock(&lock_ctx
);
67 ASSERT_EQ(0, lock_ctx
.wait());
69 librados::ObjectWriteOperation op
;
70 librbd::cls_client::object_map_resize(&op
, 0, OBJECT_NONEXISTENT
);
72 std::string oid
= librbd::ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
);
73 ASSERT_EQ(0, ictx
->md_ctx
.operate(oid
, &op
));
75 ASSERT_EQ(0, when_open_object_map(ictx
));
76 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
77 ASSERT_TRUE(flags_set
);
80 TEST_F(TestObjectMap
, InvalidateFlagOnDisk
) {
81 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
83 librbd::ImageCtx
*ictx
;
84 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
86 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
87 ASSERT_FALSE(flags_set
);
91 RWLock::WLocker
owner_locker(ictx
->owner_lock
);
92 ictx
->exclusive_lock
->try_acquire_lock(&lock_ctx
);
94 ASSERT_EQ(0, lock_ctx
.wait());
96 std::string oid
= librbd::ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
);
99 ASSERT_EQ(0, ictx
->md_ctx
.write_full(oid
, bl
));
101 ASSERT_EQ(0, when_open_object_map(ictx
));
102 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
103 ASSERT_TRUE(flags_set
);
105 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
106 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
107 ASSERT_TRUE(flags_set
);
110 TEST_F(TestObjectMap
, InvalidateFlagInMemoryOnly
) {
111 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
113 librbd::ImageCtx
*ictx
;
114 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
116 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
117 ASSERT_FALSE(flags_set
);
119 std::string oid
= librbd::ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
);
121 ASSERT_LT(0, ictx
->md_ctx
.read(oid
, valid_bl
, 0, 0));
123 bufferlist corrupt_bl
;
124 corrupt_bl
.append("corrupt");
125 ASSERT_EQ(0, ictx
->md_ctx
.write_full(oid
, corrupt_bl
));
127 ASSERT_EQ(0, when_open_object_map(ictx
));
128 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
129 ASSERT_TRUE(flags_set
);
131 ASSERT_EQ(0, ictx
->md_ctx
.write_full(oid
, valid_bl
));
132 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
133 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
134 ASSERT_FALSE(flags_set
);