From: Jason Dillaman Date: Wed, 12 Aug 2015 20:11:30 +0000 (-0400) Subject: librbd: consolidate object map invalidation to new state machine X-Git-Tag: v10.0.2~193^2~26 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=36032f8d15a41d4ef877a07698a8e360e64f85cf;p=ceph.git librbd: consolidate object map invalidation to new state machine Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/Makefile.am b/src/librbd/Makefile.am index 0d8f5b64f85..fae8664bab2 100644 --- a/src/librbd/Makefile.am +++ b/src/librbd/Makefile.am @@ -25,6 +25,7 @@ librbd_internal_la_SOURCES = \ librbd/LibrbdAdminSocketHook.cc \ librbd/LibrbdWriteback.cc \ librbd/ObjectMap.cc \ + librbd/object_map/InvalidateRequest.cc \ librbd/object_map/Request.cc \ librbd/object_map/ResizeRequest.cc \ librbd/object_map/UpdateRequest.cc \ @@ -86,6 +87,7 @@ noinst_HEADERS += \ librbd/SnapInfo.h \ librbd/TaskFinisher.h \ librbd/WatchNotifyTypes.h \ + librbd/object_map/InvalidateRequest.h \ librbd/object_map/Request.h \ librbd/object_map/ResizeRequest.h \ librbd/object_map/UpdateRequest.h \ diff --git a/src/librbd/ObjectMap.cc b/src/librbd/ObjectMap.cc index fdfd211b962..d070488b471 100644 --- a/src/librbd/ObjectMap.cc +++ b/src/librbd/ObjectMap.cc @@ -4,6 +4,7 @@ #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/internal.h" +#include "librbd/object_map/InvalidateRequest.h" #include "librbd/object_map/ResizeRequest.h" #include "librbd/object_map/UpdateRequest.h" #include "common/dout.h" @@ -513,41 +514,13 @@ void ObjectMap::invalidate(uint64_t snap_id, bool force) { return; } - flags = RBD_FLAG_OBJECT_MAP_INVALID; - if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) { - flags |= RBD_FLAG_FAST_DIFF_INVALID; - } - - CephContext *cct = m_image_ctx.cct; - lderr(cct) << &m_image_ctx << " invalidating object map" << dendl; - int r = m_image_ctx.update_flags(snap_id, flags, true); - if (r < 0) { - lderr(cct) << "failed to invalidate in-memory object map: " - << cpp_strerror(r) << dendl; - return; - } - - // do not update on-disk flags if not image owner - if (m_image_ctx.image_watcher == NULL || - (m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) && - !m_image_ctx.image_watcher->is_lock_owner())) { - return; - } + // TODO remove once all methods are async + C_SaferCond cond_ctx; + object_map::InvalidateRequest *req = new object_map::InvalidateRequest( + m_image_ctx, m_snap_id, force, &cond_ctx); + req->send(); - librados::ObjectWriteOperation op; - if (snap_id == CEPH_NOSNAP && !force) { - m_image_ctx.image_watcher->assert_header_locked(&op); - } - cls_client::set_flags(&op, snap_id, flags, flags); - - r = m_image_ctx.md_ctx.operate(m_image_ctx.header_oid, &op); - if (r == -EBUSY) { - ldout(cct, 5) << "skipping on-disk object map invalidation: " - << "image not locked by client" << dendl; - } else if (r < 0) { - lderr(cct) << "failed to invalidate on-disk object map: " << cpp_strerror(r) - << dendl; - } + cond_ctx.wait(); } } // namespace librbd diff --git a/src/librbd/object_map/InvalidateRequest.cc b/src/librbd/object_map/InvalidateRequest.cc new file mode 100644 index 00000000000..63521280cb4 --- /dev/null +++ b/src/librbd/object_map/InvalidateRequest.cc @@ -0,0 +1,70 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/object_map/InvalidateRequest.h" +#include "common/dout.h" +#include "common/errno.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::InvalidateRequest: " + +namespace librbd { +namespace object_map { + +void InvalidateRequest::send() { + assert(m_image_ctx.snap_lock.is_wlocked()); + + uint64_t snap_flags; + int r = m_image_ctx.get_flags(m_snap_id, &snap_flags); + if (r < 0 || ((snap_flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0)) { + async_complete(r); + return; + } + + CephContext *cct = m_image_ctx.cct; + lderr(cct) << this << " invalidating object map in-memory" << dendl; + + // update in-memory flags + uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID; + if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) { + flags |= RBD_FLAG_FAST_DIFF_INVALID; + } + + r = m_image_ctx.update_flags(m_snap_id, flags, true); + if (r < 0) { + async_complete(r); + } + + // do not update on-disk flags if not image owner + if (m_image_ctx.image_watcher == NULL || + (m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) && + !m_image_ctx.image_watcher->is_lock_owner())) { + async_complete(0); + return; + } + + lderr(cct) << this << " invalidating object map on-disk" << dendl; + librados::ObjectWriteOperation op; + if (m_snap_id == CEPH_NOSNAP && !m_force) { + m_image_ctx.image_watcher->assert_header_locked(&op); + } + cls_client::set_flags(&op, m_snap_id, flags, flags); + + librados::AioCompletion *rados_completion = create_callback_completion(); + r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, rados_completion, + &op); + assert(r == 0); + rados_completion->release(); +} + +bool InvalidateRequest::should_complete(int r) { + CephContext *cct = m_image_ctx.cct; + lderr(cct) << this << " " << __func__ << ": r=" << r << dendl; + return true; +} + +} // namespace object_map +} // namespace librbd diff --git a/src/librbd/object_map/InvalidateRequest.h b/src/librbd/object_map/InvalidateRequest.h new file mode 100644 index 00000000000..efc0d96c86d --- /dev/null +++ b/src/librbd/object_map/InvalidateRequest.h @@ -0,0 +1,43 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_OBJECT_MAP_INVALIDATE_REQUEST_H +#define CEPH_LIBRBD_OBJECT_MAP_INVALIDATE_REQUEST_H + +#include "include/int_types.h" +#include "librbd/AsyncRequest.h" + +class Context; + +namespace librbd { + +class ImageCtx; + +namespace object_map { + +class InvalidateRequest : public AsyncRequest<> { +public: + InvalidateRequest(ImageCtx &image_ctx, uint64_t snap_id, bool force, + Context *on_finish) + : AsyncRequest(image_ctx, on_finish), m_snap_id(snap_id), m_force(force) { + } + + virtual void send(); + +protected: + virtual bool should_complete(int r); + virtual int filter_return_code(int r) const { + // never propagate an error back to the caller + return 0; + } + +private: + uint64_t m_snap_id; + bool m_force; + +}; + +} // namespace object_map +} // namespace librbd + +#endif // CEPH_LIBRBD_OBJECT_MAP_INVALIDATE_REQUEST_H diff --git a/src/librbd/object_map/Request.cc b/src/librbd/object_map/Request.cc index 706c87cbbcf..d78cb834a89 100644 --- a/src/librbd/object_map/Request.cc +++ b/src/librbd/object_map/Request.cc @@ -9,6 +9,7 @@ #include "common/RWLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" +#include "librbd/object_map/InvalidateRequest.h" #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -60,29 +61,13 @@ bool Request::invalidate() { 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(); + RWLock::RLocker owner_locker(m_image_ctx.owner_lock); + RWLock::WLocker snap_locker(m_image_ctx.snap_lock); + InvalidateRequest *req = new InvalidateRequest(m_image_ctx, m_snap_id, true, + create_callback_context()); + req->send(); return false; }