#include "librbd/internal.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/ImageDispatchSpec.h"
+#include "librbd/io/Utils.h"
#include "librbd/object_map/DiffRequest.h"
#include "include/rados/librados.hpp"
#include "include/interval_set.h"
if (first_period_off != last_period_off) {
// map only the tail of the first period and the front of the last
// period instead of the entire range for efficiency
- Striper::file_to_extents(m_image_ctx.cct, &m_image_ctx.layout,
- m_offset, first_period_off + period - m_offset,
- 0, 0, &object_extents);
- Striper::file_to_extents(m_image_ctx.cct, &m_image_ctx.layout,
- last_period_off, m_offset + m_length - last_period_off,
- 0, 0, &object_extents);
+ io::util::file_to_extents(&m_image_ctx, m_offset,
+ first_period_off + period - m_offset, 0,
+ &object_extents);
+ io::util::file_to_extents(&m_image_ctx, last_period_off,
+ m_offset + m_length - last_period_off, 0,
+ &object_extents);
} else {
- Striper::file_to_extents(m_image_ctx.cct, &m_image_ctx.layout, m_offset,
- m_length, 0, 0, &object_extents);
+ io::util::file_to_extents(&m_image_ctx, m_offset, m_length, 0,
+ &object_extents);
}
return {object_extents.front().object_no, object_extents.back().object_no + 1};
}
uint64_t read_len = std::min(period_off + period - off, left);
if (fast_diff_enabled) {
- // map to extents
- std::map<object_t,std::vector<ObjectExtent> > object_extents;
- Striper::file_to_extents(cct, m_image_ctx.format_string,
- &m_image_ctx.layout, off, read_len, 0,
- object_extents, 0);
+ // map to objects (there would be one extent per object)
+ striper::LightweightObjectExtents object_extents;
+ io::util::file_to_extents(&m_image_ctx, off, read_len, 0,
+ &object_extents);
// get diff info for each object and merge adjacent stripe units
// into an aggregate (this also sorts them)
io::SparseExtents aggregate_sparse_extents;
- for (auto& [object, extents] : object_extents) {
- const uint64_t object_no = extents.front().objectno;
- ceph_assert(object_no >= start_object_no && object_no < end_object_no);
- uint8_t diff_state = object_diff_state[object_no - start_object_no];
- ldout(cct, 20) << "object " << object << ": diff_state="
- << (int)diff_state << dendl;
+ for (const auto& oe : object_extents) {
+ ceph_assert(oe.object_no >= start_object_no &&
+ oe.object_no < end_object_no);
+ uint8_t diff_state = object_diff_state[oe.object_no - start_object_no];
+ ldout(cct, 20) << "object "
+ << util::data_object_name(&m_image_ctx, oe.object_no)
+ << ": diff_state=" << (int)diff_state << dendl;
if (diff_state == object_map::DIFF_STATE_HOLE &&
from_snap_id == 0 && !parent_diff.empty()) {
// no data in child object -- report parent diff instead
- for (auto& oe : extents) {
- for (auto& be : oe.buffer_extents) {
- interval_set<uint64_t> o;
- o.insert(off + be.first, be.second);
- o.intersection_of(parent_diff);
- ldout(cct, 20) << " reporting parent overlap " << o << dendl;
- for (auto e = o.begin(); e != o.end(); ++e) {
- aggregate_sparse_extents.insert(e.get_start(), e.get_len(),
- {io::SPARSE_EXTENT_STATE_DATA,
- e.get_len()});
- }
+ for (const auto& be : oe.buffer_extents) {
+ interval_set<uint64_t> o;
+ o.insert(off + be.first, be.second);
+ o.intersection_of(parent_diff);
+ ldout(cct, 20) << " reporting parent overlap " << o << dendl;
+ for (auto e = o.begin(); e != o.end(); ++e) {
+ aggregate_sparse_extents.insert(e.get_start(), e.get_len(),
+ {io::SPARSE_EXTENT_STATE_DATA,
+ e.get_len()});
}
}
} else if (diff_state == object_map::DIFF_STATE_HOLE_UPDATED ||
diff_state == object_map::DIFF_STATE_DATA_UPDATED) {
auto state = (diff_state == object_map::DIFF_STATE_HOLE_UPDATED ?
io::SPARSE_EXTENT_STATE_ZEROED : io::SPARSE_EXTENT_STATE_DATA);
- for (auto& oe : extents) {
- for (auto& be : oe.buffer_extents) {
- aggregate_sparse_extents.insert(off + be.first, be.second,
- {state, be.second});
- }
+ for (const auto& be : oe.buffer_extents) {
+ aggregate_sparse_extents.insert(off + be.first, be.second,
+ {state, be.second});
}
}
}
test_deterministic_pp(image, object_off, len, 1);
}
+#ifdef HAVE_LIBCRYPTSETUP
+
+ void test_deterministic_luks1(uint64_t object_off, uint64_t len) {
+ rados_ioctx_t ioctx;
+ ASSERT_EQ(0, rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx));
+
+ rbd_image_t image;
+ int order = 22;
+ std::string name = this->get_temp_image_name();
+ ASSERT_EQ(0, create_image(ioctx, name.c_str(), 24 << 20, &order));
+ ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
+ rbd_encryption_luks1_format_options_t fopts = {
+ RBD_ENCRYPTION_ALGORITHM_AES256, "some passphrase", 15};
+ ASSERT_EQ(0, rbd_encryption_format(image, RBD_ENCRYPTION_FORMAT_LUKS1,
+ &fopts, sizeof(fopts)));
+ test_deterministic(image, object_off, len, 512);
+
+ ASSERT_EQ(0, rbd_close(image));
+ rados_ioctx_destroy(ioctx);
+ }
+
+ void test_deterministic_luks1_pp(uint64_t object_off, uint64_t len) {
+ librados::IoCtx ioctx;
+ ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx));
+
+ librbd::RBD rbd;
+ librbd::Image image;
+ int order = 22;
+ std::string name = this->get_temp_image_name();
+ ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), 24 << 20, &order));
+ ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
+ librbd::encryption_luks1_format_options_t fopts = {
+ RBD_ENCRYPTION_ALGORITHM_AES256, "some passphrase"};
+ ASSERT_EQ(0, image.encryption_format(RBD_ENCRYPTION_FORMAT_LUKS1, &fopts,
+ sizeof(fopts)));
+ test_deterministic_pp(image, object_off, len, 512);
+ }
+
+ void test_deterministic_luks2(uint64_t object_off, uint64_t len) {
+ rados_ioctx_t ioctx;
+ ASSERT_EQ(0, rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx));
+
+ rbd_image_t image;
+ int order = 22;
+ std::string name = this->get_temp_image_name();
+ ASSERT_EQ(0, create_image(ioctx, name.c_str(), 36 << 20, &order));
+ ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
+ rbd_encryption_luks2_format_options_t fopts = {
+ RBD_ENCRYPTION_ALGORITHM_AES256, "some passphrase", 15};
+ ASSERT_EQ(0, rbd_encryption_format(image, RBD_ENCRYPTION_FORMAT_LUKS2,
+ &fopts, sizeof(fopts)));
+ test_deterministic(image, object_off, len, 4096);
+
+ ASSERT_EQ(0, rbd_close(image));
+ rados_ioctx_destroy(ioctx);
+ }
+
+ void test_deterministic_luks2_pp(uint64_t object_off, uint64_t len) {
+ librados::IoCtx ioctx;
+ ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx));
+
+ librbd::RBD rbd;
+ librbd::Image image;
+ int order = 22;
+ std::string name = this->get_temp_image_name();
+ ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), 36 << 20, &order));
+ ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
+ librbd::encryption_luks2_format_options_t fopts = {
+ RBD_ENCRYPTION_ALGORITHM_AES256, "some passphrase"};
+ ASSERT_EQ(0, image.encryption_format(RBD_ENCRYPTION_FORMAT_LUKS2, &fopts,
+ sizeof(fopts)));
+ test_deterministic_pp(image, object_off, len, 4096);
+ }
+
+#endif // HAVE_LIBCRYPTSETUP
+
private:
void test_deterministic(rbd_image_t image, uint64_t object_off,
uint64_t len, uint64_t block_size) {
EXPECT_NO_FATAL_FAILURE(this->test_deterministic_pp((4 << 20) - 2, 2));
}
+#ifdef HAVE_LIBCRYPTSETUP
+
+TYPED_TEST(DiffIterateTest, DiffIterateDeterministicLUKS1)
+{
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_JOURNALING));
+
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1(0, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1((1 << 20) - 256, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1((1 << 20) - 128, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1(1 << 20, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1((4 << 20) - 256, 256));
+}
+
+TYPED_TEST(DiffIterateTest, DiffIterateDeterministicLUKS1PP)
+{
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_JOURNALING));
+
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1_pp(0, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1_pp((3 << 20) - 2, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1_pp((3 << 20) - 1, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1_pp(3 << 20, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks1_pp((4 << 20) - 2, 2));
+}
+
+TYPED_TEST(DiffIterateTest, DiffIterateDeterministicLUKS2)
+{
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_JOURNALING));
+
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2(0, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2((1 << 20) - 256, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2((1 << 20) - 128, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2(1 << 20, 256));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2((4 << 20) - 256, 256));
+}
+
+TYPED_TEST(DiffIterateTest, DiffIterateDeterministicLUKS2PP)
+{
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
+ REQUIRE(!is_feature_enabled(RBD_FEATURE_JOURNALING));
+
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2_pp(0, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2_pp((3 << 20) - 2, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2_pp((3 << 20) - 1, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2_pp(3 << 20, 2));
+ EXPECT_NO_FATAL_FAILURE(this->test_deterministic_luks2_pp((4 << 20) - 2, 2));
+}
+
+#endif // HAVE_LIBCRYPTSETUP
+
TYPED_TEST(DiffIterateTest, DiffIterateDiscard)
{
REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));