summaryrefslogtreecommitdiffstats
path: root/src/librbd/image_watcher/NotifyLockOwner.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librbd/image_watcher/NotifyLockOwner.cc')
-rw-r--r--src/librbd/image_watcher/NotifyLockOwner.cc95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/librbd/image_watcher/NotifyLockOwner.cc b/src/librbd/image_watcher/NotifyLockOwner.cc
new file mode 100644
index 00000000..ead5f214
--- /dev/null
+++ b/src/librbd/image_watcher/NotifyLockOwner.cc
@@ -0,0 +1,95 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/image_watcher/NotifyLockOwner.h"
+#include "common/errno.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/Utils.h"
+#include "librbd/WatchNotifyTypes.h"
+#include "librbd/watcher/Notifier.h"
+#include <map>
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::image_watcher::NotifyLockOwner: " \
+ << this << " " << __func__
+
+namespace librbd {
+
+namespace image_watcher {
+
+using namespace watch_notify;
+using util::create_context_callback;
+
+NotifyLockOwner::NotifyLockOwner(ImageCtx &image_ctx,
+ watcher::Notifier &notifier,
+ bufferlist &&bl, Context *on_finish)
+ : m_image_ctx(image_ctx), m_notifier(notifier), m_bl(std::move(bl)),
+ m_on_finish(on_finish) {
+}
+
+void NotifyLockOwner::send() {
+ send_notify();
+}
+
+void NotifyLockOwner::send_notify() {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 20) << dendl;
+
+ ceph_assert(m_image_ctx.owner_lock.is_locked());
+ m_notifier.notify(m_bl, &m_notify_response, create_context_callback<
+ NotifyLockOwner, &NotifyLockOwner::handle_notify>(this));
+}
+
+void NotifyLockOwner::handle_notify(int r) {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 20) << ": r=" << r << dendl;
+
+ if (r < 0 && r != -ETIMEDOUT) {
+ lderr(cct) << ": lock owner notification failed: " << cpp_strerror(r)
+ << dendl;
+ finish(r);
+ return;
+ }
+
+ bufferlist response;
+ bool lock_owner_responded = false;
+ for (auto &it : m_notify_response.acks) {
+ if (it.second.length() > 0) {
+ if (lock_owner_responded) {
+ lderr(cct) << ": duplicate lock owners detected" << dendl;
+ finish(-EINVAL);
+ return;
+ }
+ lock_owner_responded = true;
+ response.claim(it.second);
+ }
+ }
+
+ if (!lock_owner_responded) {
+ ldout(cct, 1) << ": no lock owners detected" << dendl;
+ finish(-ETIMEDOUT);
+ return;
+ }
+
+ try {
+ auto iter = response.cbegin();
+
+ ResponseMessage response_message;
+ using ceph::decode;
+ decode(response_message, iter);
+
+ r = response_message.result;
+ } catch (const buffer::error &err) {
+ r = -EINVAL;
+ }
+ finish(r);
+}
+
+void NotifyLockOwner::finish(int r) {
+ m_on_finish->complete(r);
+ delete this;
+}
+
+} // namespace image_watcher
+} // namespace librbd