summaryrefslogtreecommitdiffstats
path: root/src/osd/Session.cc
diff options
context:
space:
mode:
authorSage Weil <sage@redhat.com>2017-02-14 00:02:39 +0100
committerSage Weil <sage@redhat.com>2017-02-14 05:03:53 +0100
commitb729e6288f1e914f3fa457916493f257e82b901f (patch)
tree1c98508d789d2d35ffddd6dba43023c5555e4de3 /src/osd/Session.cc
parentosd/Session: fix race between have_backoff() and clear_backoffs() (diff)
downloadceph-b729e6288f1e914f3fa457916493f257e82b901f.tar.xz
ceph-b729e6288f1e914f3fa457916493f257e82b901f.zip
osd: fix backoff vs reset race
In OSD::ms_handle_reset, we clear session->con before removing any backoffs. That means we have to check if con has been cleared after any call to have_backoff, lest we race with ms_handle_reset and it removes the backoffs but we don't realize our client session is disconnected. Introduce a helper to do both these checks in a safe way, simplifying callers while we're at it. Signed-off-by: Sage Weil <sage@redhat.com>
Diffstat (limited to 'src/osd/Session.cc')
-rw-r--r--src/osd/Session.cc20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/osd/Session.cc b/src/osd/Session.cc
index abe1a0c9eba..2de44271344 100644
--- a/src/osd/Session.cc
+++ b/src/osd/Session.cc
@@ -81,3 +81,23 @@ void Session::ack_backoff(
}
assert(!backoff_count == backoffs.empty());
}
+
+bool Session::check_backoff(
+ CephContext *cct, spg_t pgid, const hobject_t& oid, Message *m)
+{
+ BackoffRef b(have_backoff(pgid, oid));
+ if (b) {
+ dout(10) << __func__ << " session " << this << " has backoff " << *b
+ << " for " << *m << dendl;
+ assert(!b->is_acked() || !g_conf->osd_debug_crash_on_ignored_backoff);
+ return true;
+ }
+ // we may race with ms_handle_reset. it clears session->con before removing
+ // backoffs, so if we see con is cleared here we have to abort this
+ // request.
+ if (!con) {
+ dout(10) << __func__ << " session " << this << " disconnected" << dendl;
+ return true;
+ }
+ return false;
+}