/*
 * GPL HEADER START
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 only,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License version 2 for more details (a copy is included
 * in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; If not, see
 * http://www.gnu.org/licenses/gpl-2.0.html
 *
 * GPL HEADER END
 */
/*
 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright (c) 2011, Intel Corporation.
 */
/*
 * This file is part of Lustre, http://www.lustre.org/
 * Lustre is a trademark of Sun Microsystems, Inc.
 */

#define DEBUG_SUBSYSTEM S_RPC
#include "../include/obd_support.h"
#include "../include/obd_class.h"
#include "../include/lustre_net.h"

#include "ptlrpc_internal.h"

static struct cfs_hash *conn_hash;
static struct cfs_hash_ops conn_hash_ops;

struct ptlrpc_connection *
ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self,
		      struct obd_uuid *uuid)
{
	struct ptlrpc_connection *conn, *conn2;

	conn = cfs_hash_lookup(conn_hash, &peer);
	if (conn)
		goto out;

	conn = kzalloc(sizeof(*conn), GFP_NOFS);
	if (!conn)
		return NULL;

	conn->c_peer = peer;
	conn->c_self = self;
	INIT_HLIST_NODE(&conn->c_hash);
	atomic_set(&conn->c_refcount, 1);
	if (uuid)
		obd_str2uuid(&conn->c_remote_uuid, uuid->uuid);

	/*
	 * Add the newly created conn to the hash, on key collision we
	 * lost a racing addition and must destroy our newly allocated
	 * connection.  The object which exists in the has will be
	 * returned and may be compared against out object.
	 */
	/* In the function below, .hs_keycmp resolves to
	 * conn_keycmp()
	 */
	/* coverity[overrun-buffer-val] */
	conn2 = cfs_hash_findadd_unique(conn_hash, &peer, &conn->c_hash);
	if (conn != conn2) {
		kfree(conn);
		conn = conn2;
	}
out:
	CDEBUG(D_INFO, "conn=%p refcount %d to %s\n",
	       conn, atomic_read(&conn->c_refcount),
	       libcfs_nid2str(conn->c_peer.nid));
	return conn;
}

int ptlrpc_connection_put(struct ptlrpc_connection *conn)
{
	int rc = 0;

	if (!conn)
		return rc;

	LASSERT(atomic_read(&conn->c_refcount) > 1);

	/*
	 * We do not remove connection from hashtable and
	 * do not free it even if last caller released ref,
	 * as we want to have it cached for the case it is
	 * needed again.
	 *
	 * Deallocating it and later creating new connection
	 * again would be wastful. This way we also avoid
	 * expensive locking to protect things from get/put
	 * race when found cached connection is freed by
	 * ptlrpc_connection_put().
	 *
	 * It will be freed later in module unload time,
	 * when ptlrpc_connection_fini()->lh_exit->conn_exit()
	 * path is called.
	 */
	if (atomic_dec_return(&conn->c_refcount) == 1)
		rc = 1;

	CDEBUG(D_INFO, "PUT conn=%p refcount %d to %s\n",
	       conn, atomic_read(&conn->c_refcount),
	       libcfs_nid2str(conn->c_peer.nid));

	return rc;
}

struct ptlrpc_connection *
ptlrpc_connection_addref(struct ptlrpc_connection *conn)
{
	atomic_inc(&conn->c_refcount);
	CDEBUG(D_INFO, "conn=%p refcount %d to %s\n",
	       conn, atomic_read(&conn->c_refcount),
	       libcfs_nid2str(conn->c_peer.nid));

	return conn;
}

int ptlrpc_connection_init(void)
{
	conn_hash = cfs_hash_create("CONN_HASH",
				    HASH_CONN_CUR_BITS,
				    HASH_CONN_MAX_BITS,
				    HASH_CONN_BKT_BITS, 0,
				    CFS_HASH_MIN_THETA,
				    CFS_HASH_MAX_THETA,
				    &conn_hash_ops, CFS_HASH_DEFAULT);
	if (!conn_hash)
		return -ENOMEM;

	return 0;
}

void ptlrpc_connection_fini(void)
{
	cfs_hash_putref(conn_hash);
}

/*
 * Hash operations for net_peer<->connection
 */
static unsigned
conn_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
{
	return cfs_hash_djb2_hash(key, sizeof(lnet_process_id_t), mask);
}

static int
conn_keycmp(const void *key, struct hlist_node *hnode)
{
	struct ptlrpc_connection *conn;
	const lnet_process_id_t *conn_key;

	LASSERT(key);
	conn_key = key;
	conn = 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(struct hlist_node *hnode)
{
	struct ptlrpc_connection *conn;

	conn = hlist_entry(hnode, struct ptlrpc_connection, c_hash);
	return &conn->c_peer;
}

static void *
conn_object(struct hlist_node *hnode)
{
	return hlist_entry(hnode, struct ptlrpc_connection, c_hash);
}

static void
conn_get(struct cfs_hash *hs, struct hlist_node *hnode)
{
	struct ptlrpc_connection *conn;

	conn = hlist_entry(hnode, struct ptlrpc_connection, c_hash);
	atomic_inc(&conn->c_refcount);
}

static void
conn_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
{
	struct ptlrpc_connection *conn;

	conn = hlist_entry(hnode, struct ptlrpc_connection, c_hash);
	atomic_dec(&conn->c_refcount);
}

static void
conn_exit(struct cfs_hash *hs, struct hlist_node *hnode)
{
	struct ptlrpc_connection *conn;

	conn = 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(atomic_read(&conn->c_refcount) == 0,
		 "Busy connection with %d refs\n",
		 atomic_read(&conn->c_refcount));
	kfree(conn);
}

static struct cfs_hash_ops 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,
};
