diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2016-01-23 15:57:51 +0100 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2016-03-25 18:51:40 +0100 |
commit | b5d91704f53efc5a2a93e88e323877e6889b0f5b (patch) | |
tree | 16dcc0c8a99d937f412e0986a33591c21cf33aa4 /net | |
parent | libceph: reschedule tick in mon_fault() (diff) | |
download | linux-b5d91704f53efc5a2a93e88e323877e6889b0f5b.tar.xz linux-b5d91704f53efc5a2a93e88e323877e6889b0f5b.zip |
libceph: behave in mon_fault() if cur_mon < 0
This can happen if __close_session() in ceph_monc_stop() races with
a connection reset. We need to ignore such faults, otherwise it's
likely we would take !hunting, call __schedule_delayed() and end up
with delayed_work() executing on invalid memory, among other things.
The (two!) con->private tests are useless, as nothing ever clears
con->private. Nuke them.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/mon_client.c | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index a2b45cf79dca..cf638c009cfa 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -1155,22 +1155,17 @@ static void mon_fault(struct ceph_connection *con) { struct ceph_mon_client *monc = con->private; - if (!monc) - return; - - dout("mon_fault\n"); mutex_lock(&monc->mutex); - if (!con->private) - goto out; - - if (!monc->hunting) { - dout("%s hunting for new mon\n", __func__); - reopen_session(monc); - __schedule_delayed(monc); - } else { - dout("%s already hunting\n", __func__); + dout("%s mon%d\n", __func__, monc->cur_mon); + if (monc->cur_mon >= 0) { + if (!monc->hunting) { + dout("%s hunting for new mon\n", __func__); + reopen_session(monc); + __schedule_delayed(monc); + } else { + dout("%s already hunting\n", __func__); + } } -out: mutex_unlock(&monc->mutex); } |