end_snap_id, &diff, &end_size, &exists,
&clone_end_snap_id, &read_whole_object);
- if (read_whole_object) {
+ if (read_whole_object ||
+ (!diff.empty() &&
+ ((m_list_snaps_flags & LIST_SNAPS_FLAG_WHOLE_OBJECT) != 0))) {
ldout(cct, 1) << "need to read full object" << dendl;
+ diff.clear();
diff.insert(0, image_ctx->layout.object_size);
end_size = image_ctx->layout.object_size;
clone_end_snap_id = end_snap_id;
ASSERT_EQ(expected_snapshot_delta, snapshot_delta);
}
+TEST_F(TestMockIoObjectRequest, ListSnapsWholeObject) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockTestImageCtx mock_image_ctx(*ictx);
+ mock_image_ctx.parent = &mock_image_ctx;
+
+ InSequence seq;
+
+ librados::snap_set_t snap_set;
+ snap_set.seq = 3;
+ librados::clone_info_t clone_info;
+
+ clone_info.cloneid = 3;
+ clone_info.snaps = {3};
+ clone_info.overlap = std::vector<std::pair<uint64_t,uint64_t>>{{0, 1}};
+ clone_info.size = 4194304;
+ snap_set.clones.push_back(clone_info);
+
+ clone_info.cloneid = CEPH_NOSNAP;
+ clone_info.snaps = {};
+ clone_info.overlap = {};
+ clone_info.size = 4194304;
+ snap_set.clones.push_back(clone_info);
+
+ expect_list_snaps(mock_image_ctx, snap_set, 0);
+
+ SnapshotDelta snapshot_delta;
+ C_SaferCond ctx;
+ auto req = MockObjectListSnapsRequest::create(
+ &mock_image_ctx, 0, {{0, mock_image_ctx.layout.object_size - 1}},
+ {0, CEPH_NOSNAP}, 0, {}, &snapshot_delta, &ctx);
+ req->send();
+ ASSERT_EQ(0, ctx.wait());
+
+ SnapshotDelta expected_snapshot_delta;
+ expected_snapshot_delta[{CEPH_NOSNAP,CEPH_NOSNAP}].insert(
+ 0, mock_image_ctx.layout.object_size - 1,
+ {SNAPSHOT_EXTENT_STATE_DATA, mock_image_ctx.layout.object_size - 1});
+ ASSERT_EQ(expected_snapshot_delta, snapshot_delta);
+}
+
} // namespace io
} // namespace librbd