m_image_ctx.operations->execute_snap_create(payload.snap_name.c_str(),
new C_ResponseMessage(ack_ctx),
- 0);
+ 0, false);
return false;
}
return true;
C_InvokeAsyncRequest<I> *req = new C_InvokeAsyncRequest<I>(
m_image_ctx, "snap_create", true,
- boost::bind(&Operations<I>::execute_snap_create, this, snap_name, _1, 0),
+ boost::bind(&Operations<I>::execute_snap_create, this, snap_name, _1, 0,
+ false),
boost::bind(&ImageWatcher::notify_snap_create, m_image_ctx.image_watcher,
snap_name, _1),
{-EEXIST}, on_finish);
template <typename I>
void Operations<I>::execute_snap_create(const char *snap_name,
Context *on_finish,
- uint64_t journal_op_tid) {
+ uint64_t journal_op_tid,
+ bool skip_object_map) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock == nullptr ||
m_image_ctx.exclusive_lock->is_lock_owner());
operation::SnapshotCreateRequest<I> *req =
new operation::SnapshotCreateRequest<I>(
m_image_ctx, new C_NotifyUpdate<I>(m_image_ctx, on_finish), snap_name,
- journal_op_tid);
+ journal_op_tid, skip_object_map);
req->send();
}
int snap_create(const char *snap_name);
void snap_create(const char *snap_name, Context *on_finish);
void execute_snap_create(const char *snap_name, Context *on_finish,
- uint64_t journal_op_tid);
+ uint64_t journal_op_tid, bool skip_object_map);
int snap_rollback(const char *snap_name, ProgressContext& prog_ctx);
void execute_snap_rollback(const char *snap_name, ProgressContext& prog_ctx,
void execute(const journal::SnapCreateEvent &_) {
image_ctx.operations->execute_snap_create(event.snap_name.c_str(),
on_op_complete,
- event.op_tid);
+ event.op_tid, false);
}
void execute(const journal::SnapRemoveEvent &_) {
SnapshotCreateRequest<I>::SnapshotCreateRequest(I &image_ctx,
Context *on_finish,
const std::string &snap_name,
- uint64_t journal_op_tid)
+ uint64_t journal_op_tid,
+ bool skip_object_map)
: Request<I>(image_ctx, on_finish, journal_op_tid), m_snap_name(snap_name),
- m_ret_val(0), m_snap_id(CEPH_NOSNAP) {
+ m_skip_object_map(skip_object_map), m_ret_val(0), m_snap_id(CEPH_NOSNAP) {
}
template <typename I>
update_snap_context();
image_ctx.snap_lock.get_read();
- if (image_ctx.object_map == nullptr) {
+ if (image_ctx.object_map == nullptr || m_skip_object_map) {
image_ctx.snap_lock.put_read();
finalize(0);
* (if enabled) and bubble the originating error code back to the client.
*/
SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish,
- const std::string &snap_name, uint64_t journal_op_tid);
+ const std::string &snap_name, uint64_t journal_op_tid,
+ bool skip_object_map);
protected:
virtual void send_op();
private:
std::string m_snap_name;
+ bool m_skip_object_map;
int m_ret_val;
Context **on_finish, const char *snap_name,
uint64_t op_tid) {
EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(CStrEq(snap_name), _,
- op_tid))
+ op_tid, false))
.WillOnce(DoAll(SaveArg<1>(on_finish),
NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
}
Context *on_finish,
uint64_t journal_op_tid));
MOCK_METHOD2(snap_create, void(const char *snap_name, Context *on_finish));
- MOCK_METHOD3(execute_snap_create, void(const char *snap_name,
+ MOCK_METHOD4(execute_snap_create, void(const char *snap_name,
Context *on_finish,
- uint64_t journal_op_tid));
+ uint64_t journal_op_tid,
+ bool skip_object_map));
MOCK_METHOD2(snap_remove, void(const char *snap_name, Context *on_finish));
MOCK_METHOD2(execute_snap_remove, void(const char *snap_name,
Context *on_finish));
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0);
+ mock_image_ctx, &cond_ctx, "snap1", 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0);
+ mock_image_ctx, &cond_ctx, "snap1", 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0);
+ mock_image_ctx, &cond_ctx, "snap1", 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0);
+ mock_image_ctx, &cond_ctx, "snap1", 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0);
+ mock_image_ctx, &cond_ctx, "snap1", 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
ASSERT_EQ(-EINVAL, cond_ctx.wait());
}
+TEST_F(TestMockOperationSnapshotCreateRequest, SkipObjectMap) {
+ REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
+
+ 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;
+ 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);
+ expect_update_snap_context(mock_image_ctx);
+ expect_unblock_writes(mock_image_ctx);
+
+ C_SaferCond cond_ctx;
+ MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
+ mock_image_ctx, &cond_ctx, "snap1", 0, true);
+ {
+ RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
+ req->send();
+ }
+ ASSERT_EQ(0, cond_ctx.wait());
+}
+
} // namespace operation
} // namespace librbd
void expect_snap_create(librbd::MockImageCtx &mock_image_ctx,
const std::string &snap_name, uint64_t snap_id, int r) {
- EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, 0))
+ EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, 0, true))
.WillOnce(DoAll(InvokeWithoutArgs([&mock_image_ctx, snap_id, snap_name]() {
inject_snap(mock_image_ctx, snap_id, snap_name);
}),
this);
RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
m_local_image_ctx->operations->execute_snap_create(m_snap_name.c_str(), ctx,
- 0U);
+ 0U, true);
}
template <typename I>