]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: consolidate object map invalidation to new state machine
authorJason Dillaman <dillaman@redhat.com>
Wed, 12 Aug 2015 20:11:30 +0000 (16:11 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 19 Nov 2015 01:34:33 +0000 (20:34 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/Makefile.am
src/librbd/ObjectMap.cc
src/librbd/object_map/InvalidateRequest.cc [new file with mode: 0644]
src/librbd/object_map/InvalidateRequest.h [new file with mode: 0644]
src/librbd/object_map/Request.cc

index 0d8f5b64f85e37bfd61aee152d1d14b53cf4b5d2..fae8664bab25b9aeb4a87ae410ca702910c3eeac 100644 (file)
@@ -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 \
index fdfd211b962711a615cd09f3cc334ed4ddf43180..d070488b471411c884714e476c9626946c7775eb 100644 (file)
@@ -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 (file)
index 0000000..6352128
--- /dev/null
@@ -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 (file)
index 0000000..efc0d96
--- /dev/null
@@ -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
index 706c87cbbcf6c64afefa3e8ff38ea40d0cedcc8b..d78cb834a89d2c251a6f9632307a95d4a601c08f 100644 (file)
@@ -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;
 }