: Request<I>(image_ctx, on_finish, journal_op_tid),
m_snap_namespace(snap_namespace), m_snap_name(snap_name),
m_skip_object_map(flags & SNAP_CREATE_FLAG_SKIP_OBJECT_MAP),
+ m_skip_notify_quiesce(flags & SNAP_CREATE_FLAG_SKIP_NOTIFY_QUIESCE),
m_prog_ctx(prog_ctx) {
}
template <typename I>
void SnapshotCreateRequest<I>::send_notify_quiesce() {
- I &image_ctx = this->m_image_ctx;
+ if (m_skip_notify_quiesce) {
+ send_suspend_requests();
+ return;
+ }
+ I &image_ctx = this->m_image_ctx;
CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
return this->create_context_finisher(*result);
}
+ std::shared_lock owner_locker{image_ctx.owner_lock};
send_suspend_requests();
return nullptr;
}
template <typename I>
void SnapshotCreateRequest<I>::send_suspend_aio() {
I &image_ctx = this->m_image_ctx;
- std::shared_lock owner_locker{image_ctx.owner_lock};
+ ceph_assert(ceph_mutex_is_locked(image_ctx.owner_lock));
CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
if (*result < 0) {
lderr(cct) << "failed to block writes: " << cpp_strerror(*result) << dendl;
save_result(result);
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
send_append_op_event();
lderr(cct) << "failed to commit journal entry: " << cpp_strerror(*result)
<< dendl;
save_result(result);
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
send_allocate_snap_id();
lderr(cct) << "failed to allocate snapshot id: " << cpp_strerror(*result)
<< dendl;
save_result(result);
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
send_create_snap();
save_result(result);
update_snap_context();
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
return send_create_image_state();
&m_snap_namespace);
if (mirror_ns == nullptr || !mirror_ns->is_primary()) {
update_snap_context();
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
CephContext *cct = image_ctx.cct;
save_result(result);
}
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
template <typename I>
CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
- send_notify_unquiesce();
- return nullptr;
+ return send_notify_unquiesce();
}
template <typename I>
-void SnapshotCreateRequest<I>::send_notify_unquiesce() {
+Context *SnapshotCreateRequest<I>::send_notify_unquiesce() {
I &image_ctx = this->m_image_ctx;
-
CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
image_ctx.io_image_dispatcher->unblock_writes();
+ if (m_skip_notify_quiesce) {
+ return this->create_context_finisher(m_ret_val);
+ }
+
image_ctx.image_watcher->notify_unquiesce(
m_request_id, create_context_callback<
SnapshotCreateRequest<I>,
&SnapshotCreateRequest<I>::handle_notify_unquiesce>(this));
+
+ return nullptr;
}
template <typename I>
ASSERT_EQ(0, cond_ctx.wait());
}
+TEST_F(TestMockOperationSnapshotCreateRequest, SkipNotifyQuiesce) {
+ REQUIRE_FORMAT_V2();
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ MockExclusiveLock mock_exclusive_lock;
+ if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
+ mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
+ }
+
+ MockObjectMap mock_object_map;
+ if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
+ mock_image_ctx.object_map = &mock_object_map;
+ }
+
+ expect_verify_lock_ownership(mock_image_ctx);
+ expect_op_work_queue(mock_image_ctx);
+
+ ::testing::InSequence seq;
+ expect_block_writes(mock_image_ctx);
+ expect_allocate_snap_id(mock_image_ctx, 0);
+ expect_snap_create(mock_image_ctx, 0);
+ if (!mock_image_ctx.old_format) {
+ expect_object_map_snap_create(mock_image_ctx);
+ expect_update_snap_context(mock_image_ctx);
+ }
+ expect_unblock_writes(mock_image_ctx);
+
+ C_SaferCond cond_ctx;
+ librbd::NoOpProgressContext prog_ctx;
+ MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
+ mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
+ "snap1", 0, SNAP_CREATE_FLAG_SKIP_NOTIFY_QUIESCE, prog_ctx);
+ {
+ std::shared_lock owner_locker{mock_image_ctx.owner_lock};
+ req->send();
+ }
+ ASSERT_EQ(0, cond_ctx.wait());
+}
+
TEST_F(TestMockOperationSnapshotCreateRequest, SetImageState) {
REQUIRE_FORMAT_V2();