RBD_IMAGE_OPTION_JOURNAL_POOL = 7,
RBD_IMAGE_OPTION_FEATURES_SET = 8,
RBD_IMAGE_OPTION_FEATURES_CLEAR = 9,
- RBD_IMAGE_OPTION_DATA_POOL = 10
+ RBD_IMAGE_OPTION_DATA_POOL = 10,
+ RBD_IMAGE_OPTION_FLATTEN = 11,
};
typedef enum {
template <typename I>
DeepCopyRequest<I>::DeepCopyRequest(I *src_image_ctx, I *dst_image_ctx,
librados::snap_t snap_id_start,
- librados::snap_t snap_id_end,
+ librados::snap_t snap_id_end, bool flatten,
const ObjectNumber &object_number,
ContextWQ *work_queue, SnapSeqs *snap_seqs,
ProgressContext *prog_ctx,
Context *on_finish)
: RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx),
m_dst_image_ctx(dst_image_ctx), m_snap_id_start(snap_id_start),
- m_snap_id_end(snap_id_end), m_object_number(object_number),
- m_work_queue(work_queue), m_snap_seqs(snap_seqs), m_prog_ctx(prog_ctx),
- m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
+ m_snap_id_end(snap_id_end), m_flatten(flatten),
+ m_object_number(object_number), m_work_queue(work_queue),
+ m_snap_seqs(snap_seqs), m_prog_ctx(prog_ctx), m_on_finish(on_finish),
+ m_cct(dst_image_ctx->cct),
m_lock(unique_lock_name("DeepCopyRequest::m_lock", this)) {
}
Context *ctx = create_context_callback<
DeepCopyRequest<I>, &DeepCopyRequest<I>::handle_copy_snapshots>(this);
m_snapshot_copy_request = SnapshotCopyRequest<I>::create(
- m_src_image_ctx, m_dst_image_ctx, m_snap_id_end, m_work_queue, m_snap_seqs,
- ctx);
+ m_src_image_ctx, m_dst_image_ctx, m_snap_id_end, m_flatten, m_work_queue,
+ m_snap_seqs, ctx);
m_snapshot_copy_request->get();
m_lock.Unlock();
DeepCopyRequest<I>, &DeepCopyRequest<I>::handle_copy_image>(this);
m_image_copy_request = ImageCopyRequest<I>::create(
m_src_image_ctx, m_dst_image_ctx, m_snap_id_start, m_snap_id_end,
- m_object_number, *m_snap_seqs, m_prog_ctx, ctx);
+ m_flatten, m_object_number, *m_snap_seqs, m_prog_ctx, ctx);
m_image_copy_request->get();
m_lock.Unlock();
static DeepCopyRequest* create(ImageCtxT *src_image_ctx,
ImageCtxT *dst_image_ctx,
librados::snap_t snap_id_start,
- librados::snap_t snap_id_end,
+ librados::snap_t snap_id_end, bool flatten,
const deep_copy::ObjectNumber &object_number,
ContextWQ *work_queue,
SnapSeqs *snap_seqs,
ProgressContext *prog_ctx,
Context *on_finish) {
return new DeepCopyRequest(src_image_ctx, dst_image_ctx, snap_id_start,
- snap_id_end, object_number, work_queue,
+ snap_id_end, flatten, object_number, work_queue,
snap_seqs, prog_ctx, on_finish);
}
DeepCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx,
librados::snap_t snap_id_start, librados::snap_t snap_id_end,
- const deep_copy::ObjectNumber &object_number,
+ bool flatten, const deep_copy::ObjectNumber &object_number,
ContextWQ *work_queue, SnapSeqs *snap_seqs,
ProgressContext *prog_ctx, Context *on_finish);
~DeepCopyRequest();
ImageCtxT *m_dst_image_ctx;
librados::snap_t m_snap_id_start;
librados::snap_t m_snap_id_end;
+ bool m_flatten;
deep_copy::ObjectNumber m_object_number;
ContextWQ *m_work_queue;
SnapSeqs *m_snap_seqs;
return -ENOSYS;
}
+ uint64_t flatten = 0;
+ if (opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) {
+ opts.unset(RBD_IMAGE_OPTION_FLATTEN);
+ }
+
ParentSpec parent_spec;
- {
+ if (flatten > 0) {
+ parent_spec.pool_id = -1;
+ } else {
RWLock::RLocker snap_locker(src->snap_lock);
RWLock::RLocker parent_locker(src->parent_lock);
return r;
}
- r = deep_copy(src, dest, prog_ctx);
+ r = deep_copy(src, dest, flatten > 0, prog_ctx);
int close_r = dest->state->close();
if (r == 0 && close_r < 0) {
}
template <typename I>
-int Image<I>::deep_copy(I *src, I *dest, ProgressContext &prog_ctx) {
+int Image<I>::deep_copy(I *src, I *dest, bool flatten,
+ ProgressContext &prog_ctx) {
CephContext *cct = src->cct;
librados::snap_t snap_id_start = 0;
librados::snap_t snap_id_end;
C_SaferCond cond;
SnapSeqs snap_seqs;
auto req = DeepCopyRequest<>::create(src, dest, snap_id_start, snap_id_end,
- boost::none, op_work_queue, &snap_seqs,
- &prog_ctx, &cond);
+ flatten, boost::none, op_work_queue,
+ &snap_seqs, &prog_ctx, &cond);
req->send();
int r = cond.wait();
if (r < 0) {
static int deep_copy(ImageCtxT *ictx, librados::IoCtx& dest_md_ctx,
const char *destname, ImageOptions& opts,
ProgressContext &prog_ctx);
- static int deep_copy(ImageCtxT *src, ImageCtxT *dest,
+ static int deep_copy(ImageCtxT *src, ImageCtxT *dest, bool flatten,
ProgressContext &prog_ctx);
static int snap_set(ImageCtxT *ictx,
ImageCopyRequest<I>::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx,
librados::snap_t snap_id_start,
librados::snap_t snap_id_end,
+ bool flatten,
const ObjectNumber &object_number,
const SnapSeqs &snap_seqs,
ProgressContext *prog_ctx,
Context *on_finish)
: RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx),
m_dst_image_ctx(dst_image_ctx), m_snap_id_start(snap_id_start),
- m_snap_id_end(snap_id_end), m_object_number(object_number),
- m_snap_seqs(snap_seqs), m_prog_ctx(prog_ctx), m_on_finish(on_finish),
- m_cct(dst_image_ctx->cct),
+ m_snap_id_end(snap_id_end), m_flatten(flatten),
+ m_object_number(object_number), m_snap_seqs(snap_seqs),
+ m_prog_ctx(prog_ctx), m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
m_lock(unique_lock_name("ImageCopyRequest::m_lock", this)) {
}
});
ObjectCopyRequest<I> *req = ObjectCopyRequest<I>::create(
m_src_image_ctx, m_src_parent_image_ctx, m_dst_image_ctx, m_snap_map, ono,
- ctx);
+ m_flatten, ctx);
req->send();
}
static ImageCopyRequest* create(ImageCtxT *src_image_ctx,
ImageCtxT *dst_image_ctx,
librados::snap_t snap_id_start,
- librados::snap_t snap_id_end,
+ librados::snap_t snap_id_end, bool flatten,
const ObjectNumber &object_number,
const SnapSeqs &snap_seqs,
ProgressContext *prog_ctx,
Context *on_finish) {
return new ImageCopyRequest(src_image_ctx, dst_image_ctx, snap_id_start,
- snap_id_end, object_number, snap_seqs, prog_ctx,
- on_finish);
+ snap_id_end, flatten, object_number, snap_seqs,
+ prog_ctx, on_finish);
}
ImageCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx,
librados::snap_t snap_id_start, librados::snap_t snap_id_end,
- const ObjectNumber &object_number, const SnapSeqs &snap_seqs,
- ProgressContext *prog_ctx, Context *on_finish);
+ bool flatten, const ObjectNumber &object_number,
+ const SnapSeqs &snap_seqs, ProgressContext *prog_ctx,
+ Context *on_finish);
void send();
void cancel();
ImageCtxT *m_dst_image_ctx;
librados::snap_t m_snap_id_start;
librados::snap_t m_snap_id_end;
+ bool m_flatten;
ObjectNumber m_object_number;
SnapSeqs m_snap_seqs;
ProgressContext *m_prog_ctx;
I *dst_image_ctx,
const SnapMap &snap_map,
uint64_t dst_object_number,
- Context *on_finish)
+ bool flatten, Context *on_finish)
: m_src_image_ctx(src_image_ctx),
m_src_parent_image_ctx(src_parent_image_ctx),
m_dst_image_ctx(dst_image_ctx), m_cct(dst_image_ctx->cct),
m_snap_map(snap_map), m_dst_object_number(dst_object_number),
- m_on_finish(on_finish) {
+ m_flatten(flatten), m_on_finish(on_finish) {
assert(!m_snap_map.empty());
m_src_io_ctx.dup(m_src_image_ctx->data_ctx);
return;
}
- if (noent_count == m_src_object_extents.size()) {
+ if (noent_count == m_src_object_extents.size() && !m_flatten) {
ldout(m_cct, 20) << "reading all extents skipped when no flatten"
<< dendl;
return;
ImageCtxT *src_parent_image_ctx,
ImageCtxT *dst_image_ctx,
const SnapMap &snap_map,
- uint64_t object_number,
+ uint64_t object_number, bool flatten,
Context *on_finish) {
return new ObjectCopyRequest(src_image_ctx, src_parent_image_ctx,
dst_image_ctx, snap_map, object_number,
- on_finish);
+ flatten, on_finish);
}
ObjectCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *src_parent_image_ctx,
ImageCtxT *dst_image_ctx, const SnapMap &snap_map,
- uint64_t object_number, Context *on_finish);
+ uint64_t object_number, bool flatten, Context *on_finish);
void send();
CephContext *m_cct;
const SnapMap &m_snap_map;
uint64_t m_dst_object_number;
+ bool m_flatten;
Context *m_on_finish;
decltype(m_src_image_ctx->data_ctx) m_src_io_ctx;
SnapshotCopyRequest<I>::SnapshotCopyRequest(I *src_image_ctx,
I *dst_image_ctx,
librados::snap_t snap_id_end,
- ContextWQ *work_queue,
+ bool flatten, ContextWQ *work_queue,
SnapSeqs *snap_seqs,
Context *on_finish)
: RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx),
m_dst_image_ctx(dst_image_ctx), m_snap_id_end(snap_id_end),
- m_work_queue(work_queue), m_snap_seqs_result(snap_seqs),
+ m_flatten(flatten), m_work_queue(work_queue), m_snap_seqs_result(snap_seqs),
m_snap_seqs(*snap_seqs), m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
m_lock(unique_lock_name("SnapshotCopyRequest::m_lock", this)) {
// snap ids ordered from oldest to newest
m_snap_namespace = snap_info_it->second.snap_namespace;
librbd::ParentSpec parent_spec;
uint64_t parent_overlap = 0;
- if (snap_info_it->second.parent.spec.pool_id != -1) {
+ if (!m_flatten && snap_info_it->second.parent.spec.pool_id != -1) {
parent_spec = m_dst_parent_spec;
parent_overlap = snap_info_it->second.parent.overlap;
}
uint64_t size;
ParentSpec parent_spec;
- uint64_t parent_overlap;
+ uint64_t parent_overlap = 0;
{
RWLock::RLocker src_locker(m_src_image_ctx->snap_lock);
size = m_src_image_ctx->size;
- parent_spec = m_src_image_ctx->parent_md.spec;
- parent_overlap = m_src_image_ctx->parent_md.overlap;
+ if (!m_flatten) {
+ parent_spec = m_src_image_ctx->parent_md.spec;
+ parent_overlap = m_src_image_ctx->parent_md.overlap;
+ }
}
auto ctx = create_context_callback<
public:
static SnapshotCopyRequest* create(ImageCtxT *src_image_ctx,
ImageCtxT *dst_image_ctx,
- librados::snap_t snap_id_end,
- ContextWQ *work_queue,
- SnapSeqs *snap_seqs,
+ librados::snap_t snap_id_end, bool flatten,
+ ContextWQ *work_queue, SnapSeqs *snap_seqs,
Context *on_finish) {
return new SnapshotCopyRequest(src_image_ctx, dst_image_ctx, snap_id_end,
- work_queue, snap_seqs, on_finish);
+ flatten, work_queue, snap_seqs, on_finish);
}
SnapshotCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx,
- librados::snap_t snap_id_end, ContextWQ *work_queue,
- SnapSeqs *snap_seqs, Context *on_finish);
+ librados::snap_t snap_id_end, bool flatten,
+ ContextWQ *work_queue, SnapSeqs *snap_seqs,
+ Context *on_finish);
void send();
void cancel();
ImageCtxT *m_src_image_ctx;
ImageCtxT *m_dst_image_ctx;
librados::snap_t m_snap_id_end;
+ bool m_flatten;
ContextWQ *m_work_queue;
SnapSeqs *m_snap_seqs_result;
SnapSeqs m_snap_seqs;
{RBD_IMAGE_OPTION_FEATURES_SET, UINT64},
{RBD_IMAGE_OPTION_FEATURES_CLEAR, UINT64},
{RBD_IMAGE_OPTION_DATA_POOL, STR},
+ {RBD_IMAGE_OPTION_FLATTEN, UINT64},
};
std::string image_option_name(int optname) {
return "features_clear";
case RBD_IMAGE_OPTION_DATA_POOL:
return "data_pool";
+ case RBD_IMAGE_OPTION_FLATTEN:
+ return "flatten";
default:
return "unknown (" + stringify(optname) + ")";
}
}
CephContext *cct = (CephContext *)io_ctx.cct();
+ uint64_t flatten;
+ if (opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) {
+ lderr(cct) << "create does not support 'flatten' image option" << dendl;
+ return -EINVAL;
+ }
+
ldout(cct, 10) << __func__ << " name=" << image_name << ", "
<< "id= " << id << ", "
<< "size=" << size << ", opts=" << opts << dendl;
return -EINVAL;
}
+ uint64_t flatten;
+ if (c_opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) {
+ lderr(cct) << "clone does not support 'flatten' image option" << dendl;
+ return -EINVAL;
+ }
+
// make sure parent snapshot exists
ImageCtx *p_imctx = new ImageCtx(p_name, "", p_snap_name, p_ioctx, true);
int r = p_imctx->state->open(false);
ImageOptions& opts, ProgressContext &prog_ctx, size_t sparse_size)
{
CephContext *cct = (CephContext *)dest_md_ctx.cct();
+ uint64_t flatten;
+ if (opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) {
+ lderr(cct) << "copy does not support 'flatten' image option" << dendl;
+ return -EINVAL;
+ }
+
ldout(cct, 20) << "copy " << src->name
<< (src->snap_name.length() ? "@" + src->snap_name : "")
<< " -> " << destname << " opts = " << opts << dendl;
librbd::MockTestImageCtx *src_image_ctx,
librbd::MockTestImageCtx *src_parent_image_ctx,
librbd::MockTestImageCtx *dst_image_ctx, const SnapMap &snap_map,
- uint64_t object_number, Context *on_finish) {
+ uint64_t object_number, bool flatten, Context *on_finish) {
assert(s_instance != nullptr);
Mutex::Locker locker(s_instance->lock);
s_instance->snap_map = &snap_map;
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 0, snap_id_end, boost::none,
+ 0, snap_id_end, false, boost::none,
m_snap_seqs, &no_op, &ctx);
request->send();
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 0, snap_id_end, boost::none,
+ 0, snap_id_end, false, boost::none,
m_snap_seqs, &prog_ctx, &ctx);
request->send();
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- snap_id_start, snap_id_end,
+ snap_id_start, snap_id_end, false,
boost::none, m_snap_seqs, &no_op,
&ctx);
request->send();
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 0, snap_id_end,
+ 0, snap_id_end, false,
librbd::deep_copy::ObjectNumber{0U},
m_snap_seqs, &no_op, &ctx);
request->send();
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 0, snap_id_end, boost::none,
+ 0, snap_id_end, false, boost::none,
m_snap_seqs, &no_op, &ctx);
request->send();
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 0, snap_id_end, boost::none,
+ 0, snap_id_end, false, boost::none,
m_snap_seqs, &prog_ctx, &ctx);
request->send();
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 0, 123, boost::none,
+ 0, 123, false, boost::none,
m_snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- 123, snap_id_end, boost::none,
+ 123, snap_id_end, false, boost::none,
m_snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- snap_id_start, snap_id_end,
+ snap_id_start, snap_id_end, false,
boost::none, {{0, 0}}, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
C_SaferCond ctx;
auto request = new MockImageCopyRequest(&mock_src_image_ctx,
&mock_dst_image_ctx,
- snap_id_start, snap_id_end,
+ snap_id_start, snap_id_end, false,
boost::none, {}, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
librbd::MockTestImageCtx &mock_dst_image_ctx, Context *on_finish) {
expect_get_object_name(mock_dst_image_ctx);
return new MockObjectCopyRequest(&mock_src_image_ctx, nullptr,
- &mock_dst_image_ctx, m_snap_map, 0,
+ &mock_dst_image_ctx, m_snap_map, 0, false,
on_finish);
}
librbd::MockTestImageCtx &mock_dst_image_ctx, Context *on_finish,
librados::snap_t snap_id_end = CEPH_NOSNAP) {
return new MockSnapshotCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx,
- snap_id_end, m_work_queue, &m_snap_seqs,
- on_finish);
+ snap_id_end, false, m_work_queue,
+ &m_snap_seqs, on_finish);
}
int create_snap(librbd::ImageCtx *image_ctx, const std::string &snap_name,
test_clone();
}
+TEST_F(TestDeepCopy, CloneFlatten)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ uint64_t flatten = 1;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress)
{
test_stress();
test_clone();
}
+TEST_F(TestDeepCopy, CloneFlatten_LargerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ uint64_t order = m_src_ictx->order + 1 + rand() % 2;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ uint64_t flatten = 1;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_LargerDstObjSize)
{
uint64_t order = m_src_ictx->order + 1 + rand() % 2;
test_clone();
}
+TEST_F(TestDeepCopy, CloneFlatten_SmallerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ uint64_t order = m_src_ictx->order - 1 - rand() % 2;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ uint64_t stripe_unit = m_src_ictx->stripe_unit >> 2;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit));
+ uint64_t flatten = 1;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_SmallerDstObjSize)
{
uint64_t order = m_src_ictx->order - 1 - rand() % 2;
test_clone();
}
+TEST_F(TestDeepCopy, CloneFlatten_StrippingLargerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_STRIPINGV2);
+
+ uint64_t order = m_src_ictx->order + 1;
+ uint64_t stripe_unit = 1 << (order - 2);
+ uint64_t stripe_count = 4;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count));
+ uint64_t flatten = 1;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_StrippingLargerDstObjSize)
{
REQUIRE_FEATURE(RBD_FEATURE_STRIPINGV2);
test_clone();
}
+TEST_F(TestDeepCopy, CloneFlatten_StrippingSmallerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_STRIPINGV2);
+
+ uint64_t order = m_src_ictx->order - 1 - rand() % 2;
+ uint64_t stripe_unit = 1 << (order - rand() % 4);
+ uint64_t stripe_count = 2 + rand() % 14;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count));
+ uint64_t flatten = 1;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_StrippingSmallerDstObjSize)
{
REQUIRE_FEATURE(RBD_FEATURE_STRIPINGV2);
static ImageCopyRequest* create(
librbd::MockTestImageCtx *src_image_ctx,
librbd::MockTestImageCtx *dst_image_ctx, librados::snap_t snap_id_start,
- librados::snap_t snap_id_end, const ObjectNumber &object_number,
- const SnapSeqs &snap_seqs, ProgressContext *prog_ctx,
+ librados::snap_t snap_id_end, bool flatten,
+ const ObjectNumber &object_number, const SnapSeqs &snap_seqs,
+ ProgressContext *prog_ctx,
Context *on_finish) {
assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
static SnapshotCopyRequest* create(librbd::MockTestImageCtx *src_image_ctx,
librbd::MockTestImageCtx *dst_image_ctx,
- librados::snap_t snap_id_end,
+ librados::snap_t snap_id_end, bool flatten,
ContextWQ *work_queue, SnapSeqs *snap_seqs,
Context *on_finish) {
assert(s_instance != nullptr);
librbd::SnapSeqs snap_seqs;
librbd::NoOpProgressContext no_op;
auto request = librbd::DeepCopyRequest<librbd::MockTestImageCtx>::create(
- &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none,
- m_work_queue, &snap_seqs, &no_op, &ctx);
+ &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false,
+ boost::none, m_work_queue, &snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
librbd::SnapSeqs snap_seqs;
librbd::NoOpProgressContext no_op;
auto request = librbd::DeepCopyRequest<librbd::MockTestImageCtx>::create(
- &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none,
- m_work_queue, &snap_seqs, &no_op, &ctx);
+ &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false,
+ boost::none, m_work_queue, &snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
librbd::SnapSeqs snap_seqs;
librbd::NoOpProgressContext no_op;
auto request = librbd::DeepCopyRequest<librbd::MockTestImageCtx>::create(
- &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none,
- m_work_queue, &snap_seqs, &no_op, &ctx);
+ &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false,
+ boost::none, m_work_queue, &snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
librbd::SnapSeqs snap_seqs;
librbd::NoOpProgressContext no_op;
auto request = librbd::DeepCopyRequest<librbd::MockTestImageCtx>::create(
- &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none,
- m_work_queue, &snap_seqs, &no_op, &ctx);
+ &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false,
+ boost::none, m_work_queue, &snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
librbd::NoOpProgressContext no_op;
auto request = librbd::DeepCopyRequest<librbd::MockTestImageCtx>::create(
&mock_src_image_ctx, &mock_dst_image_ctx, 0, m_src_image_ctx->snap_id,
- boost::none, m_work_queue, &snap_seqs, &no_op, &ctx);
+ false, boost::none, m_work_queue, &snap_seqs, &no_op, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
librbd::MockTestImageCtx *src_image_ctx,
librbd::MockTestImageCtx *dst_image_ctx,
librados::snap_t snap_id_start, librados::snap_t snap_id_end,
- const librbd::deep_copy::ObjectNumber &object_number,
+ bool flatten, const librbd::deep_copy::ObjectNumber &object_number,
ContextWQ *work_queue, SnapSeqs *snap_seqs, ProgressContext *prog_ctx,
Context *on_finish) {
assert(s_instance != nullptr);
m_image_copy_prog_ctx = new ImageCopyProgressContext(this);
m_image_copy_request = librbd::DeepCopyRequest<I>::create(
m_remote_image_ctx, m_local_image_ctx, snap_id_start, snap_id_end,
- object_number, m_work_queue, &m_client_meta->snap_seqs,
+ false, object_number, m_work_queue, &m_client_meta->snap_seqs,
m_image_copy_prog_ctx, ctx);
m_image_copy_request->get();
m_lock.Unlock();