]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: integrate with new object_map_snap_add/remove cls methods
authorJason Dillaman <dillaman@redhat.com>
Wed, 25 Mar 2015 16:34:27 +0000 (12:34 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 13 Apr 2015 19:24:15 +0000 (15:24 -0400)
When a snapshot is added, mark all HEAD image objects that exist as clean.
When a snapshot is removed, mark all clean objects that were dirty in the
deleted snapshot as dirty.

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

index f56b03698856b1be25c1c12df353c055215b8ba6..bd70c08478efb2e167f6a6588a6672cb5852c9a9 100644 (file)
@@ -436,6 +436,14 @@ namespace librbd {
     snap_ids.insert(pair<string, snap_t>(in_snap_name, id));
   }
 
+  void ImageCtx::rm_snap(string in_snap_name, snap_t id)
+  {
+    assert(snap_lock.is_wlocked());
+    snaps.erase(std::remove(snaps.begin(), snaps.end(), id), snaps.end());
+    snap_info.erase(id);
+    snap_ids.erase(in_snap_name);
+  }
+
   uint64_t ImageCtx::get_image_size(snap_t in_snap_id) const
   {
     assert(snap_lock.is_locked());
index 8179559458b82d87c5cfb96fd71532a0c7bc717e..1e48e02c46f4d4554e46f3c23cc545d890a0efab 100644 (file)
@@ -192,6 +192,7 @@ namespace librbd {
     void add_snap(std::string in_snap_name, librados::snap_t id,
                  uint64_t in_size, parent_info parent,
                   uint8_t protection_status, uint64_t flags);
+    void rm_snap(std::string in_snap_name, librados::snap_t id);
     uint64_t get_image_size(librados::snap_t in_snap_id) const;
     bool test_features(uint64_t test_features) const;
     int get_flags(librados::snap_t in_snap_id, uint64_t *flags) const;
index f4d520f7003d71c3d2d7b10fac58c6697a0a614c..a13b02d2e367ece684b03fe4cacbfc98d9772106 100644 (file)
@@ -150,7 +150,7 @@ bool ObjectMap::object_may_exist(uint64_t object_no) const
     return true;
   }
   uint8_t state = (*this)[object_no];
-  bool exists = (state == OBJECT_EXISTS || state == OBJECT_PENDING);
+  bool exists = (state != OBJECT_NONEXISTENT);
   ldout(m_image_ctx.cct, 20) << &m_image_ctx << " object_may_exist: "
                             << "object_no=" << object_no << " r=" << exists
                             << dendl;
@@ -299,6 +299,7 @@ void ObjectMap::snapshot_add(uint64_t snap_id) {
     lderr(cct) << "unable to load object map: " << cpp_strerror(r)
               << dendl;
     invalidate(CEPH_NOSNAP);
+    return;
   }
 
   std::string snap_oid(object_map_name(m_image_ctx.id, snap_id));
@@ -307,12 +308,96 @@ void ObjectMap::snapshot_add(uint64_t snap_id) {
     lderr(cct) << "unable to snapshot object map '" << snap_oid << "': "
               << cpp_strerror(r) << dendl;
     invalidate(snap_id);
+    return;
+  }
+
+  if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) {
+    librados::ObjectWriteOperation op;
+    rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+    cls_client::object_map_snap_add(&op);
+    r = m_image_ctx.md_ctx.operate(oid, &op);
+    if (r < 0) {
+      lderr(cct) << "unable to snapshot object map: " << cpp_strerror(r)
+                 << dendl;
+      invalidate(CEPH_NOSNAP);
+      return;
+    }
+
+    for (uint64_t i = 0; i < m_object_map.size(); ++i) {
+      if (m_object_map[i] == OBJECT_EXISTS) {
+        m_object_map[i] = OBJECT_EXISTS_CLEAN;
+      }
+    }
   }
 }
 
 int ObjectMap::snapshot_remove(uint64_t snap_id) {
+  assert(m_image_ctx.snap_lock.is_wlocked());
+  assert(snap_id != CEPH_NOSNAP);
+  CephContext *cct = m_image_ctx.cct;
+
+  int r;
+  if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) {
+    RWLock::WLocker l(m_image_ctx.object_map_lock);
+
+    uint64_t next_snap_id = CEPH_NOSNAP;
+    std::map<librados::snap_t, SnapInfo>::const_iterator it =
+      m_image_ctx.snap_info.find(snap_id);
+    assert(it != m_image_ctx.snap_info.end());
+
+    ++it;
+    if (it != m_image_ctx.snap_info.end()) {
+      next_snap_id = it->first;
+    }
+
+    ceph::BitVector<2> snap_object_map;
+    std::string snap_oid(object_map_name(m_image_ctx.id, snap_id));
+    r = cls_client::object_map_load(&m_image_ctx.md_ctx, snap_oid,
+                                    &snap_object_map);
+    if (r < 0) {
+      lderr(cct) << "error loading snapshot object map: " << cpp_strerror(r)
+                 << dendl;
+    }
+
+    if (r == 0) {
+      uint64_t flags;
+      m_image_ctx.get_flags(snap_id, &flags);
+      if ((flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0) {
+        invalidate(next_snap_id);
+        r = -EINVAL;
+      }
+    }
+
+    if (r == 0) {
+      std::string oid(object_map_name(m_image_ctx.id, next_snap_id));
+      librados::ObjectWriteOperation op;
+      if (next_snap_id == CEPH_NOSNAP) {
+        rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "",
+                                        "");
+      }
+      cls_client::object_map_snap_remove(&op, snap_object_map);
+
+      r = m_image_ctx.md_ctx.operate(oid, &op);
+      if (r < 0) {
+        lderr(cct) << "unable to remove object map snapshot: "
+                   << cpp_strerror(r) << dendl;
+        invalidate(next_snap_id);
+      }
+    }
+
+    if (r == 0 && next_snap_id == CEPH_NOSNAP) {
+      for (uint64_t i = 0; i < m_object_map.size(); ++i) {
+        if (m_object_map[i] == OBJECT_EXISTS_CLEAN &&
+            (i >= snap_object_map.size() ||
+             snap_object_map[i] == OBJECT_EXISTS)) {
+          m_object_map[i] = OBJECT_EXISTS;
+        }
+      }
+    }
+  }
+
   std::string oid(object_map_name(m_image_ctx.id, snap_id));
-  int r = m_image_ctx.md_ctx.remove(oid);
+  r = m_image_ctx.md_ctx.remove(oid);
   if (r < 0 && r != -ENOENT) {
     return r;
   }
index 522352fc7ad8842d7fdbbb46d9ca938fe26f11d3..50cb082497e90bc35c46c3061b18d6734edf56e1 100644 (file)
@@ -682,46 +682,50 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type,
     RWLock::RLocker md_locker(ictx->md_lock);
     snap_t snap_id;
     {
-      // block for purposes of auto-destruction of snap_locker on early return
-      RWLock::RLocker snap_locker(ictx->snap_lock);
+      RWLock::WLocker snap_locker(ictx->snap_lock);
       snap_id = ictx->get_snap_id(snap_name);
-      if (snap_id == CEPH_NOSNAP)
-       return -ENOENT;
+      if (snap_id == CEPH_NOSNAP) {
+        return -ENOENT;
+      }
 
-      parent_spec our_pspec;
-      RWLock::RLocker parent_locker(ictx->parent_lock);
-      r = ictx->get_parent_spec(snap_id, &our_pspec);
+      r = ictx->object_map.snapshot_remove(snap_id);
       if (r < 0) {
-       lderr(ictx->cct) << "snap_remove: can't get parent spec" << dendl;
-       return r;
+        lderr(ictx->cct) << "snap_remove: failed to remove snapshot object map"
+                        << dendl;
+        return r;
       }
 
-      if (ictx->parent_md.spec != our_pspec &&
-         (scan_for_parents(ictx, our_pspec, snap_id) == -ENOENT)) {
-        r = cls_client::remove_child(&ictx->md_ctx, RBD_CHILDREN,
-                                    our_pspec, ictx->id);
-       if (r < 0 && r != -ENOENT) {
-          lderr(ictx->cct) << "snap_remove: failed to deregister from parent "
-                           << "image" << dendl;
+      {
+        parent_spec our_pspec;
+        RWLock::RLocker parent_locker(ictx->parent_lock);
+        r = ictx->get_parent_spec(snap_id, &our_pspec);
+        if (r < 0) {
+         lderr(ictx->cct) << "snap_remove: can't get parent spec" << dendl;
          return r;
         }
-      }
-    }
 
-    r = ictx->object_map.snapshot_remove(snap_id);
-    if (r < 0) {
-      lderr(ictx->cct) << "snap_remove: failed to remove snapshot object map"
-                      << dendl;
-      return 0;
-    }
+        if (ictx->parent_md.spec != our_pspec &&
+           (scan_for_parents(ictx, our_pspec, snap_id) == -ENOENT)) {
+          r = cls_client::remove_child(&ictx->md_ctx, RBD_CHILDREN,
+                                      our_pspec, ictx->id);
+         if (r < 0 && r != -ENOENT) {
+            lderr(ictx->cct) << "snap_remove: failed to deregister from parent "
+                             << "image" << dendl;
+           return r;
+          }
+        }
+      }
 
-    r = rm_snap(ictx, snap_name);
-    if (r < 0) {
-      return r;
+      r = rm_snap(ictx, snap_name, snap_id);
+      if (r < 0) {
+        return r;
+      }
     }
 
     r = ictx->data_ctx.selfmanaged_snap_remove(snap_id);
     if (r < 0) {
+      lderr(ictx->cct) << "snap_remove: failed to remove RADOS snapshot"
+                       << dendl;
       return r;
     }
 
@@ -2003,17 +2007,19 @@ reprotect_and_return_err:
     return 0;
   }
 
-  int rm_snap(ImageCtx *ictx, const char *snap_name)
+  int rm_snap(ImageCtx *ictx, const char *snap_name, uint64_t snap_id)
   {
+    assert(ictx->snap_lock.is_wlocked());
+
     int r;
     if (ictx->old_format) {
       r = cls_client::old_snapshot_remove(&ictx->md_ctx,
                                          ictx->header_oid, snap_name);
     } else {
-      RWLock::RLocker l(ictx->snap_lock);
-      r = cls_client::snapshot_remove(&ictx->md_ctx,
-                                     ictx->header_oid,
-                                     ictx->get_snap_id(snap_name));
+      r = cls_client::snapshot_remove(&ictx->md_ctx, ictx->header_oid, snap_id);
+      if (r == 0) {
+        ictx->rm_snap(snap_name, snap_id);
+      }
     }
 
     if (r < 0) {
index e384543a9b3555ec290e7e91a2f6daf874b940de..36ca6b96db7205b22b9f7af637b9306e293ffdc0 100644 (file)
@@ -123,7 +123,7 @@ namespace librbd {
   int snap_is_protected(ImageCtx *ictx, const char *snap_name,
                        bool *is_protected);
   int add_snap(ImageCtx *ictx, const char *snap_name);
-  int rm_snap(ImageCtx *ictx, const char *snap_name);
+  int rm_snap(ImageCtx *ictx, const char *snap_name, uint64_t snap_id);
   int refresh_parent(ImageCtx *ictx);
   int ictx_check(ImageCtx *ictx);
   int ictx_refresh(ImageCtx *ictx);