summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2016-01-23 15:57:51 +0100
committerIlya Dryomov <idryomov@gmail.com>2016-03-25 18:51:40 +0100
commitb5d91704f53efc5a2a93e88e323877e6889b0f5b (patch)
tree16dcc0c8a99d937f412e0986a33591c21cf33aa4 /net
parentlibceph: reschedule tick in mon_fault() (diff)
downloadlinux-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.c23
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);
}