]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/librbd/ObjectMap.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / ObjectMap.cc
index 50cbfda89220edc23747aa1a8763401754ecd6f7..0d60cc95f94e5790c012993c2e951a8b62c073f9 100644 (file)
 
 namespace librbd {
 
+using librbd::util::create_context_callback;
+
 template <typename I>
 ObjectMap<I>::ObjectMap(I &image_ctx, uint64_t snap_id)
-  : m_image_ctx(image_ctx), m_snap_id(snap_id),
+  : RefCountedObject(image_ctx.cct),
+    m_image_ctx(image_ctx), m_snap_id(snap_id),
+    m_lock(ceph::make_shared_mutex(util::unique_lock_name("librbd::ObjectMap::lock", this))),
     m_update_guard(new UpdateGuard(m_image_ctx.cct)) {
 }
 
@@ -68,18 +72,10 @@ bool ObjectMap<I>::is_compatible(const file_layout_t& layout, uint64_t size) {
   return (object_count <= cls::rbd::MAX_OBJECT_MAP_OBJECT_COUNT);
 }
 
-template <typename I>
-ceph::BitVector<2u>::Reference ObjectMap<I>::operator[](uint64_t object_no)
-{
-  ceph_assert(m_image_ctx.object_map_lock.is_wlocked());
-  ceph_assert(object_no < m_object_map.size());
-  return m_object_map[object_no];
-}
-
 template <typename I>
 uint8_t ObjectMap<I>::operator[](uint64_t object_no) const
 {
-  ceph_assert(m_image_ctx.object_map_lock.is_locked());
+  std::shared_lock locker{m_lock};
   ceph_assert(object_no < m_object_map.size());
   return m_object_map[object_no];
 }
@@ -87,23 +83,22 @@ uint8_t ObjectMap<I>::operator[](uint64_t object_no) const
 template <typename I>
 bool ObjectMap<I>::object_may_exist(uint64_t object_no) const
 {
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
 
   // Fall back to default logic if object map is disabled or invalid
   if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
-                                 m_image_ctx.snap_lock)) {
+                                 m_image_ctx.image_lock)) {
     return true;
   }
 
   bool flags_set;
   int r = m_image_ctx.test_flags(m_image_ctx.snap_id,
                                  RBD_FLAG_OBJECT_MAP_INVALID,
-                                 m_image_ctx.snap_lock, &flags_set);
+                                 m_image_ctx.image_lock, &flags_set);
   if (r < 0 || flags_set) {
     return true;
   }
 
-  RWLock::RLocker l(m_image_ctx.object_map_lock);
   uint8_t state = (*this)[object_no];
   bool exists = (state != OBJECT_NONEXISTENT);
   ldout(m_image_ctx.cct, 20) << "object_no=" << object_no << " r=" << exists
@@ -114,23 +109,22 @@ bool ObjectMap<I>::object_may_exist(uint64_t object_no) const
 template <typename I>
 bool ObjectMap<I>::object_may_not_exist(uint64_t object_no) const
 {
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
 
   // Fall back to default logic if object map is disabled or invalid
   if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
-                                 m_image_ctx.snap_lock)) {
+                                 m_image_ctx.image_lock)) {
     return true;
   }
 
   bool flags_set;
   int r = m_image_ctx.test_flags(m_image_ctx.snap_id,
                                  RBD_FLAG_OBJECT_MAP_INVALID,
-                                 m_image_ctx.snap_lock, &flags_set);
+                                 m_image_ctx.image_lock, &flags_set);
   if (r < 0 || flags_set) {
     return true;
   }
 
-  RWLock::RLocker l(m_image_ctx.object_map_lock);
   uint8_t state = (*this)[object_no];
   bool nonexistent = (state != OBJECT_EXISTS && state != OBJECT_EXISTS_CLEAN);
   ldout(m_image_ctx.cct, 20) << "object_no=" << object_no << " r="
@@ -141,7 +135,7 @@ bool ObjectMap<I>::object_may_not_exist(uint64_t object_no) const
 template <typename I>
 bool ObjectMap<I>::update_required(const ceph::BitVector<2>::Iterator& it,
                                    uint8_t new_state) {
-  ceph_assert(m_image_ctx.object_map_lock.is_wlocked());
+  ceph_assert(ceph_mutex_is_locked(m_lock));
   uint8_t state = *it;
   if ((state == new_state) ||
       (new_state == OBJECT_PENDING && state == OBJECT_NONEXISTENT) ||
@@ -153,74 +147,84 @@ bool ObjectMap<I>::update_required(const ceph::BitVector<2>::Iterator& it,
 
 template <typename I>
 void ObjectMap<I>::open(Context *on_finish) {
+  Context *ctx = create_context_callback<Context>(on_finish, this);
+
   auto req = object_map::RefreshRequest<I>::create(
-    m_image_ctx, &m_object_map, m_snap_id, on_finish);
+    m_image_ctx, &m_lock, &m_object_map, m_snap_id, ctx);
   req->send();
 }
 
 template <typename I>
 void ObjectMap<I>::close(Context *on_finish) {
+  Context *ctx = create_context_callback<Context>(on_finish, this);
+
   if (m_snap_id != CEPH_NOSNAP) {
-    m_image_ctx.op_work_queue->queue(on_finish, 0);
+    m_image_ctx.op_work_queue->queue(ctx, 0);
     return;
   }
 
-  auto req = object_map::UnlockRequest<I>::create(m_image_ctx, on_finish);
+  auto req = object_map::UnlockRequest<I>::create(m_image_ctx, ctx);
   req->send();
 }
 
 template <typename I>
 bool ObjectMap<I>::set_object_map(ceph::BitVector<2> &target_object_map) {
-  ceph_assert(m_image_ctx.owner_lock.is_locked());
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.owner_lock));
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
   ceph_assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
-                                        m_image_ctx.snap_lock));
-  RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock);
+                                        m_image_ctx.image_lock));
+  std::unique_lock locker{m_lock};
   m_object_map = target_object_map;
   return true;
 }
 
 template <typename I>
 void ObjectMap<I>::rollback(uint64_t snap_id, Context *on_finish) {
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
-  ceph_assert(m_image_ctx.object_map_lock.is_wlocked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
+
+  std::unique_lock locker{m_lock};
+  Context *ctx = create_context_callback<Context>(on_finish, this);
 
   object_map::SnapshotRollbackRequest *req =
-    new object_map::SnapshotRollbackRequest(m_image_ctx, snap_id, on_finish);
+    new object_map::SnapshotRollbackRequest(m_image_ctx, snap_id, ctx);
   req->send();
 }
 
 template <typename I>
 void ObjectMap<I>::snapshot_add(uint64_t snap_id, Context *on_finish) {
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
   ceph_assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
   ceph_assert(snap_id != CEPH_NOSNAP);
 
+  Context *ctx = create_context_callback<Context>(on_finish, this);
+
   object_map::SnapshotCreateRequest *req =
-    new object_map::SnapshotCreateRequest(m_image_ctx, &m_object_map, snap_id,
-                                          on_finish);
+    new object_map::SnapshotCreateRequest(m_image_ctx, &m_lock, &m_object_map,
+                                          snap_id, ctx);
   req->send();
 }
 
 template <typename I>
 void ObjectMap<I>::snapshot_remove(uint64_t snap_id, Context *on_finish) {
-  ceph_assert(m_image_ctx.snap_lock.is_wlocked());
+  ceph_assert(ceph_mutex_is_wlocked(m_image_ctx.image_lock));
   ceph_assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
   ceph_assert(snap_id != CEPH_NOSNAP);
 
+  Context *ctx = create_context_callback<Context>(on_finish, this);
+
   object_map::SnapshotRemoveRequest *req =
-    new object_map::SnapshotRemoveRequest(m_image_ctx, &m_object_map, snap_id,
-                                          on_finish);
+    new object_map::SnapshotRemoveRequest(m_image_ctx, &m_lock, &m_object_map,
+                                          snap_id, ctx);
   req->send();
 }
 
 template <typename I>
 void ObjectMap<I>::aio_save(Context *on_finish) {
-  ceph_assert(m_image_ctx.owner_lock.is_locked());
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.owner_lock));
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
   ceph_assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
-                                        m_image_ctx.snap_lock));
-  RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock);
+                                        m_image_ctx.image_lock));
+  std::shared_lock locker{m_lock};
 
   librados::ObjectWriteOperation op;
   if (m_snap_id == CEPH_NOSNAP) {
@@ -228,8 +232,10 @@ void ObjectMap<I>::aio_save(Context *on_finish) {
   }
   cls_client::object_map_save(&op, m_object_map);
 
+  Context *ctx = create_context_callback<Context>(on_finish, this);
+
   std::string oid(object_map_name(m_image_ctx.id, m_snap_id));
-  librados::AioCompletion *comp = util::create_rados_callback(on_finish);
+  librados::AioCompletion *comp = util::create_rados_callback(ctx);
 
   int r = m_image_ctx.md_ctx.aio_operate(oid, comp, &op);
   ceph_assert(r == 0);
@@ -239,17 +245,19 @@ void ObjectMap<I>::aio_save(Context *on_finish) {
 template <typename I>
 void ObjectMap<I>::aio_resize(uint64_t new_size, uint8_t default_object_state,
                              Context *on_finish) {
-  ceph_assert(m_image_ctx.owner_lock.is_locked());
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.owner_lock));
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
   ceph_assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
-                                        m_image_ctx.snap_lock));
+                                        m_image_ctx.image_lock));
   ceph_assert(m_image_ctx.image_watcher != NULL);
   ceph_assert(m_image_ctx.exclusive_lock == nullptr ||
               m_image_ctx.exclusive_lock->is_lock_owner());
 
+  Context *ctx = create_context_callback<Context>(on_finish, this);
+
   object_map::ResizeRequest *req = new object_map::ResizeRequest(
-    m_image_ctx, &m_object_map, m_snap_id, new_size, default_object_state,
-    on_finish);
+    m_image_ctx, &m_lock, &m_object_map, m_snap_id, new_size,
+    default_object_state, ctx);
   req->send();
 }
 
@@ -258,8 +266,8 @@ void ObjectMap<I>::detained_aio_update(UpdateOperation &&op) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << dendl;
 
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
-  ceph_assert(m_image_ctx.object_map_lock.is_wlocked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
+  ceph_assert(ceph_mutex_is_wlocked(m_lock));
 
   BlockGuardCell *cell;
   int r = m_update_guard->detain({op.start_object_no, op.end_object_no},
@@ -282,7 +290,7 @@ void ObjectMap<I>::detained_aio_update(UpdateOperation &&op) {
 
   ldout(cct, 20) << "in-flight update cell: " << cell << dendl;
   Context *on_finish = op.on_finish;
-  Context *ctx = new FunctionContext([this, cell, on_finish](int r) {
+  Context *ctx = new LambdaContext([this, cell, on_finish](int r) {
       handle_detained_aio_update(cell, r, on_finish);
     });
   aio_update(CEPH_NOSNAP, op.start_object_no, op.end_object_no, op.new_state,
@@ -299,8 +307,8 @@ void ObjectMap<I>::handle_detained_aio_update(BlockGuardCell *cell, int r,
   m_update_guard->release(cell, &block_ops);
 
   {
-    RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
-    RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
+    std::shared_lock image_locker{m_image_ctx.image_lock};
+    std::unique_lock locker{m_lock};
     for (auto &op : block_ops) {
       detained_aio_update(std::move(op));
     }
@@ -315,13 +323,11 @@ void ObjectMap<I>::aio_update(uint64_t snap_id, uint64_t start_object_no,
                               const boost::optional<uint8_t> &current_state,
                               const ZTracer::Trace &parent_trace,
                               bool ignore_enoent, Context *on_finish) {
-  ceph_assert(m_image_ctx.snap_lock.is_locked());
+  ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
   ceph_assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
   ceph_assert(m_image_ctx.image_watcher != nullptr);
   ceph_assert(m_image_ctx.exclusive_lock == nullptr ||
               m_image_ctx.exclusive_lock->is_lock_owner());
-  ceph_assert(snap_id != CEPH_NOSNAP ||
-              m_image_ctx.object_map_lock.is_wlocked());
   ceph_assert(start_object_no < end_object_no);
 
   CephContext *cct = m_image_ctx.cct;
@@ -331,6 +337,7 @@ void ObjectMap<I>::aio_update(uint64_t snap_id, uint64_t start_object_no,
                        stringify(static_cast<uint32_t>(*current_state)) : "")
                 << "->" << static_cast<uint32_t>(new_state) << dendl;
   if (snap_id == CEPH_NOSNAP) {
+    ceph_assert(ceph_mutex_is_wlocked(m_lock));
     end_object_no = std::min(end_object_no, m_object_map.size());
     if (start_object_no >= end_object_no) {
       ldout(cct, 20) << "skipping update of invalid object map" << dendl;
@@ -353,8 +360,9 @@ void ObjectMap<I>::aio_update(uint64_t snap_id, uint64_t start_object_no,
   }
 
   auto req = object_map::UpdateRequest<I>::create(
-    m_image_ctx, &m_object_map, snap_id, start_object_no, end_object_no,
-    new_state, current_state, parent_trace, ignore_enoent, on_finish);
+    m_image_ctx, &m_lock, &m_object_map, snap_id, start_object_no,
+    end_object_no, new_state, current_state, parent_trace, ignore_enoent,
+    on_finish);
   req->send();
 }