+
+static int
+conn_keycmp(const void *key, cfs_hlist_node_t *hnode)
+{
+ struct ptlrpc_connection *conn;
+ const lnet_process_id_t *conn_key;
+
+ LASSERT(key != NULL);
+ conn_key = (lnet_process_id_t*)key;
+ conn = cfs_hlist_entry(hnode, struct ptlrpc_connection, c_hash);
+
+ return conn_key->nid == conn->c_peer.nid &&
+ conn_key->pid == conn->c_peer.pid;
+}
+
+static void *
+conn_key(cfs_hlist_node_t *hnode)
+{
+ struct ptlrpc_connection *conn;
+ conn = cfs_hlist_entry(hnode, struct ptlrpc_connection, c_hash);
+ return &conn->c_peer;
+}
+
+static void *
+conn_object(cfs_hlist_node_t *hnode)
+{
+ return cfs_hlist_entry(hnode, struct ptlrpc_connection, c_hash);
+}
+
+static void
+conn_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct ptlrpc_connection *conn;
+
+ conn = cfs_hlist_entry(hnode, struct ptlrpc_connection, c_hash);
+ cfs_atomic_inc(&conn->c_refcount);
+}
+
+static void
+conn_put_locked(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct ptlrpc_connection *conn;
+
+ conn = cfs_hlist_entry(hnode, struct ptlrpc_connection, c_hash);
+ cfs_atomic_dec(&conn->c_refcount);
+}
+
+static void
+conn_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct ptlrpc_connection *conn;
+
+ conn = cfs_hlist_entry(hnode, struct ptlrpc_connection, c_hash);
+ /*
+ * Nothing should be left. Connection user put it and
+ * connection also was deleted from table by this time
+ * so we should have 0 refs.
+ */
+ LASSERTF(cfs_atomic_read(&conn->c_refcount) == 0,
+ "Busy connection with %d refs\n",
+ cfs_atomic_read(&conn->c_refcount));
+ OBD_FREE_PTR(conn);
+}
+
+static cfs_hash_ops_t conn_hash_ops = {
+ .hs_hash = conn_hashfn,
+ .hs_keycmp = conn_keycmp,
+ .hs_key = conn_key,
+ .hs_object = conn_object,
+ .hs_get = conn_get,
+ .hs_put_locked = conn_put_locked,
+ .hs_exit = conn_exit,
+};