From: Jason Dillaman Date: Wed, 12 Aug 2015 14:31:53 +0000 (-0400) Subject: librbd: move object map async ops to standalone classes X-Git-Tag: v10.0.2~193^2~27 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7b1170a8431be4ecc9e16b407227147dceefb86a;p=ceph.git librbd: move object map async ops to standalone classes In preparation for creating new async snapshot-related object map operations, move the existing object map async ops to there own namespace. Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/CopyupRequest.cc b/src/librbd/CopyupRequest.cc index 5c3973a2b97..fdb3d627080 100644 --- a/src/librbd/CopyupRequest.cc +++ b/src/librbd/CopyupRequest.cc @@ -57,6 +57,7 @@ public: state = OBJECT_EXISTS_CLEAN; } + RWLock::RLocker snap_locker(m_image_ctx.snap_lock); RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock); m_image_ctx.object_map.aio_update(snap_id, m_object_no, m_object_no + 1, state, boost::optional(), this); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index d7010e3b913..28e8f7455af 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -25,6 +25,7 @@ #include "osdc/ObjectCacher.h" #include "cls/rbd/cls_rbd_client.h" +#include "librbd/AsyncRequest.h" #include "librbd/LibrbdWriteback.h" #include "librbd/ObjectMap.h" #include "librbd/SnapInfo.h" @@ -37,9 +38,9 @@ class PerfCounters; namespace librbd { + struct ImageCtx; class AioImageRequestWQ; class AsyncOperation; - template class AsyncRequest; class CopyupRequest; class LibrbdAdminSocketHook; class ImageWatcher; diff --git a/src/librbd/Makefile.am b/src/librbd/Makefile.am index 246e94c11a4..0d8f5b64f85 100644 --- a/src/librbd/Makefile.am +++ b/src/librbd/Makefile.am @@ -25,6 +25,9 @@ librbd_internal_la_SOURCES = \ librbd/LibrbdAdminSocketHook.cc \ librbd/LibrbdWriteback.cc \ librbd/ObjectMap.cc \ + librbd/object_map/Request.cc \ + librbd/object_map/ResizeRequest.cc \ + librbd/object_map/UpdateRequest.cc \ librbd/operation/FlattenRequest.cc \ librbd/operation/RebuildObjectMapRequest.cc \ librbd/operation/Request.cc \ @@ -83,6 +86,9 @@ noinst_HEADERS += \ librbd/SnapInfo.h \ librbd/TaskFinisher.h \ librbd/WatchNotifyTypes.h \ + librbd/object_map/Request.h \ + librbd/object_map/ResizeRequest.h \ + librbd/object_map/UpdateRequest.h \ librbd/operation/FlattenRequest.h \ librbd/operation/RebuildObjectMapRequest.h \ librbd/operation/Request.h \ diff --git a/src/librbd/ObjectMap.cc b/src/librbd/ObjectMap.cc index e1f2e17796f..fdfd211b962 100644 --- a/src/librbd/ObjectMap.cc +++ b/src/librbd/ObjectMap.cc @@ -4,6 +4,8 @@ #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/internal.h" +#include "librbd/object_map/ResizeRequest.h" +#include "librbd/object_map/UpdateRequest.h" #include "common/dout.h" #include "common/errno.h" #include "include/stringify.h" @@ -200,7 +202,8 @@ void ObjectMap::refresh(uint64_t snap_id) r = m_image_ctx.md_ctx.operate(oid, &op); if (r == 0) { m_object_map.clear(); - resize(num_objs, OBJECT_NONEXISTENT); + object_map::ResizeRequest::resize(&m_object_map, num_objs, + OBJECT_NONEXISTENT); } } if (r < 0) { @@ -229,7 +232,8 @@ void ObjectMap::refresh(uint64_t snap_id) r = m_image_ctx.md_ctx.operate(oid, &op); if (r == 0) { - resize(num_objs, OBJECT_NONEXISTENT); + object_map::ResizeRequest::resize(&m_object_map, num_objs, + OBJECT_NONEXISTENT); } } else if (m_object_map.size() > num_objs) { // resize op might have been interrupted @@ -437,8 +441,9 @@ void ObjectMap::aio_resize(uint64_t new_size, uint8_t default_object_state, assert(!m_image_ctx.image_watcher->is_lock_supported() || m_image_ctx.image_watcher->is_lock_owner()); - ResizeRequest *req = new ResizeRequest( - m_image_ctx, m_snap_id, new_size, default_object_state, on_finish); + object_map::ResizeRequest *req = new object_map::ResizeRequest( + m_image_ctx, &m_object_map, m_snap_id, new_size, default_object_state, + on_finish); req->send(); } @@ -493,10 +498,9 @@ void ObjectMap::aio_update(uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, Context *on_finish) { - UpdateRequest *req = new UpdateRequest(m_image_ctx, snap_id, - start_object_no, end_object_no, - new_state, current_state, - on_finish); + object_map::UpdateRequest *req = new object_map::UpdateRequest( + m_image_ctx, &m_object_map, snap_id, start_object_no, end_object_no, + new_state, current_state, on_finish); req->send(); } @@ -546,161 +550,4 @@ void ObjectMap::invalidate(uint64_t snap_id, bool force) { } } -void ObjectMap::resize(uint64_t num_objs, uint8_t defualt_state) { - size_t orig_object_map_size = m_object_map.size(); - m_object_map.resize(num_objs); - for (uint64_t i = orig_object_map_size; - i < m_object_map.size(); ++i) { - m_object_map[i] = defualt_state; - } -} - -bool ObjectMap::Request::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; - ldout(cct, 20) << &m_image_ctx << " should_complete: r=" << r << dendl; - - switch (m_state) - { - case STATE_REQUEST: - if (r == -EBUSY) { - lderr(cct) << "object map lock not owned by client" << dendl; - return invalidate(); - } else if (r < 0) { - lderr(cct) << "failed to update object map: " << cpp_strerror(r) - << dendl; - return invalidate(); - } - - { - RWLock::WLocker l2(m_image_ctx.object_map_lock); - finish(&m_image_ctx.object_map); - } - return true; - - case STATE_INVALIDATE: - ldout(cct, 20) << "INVALIDATE" << dendl; - if (r < 0) { - lderr(cct) << "failed to invalidate object map: " << cpp_strerror(r) - << dendl; - } - return true; - - default: - lderr(cct) << "invalid state: " << m_state << dendl; - assert(false); - break; - } - return false; -} - -bool ObjectMap::Request::invalidate() { - if (m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID)) { - return true; - } - - CephContext *cct = m_image_ctx.cct; - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); - - // requests shouldn't be running while using snapshots - assert(m_image_ctx.snap_id == CEPH_NOSNAP); - - uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID; - if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) { - flags |= RBD_FLAG_FAST_DIFF_INVALID; - } - - lderr(cct) << &m_image_ctx << " invalidating object map" << dendl; - m_state = STATE_INVALIDATE; - m_image_ctx.flags |= flags; - - librados::ObjectWriteOperation op; - cls_client::set_flags(&op, CEPH_NOSNAP, flags, flags); - - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, - rados_completion, &op); - assert(r == 0); - rados_completion->release(); - return false; -} - -void ObjectMap::ResizeRequest::send() { - CephContext *cct = m_image_ctx.cct; - - RWLock::WLocker l(m_image_ctx.object_map_lock); - m_num_objs = Striper::get_num_objects(m_image_ctx.layout, m_new_size); - - ldout(cct, 5) << &m_image_ctx << " resizing on-disk object map: " - << m_num_objs << dendl; - - librados::ObjectWriteOperation op; - if (m_snap_id == CEPH_NOSNAP) { - rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", ""); - } - cls_client::object_map_resize(&op, m_num_objs, m_default_object_state); - - librados::AioCompletion *rados_completion = create_callback_completion(); - std::string oid(object_map_name(m_image_ctx.id, m_snap_id)); - int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); - assert(r == 0); - rados_completion->release(); -} - -void ObjectMap::ResizeRequest::finish(ObjectMap *object_map) { - CephContext *cct = m_image_ctx.cct; - - ldout(cct, 5) << &m_image_ctx << " resizing in-memory object map: " - << m_num_objs << dendl; - object_map->resize(m_num_objs, m_default_object_state); -} - -void ObjectMap::UpdateRequest::send() { - assert(m_image_ctx.object_map_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; - - // safe to update in-memory state first without handling rollback since any - // failures will invalidate the object map - ldout(cct, 20) << &m_image_ctx << " updating object map" - << (m_snap_id != CEPH_NOSNAP ? - " snap " + stringify(m_snap_id) : std::string()) - << ": [" - << m_start_object_no << "," << m_end_object_no << ") = " - << (m_current_state ? - stringify(static_cast(*m_current_state)) : "") - << "->" << static_cast(m_new_state) - << dendl; - - ObjectMap& object_map = m_image_ctx.object_map; - if (m_snap_id == object_map.m_snap_id) { - assert(m_image_ctx.object_map_lock.is_wlocked()); - for (uint64_t object_no = m_start_object_no; - object_no < MIN(m_end_object_no, object_map.m_object_map.size()); - ++object_no) { - uint8_t state = object_map.m_object_map[object_no]; - if (!m_current_state || state == *m_current_state || - (*m_current_state == OBJECT_EXISTS && state == OBJECT_EXISTS_CLEAN)) { - object_map.m_object_map[object_no] = m_new_state; - } - } - } - - librados::ObjectWriteOperation op; - if (m_snap_id == CEPH_NOSNAP) { - rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", ""); - } - cls_client::object_map_update(&op, m_start_object_no, m_end_object_no, - m_new_state, m_current_state); - - librados::AioCompletion *rados_completion = create_callback_completion(); - std::string oid(object_map_name(m_image_ctx.id, m_snap_id)); - int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); - assert(r == 0); - rados_completion->release(); -} - -void ObjectMap::UpdateRequest::finish(ObjectMap *object_map) { - ldout(m_image_ctx.cct, 20) << &m_image_ctx << " on-disk object map updated" - << dendl; -} - } // namespace librbd diff --git a/src/librbd/ObjectMap.h b/src/librbd/ObjectMap.h index f0d1bbe9434..b175c3669ff 100644 --- a/src/librbd/ObjectMap.h +++ b/src/librbd/ObjectMap.h @@ -7,7 +7,6 @@ #include "include/rados/librados.hpp" #include "include/rbd/object_map_types.h" #include "common/bit_vector.hpp" -#include "librbd/AsyncRequest.h" #include class Context; @@ -60,89 +59,12 @@ public: bool enabled() const; private: - - class Request : public AsyncRequest<> { - public: - Request(ImageCtx &image_ctx, uint64_t snap_id, Context *on_finish) - : AsyncRequest(image_ctx, on_finish), m_snap_id(snap_id), - m_state(STATE_REQUEST) - { - } - - protected: - const uint64_t m_snap_id; - - virtual bool should_complete(int r); - virtual int filter_return_code(int r) const { - // never propagate an error back to the caller - return 0; - } - virtual void finish(ObjectMap *object_map) = 0; - private: - /** - * ---> STATE_REQUEST ---> - * | ^ - * v | - * STATE_INVALIDATE -------/ - */ - enum State { - STATE_REQUEST, - STATE_INVALIDATE - }; - - State m_state; - - bool invalidate(); - }; - - class ResizeRequest : public Request { - public: - ResizeRequest(ImageCtx &image_ctx, uint64_t snap_id, uint64_t new_size, - uint8_t default_object_state, Context *on_finish) - : Request(image_ctx, snap_id, on_finish), m_num_objs(0), - m_new_size(new_size), m_default_object_state(default_object_state) - { - } - - virtual void send(); - protected: - virtual void finish(ObjectMap *object_map); - private: - uint64_t m_num_objs; - uint64_t m_new_size; - uint8_t m_default_object_state; - }; - - class UpdateRequest : public Request { - public: - UpdateRequest(ImageCtx &image_ctx, uint64_t snap_id, - uint64_t start_object_no, uint64_t end_object_no, - uint8_t new_state, - const boost::optional ¤t_state, - Context *on_finish) - : Request(image_ctx, snap_id, on_finish), - m_start_object_no(start_object_no), m_end_object_no(end_object_no), - m_new_state(new_state), m_current_state(current_state) - { - } - - virtual void send(); - protected: - virtual void finish(ObjectMap *object_map); - private: - uint64_t m_start_object_no; - uint64_t m_end_object_no; - uint8_t m_new_state; - boost::optional m_current_state; - }; - ImageCtx &m_image_ctx; ceph::BitVector<2> m_object_map; uint64_t m_snap_id; bool m_enabled; void invalidate(uint64_t snap_id, bool force); - void resize(uint64_t num_objs, uint8_t default_state); }; } // namespace librbd diff --git a/src/librbd/object_map/Request.cc b/src/librbd/object_map/Request.cc new file mode 100644 index 00000000000..706c87cbbcf --- /dev/null +++ b/src/librbd/object_map/Request.cc @@ -0,0 +1,90 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/object_map/Request.h" +#include "include/rados/librados.hpp" +#include "include/rbd/librbd.hpp" +#include "common/dout.h" +#include "common/errno.h" +#include "common/RWLock.h" +#include "librbd/ImageCtx.h" +#include "librbd/ImageWatcher.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::object_map::Request: " + +namespace librbd { +namespace object_map { + +bool Request::should_complete(int r) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 20) << &m_image_ctx << " should_complete: r=" << r << dendl; + + switch (m_state) + { + case STATE_REQUEST: + if (r == -EBUSY) { + lderr(cct) << "object map lock not owned by client" << dendl; + return invalidate(); + } else if (r < 0) { + lderr(cct) << "failed to update object map: " << cpp_strerror(r) + << dendl; + return invalidate(); + } + + { + RWLock::WLocker l2(m_image_ctx.object_map_lock); + finish(); + } + return true; + + case STATE_INVALIDATE: + ldout(cct, 20) << "INVALIDATE" << dendl; + if (r < 0) { + lderr(cct) << "failed to invalidate object map: " << cpp_strerror(r) + << dendl; + } + return true; + + default: + lderr(cct) << "invalid state: " << m_state << dendl; + assert(false); + break; + } + return false; +} + +bool Request::invalidate() { + if (m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID)) { + return true; + } + + CephContext *cct = m_image_ctx.cct; + RWLock::WLocker snap_locker(m_image_ctx.snap_lock); + + // requests shouldn't be running while using snapshots + assert(m_image_ctx.snap_id == CEPH_NOSNAP); + + uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID; + if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) { + flags |= RBD_FLAG_FAST_DIFF_INVALID; + } + + lderr(cct) << &m_image_ctx << " invalidating object map" << dendl; + m_state = STATE_INVALIDATE; + m_image_ctx.flags |= flags; + + librados::ObjectWriteOperation op; + cls_client::set_flags(&op, CEPH_NOSNAP, flags, flags); + + librados::AioCompletion *rados_completion = create_callback_completion(); + int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, + rados_completion, &op); + assert(r == 0); + rados_completion->release(); + return false; +} + +} // namespace object_map +} // namespace librbd diff --git a/src/librbd/object_map/Request.h b/src/librbd/object_map/Request.h new file mode 100644 index 00000000000..fdc22de0824 --- /dev/null +++ b/src/librbd/object_map/Request.h @@ -0,0 +1,58 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_OBJECT_MAP_REQUEST_H +#define CEPH_LIBRBD_OBJECT_MAP_REQUEST_H + +#include "include/int_types.h" +#include "librbd/AsyncRequest.h" + +class Context; + +namespace librbd { + +class ImageCtx; + +namespace object_map { + +class Request : public AsyncRequest<> { +public: + Request(ImageCtx &image_ctx, uint64_t snap_id, Context *on_finish) + : AsyncRequest(image_ctx, on_finish), m_snap_id(snap_id), + m_state(STATE_REQUEST) + { + } + + virtual void send() = 0; + +protected: + const uint64_t m_snap_id; + + virtual bool should_complete(int r); + virtual int filter_return_code(int r) const { + // never propagate an error back to the caller + return 0; + } + virtual void finish() = 0; + +private: + /** + * ---> STATE_REQUEST ---> + * | ^ + * v | + * STATE_INVALIDATE -------/ + */ + enum State { + STATE_REQUEST, + STATE_INVALIDATE + }; + + State m_state; + + bool invalidate(); +}; + +} // namespace object_map +} // namespace librbd + +#endif // CEPH_LIBRBD_OBJECT_MAP_REQUEST_H diff --git a/src/librbd/object_map/ResizeRequest.cc b/src/librbd/object_map/ResizeRequest.cc new file mode 100644 index 00000000000..8bdb64c4c6c --- /dev/null +++ b/src/librbd/object_map/ResizeRequest.cc @@ -0,0 +1,58 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/object_map/ResizeRequest.h" +#include "common/dout.h" +#include "common/errno.h" +#include "librbd/ImageCtx.h" +#include "librbd/ObjectMap.h" +#include "cls/lock/cls_lock_client.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::object_map::ResizeRequest: " + +namespace librbd { +namespace object_map { + +void ResizeRequest::resize(ceph::BitVector<2> *object_map, uint64_t num_objs, + uint8_t default_state) { + size_t orig_object_map_size = object_map->size(); + object_map->resize(num_objs); + for (uint64_t i = orig_object_map_size; i < object_map->size(); ++i) { + (*object_map)[i] = default_state; + } +} + +void ResizeRequest::send() { + CephContext *cct = m_image_ctx.cct; + + RWLock::WLocker l(m_image_ctx.object_map_lock); + m_num_objs = Striper::get_num_objects(m_image_ctx.layout, m_new_size); + + ldout(cct, 5) << &m_image_ctx << " resizing on-disk object map: " + << m_num_objs << dendl; + + librados::ObjectWriteOperation op; + if (m_snap_id == CEPH_NOSNAP) { + rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", ""); + } + cls_client::object_map_resize(&op, m_num_objs, m_default_object_state); + + librados::AioCompletion *rados_completion = create_callback_completion(); + std::string oid(ObjectMap::object_map_name(m_image_ctx.id, m_snap_id)); + int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); + assert(r == 0); + rados_completion->release(); +} + +void ResizeRequest::finish() { + CephContext *cct = m_image_ctx.cct; + + ldout(cct, 5) << &m_image_ctx << " resizing in-memory object map: " + << m_num_objs << dendl; + resize(m_object_map, m_num_objs, m_default_object_state); +} + +} // namespace object_map +} // namespace librbd diff --git a/src/librbd/object_map/ResizeRequest.h b/src/librbd/object_map/ResizeRequest.h new file mode 100644 index 00000000000..ca9539344c4 --- /dev/null +++ b/src/librbd/object_map/ResizeRequest.h @@ -0,0 +1,48 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_OBJECT_MAP_RESIZE_REQUEST_H +#define CEPH_LIBRBD_OBJECT_MAP_RESIZE_REQUEST_H + +#include "include/int_types.h" +#include "librbd/object_map/Request.h" +#include "common/bit_vector.hpp" + +class Context; + +namespace librbd { + +class ImageCtx; + +namespace object_map { + +class ResizeRequest : public Request { +public: + ResizeRequest(ImageCtx &image_ctx, ceph::BitVector<2> *object_map, + uint64_t snap_id, uint64_t new_size, + uint8_t default_object_state, Context *on_finish) + : Request(image_ctx, snap_id, on_finish), m_object_map(object_map), + m_num_objs(0), m_new_size(new_size), + m_default_object_state(default_object_state) + { + } + + static void resize(ceph::BitVector<2> *object_map, uint64_t num_objs, + uint8_t default_state); + + virtual void send(); + +protected: + virtual void finish(); + +private: + ceph::BitVector<2> *m_object_map; + uint64_t m_num_objs; + uint64_t m_new_size; + uint8_t m_default_object_state; +}; + +} // namespace object_map +} // namespace librbd + +#endif // CEPH_LIBRBD_OBJECT_MAP_RESIZE_REQUEST_H diff --git a/src/librbd/object_map/UpdateRequest.cc b/src/librbd/object_map/UpdateRequest.cc new file mode 100644 index 00000000000..eef548828f8 --- /dev/null +++ b/src/librbd/object_map/UpdateRequest.cc @@ -0,0 +1,72 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/object_map/UpdateRequest.h" +#include "include/rbd/object_map_types.h" +#include "include/stringify.h" +#include "common/dout.h" +#include "common/errno.h" +#include "librbd/ImageCtx.h" +#include "librbd/ObjectMap.h" +#include "cls/lock/cls_lock_client.h" +#include + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::object_map::UpdateRequest: " + +namespace librbd { +namespace object_map { + +void UpdateRequest::send() { + assert(m_image_ctx.snap_lock.is_locked()); + assert(m_image_ctx.object_map_lock.is_locked()); + CephContext *cct = m_image_ctx.cct; + + // safe to update in-memory state first without handling rollback since any + // failures will invalidate the object map + ldout(cct, 20) << &m_image_ctx << " updating object map" + << (m_snap_id != CEPH_NOSNAP ? + " snap " + stringify(m_snap_id) : std::string()) + << ": [" + << m_start_object_no << "," << m_end_object_no << ") = " + << (m_current_state ? + stringify(static_cast(*m_current_state)) : "") + << "->" << static_cast(m_new_state) + << dendl; + + // rebuilding the object map might update on-disk only + if (m_snap_id == m_image_ctx.snap_id) { + assert(m_image_ctx.object_map_lock.is_wlocked()); + for (uint64_t object_no = m_start_object_no; + object_no < MIN(m_end_object_no, m_object_map.size()); + ++object_no) { + uint8_t state = m_object_map[object_no]; + if (!m_current_state || state == *m_current_state || + (*m_current_state == OBJECT_EXISTS && state == OBJECT_EXISTS_CLEAN)) { + m_object_map[object_no] = m_new_state; + } + } + } + + librados::ObjectWriteOperation op; + if (m_snap_id == CEPH_NOSNAP) { + rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", ""); + } + cls_client::object_map_update(&op, m_start_object_no, m_end_object_no, + m_new_state, m_current_state); + + librados::AioCompletion *rados_completion = create_callback_completion(); + std::string oid(ObjectMap::object_map_name(m_image_ctx.id, m_snap_id)); + int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); + assert(r == 0); + rados_completion->release(); +} + +void UpdateRequest::finish() { + ldout(m_image_ctx.cct, 20) << &m_image_ctx << " on-disk object map updated" + << dendl; +} + +} // namespace object_map +} // namespace librbd diff --git a/src/librbd/object_map/UpdateRequest.h b/src/librbd/object_map/UpdateRequest.h new file mode 100644 index 00000000000..6c277b01a63 --- /dev/null +++ b/src/librbd/object_map/UpdateRequest.h @@ -0,0 +1,49 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_OBJECT_MAP_UPDATE_REQUEST_H +#define CEPH_LIBRBD_OBJECT_MAP_UPDATE_REQUEST_H + +#include "include/int_types.h" +#include "librbd/object_map/Request.h" +#include "common/bit_vector.hpp" +#include + +class Context; + +namespace librbd { + +class ImageCtx; + +namespace object_map { + +class UpdateRequest : public Request { +public: + UpdateRequest(ImageCtx &image_ctx, ceph::BitVector<2> *object_map, + uint64_t snap_id, uint64_t start_object_no, + uint64_t end_object_no, uint8_t new_state, + const boost::optional ¤t_state, + Context *on_finish) + : Request(image_ctx, snap_id, on_finish), m_object_map(*object_map), + m_start_object_no(start_object_no), m_end_object_no(end_object_no), + m_new_state(new_state), m_current_state(current_state) + { + } + + virtual void send(); + +protected: + virtual void finish(); + +private: + ceph::BitVector<2> &m_object_map; + uint64_t m_start_object_no; + uint64_t m_end_object_no; + uint8_t m_new_state; + boost::optional m_current_state; +}; + +} // namespace object_map +} // namespace librbd + +#endif // CEPH_LIBRBD_OBJECT_MAP_UPDATE_REQUEST_H