summaryrefslogtreecommitdiffstats
path: root/src/test/librbd/crypto
diff options
context:
space:
mode:
authorOr Ozeri <oro@il.ibm.com>2020-10-29 12:42:17 +0100
committerOr Ozeri <oro@il.ibm.com>2020-11-04 09:25:45 +0100
commit27c24d39ed00ea2273dce59d56c3540c93be2a4f (patch)
treeb636c0d68c0d7b3a69c2eef6361f5a1a70532ee4 /src/test/librbd/crypto
parentMerge pull request #37757 from votdev/issue_47884_display_time (diff)
downloadceph-27c24d39ed00ea2273dce59d56c3540c93be2a4f.tar.xz
ceph-27c24d39ed00ea2273dce59d56c3540c93be2a4f.zip
librbd: wait for copyup in unaligned crypto write
librbd copyup is not built to handle unaligned encrypted writes. Therefore, a such write should kick-off a copyup and wait for it to complete before executing. This commit implements this logic. Signed-off-by: Or Ozeri <oro@il.ibm.com>
Diffstat (limited to 'src/test/librbd/crypto')
-rw-r--r--src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc123
1 files changed, 121 insertions, 2 deletions
diff --git a/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc b/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc
index 181cc2caf94..805a83d75bd 100644
--- a/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc
+++ b/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc
@@ -4,11 +4,21 @@
#include "test/librbd/test_mock_fixture.h"
#include "test/librbd/test_support.h"
#include "test/librbd/mock/MockImageCtx.h"
+#include "test/librbd/mock/MockObjectMap.h"
#include "test/librbd/mock/crypto/MockCryptoInterface.h"
#include "librbd/crypto/CryptoObjectDispatch.h"
#include "librbd/io/ObjectDispatchSpec.h"
#include "librbd/io/Utils.h"
+#include "librbd/io/Utils.cc"
+template bool librbd::io::util::trigger_copyup(
+ MockImageCtx *image_ctx, uint64_t object_no, IOContext io_context,
+ Context* on_finish);
+
+#include "librbd/io/ObjectRequest.cc"
+template class librbd::io::ObjectWriteRequest<librbd::MockImageCtx>;
+template class librbd::io::AbstractObjectWriteRequest<librbd::MockImageCtx>;
+
namespace librbd {
namespace util {
@@ -20,6 +30,29 @@ inline ImageCtx *get_image_ctx(MockImageCtx *image_ctx) {
} // namespace util
namespace io {
+
+template <>
+struct CopyupRequest<librbd::MockImageCtx> {
+ MOCK_METHOD0(send, void());
+ MOCK_METHOD2(append_request, void(
+ AbstractObjectWriteRequest<librbd::MockImageCtx>*,
+ const Extents&));
+
+ static CopyupRequest* s_instance;
+ static CopyupRequest* create(librbd::MockImageCtx *ictx,
+ uint64_t objectno, Extents &&image_extents,
+ const ZTracer::Trace &parent_trace) {
+ return s_instance;
+ }
+
+ CopyupRequest() {
+ s_instance = this;
+ }
+};
+
+CopyupRequest<librbd::MockImageCtx>* CopyupRequest<
+ librbd::MockImageCtx>::s_instance = nullptr;
+
namespace util {
namespace {
@@ -63,10 +96,14 @@ using ::testing::_;
using ::testing::ElementsAre;
using ::testing::Invoke;
using ::testing::Pair;
+using ::testing::Return;
using ::testing::WithArg;
struct TestMockCryptoCryptoObjectDispatch : public TestMockFixture {
typedef CryptoObjectDispatch<librbd::MockImageCtx> MockCryptoObjectDispatch;
+ typedef io::AbstractObjectWriteRequest<librbd::MockImageCtx>
+ MockAbstractObjectWriteRequest;
+ typedef io::CopyupRequest<librbd::MockImageCtx> MockCopyupRequest;
typedef io::util::Mock MockUtils;
MockCryptoInterface* crypto;
@@ -83,6 +120,7 @@ struct TestMockCryptoCryptoObjectDispatch : public TestMockFixture {
io::Extents extent_map;
int object_dispatch_flags = 0;
MockUtils mock_utils;
+ MockCopyupRequest copyup_request;
void SetUp() override {
TestMockFixture::SetUp();
@@ -91,7 +129,8 @@ struct TestMockCryptoCryptoObjectDispatch : public TestMockFixture {
ASSERT_EQ(0, open_image(m_image_name, &ictx));
crypto = new MockCryptoInterface();
mock_image_ctx = new MockImageCtx(*ictx);
- mock_crypto_object_dispatch = new MockCryptoObjectDispatch(mock_image_ctx, crypto);
+ mock_crypto_object_dispatch = new MockCryptoObjectDispatch(
+ mock_image_ctx, crypto);
data.append(std::string(4096, '1'));
}
@@ -136,7 +175,8 @@ struct TestMockCryptoCryptoObjectDispatch : public TestMockFixture {
int r) {
EXPECT_CALL(mock_utils,
read_parent(_, object_no, extents, snap_id, _, _))
- .WillOnce(WithArg<5>(CompleteContext(r, static_cast<asio::ContextWQ*>(nullptr))));
+ .WillOnce(WithArg<5>(CompleteContext(
+ r, static_cast<asio::ContextWQ*>(nullptr))));
}
void expect_object_write(uint64_t object_off, const std::string& data,
@@ -172,6 +212,37 @@ struct TestMockCryptoCryptoObjectDispatch : public TestMockFixture {
}));
}
+ void expect_get_object_size() {
+ EXPECT_CALL(*mock_image_ctx, get_object_size()).WillOnce(Return(
+ mock_image_ctx->layout.object_size));
+ }
+
+ void expect_get_parent_overlap(uint64_t overlap) {
+ EXPECT_CALL(*mock_image_ctx, get_parent_overlap(_, _))
+ .WillOnce(WithArg<1>(Invoke([overlap](uint64_t *o) {
+ *o = overlap;
+ return 0;
+ })));
+ }
+
+ void expect_prune_parent_extents(uint64_t object_overlap) {
+ EXPECT_CALL(*mock_image_ctx, prune_parent_extents(_, _))
+ .WillOnce(Return(object_overlap));
+ }
+
+ void expect_copyup(MockAbstractObjectWriteRequest** write_request, int r) {
+ EXPECT_CALL(copyup_request, append_request(_, _))
+ .WillOnce(WithArg<0>(
+ Invoke([write_request](
+ MockAbstractObjectWriteRequest *req) {
+ *write_request = req;
+ })));
+ EXPECT_CALL(copyup_request, send())
+ .WillOnce(Invoke([write_request, r]() {
+ (*write_request)->handle_copyup(r);
+ }));
+ }
+
void expect_encrypt(int count = 1) {
EXPECT_CALL(*crypto, encrypt(_, _)).Times(count);
}
@@ -365,6 +436,8 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteWithNoObject) {
ASSERT_EQ(dispatch_result, io::DISPATCH_RESULT_COMPLETE);
ASSERT_EQ(on_finish, &finished_cond);
+ expect_get_object_size();
+ expect_get_parent_overlap(0);
auto expected_data = (std::string(1, '\0') + std::string(8192, '1') +
std::string(4095, '\0'));
expect_object_write(0, expected_data, io::OBJECT_WRITE_FLAG_CREATE_EXCLUSIVE,
@@ -387,6 +460,8 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteFailCreate) {
ASSERT_EQ(dispatch_result, io::DISPATCH_RESULT_COMPLETE);
ASSERT_EQ(on_finish, &finished_cond);
+ expect_get_object_size();
+ expect_get_parent_overlap(0);
auto expected_data = (std::string(1, '\0') + std::string(8192, '1') +
std::string(4095, '\0'));
expect_object_write(0, expected_data, io::OBJECT_WRITE_FLAG_CREATE_EXCLUSIVE,
@@ -410,6 +485,50 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteFailCreate) {
ASSERT_EQ(0, dispatched_cond.wait());
}
+TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteCopyup) {
+ MockObjectMap mock_object_map;
+ mock_image_ctx->object_map = &mock_object_map;
+ MockExclusiveLock mock_exclusive_lock;
+ mock_image_ctx->exclusive_lock = &mock_exclusive_lock;
+
+ ceph::bufferlist write_data;
+ write_data.append(std::string(8192, '1'));
+ io::ReadExtents extents = {{0, 4096}, {8192, 4096}};
+ expect_object_read(&extents);
+ ASSERT_TRUE(mock_crypto_object_dispatch->write(
+ 0, 1, std::move(write_data), mock_image_ctx->get_data_io_context(),
+ 0, 0, std::nullopt, {}, nullptr, nullptr, &dispatch_result,
+ &on_finish, on_dispatched));
+ ASSERT_EQ(dispatch_result, io::DISPATCH_RESULT_COMPLETE);
+ ASSERT_EQ(on_finish, &finished_cond);
+
+ expect_get_object_size();
+ expect_get_parent_overlap(mock_image_ctx->layout.object_size);
+ expect_prune_parent_extents(mock_image_ctx->layout.object_size);
+ EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillRepeatedly(
+ Return(true));
+ EXPECT_CALL(*mock_image_ctx->object_map, object_may_exist(0)).WillOnce(
+ Return(false));
+ MockAbstractObjectWriteRequest *write_request = nullptr;
+ expect_copyup(&write_request, 0);
+
+ // unaligned write restarted
+ uint64_t version = 1234;
+ extents[0].bl.append(std::string(4096, '2'));
+ extents[1].bl.append(std::string(4096, '3'));
+ expect_object_read(&extents, version);
+ dispatcher_ctx->complete(-ENOENT); // complete first read
+ ASSERT_EQ(ETIMEDOUT, dispatched_cond.wait_for(0));
+
+ auto expected_data =
+ std::string("2") + std::string(8192, '1') + std::string(4095, '3');
+ expect_object_write(0, expected_data, 0, std::make_optional(version));
+ dispatcher_ctx->complete(0); // complete second read
+ ASSERT_EQ(ETIMEDOUT, dispatched_cond.wait_for(0));
+ dispatcher_ctx->complete(0); // complete write
+ ASSERT_EQ(0, dispatched_cond.wait());
+}
+
TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteFailVersionCheck) {
ceph::bufferlist write_data;
uint64_t version = 1234;