X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fptlrpc%2Fconnection.c;h=1d2e228c8247d64914531b112c4745dcbee6d44c;hb=64f4bd9dd2d5a663708fb371f0b7bd00ed4e9620;hp=a34ff43ef7c0c4f7911b43d3cadaed9a3662dfe3;hpb=03c37362be026eb31c79dc3be28f35e28df1a3b0;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/connection.c b/lustre/ptlrpc/connection.c index a34ff43..1d2e228 100644 --- a/lustre/ptlrpc/connection.c +++ b/lustre/ptlrpc/connection.c @@ -3,80 +3,128 @@ * * Copyright (C) 2002 Cluster File Systems, Inc. * - * This file is part of Lustre, http://www.lustre.org. + * This file is part of the Lustre file system, http://www.lustre.org + * Lustre is a trademark of Cluster File Systems, Inc. * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * You may have signed or agreed to another license before downloading + * this software. If so, you are bound by the terms and conditions + * of that agreement, and the following does not apply to you. See the + * LICENSE file included with this distribution for more information. * - * Lustre 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 for more details. + * If you did not agree to a different license, then this copy of Lustre + * is open source software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * In either case, Lustre 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 + * license text for more details. * */ -#define EXPORT_SYMTAB - #define DEBUG_SUBSYSTEM S_RPC +#ifdef __KERNEL__ +#include +#include +#include +#else +#include +#endif -#include +#include "ptlrpc_internal.h" static spinlock_t conn_lock; static struct list_head conn_list; static struct list_head conn_unused_list; -struct ptlrpc_connection *ptlrpc_get_connection(struct lustre_peer *peer) +void ptlrpc_dump_connections(void) { - struct list_head *tmp, *pos; + struct list_head *tmp; struct ptlrpc_connection *c; ENTRY; - spin_lock(&conn_lock); list_for_each(tmp, &conn_list) { c = list_entry(tmp, struct ptlrpc_connection, c_link); - if (memcmp(peer, &c->c_peer, sizeof(*peer)) == 0) { - atomic_inc(&c->c_refcount); - GOTO(out, c); - } + CERROR("Connection %p/%s has refcount %d (nid=%s->%s)\n", + c, c->c_remote_uuid.uuid, atomic_read(&c->c_refcount), + libcfs_nid2str(c->c_self), + libcfs_nid2str(c->c_peer.nid)); } + EXIT; +} - list_for_each_safe(tmp, pos, &conn_unused_list) { +struct ptlrpc_connection* +ptlrpc_lookup_conn_locked (lnet_process_id_t peer) +{ + struct ptlrpc_connection *c; + struct list_head *tmp; + + list_for_each(tmp, &conn_list) { c = list_entry(tmp, struct ptlrpc_connection, c_link); - if (memcmp(peer, &c->c_peer, sizeof(*peer)) == 0) { - atomic_inc(&c->c_refcount); + + if (peer.nid == c->c_peer.nid && + peer.pid == c->c_peer.pid) + return ptlrpc_connection_addref(c); + } + + list_for_each(tmp, &conn_unused_list) { + c = list_entry(tmp, struct ptlrpc_connection, c_link); + + if (peer.nid == c->c_peer.nid && + peer.pid == c->c_peer.pid) { list_del(&c->c_link); list_add(&c->c_link, &conn_list); - GOTO(out, c); + return ptlrpc_connection_addref(c); } } - /* FIXME: this should be a slab once we can validate slab addresses - * without OOPSing */ + return NULL; +} + + +struct ptlrpc_connection *ptlrpc_get_connection(lnet_process_id_t peer, + lnet_nid_t self, struct obd_uuid *uuid) +{ + struct ptlrpc_connection *c; + struct ptlrpc_connection *c2; + ENTRY; + + CDEBUG(D_INFO, "self %s peer %s\n", + libcfs_nid2str(self), libcfs_id2str(peer)); + + spin_lock(&conn_lock); + + c = ptlrpc_lookup_conn_locked(peer); + + spin_unlock(&conn_lock); + + if (c != NULL) + RETURN (c); + OBD_ALLOC(c, sizeof(*c)); if (c == NULL) - GOTO(out, c); - - c->c_level = LUSTRE_CONN_NEW; - c->c_xid_in = 1; - c->c_xid_out = 1; - c->c_generation = 1; - c->c_epoch = 1; - c->c_bootcount = 0; + RETURN (NULL); + atomic_set(&c->c_refcount, 1); - spin_lock_init(&c->c_lock); + c->c_peer = peer; + c->c_self = self; + if (uuid != NULL) + obd_str2uuid(&c->c_remote_uuid, uuid->uuid); - memcpy(&c->c_peer, peer, sizeof(c->c_peer)); - list_add(&c->c_link, &conn_list); + spin_lock(&conn_lock); - EXIT; - out: + c2 = ptlrpc_lookup_conn_locked(peer); + if (c2 == NULL) + list_add(&c->c_link, &conn_list); + spin_unlock(&conn_lock); - return c; + + if (c2 == NULL) + RETURN (c); + + OBD_FREE(c, sizeof(*c)); + RETURN (c2); } int ptlrpc_put_connection(struct ptlrpc_connection *c) @@ -84,6 +132,15 @@ int ptlrpc_put_connection(struct ptlrpc_connection *c) int rc = 0; ENTRY; + if (c == NULL) { + CERROR("NULL connection\n"); + RETURN(0); + } + + CDEBUG (D_INFO, "connection=%p refcount %d to %s\n", + c, atomic_read(&c->c_refcount) - 1, + libcfs_nid2str(c->c_peer.nid)); + if (atomic_dec_and_test(&c->c_refcount)) { spin_lock(&conn_lock); list_del(&c->c_link); @@ -91,6 +148,9 @@ int ptlrpc_put_connection(struct ptlrpc_connection *c) spin_unlock(&conn_lock); rc = 1; } + if (atomic_read(&c->c_refcount) < 0) + CERROR("connection %p refcount %d!\n", + c, atomic_read(&c->c_refcount)); RETURN(rc); } @@ -99,14 +159,17 @@ struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *c) { ENTRY; atomic_inc(&c->c_refcount); + CDEBUG (D_INFO, "connection=%p refcount %d to %s\n", + c, atomic_read(&c->c_refcount), + libcfs_nid2str(c->c_peer.nid)); RETURN(c); } void ptlrpc_init_connection(void) { - INIT_LIST_HEAD(&conn_list); - INIT_LIST_HEAD(&conn_unused_list); - conn_lock = SPIN_LOCK_UNLOCKED; + CFS_INIT_LIST_HEAD(&conn_list); + CFS_INIT_LIST_HEAD(&conn_unused_list); + spin_lock_init(&conn_lock); } void ptlrpc_cleanup_connection(void) @@ -122,9 +185,9 @@ void ptlrpc_cleanup_connection(void) } list_for_each_safe(tmp, pos, &conn_list) { c = list_entry(tmp, struct ptlrpc_connection, c_link); - CERROR("Connection %p has refcount %d at cleanup (nid=%lu)!\n", - c, atomic_read(&c->c_refcount), - (unsigned long)c->c_peer.peer_nid); + CERROR("Connection %p/%s has refcount %d (nid=%s)\n", + c, c->c_remote_uuid.uuid, atomic_read(&c->c_refcount), + libcfs_nid2str(c->c_peer.nid)); list_del(&c->c_link); OBD_FREE(c, sizeof(*c)); }