aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
authorChristine Caulfield <ccaulfie@redhat.com>2009-01-28 13:57:40 -0500
committerDavid Teigland <teigland@redhat.com>2009-03-11 13:20:58 -0400
commit5e9ccc372dc855900c4a75b21286038938e288c7 (patch)
tree323ac103ab37ba5adfa3dc66ff90ec03c77b7517 /fs/dlm
parent2cf12c0bf261e19d9641d7b8aa220e2651a03289 (diff)
dlm: replace idr with hash table for connections
Integer nodeids can be too large for the idr code; use a hash table instead. Signed-off-by: Christine Caulfield <ccaulfie@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/lowcomms.c171
1 files changed, 92 insertions, 79 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 982314c472c1..609108a83267 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -2,7 +2,7 @@
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6** 6**
7** This copyrighted material is made available to anyone wishing to use, 7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions 8** modify, copy, or redistribute it subject to the terms and conditions
@@ -48,7 +48,6 @@
48#include <net/sock.h> 48#include <net/sock.h>
49#include <net/tcp.h> 49#include <net/tcp.h>
50#include <linux/pagemap.h> 50#include <linux/pagemap.h>
51#include <linux/idr.h>
52#include <linux/file.h> 51#include <linux/file.h>
53#include <linux/mutex.h> 52#include <linux/mutex.h>
54#include <linux/sctp.h> 53#include <linux/sctp.h>
@@ -61,6 +60,7 @@
61#include "config.h" 60#include "config.h"
62 61
63#define NEEDED_RMEM (4*1024*1024) 62#define NEEDED_RMEM (4*1024*1024)
63#define CONN_HASH_SIZE 32
64 64
65struct cbuf { 65struct cbuf {
66 unsigned int base; 66 unsigned int base;
@@ -115,6 +115,7 @@ struct connection {
115 int retries; 115 int retries;
116#define MAX_CONNECT_RETRIES 3 116#define MAX_CONNECT_RETRIES 3
117 int sctp_assoc; 117 int sctp_assoc;
118 struct hlist_node list;
118 struct connection *othercon; 119 struct connection *othercon;
119 struct work_struct rwork; /* Receive workqueue */ 120 struct work_struct rwork; /* Receive workqueue */
120 struct work_struct swork; /* Send workqueue */ 121 struct work_struct swork; /* Send workqueue */
@@ -139,14 +140,37 @@ static int dlm_local_count;
139static struct workqueue_struct *recv_workqueue; 140static struct workqueue_struct *recv_workqueue;
140static struct workqueue_struct *send_workqueue; 141static struct workqueue_struct *send_workqueue;
141 142
142static DEFINE_IDR(connections_idr); 143static struct hlist_head connection_hash[CONN_HASH_SIZE];
143static DEFINE_MUTEX(connections_lock); 144static DEFINE_MUTEX(connections_lock);
144static int max_nodeid;
145static struct kmem_cache *con_cache; 145static struct kmem_cache *con_cache;
146 146
147static void process_recv_sockets(struct work_struct *work); 147static void process_recv_sockets(struct work_struct *work);
148static void process_send_sockets(struct work_struct *work); 148static void process_send_sockets(struct work_struct *work);
149 149
150
151/* This is deliberately very simple because most clusters have simple
152 sequential nodeids, so we should be able to go straight to a connection
153 struct in the array */
154static inline int nodeid_hash(int nodeid)
155{
156 return nodeid & (CONN_HASH_SIZE-1);
157}
158
159static struct connection *__find_con(int nodeid)
160{
161 int r;
162 struct hlist_node *h;
163 struct connection *con;
164
165 r = nodeid_hash(nodeid);
166
167 hlist_for_each_entry(con, h, &connection_hash[r], list) {
168 if (con->nodeid == nodeid)
169 return con;
170 }
171 return NULL;
172}
173
150/* 174/*
151 * If 'allocation' is zero then we don't attempt to create a new 175 * If 'allocation' is zero then we don't attempt to create a new
152 * connection structure for this node. 176 * connection structure for this node.
@@ -155,31 +179,17 @@ static struct connection *__nodeid2con(int nodeid, gfp_t alloc)
155{ 179{
156 struct connection *con = NULL; 180 struct connection *con = NULL;
157 int r; 181 int r;
158 int n;
159 182
160 con = idr_find(&connections_idr, nodeid); 183 con = __find_con(nodeid);
161 if (con || !alloc) 184 if (con || !alloc)
162 return con; 185 return con;
163 186
164 r = idr_pre_get(&connections_idr, alloc);
165 if (!r)
166 return NULL;
167
168 con = kmem_cache_zalloc(con_cache, alloc); 187 con = kmem_cache_zalloc(con_cache, alloc);
169 if (!con) 188 if (!con)
170 return NULL; 189 return NULL;
171 190
172 r = idr_get_new_above(&connections_idr, con, nodeid, &n); 191 r = nodeid_hash(nodeid);
173 if (r) { 192 hlist_add_head(&con->list, &connection_hash[r]);
174 kmem_cache_free(con_cache, con);
175 return NULL;
176 }
177
178 if (n != nodeid) {
179 idr_remove(&connections_idr, n);
180 kmem_cache_free(con_cache, con);
181 return NULL;
182 }
183 193
184 con->nodeid = nodeid; 194 con->nodeid = nodeid;
185 mutex_init(&con->sock_mutex); 195 mutex_init(&con->sock_mutex);
@@ -190,19 +200,30 @@ static struct connection *__nodeid2con(int nodeid, gfp_t alloc)
190 200
191 /* Setup action pointers for child sockets */ 201 /* Setup action pointers for child sockets */
192 if (con->nodeid) { 202 if (con->nodeid) {
193 struct connection *zerocon = idr_find(&connections_idr, 0); 203 struct connection *zerocon = __find_con(0);
194 204
195 con->connect_action = zerocon->connect_action; 205 con->connect_action = zerocon->connect_action;
196 if (!con->rx_action) 206 if (!con->rx_action)
197 con->rx_action = zerocon->rx_action; 207 con->rx_action = zerocon->rx_action;
198 } 208 }
199 209
200 if (nodeid > max_nodeid)
201 max_nodeid = nodeid;
202
203 return con; 210 return con;
204} 211}
205 212
213/* Loop round all connections */
214static void foreach_conn(void (*conn_func)(struct connection *c))
215{
216 int i;
217 struct hlist_node *h, *n;
218 struct connection *con;
219
220 for (i = 0; i < CONN_HASH_SIZE; i++) {
221 hlist_for_each_entry_safe(con, h, n, &connection_hash[i], list){
222 conn_func(con);
223 }
224 }
225}
226
206static struct connection *nodeid2con(int nodeid, gfp_t allocation) 227static struct connection *nodeid2con(int nodeid, gfp_t allocation)
207{ 228{
208 struct connection *con; 229 struct connection *con;
@@ -218,14 +239,17 @@ static struct connection *nodeid2con(int nodeid, gfp_t allocation)
218static struct connection *assoc2con(int assoc_id) 239static struct connection *assoc2con(int assoc_id)
219{ 240{
220 int i; 241 int i;
242 struct hlist_node *h;
221 struct connection *con; 243 struct connection *con;
222 244
223 mutex_lock(&connections_lock); 245 mutex_lock(&connections_lock);
224 for (i=0; i<=max_nodeid; i++) { 246
225 con = __nodeid2con(i, 0); 247 for (i = 0 ; i < CONN_HASH_SIZE; i++) {
226 if (con && con->sctp_assoc == assoc_id) { 248 hlist_for_each_entry(con, h, &connection_hash[i], list) {
227 mutex_unlock(&connections_lock); 249 if (con && con->sctp_assoc == assoc_id) {
228 return con; 250 mutex_unlock(&connections_lock);
251 return con;
252 }
229 } 253 }
230 } 254 }
231 mutex_unlock(&connections_lock); 255 mutex_unlock(&connections_lock);
@@ -376,25 +400,23 @@ static void sctp_send_shutdown(sctp_assoc_t associd)
376 log_print("send EOF to node failed: %d", ret); 400 log_print("send EOF to node failed: %d", ret);
377} 401}
378 402
403static void sctp_init_failed_foreach(struct connection *con)
404{
405 con->sctp_assoc = 0;
406 if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
407 if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
408 queue_work(send_workqueue, &con->swork);
409 }
410}
411
379/* INIT failed but we don't know which node... 412/* INIT failed but we don't know which node...
380 restart INIT on all pending nodes */ 413 restart INIT on all pending nodes */
381static void sctp_init_failed(void) 414static void sctp_init_failed(void)
382{ 415{
383 int i;
384 struct connection *con;
385
386 mutex_lock(&connections_lock); 416 mutex_lock(&connections_lock);
387 for (i=1; i<=max_nodeid; i++) { 417
388 con = __nodeid2con(i, 0); 418 foreach_conn(sctp_init_failed_foreach);
389 if (!con) 419
390 continue;
391 con->sctp_assoc = 0;
392 if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
393 if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
394 queue_work(send_workqueue, &con->swork);
395 }
396 }
397 }
398 mutex_unlock(&connections_lock); 420 mutex_unlock(&connections_lock);
399} 421}
400 422
@@ -1313,13 +1335,10 @@ out_connect:
1313 1335
1314static void clean_one_writequeue(struct connection *con) 1336static void clean_one_writequeue(struct connection *con)
1315{ 1337{
1316 struct list_head *list; 1338 struct writequeue_entry *e, *safe;
1317 struct list_head *temp;
1318 1339
1319 spin_lock(&con->writequeue_lock); 1340 spin_lock(&con->writequeue_lock);
1320 list_for_each_safe(list, temp, &con->writequeue) { 1341 list_for_each_entry_safe(e, safe, &con->writequeue, list) {
1321 struct writequeue_entry *e =
1322 list_entry(list, struct writequeue_entry, list);
1323 list_del(&e->list); 1342 list_del(&e->list);
1324 free_entry(e); 1343 free_entry(e);
1325 } 1344 }
@@ -1369,14 +1388,7 @@ static void process_send_sockets(struct work_struct *work)
1369/* Discard all entries on the write queues */ 1388/* Discard all entries on the write queues */
1370static void clean_writequeues(void) 1389static void clean_writequeues(void)
1371{ 1390{
1372 int nodeid; 1391 foreach_conn(clean_one_writequeue);
1373
1374 for (nodeid = 1; nodeid <= max_nodeid; nodeid++) {
1375 struct connection *con = __nodeid2con(nodeid, 0);
1376
1377 if (con)
1378 clean_one_writequeue(con);
1379 }
1380} 1392}
1381 1393
1382static void work_stop(void) 1394static void work_stop(void)
@@ -1406,23 +1418,29 @@ static int work_start(void)
1406 return 0; 1418 return 0;
1407} 1419}
1408 1420
1409void dlm_lowcomms_stop(void) 1421static void stop_conn(struct connection *con)
1410{ 1422{
1411 int i; 1423 con->flags |= 0x0F;
1412 struct connection *con; 1424 if (con->sock)
1425 con->sock->sk->sk_user_data = NULL;
1426}
1413 1427
1428static void free_conn(struct connection *con)
1429{
1430 close_connection(con, true);
1431 if (con->othercon)
1432 kmem_cache_free(con_cache, con->othercon);
1433 hlist_del(&con->list);
1434 kmem_cache_free(con_cache, con);
1435}
1436
1437void dlm_lowcomms_stop(void)
1438{
1414 /* Set all the flags to prevent any 1439 /* Set all the flags to prevent any
1415 socket activity. 1440 socket activity.
1416 */ 1441 */
1417 mutex_lock(&connections_lock); 1442 mutex_lock(&connections_lock);
1418 for (i = 0; i <= max_nodeid; i++) { 1443 foreach_conn(stop_conn);
1419 con = __nodeid2con(i, 0);
1420 if (con) {
1421 con->flags |= 0x0F;
1422 if (con->sock)
1423 con->sock->sk->sk_user_data = NULL;
1424 }
1425 }
1426 mutex_unlock(&connections_lock); 1444 mutex_unlock(&connections_lock);
1427 1445
1428 work_stop(); 1446 work_stop();
@@ -1430,25 +1448,20 @@ void dlm_lowcomms_stop(void)
1430 mutex_lock(&connections_lock); 1448 mutex_lock(&connections_lock);
1431 clean_writequeues(); 1449 clean_writequeues();
1432 1450
1433 for (i = 0; i <= max_nodeid; i++) { 1451 foreach_conn(free_conn);
1434 con = __nodeid2con(i, 0); 1452
1435 if (con) {
1436 close_connection(con, true);
1437 if (con->othercon)
1438 kmem_cache_free(con_cache, con->othercon);
1439 kmem_cache_free(con_cache, con);
1440 }
1441 }
1442 max_nodeid = 0;
1443 mutex_unlock(&connections_lock); 1453 mutex_unlock(&connections_lock);
1444 kmem_cache_destroy(con_cache); 1454 kmem_cache_destroy(con_cache);
1445 idr_init(&connections_idr);
1446} 1455}
1447 1456
1448int dlm_lowcomms_start(void) 1457int dlm_lowcomms_start(void)
1449{ 1458{
1450 int error = -EINVAL; 1459 int error = -EINVAL;
1451 struct connection *con; 1460 struct connection *con;
1461 int i;
1462
1463 for (i = 0; i < CONN_HASH_SIZE; i++)
1464 INIT_HLIST_HEAD(&connection_hash[i]);
1452 1465
1453 init_local(); 1466 init_local();
1454 if (!dlm_local_count) { 1467 if (!dlm_local_count) {