]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: track complete async operation requests
authorMykola Golub <mgolub@suse.com>
Sun, 6 Sep 2020 12:48:53 +0000 (13:48 +0100)
committerMykola Golub <mgolub@suse.com>
Mon, 14 Feb 2022 10:16:03 +0000 (12:16 +0200)
to prevent duplicate maintenance operations due to RPC hiccups.

Fixes: https://tracker.ceph.com/issues/46803
Signed-off-by: Mykola Golub <mgolub@suse.com>
(cherry picked from commit 07fbc4b71df450655dec046c10e919dbfde989ba)

Conflicts:
src/librbd/ImageWatcher.cc (no quiesce requests in octopus)

src/librbd/ImageWatcher.cc
src/librbd/ImageWatcher.h

index c46549a78d3d57479732cb3bad6279f69801842e..4b067025b9d16a79416d14a34ba875f4028ff023 100644 (file)
@@ -166,7 +166,7 @@ void ImageWatcher<I>::handle_async_complete(const AsyncRequestId &request,
   }
 
   std::unique_lock async_request_locker{m_async_request_lock};
-  m_async_pending.erase(request);
+  mark_async_request_complete(request);
   m_async_op_tracker.finish_op();
 }
 
@@ -489,6 +489,36 @@ void ImageWatcher<I>::notify_lock_owner(const Payload& payload,
   notify_lock_owner->send();
 }
 
+template <typename I>
+bool ImageWatcher<I>::is_new_request(const AsyncRequestId &id) const {
+  ceph_assert(ceph_mutex_is_locked(m_async_request_lock));
+
+  return m_async_pending.count(id) == 0 && m_async_complete.count(id) == 0;
+}
+
+template <typename I>
+bool ImageWatcher<I>::mark_async_request_complete(const AsyncRequestId &id) {
+  ceph_assert(ceph_mutex_is_locked(m_async_request_lock));
+
+  bool found = m_async_pending.erase(id);
+
+  auto now = ceph_clock_now();
+
+  auto it = m_async_complete_expiration.begin();
+  while (it != m_async_complete_expiration.end() && it->first < now) {
+    m_async_complete.erase(it->second);
+    it = m_async_complete_expiration.erase(it);
+  }
+
+  if (m_async_complete.insert(id).second) {
+    auto expiration_time = now;
+    expiration_time += 600;
+    m_async_complete_expiration.insert({expiration_time, id});
+  }
+
+  return found;
+}
+
 template <typename I>
 Context *ImageWatcher<I>::remove_async_request(const AsyncRequestId &id) {
   std::unique_lock async_request_locker{m_async_request_lock};
@@ -570,7 +600,7 @@ int ImageWatcher<I>::prepare_async_request(const AsyncRequestId& async_request_i
     return -ERESTART;
   } else {
     std::unique_lock l{m_async_request_lock};
-    if (m_async_pending.count(async_request_id) == 0) {
+    if (is_new_request(async_request_id)) {
       m_async_pending.insert(async_request_id);
       *new_request = true;
       *prog_ctx = new RemoteProgressContext(*this, async_request_id);
index 2d97467617e8dfb3f8ad219bee324e7780517bfb..b71e83dc972c0cf3f641c88ddcff03415e581de7 100644 (file)
@@ -168,6 +168,9 @@ private:
   ceph::shared_mutex m_async_request_lock;
   std::map<watch_notify::AsyncRequestId, AsyncRequest> m_async_requests;
   std::set<watch_notify::AsyncRequestId> m_async_pending;
+  std::set<watch_notify::AsyncRequestId> m_async_complete;
+  std::set<std::pair<utime_t,
+                     watch_notify::AsyncRequestId>> m_async_complete_expiration;
 
   ceph::mutex m_owner_client_id_lock;
   watch_notify::ClientId m_owner_client_id;
@@ -188,6 +191,8 @@ private:
   void notify_lock_owner(const watch_notify::Payload& payload,
                          Context *on_finish);
 
+  bool is_new_request(const watch_notify::AsyncRequestId &id) const;
+  bool mark_async_request_complete(const watch_notify::AsyncRequestId &id);
   Context *remove_async_request(const watch_notify::AsyncRequestId &id);
   void schedule_async_request_timed_out(const watch_notify::AsyncRequestId &id);
   void async_request_timed_out(const watch_notify::AsyncRequestId &id);