]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: allow snapshot object maps to be updated
authorJason Dillaman <dillaman@redhat.com>
Sat, 21 Mar 2015 18:40:26 +0000 (14:40 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 10 Apr 2015 18:10:05 +0000 (14:10 -0400)
Rebuild will need to be able to update/resize the object maps
for image snapshots.  This was previously not permitted.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/ObjectMap.cc
src/librbd/ObjectMap.h

index 4c9e2a73cdf4c2a2b1233e8631f7eaee75ef9073..5e40555cc9acd47a7243b40476b2c0983f71441d 100644 (file)
@@ -17,7 +17,7 @@
 namespace librbd {
 
 ObjectMap::ObjectMap(ImageCtx &image_ctx)
-  : m_image_ctx(image_ctx), m_enabled(false)
+  : m_image_ctx(image_ctx), m_snap_id(CEPH_NOSNAP), m_enabled(false)
 {
 }
 
@@ -154,6 +154,7 @@ void ObjectMap::refresh(uint64_t snap_id)
 {
   assert(m_image_ctx.snap_lock.is_wlocked());
   RWLock::WLocker l(m_image_ctx.object_map_lock);
+  m_snap_id = snap_id;
 
   if ((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) == 0 ||
       (m_image_ctx.snap_id == snap_id && !m_image_ctx.snap_exists)) {
@@ -178,7 +179,10 @@ void ObjectMap::refresh(uint64_t snap_id)
     invalidate(snap_id);
 
     librados::ObjectWriteOperation op;
-    rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+    if (snap_id == CEPH_NOSNAP) {
+      rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "",
+                                      "");
+    }
     op.truncate(0);
     cls_client::object_map_resize(&op, num_objs, OBJECT_NONEXISTENT);
 
@@ -206,7 +210,10 @@ void ObjectMap::refresh(uint64_t snap_id)
 
     // correct the size issue so future IO can keep the object map in sync
     librados::ObjectWriteOperation op;
-    rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+    if (snap_id == CEPH_NOSNAP) {
+      rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "",
+                                      "");
+    }
     cls_client::object_map_resize(&op, num_objs, OBJECT_NONEXISTENT);
 
     r = m_image_ctx.md_ctx.operate(oid, &op);
@@ -300,10 +307,11 @@ void ObjectMap::aio_resize(uint64_t new_size, uint8_t default_object_state,
                           Context *on_finish) {
   assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP));
   assert(m_image_ctx.owner_lock.is_locked());
-  assert(m_image_ctx.image_watcher->is_lock_owner());
+  assert(!m_image_ctx.image_watcher->is_lock_supported() ||
+         m_image_ctx.image_watcher->is_lock_owner());
 
   ResizeRequest *req = new ResizeRequest(
-    m_image_ctx, new_size, default_object_state, on_finish);
+    m_image_ctx, m_snap_id, new_size, default_object_state, on_finish);
   req->send();
 }
 
@@ -322,7 +330,8 @@ bool ObjectMap::aio_update(uint64_t start_object_no, uint64_t end_object_no,
 {
   assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP));
   assert(m_image_ctx.owner_lock.is_locked());
-  assert(m_image_ctx.image_watcher->is_lock_owner());
+  assert(!m_image_ctx.image_watcher->is_lock_supported() ||
+         m_image_ctx.image_watcher->is_lock_owner());
   assert(m_image_ctx.object_map_lock.is_wlocked());
   assert(start_object_no < end_object_no);
 
@@ -339,9 +348,10 @@ bool ObjectMap::aio_update(uint64_t start_object_no, uint64_t end_object_no,
        ++object_no) {
     if ((!current_state || m_object_map[object_no] == *current_state) &&
         m_object_map[object_no] != new_state) {
-      UpdateRequest *req = new UpdateRequest(m_image_ctx, start_object_no,
-                                            end_object_no, new_state,
-                                            current_state, on_finish);
+      UpdateRequest *req = new UpdateRequest(m_image_ctx, m_snap_id,
+                                             start_object_no, end_object_no,
+                                             new_state, current_state,
+                                             on_finish);
       req->send();
       return true;
     }
@@ -462,11 +472,13 @@ void ObjectMap::ResizeRequest::send() {
                << m_num_objs << dendl;
 
   librados::ObjectWriteOperation op;
-  rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+  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, CEPH_NOSNAP));
+  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();
@@ -503,12 +515,14 @@ void ObjectMap::UpdateRequest::send() {
   }
 
   librados::ObjectWriteOperation op;
-  rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+  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, CEPH_NOSNAP));
+  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();
index 653bba55308623c89d77477f23c9a3be03fcce63..78ee5f3231fe0e3fcace2b8585329e402998cbb6 100644 (file)
@@ -57,15 +57,17 @@ private:
 
   class Request : public AsyncRequest {
   public:
-    Request(ImageCtx &image_ctx, Context *on_finish)
-      : AsyncRequest(image_ctx, on_finish), m_state(STATE_REQUEST)
+    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 void finish(ObjectMap *object_map) = 0;
-
   private:
     /**
      * <start> ---> STATE_REQUEST ---> <finish>
@@ -81,14 +83,14 @@ private:
     State m_state;
 
     bool invalidate();
-  }; 
+  };
 
   class ResizeRequest : public Request {
   public:
-    ResizeRequest(ImageCtx &image_ctx, uint64_t new_size,
+    ResizeRequest(ImageCtx &image_ctx, uint64_t snap_id, uint64_t new_size,
                  uint8_t default_object_state, Context *on_finish)
-      : Request(image_ctx, on_finish), m_num_objs(0), m_new_size(new_size),
-        m_default_object_state(default_object_state)
+      : Request(image_ctx, snap_id, on_finish), m_num_objs(0),
+        m_new_size(new_size), m_default_object_state(default_object_state)
     {
     }
 
@@ -103,13 +105,14 @@ private:
 
   class UpdateRequest : public Request {
   public:
-    UpdateRequest(ImageCtx &image_ctx, uint64_t start_object_no,
-                 uint64_t end_object_no, uint8_t new_state,
+    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<uint8_t> &current_state,
                  Context *on_finish)
-      : Request(image_ctx, 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)
+      : 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)
     {
     }
 
@@ -125,6 +128,7 @@ private:
 
   ImageCtx &m_image_ctx;
   ceph::BitVector<2> m_object_map;
+  uint64_t m_snap_id;
   bool m_enabled;
 
   void invalidate(uint64_t snap_id);