Commit 992f0b22 authored by Liang Zhen's avatar Liang Zhen Committed by Greg Kroah-Hartman
Browse files

staging: lustre: take extra refcount in kiblnd_connreq_done



refcount taken by cmid is not reliable after kiblnd_connreq_done
released the glock because this connection is visible to other
threads, another thread can find and close this connection right
after kiblnd_connreq_done released the glock, if kiblnd_cm_callback
for RDMA_CM_EVENT_DISCONNECTED is called, it can release the
connection refcount taken by cmid. It means the connection could be
destroyed before kiblnd_connreq_done() finish operations on it.

Signed-off-by: default avatarLiang Zhen <liang.zhen@intel.com>
ntel-bug-id: https://jira.hpdd.intel.com/browse/LU-7210
Reviewed-on: http://review.whamcloud.com/17527


Reviewed-by: default avatarDoug Oucharek <doug.s.oucharek@intel.com>
Reviewed-by: default avatarJames Simmons <uja.ornl@yahoo.com>
Tested-by: default avatarJames Simmons <uja.ornl@yahoo.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a01fa108
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -939,8 +939,6 @@ kiblnd_check_sends(kib_conn_t *conn)
			kiblnd_queue_tx_locked(tx, conn);
	}

	kiblnd_conn_addref(conn); /* 1 ref for me.... (see b21911) */

	for (;;) {
		int credit;

@@ -966,8 +964,6 @@ kiblnd_check_sends(kib_conn_t *conn)
	}

	spin_unlock(&conn->ibc_lock);

	kiblnd_conn_decref(conn); /* ...until here */
}

static void
@@ -2131,6 +2127,16 @@ kiblnd_connreq_done(kib_conn_t *conn, int status)
		return;
	}

	/**
	 * refcount taken by cmid is not reliable after I released the glock
	 * because this connection is visible to other threads now, another
	 * thread can find and close this connection right after I released
	 * the glock, if kiblnd_cm_callback for RDMA_CM_EVENT_DISCONNECTED is
	 * called, it can release the connection refcount taken by cmid.
	 * It means the connection could be destroyed before I finish my
	 * operations on it.
	 */
	kiblnd_conn_addref(conn);
	write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags);

	/* Schedule blocked txs */
@@ -2146,6 +2152,8 @@ kiblnd_connreq_done(kib_conn_t *conn, int status)

	/* schedule blocked rxs */
	kiblnd_handle_early_rxs(conn);

	kiblnd_conn_decref(conn);
}

static void