Whamcloud - gitweb
land b1_5 onto HEAD
[fs/lustre-release.git] / lustre / ptlrpc / connection.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of the Lustre file system, http://www.lustre.org
7  *   Lustre is a trademark of Cluster File Systems, Inc.
8  *
9  *   You may have signed or agreed to another license before downloading
10  *   this software.  If so, you are bound by the terms and conditions
11  *   of that agreement, and the following does not apply to you.  See the
12  *   LICENSE file included with this distribution for more information.
13  *
14  *   If you did not agree to a different license, then this copy of Lustre
15  *   is open source software; you can redistribute it and/or modify it
16  *   under the terms of version 2 of the GNU General Public License as
17  *   published by the Free Software Foundation.
18  *
19  *   In either case, Lustre is distributed in the hope that it will be
20  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *   license text for more details.
23  *
24  */
25
26 #define DEBUG_SUBSYSTEM S_RPC
27 #ifdef __KERNEL__
28 #include <obd_support.h>
29 #include <obd_class.h>
30 #include <lustre_net.h>
31 #else
32 #include <liblustre.h>
33 #endif
34
35 #include "ptlrpc_internal.h"
36
37 static spinlock_t conn_lock;
38 static struct list_head conn_list;
39 static struct list_head conn_unused_list;
40
41 void ptlrpc_dump_connections(void)
42 {
43         struct list_head *tmp;
44         struct ptlrpc_connection *c;
45         ENTRY;
46
47         list_for_each(tmp, &conn_list) {
48                 c = list_entry(tmp, struct ptlrpc_connection, c_link);
49                 CERROR("Connection %p/%s has refcount %d (nid=%s->%s)\n",
50                        c, c->c_remote_uuid.uuid, atomic_read(&c->c_refcount),
51                        libcfs_nid2str(c->c_self), 
52                        libcfs_nid2str(c->c_peer.nid));
53         }
54         EXIT;
55 }
56
57 struct ptlrpc_connection*
58 ptlrpc_lookup_conn_locked (lnet_process_id_t peer)
59 {
60         struct ptlrpc_connection *c;
61         struct list_head         *tmp;
62
63         list_for_each(tmp, &conn_list) {
64                 c = list_entry(tmp, struct ptlrpc_connection, c_link);
65
66                 if (peer.nid == c->c_peer.nid &&
67                     peer.pid == c->c_peer.pid)
68                         return ptlrpc_connection_addref(c);
69         }
70
71         list_for_each(tmp, &conn_unused_list) {
72                 c = list_entry(tmp, struct ptlrpc_connection, c_link);
73
74                 if (peer.nid == c->c_peer.nid &&
75                     peer.pid == c->c_peer.pid) {
76                         list_del(&c->c_link);
77                         list_add(&c->c_link, &conn_list);
78                         return ptlrpc_connection_addref(c);
79                 }
80         }
81
82         return NULL;
83 }
84
85
86 struct ptlrpc_connection *ptlrpc_get_connection(lnet_process_id_t peer,
87                                                 lnet_nid_t self, struct obd_uuid *uuid)
88 {
89         struct ptlrpc_connection *c;
90         struct ptlrpc_connection *c2;
91         ENTRY;
92
93         CDEBUG(D_INFO, "self %s peer %s\n", 
94                libcfs_nid2str(self), libcfs_id2str(peer));
95
96         spin_lock(&conn_lock);
97
98         c = ptlrpc_lookup_conn_locked(peer);
99         
100         spin_unlock(&conn_lock);
101
102         if (c != NULL)
103                 RETURN (c);
104         
105         OBD_ALLOC(c, sizeof(*c));
106         if (c == NULL)
107                 RETURN (NULL);
108
109         atomic_set(&c->c_refcount, 1);
110         c->c_peer = peer;
111         c->c_self = self;
112         if (uuid != NULL)
113                 obd_str2uuid(&c->c_remote_uuid, uuid->uuid);
114
115         spin_lock(&conn_lock);
116
117         c2 = ptlrpc_lookup_conn_locked(peer);
118         if (c2 == NULL)
119                 list_add(&c->c_link, &conn_list);
120         
121         spin_unlock(&conn_lock);
122
123         if (c2 == NULL)
124                 RETURN (c);
125         
126         OBD_FREE(c, sizeof(*c));
127         RETURN (c2);
128 }
129
130 int ptlrpc_put_connection(struct ptlrpc_connection *c)
131 {
132         int rc = 0;
133         ENTRY;
134
135         if (c == NULL) {
136                 CERROR("NULL connection\n");
137                 RETURN(0);
138         }
139
140         CDEBUG (D_INFO, "connection=%p refcount %d to %s\n",
141                 c, atomic_read(&c->c_refcount) - 1, 
142                 libcfs_nid2str(c->c_peer.nid));
143
144         if (atomic_dec_and_test(&c->c_refcount)) {
145                 spin_lock(&conn_lock);
146                 list_del(&c->c_link);
147                 list_add(&c->c_link, &conn_unused_list);
148                 spin_unlock(&conn_lock);
149                 rc = 1;
150         }
151         if (atomic_read(&c->c_refcount) < 0)
152                 CERROR("connection %p refcount %d!\n",
153                        c, atomic_read(&c->c_refcount));
154
155         RETURN(rc);
156 }
157
158 struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *c)
159 {
160         ENTRY;
161         atomic_inc(&c->c_refcount);
162         CDEBUG (D_INFO, "connection=%p refcount %d to %s\n",
163                 c, atomic_read(&c->c_refcount),
164                 libcfs_nid2str(c->c_peer.nid));
165         RETURN(c);
166 }
167
168 void ptlrpc_init_connection(void)
169 {
170         CFS_INIT_LIST_HEAD(&conn_list);
171         CFS_INIT_LIST_HEAD(&conn_unused_list);
172         spin_lock_init(&conn_lock);
173 }
174
175 void ptlrpc_cleanup_connection(void)
176 {
177         struct list_head *tmp, *pos;
178         struct ptlrpc_connection *c;
179
180         spin_lock(&conn_lock);
181         list_for_each_safe(tmp, pos, &conn_unused_list) {
182                 c = list_entry(tmp, struct ptlrpc_connection, c_link);
183                 list_del(&c->c_link);
184                 OBD_FREE(c, sizeof(*c));
185         }
186         list_for_each_safe(tmp, pos, &conn_list) {
187                 c = list_entry(tmp, struct ptlrpc_connection, c_link);
188                 CERROR("Connection %p/%s has refcount %d (nid=%s)\n",
189                        c, c->c_remote_uuid.uuid, atomic_read(&c->c_refcount),
190                        libcfs_nid2str(c->c_peer.nid));
191                 list_del(&c->c_link);
192                 OBD_FREE(c, sizeof(*c));
193         }
194         spin_unlock(&conn_lock);
195 }