From: Mykola Golub Date: Sun, 6 Sep 2020 12:48:53 +0000 (+0100) Subject: librbd: track complete async operation requests X-Git-Tag: v15.2.17~119^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d74153f0e2ada512137c895e704c2c61042933f8;p=ceph.git librbd: track complete async operation requests to prevent duplicate maintenance operations due to RPC hiccups. Fixes: https://tracker.ceph.com/issues/46803 Signed-off-by: Mykola Golub (cherry picked from commit 07fbc4b71df450655dec046c10e919dbfde989ba) Conflicts: src/librbd/ImageWatcher.cc (no quiesce requests in octopus) --- diff --git a/src/librbd/ImageWatcher.cc b/src/librbd/ImageWatcher.cc index c46549a78d3..4b067025b9d 100644 --- a/src/librbd/ImageWatcher.cc +++ b/src/librbd/ImageWatcher.cc @@ -166,7 +166,7 @@ void ImageWatcher::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::notify_lock_owner(const Payload& payload, notify_lock_owner->send(); } +template +bool ImageWatcher::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 +bool ImageWatcher::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 Context *ImageWatcher::remove_async_request(const AsyncRequestId &id) { std::unique_lock async_request_locker{m_async_request_lock}; @@ -570,7 +600,7 @@ int ImageWatcher::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); diff --git a/src/librbd/ImageWatcher.h b/src/librbd/ImageWatcher.h index 2d97467617e..b71e83dc972 100644 --- a/src/librbd/ImageWatcher.h +++ b/src/librbd/ImageWatcher.h @@ -168,6 +168,9 @@ private: ceph::shared_mutex m_async_request_lock; std::map m_async_requests; std::set m_async_pending; + std::set m_async_complete; + std::set> 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);