From: Jason Dillaman Date: Wed, 25 Mar 2015 16:34:27 +0000 (-0400) Subject: librbd: integrate with new object_map_snap_add/remove cls methods X-Git-Tag: v9.0.1~55^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c26f58c747e1f6e4ce9512477bbf9f38277e70e9;p=ceph.git librbd: integrate with new object_map_snap_add/remove cls methods 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 --- diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index f56b0369885..bd70c08478e 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -436,6 +436,14 @@ namespace librbd { snap_ids.insert(pair(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()); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 8179559458b..1e48e02c46f 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -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; diff --git a/src/librbd/ObjectMap.cc b/src/librbd/ObjectMap.cc index f4d520f7003..a13b02d2e36 100644 --- a/src/librbd/ObjectMap.cc +++ b/src/librbd/ObjectMap.cc @@ -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::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; } diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 522352fc7ad..50cb082497e 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -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) { diff --git a/src/librbd/internal.h b/src/librbd/internal.h index e384543a9b3..36ca6b96db7 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -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);