msgr: do not reopen failed lossy Connections

There was a race where:

 - sending stuff to a lossy Connection
 - it fails, and queues itself for reap, queues a RESET event
 - reaper clears the Pipe
 - some thread queues new messages and the Pipe is reopened, messages sent
 - RESET event delivered to dispatch, connection is closed and reopened.

The result was that messages got sent to the OSD out of order during the
window between the fault() and ms_handle_reset() getting called.  This will
prevent that.

Signed-off-by: Sage Weil <sage@inktank.com>
This commit is contained in:
Sage Weil 2012-07-19 09:30:33 -07:00
parent 9a4e702795
commit 2e67b7a383
2 changed files with 22 additions and 19 deletions

View File

@ -199,6 +199,18 @@ public:
return pipe->get();
return NULL;
}
bool try_get_pipe(RefCountedObject **p) {
Mutex::Locker l(lock);
if (failed) {
*p = NULL;
} else {
if (pipe)
*p = pipe->get();
else
*p = NULL;
}
return !failed;
}
void clear_pipe(RefCountedObject *old_p) {
if (old_p == pipe) {
Mutex::Locker l(lock);

View File

@ -382,8 +382,12 @@ void SimpleMessenger::submit_message(Message *m, Connection *con, const entity_a
{
Pipe *pipe = NULL;
if (con) {
pipe = con ? (Pipe *)con->pipe : NULL;
// we don't want to deal with ref-counting here, so we don't use get_pipe()
bool ok = con->try_get_pipe((RefCountedObject**)&pipe);
if (!ok) {
ldout(cct,0) << "submit_message " << *m << " on failed lossy con, dropping message " << m << dendl;
m->put();
return;
}
con->get();
}
@ -395,23 +399,10 @@ void SimpleMessenger::submit_message(Message *m, Connection *con, const entity_a
} else {
// remote pipe.
if (pipe) {
pipe->pipe_lock.Lock();
if (pipe->state == Pipe::STATE_CLOSED) {
ldout(cct,0) << "submit_message " << *m << " remote, " << dest_addr << ", ignoring closed pipe, dropping message " << m << dendl;
pipe->unregister_pipe();
pipe->pipe_lock.Unlock();
pipe = 0;
assert(con);
con->put();
return;
} else {
ldout(cct,20) << "submit_message " << *m << " remote, " << dest_addr << ", have pipe." << dendl;
pipe->_send(m);
pipe->pipe_lock.Unlock();
}
}
if (!pipe) {
ldout(cct,20) << "submit_message " << *m << " remote, " << dest_addr << ", have pipe." << dendl;
pipe->send(m);
pipe->put();
} else {
const Policy& policy = get_policy(dest_type);
if (policy.server) {
ldout(cct,20) << "submit_message " << *m << " remote, " << dest_addr << ", lossy server for target type "