diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index 0370981819d..3abb4f677eb 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -150,6 +150,12 @@ public: journal_policy = new journal::StandardPolicy(this); } + ImageCtx::ImageCtx(const string &image_name, const string &image_id, + uint64_t snap_id, IoCtx& p, bool ro) + : ImageCtx(image_name, image_id, "", p, ro) { + open_snap_id = snap_id; + } + ImageCtx::~ImageCtx() { assert(image_watcher == NULL); assert(exclusive_lock == NULL); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 0881e6129d1..b2558ea471e 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -69,6 +69,7 @@ namespace librbd { // a format librados can understand std::map snap_info; std::map, librados::snap_t> snap_ids; + uint64_t open_snap_id = CEPH_NOSNAP; uint64_t snap_id; bool snap_exists; // false if our snap_id was deleted // whether the image was opened read-only. cannot be changed after opening @@ -223,6 +224,12 @@ namespace librbd { const char *snap, IoCtx& p, bool read_only) { return new ImageCtx(image_name, image_id, snap, p, read_only); } + static ImageCtx* create(const std::string &image_name, + const std::string &image_id, + librados::snap_t snap_id, IoCtx& p, + bool read_only) { + return new ImageCtx(image_name, image_id, snap_id, p, read_only); + } void destroy() { delete this; } @@ -234,6 +241,8 @@ namespace librbd { */ ImageCtx(const std::string &image_name, const std::string &image_id, const char *snap, IoCtx& p, bool read_only); + ImageCtx(const std::string &image_name, const std::string &image_id, + librados::snap_t snap_id, IoCtx& p, bool read_only); ~ImageCtx(); void init(); void shutdown(); diff --git a/src/librbd/api/Image.cc b/src/librbd/api/Image.cc index 27599921134..fee4cde84c2 100644 --- a/src/librbd/api/Image.cc +++ b/src/librbd/api/Image.cc @@ -262,7 +262,7 @@ int Image::deep_copy(I *src, librados::IoCtx& dest_md_ctx, } opts.set(RBD_IMAGE_OPTION_ORDER, static_cast(order)); - ImageCtx *dest = new librbd::ImageCtx(destname, "", NULL, + ImageCtx *dest = new librbd::ImageCtx(destname, "", nullptr, dest_md_ctx, false); r = dest->state->open(0); if (r < 0) { diff --git a/src/librbd/image/CloneRequest.cc b/src/librbd/image/CloneRequest.cc index 18dbbcd42e4..7d6ef5764ea 100644 --- a/src/librbd/image/CloneRequest.cc +++ b/src/librbd/image/CloneRequest.cc @@ -325,7 +325,7 @@ template void CloneRequest::open_child() { ldout(m_cct, 20) << dendl; - m_imctx = I::create(m_name, "", NULL, m_ioctx, false); + m_imctx = I::create(m_name, "", nullptr, m_ioctx, false); using klass = CloneRequest; Context *ctx = create_context_callback< diff --git a/src/librbd/image/OpenRequest.cc b/src/librbd/image/OpenRequest.cc index 89f2a5d0d19..8f3b78f1a60 100644 --- a/src/librbd/image/OpenRequest.cc +++ b/src/librbd/image/OpenRequest.cc @@ -516,7 +516,8 @@ Context *OpenRequest::handle_register_watch(int *result) { template Context *OpenRequest::send_set_snap(int *result) { - if (m_image_ctx->snap_name.empty()) { + if (m_image_ctx->snap_name.empty() && + m_image_ctx->open_snap_id == CEPH_NOSNAP) { *result = 0; return m_on_finish; } @@ -525,7 +526,8 @@ Context *OpenRequest::send_set_snap(int *result) { ldout(cct, 10) << this << " " << __func__ << dendl; uint64_t snap_id = CEPH_NOSNAP; - { + std::swap(m_image_ctx->open_snap_id, snap_id); + if (snap_id == CEPH_NOSNAP) { RWLock::RLocker snap_locker(m_image_ctx->snap_lock); snap_id = m_image_ctx->get_snap_id(m_image_ctx->snap_namespace, m_image_ctx->snap_name); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 97ba292907e..bf19b63d2c3 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -602,7 +602,7 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) ioctx.set_namespace(ictx->md_ctx.get_namespace()); for (auto &id_it : info.second) { - ImageCtx *imctx = new ImageCtx("", id_it, NULL, ioctx, false); + ImageCtx *imctx = new ImageCtx("", id_it, nullptr, ioctx, false); int r = imctx->state->open(0); if (r < 0) { lderr(cct) << "error opening image: " @@ -1813,8 +1813,8 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) } opts.set(RBD_IMAGE_OPTION_ORDER, static_cast(order)); - ImageCtx *dest = new librbd::ImageCtx(destname, "", NULL, - dest_md_ctx, false); + ImageCtx *dest = new librbd::ImageCtx(destname, "", nullptr, dest_md_ctx, + false); r = dest->state->open(0); if (r < 0) { lderr(cct) << "failed to read newly created header" << dendl; diff --git a/src/test/librbd/test_fixture.cc b/src/test/librbd/test_fixture.cc index a16e9f66d12..9eee5f2f4a2 100644 --- a/src/test/librbd/test_fixture.cc +++ b/src/test/librbd/test_fixture.cc @@ -75,7 +75,7 @@ void TestFixture::TearDown() { int TestFixture::open_image(const std::string &image_name, librbd::ImageCtx **ictx) { - *ictx = new librbd::ImageCtx(image_name.c_str(), "", NULL, m_ioctx, false); + *ictx = new librbd::ImageCtx(image_name.c_str(), "", nullptr, m_ioctx, false); m_ictxs.insert(*ictx); return (*ictx)->state->open(false); diff --git a/src/test/rbd_mirror/test_fixture.cc b/src/test/rbd_mirror/test_fixture.cc index b2a51cae32a..1c312a9a871 100644 --- a/src/test/rbd_mirror/test_fixture.cc +++ b/src/test/rbd_mirror/test_fixture.cc @@ -97,7 +97,7 @@ int TestFixture::create_image(librbd::RBD &rbd, librados::IoCtx &ioctx, int TestFixture::open_image(librados::IoCtx &io_ctx, const std::string &image_name, librbd::ImageCtx **image_ctx) { - *image_ctx = new librbd::ImageCtx(image_name.c_str(), "", NULL, io_ctx, + *image_ctx = new librbd::ImageCtx(image_name.c_str(), "", nullptr, io_ctx, false); m_image_ctxs.insert(*image_ctx); return (*image_ctx)->state->open(false);