diff options
Diffstat (limited to 'fs/ocfs2/cluster')
-rw-r--r-- | fs/ocfs2/cluster/Makefile | 2 | ||||
-rw-r--r-- | fs/ocfs2/cluster/netdebug.c | 441 | ||||
-rw-r--r-- | fs/ocfs2/cluster/nodemanager.c | 5 | ||||
-rw-r--r-- | fs/ocfs2/cluster/sys.c | 9 | ||||
-rw-r--r-- | fs/ocfs2/cluster/tcp.c | 164 | ||||
-rw-r--r-- | fs/ocfs2/cluster/tcp.h | 32 | ||||
-rw-r--r-- | fs/ocfs2/cluster/tcp_internal.h | 26 |
7 files changed, 635 insertions, 44 deletions
diff --git a/fs/ocfs2/cluster/Makefile b/fs/ocfs2/cluster/Makefile index cdd162f13650..bc8c5e7d8608 100644 --- a/fs/ocfs2/cluster/Makefile +++ b/fs/ocfs2/cluster/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o | 1 | obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o |
2 | 2 | ||
3 | ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \ | 3 | ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \ |
4 | quorum.o tcp.o ver.o | 4 | quorum.o tcp.o netdebug.o ver.o |
diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c new file mode 100644 index 000000000000..7bf3c0ea7bd9 --- /dev/null +++ b/fs/ocfs2/cluster/netdebug.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /* -*- mode: c; c-basic-offset: 8; -*- | ||
2 | * vim: noexpandtab sw=8 ts=8 sts=0: | ||
3 | * | ||
4 | * netdebug.c | ||
5 | * | ||
6 | * debug functionality for o2net | ||
7 | * | ||
8 | * Copyright (C) 2005, 2008 Oracle. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public | ||
12 | * License as published by the Free Software Foundation; either | ||
13 | * version 2 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public | ||
21 | * License along with this program; if not, write to the | ||
22 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
23 | * Boston, MA 021110-1307, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #ifdef CONFIG_DEBUG_FS | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/idr.h> | ||
33 | #include <linux/kref.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | #include <linux/debugfs.h> | ||
36 | |||
37 | #include <linux/uaccess.h> | ||
38 | |||
39 | #include "tcp.h" | ||
40 | #include "nodemanager.h" | ||
41 | #define MLOG_MASK_PREFIX ML_TCP | ||
42 | #include "masklog.h" | ||
43 | |||
44 | #include "tcp_internal.h" | ||
45 | |||
46 | #define O2NET_DEBUG_DIR "o2net" | ||
47 | #define SC_DEBUG_NAME "sock_containers" | ||
48 | #define NST_DEBUG_NAME "send_tracking" | ||
49 | |||
50 | static struct dentry *o2net_dentry; | ||
51 | static struct dentry *sc_dentry; | ||
52 | static struct dentry *nst_dentry; | ||
53 | |||
54 | static DEFINE_SPINLOCK(o2net_debug_lock); | ||
55 | |||
56 | static LIST_HEAD(sock_containers); | ||
57 | static LIST_HEAD(send_tracking); | ||
58 | |||
59 | void o2net_debug_add_nst(struct o2net_send_tracking *nst) | ||
60 | { | ||
61 | spin_lock(&o2net_debug_lock); | ||
62 | list_add(&nst->st_net_debug_item, &send_tracking); | ||
63 | spin_unlock(&o2net_debug_lock); | ||
64 | } | ||
65 | |||
66 | void o2net_debug_del_nst(struct o2net_send_tracking *nst) | ||
67 | { | ||
68 | spin_lock(&o2net_debug_lock); | ||
69 | if (!list_empty(&nst->st_net_debug_item)) | ||
70 | list_del_init(&nst->st_net_debug_item); | ||
71 | spin_unlock(&o2net_debug_lock); | ||
72 | } | ||
73 | |||
74 | static struct o2net_send_tracking | ||
75 | *next_nst(struct o2net_send_tracking *nst_start) | ||
76 | { | ||
77 | struct o2net_send_tracking *nst, *ret = NULL; | ||
78 | |||
79 | assert_spin_locked(&o2net_debug_lock); | ||
80 | |||
81 | list_for_each_entry(nst, &nst_start->st_net_debug_item, | ||
82 | st_net_debug_item) { | ||
83 | /* discover the head of the list */ | ||
84 | if (&nst->st_net_debug_item == &send_tracking) | ||
85 | break; | ||
86 | |||
87 | /* use st_task to detect real nsts in the list */ | ||
88 | if (nst->st_task != NULL) { | ||
89 | ret = nst; | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static void *nst_seq_start(struct seq_file *seq, loff_t *pos) | ||
98 | { | ||
99 | struct o2net_send_tracking *nst, *dummy_nst = seq->private; | ||
100 | |||
101 | spin_lock(&o2net_debug_lock); | ||
102 | nst = next_nst(dummy_nst); | ||
103 | spin_unlock(&o2net_debug_lock); | ||
104 | |||
105 | return nst; | ||
106 | } | ||
107 | |||
108 | static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
109 | { | ||
110 | struct o2net_send_tracking *nst, *dummy_nst = seq->private; | ||
111 | |||
112 | spin_lock(&o2net_debug_lock); | ||
113 | nst = next_nst(dummy_nst); | ||
114 | list_del_init(&dummy_nst->st_net_debug_item); | ||
115 | if (nst) | ||
116 | list_add(&dummy_nst->st_net_debug_item, | ||
117 | &nst->st_net_debug_item); | ||
118 | spin_unlock(&o2net_debug_lock); | ||
119 | |||
120 | return nst; /* unused, just needs to be null when done */ | ||
121 | } | ||
122 | |||
123 | static int nst_seq_show(struct seq_file *seq, void *v) | ||
124 | { | ||
125 | struct o2net_send_tracking *nst, *dummy_nst = seq->private; | ||
126 | |||
127 | spin_lock(&o2net_debug_lock); | ||
128 | nst = next_nst(dummy_nst); | ||
129 | |||
130 | if (nst != NULL) { | ||
131 | /* get_task_comm isn't exported. oh well. */ | ||
132 | seq_printf(seq, "%p:\n" | ||
133 | " pid: %lu\n" | ||
134 | " tgid: %lu\n" | ||
135 | " process name: %s\n" | ||
136 | " node: %u\n" | ||
137 | " sc: %p\n" | ||
138 | " message id: %d\n" | ||
139 | " message type: %u\n" | ||
140 | " message key: 0x%08x\n" | ||
141 | " sock acquiry: %lu.%lu\n" | ||
142 | " send start: %lu.%lu\n" | ||
143 | " wait start: %lu.%lu\n", | ||
144 | nst, (unsigned long)nst->st_task->pid, | ||
145 | (unsigned long)nst->st_task->tgid, | ||
146 | nst->st_task->comm, nst->st_node, | ||
147 | nst->st_sc, nst->st_id, nst->st_msg_type, | ||
148 | nst->st_msg_key, | ||
149 | nst->st_sock_time.tv_sec, nst->st_sock_time.tv_usec, | ||
150 | nst->st_send_time.tv_sec, nst->st_send_time.tv_usec, | ||
151 | nst->st_status_time.tv_sec, | ||
152 | nst->st_status_time.tv_usec); | ||
153 | } | ||
154 | |||
155 | spin_unlock(&o2net_debug_lock); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void nst_seq_stop(struct seq_file *seq, void *v) | ||
161 | { | ||
162 | } | ||
163 | |||
164 | static struct seq_operations nst_seq_ops = { | ||
165 | .start = nst_seq_start, | ||
166 | .next = nst_seq_next, | ||
167 | .stop = nst_seq_stop, | ||
168 | .show = nst_seq_show, | ||
169 | }; | ||
170 | |||
171 | static int nst_fop_open(struct inode *inode, struct file *file) | ||
172 | { | ||
173 | struct o2net_send_tracking *dummy_nst; | ||
174 | struct seq_file *seq; | ||
175 | int ret; | ||
176 | |||
177 | dummy_nst = kmalloc(sizeof(struct o2net_send_tracking), GFP_KERNEL); | ||
178 | if (dummy_nst == NULL) { | ||
179 | ret = -ENOMEM; | ||
180 | goto out; | ||
181 | } | ||
182 | dummy_nst->st_task = NULL; | ||
183 | |||
184 | ret = seq_open(file, &nst_seq_ops); | ||
185 | if (ret) | ||
186 | goto out; | ||
187 | |||
188 | seq = file->private_data; | ||
189 | seq->private = dummy_nst; | ||
190 | o2net_debug_add_nst(dummy_nst); | ||
191 | |||
192 | dummy_nst = NULL; | ||
193 | |||
194 | out: | ||
195 | kfree(dummy_nst); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | static int nst_fop_release(struct inode *inode, struct file *file) | ||
200 | { | ||
201 | struct seq_file *seq = file->private_data; | ||
202 | struct o2net_send_tracking *dummy_nst = seq->private; | ||
203 | |||
204 | o2net_debug_del_nst(dummy_nst); | ||
205 | return seq_release_private(inode, file); | ||
206 | } | ||
207 | |||
208 | static struct file_operations nst_seq_fops = { | ||
209 | .open = nst_fop_open, | ||
210 | .read = seq_read, | ||
211 | .llseek = seq_lseek, | ||
212 | .release = nst_fop_release, | ||
213 | }; | ||
214 | |||
215 | void o2net_debug_add_sc(struct o2net_sock_container *sc) | ||
216 | { | ||
217 | spin_lock(&o2net_debug_lock); | ||
218 | list_add(&sc->sc_net_debug_item, &sock_containers); | ||
219 | spin_unlock(&o2net_debug_lock); | ||
220 | } | ||
221 | |||
222 | void o2net_debug_del_sc(struct o2net_sock_container *sc) | ||
223 | { | ||
224 | spin_lock(&o2net_debug_lock); | ||
225 | list_del_init(&sc->sc_net_debug_item); | ||
226 | spin_unlock(&o2net_debug_lock); | ||
227 | } | ||
228 | |||
229 | static struct o2net_sock_container | ||
230 | *next_sc(struct o2net_sock_container *sc_start) | ||
231 | { | ||
232 | struct o2net_sock_container *sc, *ret = NULL; | ||
233 | |||
234 | assert_spin_locked(&o2net_debug_lock); | ||
235 | |||
236 | list_for_each_entry(sc, &sc_start->sc_net_debug_item, | ||
237 | sc_net_debug_item) { | ||
238 | /* discover the head of the list miscast as a sc */ | ||
239 | if (&sc->sc_net_debug_item == &sock_containers) | ||
240 | break; | ||
241 | |||
242 | /* use sc_page to detect real scs in the list */ | ||
243 | if (sc->sc_page != NULL) { | ||
244 | ret = sc; | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | static void *sc_seq_start(struct seq_file *seq, loff_t *pos) | ||
253 | { | ||
254 | struct o2net_sock_container *sc, *dummy_sc = seq->private; | ||
255 | |||
256 | spin_lock(&o2net_debug_lock); | ||
257 | sc = next_sc(dummy_sc); | ||
258 | spin_unlock(&o2net_debug_lock); | ||
259 | |||
260 | return sc; | ||
261 | } | ||
262 | |||
263 | static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
264 | { | ||
265 | struct o2net_sock_container *sc, *dummy_sc = seq->private; | ||
266 | |||
267 | spin_lock(&o2net_debug_lock); | ||
268 | sc = next_sc(dummy_sc); | ||
269 | list_del_init(&dummy_sc->sc_net_debug_item); | ||
270 | if (sc) | ||
271 | list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item); | ||
272 | spin_unlock(&o2net_debug_lock); | ||
273 | |||
274 | return sc; /* unused, just needs to be null when done */ | ||
275 | } | ||
276 | |||
277 | #define TV_SEC_USEC(TV) TV.tv_sec, TV.tv_usec | ||
278 | |||
279 | static int sc_seq_show(struct seq_file *seq, void *v) | ||
280 | { | ||
281 | struct o2net_sock_container *sc, *dummy_sc = seq->private; | ||
282 | |||
283 | spin_lock(&o2net_debug_lock); | ||
284 | sc = next_sc(dummy_sc); | ||
285 | |||
286 | if (sc != NULL) { | ||
287 | struct inet_sock *inet = NULL; | ||
288 | |||
289 | __be32 saddr = 0, daddr = 0; | ||
290 | __be16 sport = 0, dport = 0; | ||
291 | |||
292 | if (sc->sc_sock) { | ||
293 | inet = inet_sk(sc->sc_sock->sk); | ||
294 | /* the stack's structs aren't sparse endian clean */ | ||
295 | saddr = (__force __be32)inet->saddr; | ||
296 | daddr = (__force __be32)inet->daddr; | ||
297 | sport = (__force __be16)inet->sport; | ||
298 | dport = (__force __be16)inet->dport; | ||
299 | } | ||
300 | |||
301 | /* XXX sigh, inet-> doesn't have sparse annotation so any | ||
302 | * use of it here generates a warning with -Wbitwise */ | ||
303 | seq_printf(seq, "%p:\n" | ||
304 | " krefs: %d\n" | ||
305 | " sock: %u.%u.%u.%u:%u -> " | ||
306 | "%u.%u.%u.%u:%u\n" | ||
307 | " remote node: %s\n" | ||
308 | " page off: %zu\n" | ||
309 | " handshake ok: %u\n" | ||
310 | " timer: %lu.%lu\n" | ||
311 | " data ready: %lu.%lu\n" | ||
312 | " advance start: %lu.%lu\n" | ||
313 | " advance stop: %lu.%lu\n" | ||
314 | " func start: %lu.%lu\n" | ||
315 | " func stop: %lu.%lu\n" | ||
316 | " func key: %u\n" | ||
317 | " func type: %u\n", | ||
318 | sc, | ||
319 | atomic_read(&sc->sc_kref.refcount), | ||
320 | NIPQUAD(saddr), inet ? ntohs(sport) : 0, | ||
321 | NIPQUAD(daddr), inet ? ntohs(dport) : 0, | ||
322 | sc->sc_node->nd_name, | ||
323 | sc->sc_page_off, | ||
324 | sc->sc_handshake_ok, | ||
325 | TV_SEC_USEC(sc->sc_tv_timer), | ||
326 | TV_SEC_USEC(sc->sc_tv_data_ready), | ||
327 | TV_SEC_USEC(sc->sc_tv_advance_start), | ||
328 | TV_SEC_USEC(sc->sc_tv_advance_stop), | ||
329 | TV_SEC_USEC(sc->sc_tv_func_start), | ||
330 | TV_SEC_USEC(sc->sc_tv_func_stop), | ||
331 | sc->sc_msg_key, | ||
332 | sc->sc_msg_type); | ||
333 | } | ||
334 | |||
335 | |||
336 | spin_unlock(&o2net_debug_lock); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static void sc_seq_stop(struct seq_file *seq, void *v) | ||
342 | { | ||
343 | } | ||
344 | |||
345 | static struct seq_operations sc_seq_ops = { | ||
346 | .start = sc_seq_start, | ||
347 | .next = sc_seq_next, | ||
348 | .stop = sc_seq_stop, | ||
349 | .show = sc_seq_show, | ||
350 | }; | ||
351 | |||
352 | static int sc_fop_open(struct inode *inode, struct file *file) | ||
353 | { | ||
354 | struct o2net_sock_container *dummy_sc; | ||
355 | struct seq_file *seq; | ||
356 | int ret; | ||
357 | |||
358 | dummy_sc = kmalloc(sizeof(struct o2net_sock_container), GFP_KERNEL); | ||
359 | if (dummy_sc == NULL) { | ||
360 | ret = -ENOMEM; | ||
361 | goto out; | ||
362 | } | ||
363 | dummy_sc->sc_page = NULL; | ||
364 | |||
365 | ret = seq_open(file, &sc_seq_ops); | ||
366 | if (ret) | ||
367 | goto out; | ||
368 | |||
369 | seq = file->private_data; | ||
370 | seq->private = dummy_sc; | ||
371 | o2net_debug_add_sc(dummy_sc); | ||
372 | |||
373 | dummy_sc = NULL; | ||
374 | |||
375 | out: | ||
376 | kfree(dummy_sc); | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | static int sc_fop_release(struct inode *inode, struct file *file) | ||
381 | { | ||
382 | struct seq_file *seq = file->private_data; | ||
383 | struct o2net_sock_container *dummy_sc = seq->private; | ||
384 | |||
385 | o2net_debug_del_sc(dummy_sc); | ||
386 | return seq_release_private(inode, file); | ||
387 | } | ||
388 | |||
389 | static struct file_operations sc_seq_fops = { | ||
390 | .open = sc_fop_open, | ||
391 | .read = seq_read, | ||
392 | .llseek = seq_lseek, | ||
393 | .release = sc_fop_release, | ||
394 | }; | ||
395 | |||
396 | int o2net_debugfs_init(void) | ||
397 | { | ||
398 | o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL); | ||
399 | if (!o2net_dentry) { | ||
400 | mlog_errno(-ENOMEM); | ||
401 | goto bail; | ||
402 | } | ||
403 | |||
404 | nst_dentry = debugfs_create_file(NST_DEBUG_NAME, S_IFREG|S_IRUSR, | ||
405 | o2net_dentry, NULL, | ||
406 | &nst_seq_fops); | ||
407 | if (!nst_dentry) { | ||
408 | mlog_errno(-ENOMEM); | ||
409 | goto bail; | ||
410 | } | ||
411 | |||
412 | sc_dentry = debugfs_create_file(SC_DEBUG_NAME, S_IFREG|S_IRUSR, | ||
413 | o2net_dentry, NULL, | ||
414 | &sc_seq_fops); | ||
415 | if (!sc_dentry) { | ||
416 | mlog_errno(-ENOMEM); | ||
417 | goto bail; | ||
418 | } | ||
419 | |||
420 | return 0; | ||
421 | bail: | ||
422 | if (sc_dentry) | ||
423 | debugfs_remove(sc_dentry); | ||
424 | if (nst_dentry) | ||
425 | debugfs_remove(nst_dentry); | ||
426 | if (o2net_dentry) | ||
427 | debugfs_remove(o2net_dentry); | ||
428 | return -ENOMEM; | ||
429 | } | ||
430 | |||
431 | void o2net_debugfs_exit(void) | ||
432 | { | ||
433 | if (sc_dentry) | ||
434 | debugfs_remove(sc_dentry); | ||
435 | if (nst_dentry) | ||
436 | debugfs_remove(nst_dentry); | ||
437 | if (o2net_dentry) | ||
438 | debugfs_remove(o2net_dentry); | ||
439 | } | ||
440 | |||
441 | #endif /* CONFIG_DEBUG_FS */ | ||
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index 709fba25bf7e..cf9401e8cd0b 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c | |||
@@ -959,7 +959,10 @@ static int __init init_o2nm(void) | |||
959 | cluster_print_version(); | 959 | cluster_print_version(); |
960 | 960 | ||
961 | o2hb_init(); | 961 | o2hb_init(); |
962 | o2net_init(); | 962 | |
963 | ret = o2net_init(); | ||
964 | if (ret) | ||
965 | goto out; | ||
963 | 966 | ||
964 | ocfs2_table_header = register_sysctl_table(ocfs2_root_table); | 967 | ocfs2_table_header = register_sysctl_table(ocfs2_root_table); |
965 | if (!ocfs2_table_header) { | 968 | if (!ocfs2_table_header) { |
diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c index 0c095ce7723d..98429fd68499 100644 --- a/fs/ocfs2/cluster/sys.c +++ b/fs/ocfs2/cluster/sys.c | |||
@@ -57,6 +57,7 @@ static struct kset *o2cb_kset; | |||
57 | void o2cb_sys_shutdown(void) | 57 | void o2cb_sys_shutdown(void) |
58 | { | 58 | { |
59 | mlog_sys_shutdown(); | 59 | mlog_sys_shutdown(); |
60 | sysfs_remove_link(NULL, "o2cb"); | ||
60 | kset_unregister(o2cb_kset); | 61 | kset_unregister(o2cb_kset); |
61 | } | 62 | } |
62 | 63 | ||
@@ -68,6 +69,14 @@ int o2cb_sys_init(void) | |||
68 | if (!o2cb_kset) | 69 | if (!o2cb_kset) |
69 | return -ENOMEM; | 70 | return -ENOMEM; |
70 | 71 | ||
72 | /* | ||
73 | * Create this symlink for backwards compatibility with old | ||
74 | * versions of ocfs2-tools which look for things in /sys/o2cb. | ||
75 | */ | ||
76 | ret = sysfs_create_link(NULL, &o2cb_kset->kobj, "o2cb"); | ||
77 | if (ret) | ||
78 | goto error; | ||
79 | |||
71 | ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); | 80 | ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); |
72 | if (ret) | 81 | if (ret) |
73 | goto error; | 82 | goto error; |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index b8057c51b205..1e44ad14881a 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -142,23 +142,65 @@ static void o2net_idle_timer(unsigned long data); | |||
142 | static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); | 142 | static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); |
143 | static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc); | 143 | static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc); |
144 | 144 | ||
145 | /* | 145 | static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, |
146 | * FIXME: These should use to_o2nm_cluster_from_node(), but we end up | 146 | u32 msgkey, struct task_struct *task, u8 node) |
147 | * losing our parent link to the cluster during shutdown. This can be | 147 | { |
148 | * solved by adding a pre-removal callback to configfs, or passing | 148 | #ifdef CONFIG_DEBUG_FS |
149 | * around the cluster with the node. -jeffm | 149 | INIT_LIST_HEAD(&nst->st_net_debug_item); |
150 | */ | 150 | nst->st_task = task; |
151 | static inline int o2net_reconnect_delay(struct o2nm_node *node) | 151 | nst->st_msg_type = msgtype; |
152 | nst->st_msg_key = msgkey; | ||
153 | nst->st_node = node; | ||
154 | #endif | ||
155 | } | ||
156 | |||
157 | static void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) | ||
158 | { | ||
159 | #ifdef CONFIG_DEBUG_FS | ||
160 | do_gettimeofday(&nst->st_sock_time); | ||
161 | #endif | ||
162 | } | ||
163 | |||
164 | static void o2net_set_nst_send_time(struct o2net_send_tracking *nst) | ||
165 | { | ||
166 | #ifdef CONFIG_DEBUG_FS | ||
167 | do_gettimeofday(&nst->st_send_time); | ||
168 | #endif | ||
169 | } | ||
170 | |||
171 | static void o2net_set_nst_status_time(struct o2net_send_tracking *nst) | ||
172 | { | ||
173 | #ifdef CONFIG_DEBUG_FS | ||
174 | do_gettimeofday(&nst->st_status_time); | ||
175 | #endif | ||
176 | } | ||
177 | |||
178 | static void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, | ||
179 | struct o2net_sock_container *sc) | ||
180 | { | ||
181 | #ifdef CONFIG_DEBUG_FS | ||
182 | nst->st_sc = sc; | ||
183 | #endif | ||
184 | } | ||
185 | |||
186 | static void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id) | ||
187 | { | ||
188 | #ifdef CONFIG_DEBUG_FS | ||
189 | nst->st_id = msg_id; | ||
190 | #endif | ||
191 | } | ||
192 | |||
193 | static inline int o2net_reconnect_delay(void) | ||
152 | { | 194 | { |
153 | return o2nm_single_cluster->cl_reconnect_delay_ms; | 195 | return o2nm_single_cluster->cl_reconnect_delay_ms; |
154 | } | 196 | } |
155 | 197 | ||
156 | static inline int o2net_keepalive_delay(struct o2nm_node *node) | 198 | static inline int o2net_keepalive_delay(void) |
157 | { | 199 | { |
158 | return o2nm_single_cluster->cl_keepalive_delay_ms; | 200 | return o2nm_single_cluster->cl_keepalive_delay_ms; |
159 | } | 201 | } |
160 | 202 | ||
161 | static inline int o2net_idle_timeout(struct o2nm_node *node) | 203 | static inline int o2net_idle_timeout(void) |
162 | { | 204 | { |
163 | return o2nm_single_cluster->cl_idle_timeout_ms; | 205 | return o2nm_single_cluster->cl_idle_timeout_ms; |
164 | } | 206 | } |
@@ -296,6 +338,7 @@ static void sc_kref_release(struct kref *kref) | |||
296 | o2nm_node_put(sc->sc_node); | 338 | o2nm_node_put(sc->sc_node); |
297 | sc->sc_node = NULL; | 339 | sc->sc_node = NULL; |
298 | 340 | ||
341 | o2net_debug_del_sc(sc); | ||
299 | kfree(sc); | 342 | kfree(sc); |
300 | } | 343 | } |
301 | 344 | ||
@@ -336,6 +379,7 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node) | |||
336 | 379 | ||
337 | ret = sc; | 380 | ret = sc; |
338 | sc->sc_page = page; | 381 | sc->sc_page = page; |
382 | o2net_debug_add_sc(sc); | ||
339 | sc = NULL; | 383 | sc = NULL; |
340 | page = NULL; | 384 | page = NULL; |
341 | 385 | ||
@@ -399,8 +443,6 @@ static void o2net_set_nn_state(struct o2net_node *nn, | |||
399 | mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid); | 443 | mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid); |
400 | mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc); | 444 | mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc); |
401 | 445 | ||
402 | /* we won't reconnect after our valid conn goes away for | ||
403 | * this hb iteration.. here so it shows up in the logs */ | ||
404 | if (was_valid && !valid && err == 0) | 446 | if (was_valid && !valid && err == 0) |
405 | err = -ENOTCONN; | 447 | err = -ENOTCONN; |
406 | 448 | ||
@@ -430,11 +472,6 @@ static void o2net_set_nn_state(struct o2net_node *nn, | |||
430 | 472 | ||
431 | if (!was_valid && valid) { | 473 | if (!was_valid && valid) { |
432 | o2quo_conn_up(o2net_num_from_nn(nn)); | 474 | o2quo_conn_up(o2net_num_from_nn(nn)); |
433 | /* this is a bit of a hack. we only try reconnecting | ||
434 | * when heartbeating starts until we get a connection. | ||
435 | * if that connection then dies we don't try reconnecting. | ||
436 | * the only way to start connecting again is to down | ||
437 | * heartbeat and bring it back up. */ | ||
438 | cancel_delayed_work(&nn->nn_connect_expired); | 475 | cancel_delayed_work(&nn->nn_connect_expired); |
439 | printk(KERN_INFO "o2net: %s " SC_NODEF_FMT "\n", | 476 | printk(KERN_INFO "o2net: %s " SC_NODEF_FMT "\n", |
440 | o2nm_this_node() > sc->sc_node->nd_num ? | 477 | o2nm_this_node() > sc->sc_node->nd_num ? |
@@ -451,12 +488,24 @@ static void o2net_set_nn_state(struct o2net_node *nn, | |||
451 | /* delay if we're withing a RECONNECT_DELAY of the | 488 | /* delay if we're withing a RECONNECT_DELAY of the |
452 | * last attempt */ | 489 | * last attempt */ |
453 | delay = (nn->nn_last_connect_attempt + | 490 | delay = (nn->nn_last_connect_attempt + |
454 | msecs_to_jiffies(o2net_reconnect_delay(NULL))) | 491 | msecs_to_jiffies(o2net_reconnect_delay())) |
455 | - jiffies; | 492 | - jiffies; |
456 | if (delay > msecs_to_jiffies(o2net_reconnect_delay(NULL))) | 493 | if (delay > msecs_to_jiffies(o2net_reconnect_delay())) |
457 | delay = 0; | 494 | delay = 0; |
458 | mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay); | 495 | mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay); |
459 | queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay); | 496 | queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay); |
497 | |||
498 | /* | ||
499 | * Delay the expired work after idle timeout. | ||
500 | * | ||
501 | * We might have lots of failed connection attempts that run | ||
502 | * through here but we only cancel the connect_expired work when | ||
503 | * a connection attempt succeeds. So only the first enqueue of | ||
504 | * the connect_expired work will do anything. The rest will see | ||
505 | * that it's already queued and do nothing. | ||
506 | */ | ||
507 | delay += msecs_to_jiffies(o2net_idle_timeout()); | ||
508 | queue_delayed_work(o2net_wq, &nn->nn_connect_expired, delay); | ||
460 | } | 509 | } |
461 | 510 | ||
462 | /* keep track of the nn's sc ref for the caller */ | 511 | /* keep track of the nn's sc ref for the caller */ |
@@ -914,6 +963,9 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
914 | struct o2net_status_wait nsw = { | 963 | struct o2net_status_wait nsw = { |
915 | .ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item), | 964 | .ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item), |
916 | }; | 965 | }; |
966 | struct o2net_send_tracking nst; | ||
967 | |||
968 | o2net_init_nst(&nst, msg_type, key, current, target_node); | ||
917 | 969 | ||
918 | if (o2net_wq == NULL) { | 970 | if (o2net_wq == NULL) { |
919 | mlog(0, "attempt to tx without o2netd running\n"); | 971 | mlog(0, "attempt to tx without o2netd running\n"); |
@@ -939,6 +991,10 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
939 | goto out; | 991 | goto out; |
940 | } | 992 | } |
941 | 993 | ||
994 | o2net_debug_add_nst(&nst); | ||
995 | |||
996 | o2net_set_nst_sock_time(&nst); | ||
997 | |||
942 | ret = wait_event_interruptible(nn->nn_sc_wq, | 998 | ret = wait_event_interruptible(nn->nn_sc_wq, |
943 | o2net_tx_can_proceed(nn, &sc, &error)); | 999 | o2net_tx_can_proceed(nn, &sc, &error)); |
944 | if (!ret && error) | 1000 | if (!ret && error) |
@@ -946,6 +1002,8 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
946 | if (ret) | 1002 | if (ret) |
947 | goto out; | 1003 | goto out; |
948 | 1004 | ||
1005 | o2net_set_nst_sock_container(&nst, sc); | ||
1006 | |||
949 | veclen = caller_veclen + 1; | 1007 | veclen = caller_veclen + 1; |
950 | vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC); | 1008 | vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC); |
951 | if (vec == NULL) { | 1009 | if (vec == NULL) { |
@@ -972,6 +1030,9 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
972 | goto out; | 1030 | goto out; |
973 | 1031 | ||
974 | msg->msg_num = cpu_to_be32(nsw.ns_id); | 1032 | msg->msg_num = cpu_to_be32(nsw.ns_id); |
1033 | o2net_set_nst_msg_id(&nst, nsw.ns_id); | ||
1034 | |||
1035 | o2net_set_nst_send_time(&nst); | ||
975 | 1036 | ||
976 | /* finally, convert the message header to network byte-order | 1037 | /* finally, convert the message header to network byte-order |
977 | * and send */ | 1038 | * and send */ |
@@ -986,6 +1047,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
986 | } | 1047 | } |
987 | 1048 | ||
988 | /* wait on other node's handler */ | 1049 | /* wait on other node's handler */ |
1050 | o2net_set_nst_status_time(&nst); | ||
989 | wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw)); | 1051 | wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw)); |
990 | 1052 | ||
991 | /* Note that we avoid overwriting the callers status return | 1053 | /* Note that we avoid overwriting the callers status return |
@@ -998,6 +1060,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
998 | mlog(0, "woken, returning system status %d, user status %d\n", | 1060 | mlog(0, "woken, returning system status %d, user status %d\n", |
999 | ret, nsw.ns_status); | 1061 | ret, nsw.ns_status); |
1000 | out: | 1062 | out: |
1063 | o2net_debug_del_nst(&nst); /* must be before dropping sc and node */ | ||
1001 | if (sc) | 1064 | if (sc) |
1002 | sc_put(sc); | 1065 | sc_put(sc); |
1003 | if (vec) | 1066 | if (vec) |
@@ -1154,23 +1217,23 @@ static int o2net_check_handshake(struct o2net_sock_container *sc) | |||
1154 | * but isn't. This can ultimately cause corruption. | 1217 | * but isn't. This can ultimately cause corruption. |
1155 | */ | 1218 | */ |
1156 | if (be32_to_cpu(hand->o2net_idle_timeout_ms) != | 1219 | if (be32_to_cpu(hand->o2net_idle_timeout_ms) != |
1157 | o2net_idle_timeout(sc->sc_node)) { | 1220 | o2net_idle_timeout()) { |
1158 | mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of " | 1221 | mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of " |
1159 | "%u ms, but we use %u ms locally. disconnecting\n", | 1222 | "%u ms, but we use %u ms locally. disconnecting\n", |
1160 | SC_NODEF_ARGS(sc), | 1223 | SC_NODEF_ARGS(sc), |
1161 | be32_to_cpu(hand->o2net_idle_timeout_ms), | 1224 | be32_to_cpu(hand->o2net_idle_timeout_ms), |
1162 | o2net_idle_timeout(sc->sc_node)); | 1225 | o2net_idle_timeout()); |
1163 | o2net_ensure_shutdown(nn, sc, -ENOTCONN); | 1226 | o2net_ensure_shutdown(nn, sc, -ENOTCONN); |
1164 | return -1; | 1227 | return -1; |
1165 | } | 1228 | } |
1166 | 1229 | ||
1167 | if (be32_to_cpu(hand->o2net_keepalive_delay_ms) != | 1230 | if (be32_to_cpu(hand->o2net_keepalive_delay_ms) != |
1168 | o2net_keepalive_delay(sc->sc_node)) { | 1231 | o2net_keepalive_delay()) { |
1169 | mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of " | 1232 | mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of " |
1170 | "%u ms, but we use %u ms locally. disconnecting\n", | 1233 | "%u ms, but we use %u ms locally. disconnecting\n", |
1171 | SC_NODEF_ARGS(sc), | 1234 | SC_NODEF_ARGS(sc), |
1172 | be32_to_cpu(hand->o2net_keepalive_delay_ms), | 1235 | be32_to_cpu(hand->o2net_keepalive_delay_ms), |
1173 | o2net_keepalive_delay(sc->sc_node)); | 1236 | o2net_keepalive_delay()); |
1174 | o2net_ensure_shutdown(nn, sc, -ENOTCONN); | 1237 | o2net_ensure_shutdown(nn, sc, -ENOTCONN); |
1175 | return -1; | 1238 | return -1; |
1176 | } | 1239 | } |
@@ -1193,6 +1256,7 @@ static int o2net_check_handshake(struct o2net_sock_container *sc) | |||
1193 | * shut down already */ | 1256 | * shut down already */ |
1194 | if (nn->nn_sc == sc) { | 1257 | if (nn->nn_sc == sc) { |
1195 | o2net_sc_reset_idle_timer(sc); | 1258 | o2net_sc_reset_idle_timer(sc); |
1259 | atomic_set(&nn->nn_timeout, 0); | ||
1196 | o2net_set_nn_state(nn, sc, 1, 0); | 1260 | o2net_set_nn_state(nn, sc, 1, 0); |
1197 | } | 1261 | } |
1198 | spin_unlock(&nn->nn_lock); | 1262 | spin_unlock(&nn->nn_lock); |
@@ -1347,12 +1411,11 @@ static void o2net_initialize_handshake(void) | |||
1347 | { | 1411 | { |
1348 | o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32( | 1412 | o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32( |
1349 | O2HB_MAX_WRITE_TIMEOUT_MS); | 1413 | O2HB_MAX_WRITE_TIMEOUT_MS); |
1350 | o2net_hand->o2net_idle_timeout_ms = cpu_to_be32( | 1414 | o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(o2net_idle_timeout()); |
1351 | o2net_idle_timeout(NULL)); | ||
1352 | o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32( | 1415 | o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32( |
1353 | o2net_keepalive_delay(NULL)); | 1416 | o2net_keepalive_delay()); |
1354 | o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32( | 1417 | o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32( |
1355 | o2net_reconnect_delay(NULL)); | 1418 | o2net_reconnect_delay()); |
1356 | } | 1419 | } |
1357 | 1420 | ||
1358 | /* ------------------------------------------------------------ */ | 1421 | /* ------------------------------------------------------------ */ |
@@ -1391,14 +1454,15 @@ static void o2net_sc_send_keep_req(struct work_struct *work) | |||
1391 | static void o2net_idle_timer(unsigned long data) | 1454 | static void o2net_idle_timer(unsigned long data) |
1392 | { | 1455 | { |
1393 | struct o2net_sock_container *sc = (struct o2net_sock_container *)data; | 1456 | struct o2net_sock_container *sc = (struct o2net_sock_container *)data; |
1457 | struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); | ||
1394 | struct timeval now; | 1458 | struct timeval now; |
1395 | 1459 | ||
1396 | do_gettimeofday(&now); | 1460 | do_gettimeofday(&now); |
1397 | 1461 | ||
1398 | printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u " | 1462 | printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u " |
1399 | "seconds, shutting it down.\n", SC_NODEF_ARGS(sc), | 1463 | "seconds, shutting it down.\n", SC_NODEF_ARGS(sc), |
1400 | o2net_idle_timeout(sc->sc_node) / 1000, | 1464 | o2net_idle_timeout() / 1000, |
1401 | o2net_idle_timeout(sc->sc_node) % 1000); | 1465 | o2net_idle_timeout() % 1000); |
1402 | mlog(ML_NOTICE, "here are some times that might help debug the " | 1466 | mlog(ML_NOTICE, "here are some times that might help debug the " |
1403 | "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv " | 1467 | "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv " |
1404 | "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n", | 1468 | "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n", |
@@ -1413,6 +1477,12 @@ static void o2net_idle_timer(unsigned long data) | |||
1413 | sc->sc_tv_func_start.tv_sec, (long) sc->sc_tv_func_start.tv_usec, | 1477 | sc->sc_tv_func_start.tv_sec, (long) sc->sc_tv_func_start.tv_usec, |
1414 | sc->sc_tv_func_stop.tv_sec, (long) sc->sc_tv_func_stop.tv_usec); | 1478 | sc->sc_tv_func_stop.tv_sec, (long) sc->sc_tv_func_stop.tv_usec); |
1415 | 1479 | ||
1480 | /* | ||
1481 | * Initialize the nn_timeout so that the next connection attempt | ||
1482 | * will continue in o2net_start_connect. | ||
1483 | */ | ||
1484 | atomic_set(&nn->nn_timeout, 1); | ||
1485 | |||
1416 | o2net_sc_queue_work(sc, &sc->sc_shutdown_work); | 1486 | o2net_sc_queue_work(sc, &sc->sc_shutdown_work); |
1417 | } | 1487 | } |
1418 | 1488 | ||
@@ -1420,10 +1490,10 @@ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc) | |||
1420 | { | 1490 | { |
1421 | o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); | 1491 | o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); |
1422 | o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work, | 1492 | o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work, |
1423 | msecs_to_jiffies(o2net_keepalive_delay(sc->sc_node))); | 1493 | msecs_to_jiffies(o2net_keepalive_delay())); |
1424 | do_gettimeofday(&sc->sc_tv_timer); | 1494 | do_gettimeofday(&sc->sc_tv_timer); |
1425 | mod_timer(&sc->sc_idle_timeout, | 1495 | mod_timer(&sc->sc_idle_timeout, |
1426 | jiffies + msecs_to_jiffies(o2net_idle_timeout(sc->sc_node))); | 1496 | jiffies + msecs_to_jiffies(o2net_idle_timeout())); |
1427 | } | 1497 | } |
1428 | 1498 | ||
1429 | static void o2net_sc_postpone_idle(struct o2net_sock_container *sc) | 1499 | static void o2net_sc_postpone_idle(struct o2net_sock_container *sc) |
@@ -1447,6 +1517,7 @@ static void o2net_start_connect(struct work_struct *work) | |||
1447 | struct socket *sock = NULL; | 1517 | struct socket *sock = NULL; |
1448 | struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; | 1518 | struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; |
1449 | int ret = 0, stop; | 1519 | int ret = 0, stop; |
1520 | unsigned int timeout; | ||
1450 | 1521 | ||
1451 | /* if we're greater we initiate tx, otherwise we accept */ | 1522 | /* if we're greater we initiate tx, otherwise we accept */ |
1452 | if (o2nm_this_node() <= o2net_num_from_nn(nn)) | 1523 | if (o2nm_this_node() <= o2net_num_from_nn(nn)) |
@@ -1466,8 +1537,17 @@ static void o2net_start_connect(struct work_struct *work) | |||
1466 | } | 1537 | } |
1467 | 1538 | ||
1468 | spin_lock(&nn->nn_lock); | 1539 | spin_lock(&nn->nn_lock); |
1469 | /* see if we already have one pending or have given up */ | 1540 | /* |
1470 | stop = (nn->nn_sc || nn->nn_persistent_error); | 1541 | * see if we already have one pending or have given up. |
1542 | * For nn_timeout, it is set when we close the connection | ||
1543 | * because of the idle time out. So it means that we have | ||
1544 | * at least connected to that node successfully once, | ||
1545 | * now try to connect to it again. | ||
1546 | */ | ||
1547 | timeout = atomic_read(&nn->nn_timeout); | ||
1548 | stop = (nn->nn_sc || | ||
1549 | (nn->nn_persistent_error && | ||
1550 | (nn->nn_persistent_error != -ENOTCONN || timeout == 0))); | ||
1471 | spin_unlock(&nn->nn_lock); | 1551 | spin_unlock(&nn->nn_lock); |
1472 | if (stop) | 1552 | if (stop) |
1473 | goto out; | 1553 | goto out; |
@@ -1555,8 +1635,8 @@ static void o2net_connect_expired(struct work_struct *work) | |||
1555 | mlog(ML_ERROR, "no connection established with node %u after " | 1635 | mlog(ML_ERROR, "no connection established with node %u after " |
1556 | "%u.%u seconds, giving up and returning errors.\n", | 1636 | "%u.%u seconds, giving up and returning errors.\n", |
1557 | o2net_num_from_nn(nn), | 1637 | o2net_num_from_nn(nn), |
1558 | o2net_idle_timeout(NULL) / 1000, | 1638 | o2net_idle_timeout() / 1000, |
1559 | o2net_idle_timeout(NULL) % 1000); | 1639 | o2net_idle_timeout() % 1000); |
1560 | 1640 | ||
1561 | o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); | 1641 | o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); |
1562 | } | 1642 | } |
@@ -1579,6 +1659,7 @@ void o2net_disconnect_node(struct o2nm_node *node) | |||
1579 | 1659 | ||
1580 | /* don't reconnect until it's heartbeating again */ | 1660 | /* don't reconnect until it's heartbeating again */ |
1581 | spin_lock(&nn->nn_lock); | 1661 | spin_lock(&nn->nn_lock); |
1662 | atomic_set(&nn->nn_timeout, 0); | ||
1582 | o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); | 1663 | o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); |
1583 | spin_unlock(&nn->nn_lock); | 1664 | spin_unlock(&nn->nn_lock); |
1584 | 1665 | ||
@@ -1610,20 +1691,15 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num, | |||
1610 | 1691 | ||
1611 | /* ensure an immediate connect attempt */ | 1692 | /* ensure an immediate connect attempt */ |
1612 | nn->nn_last_connect_attempt = jiffies - | 1693 | nn->nn_last_connect_attempt = jiffies - |
1613 | (msecs_to_jiffies(o2net_reconnect_delay(node)) + 1); | 1694 | (msecs_to_jiffies(o2net_reconnect_delay()) + 1); |
1614 | 1695 | ||
1615 | if (node_num != o2nm_this_node()) { | 1696 | if (node_num != o2nm_this_node()) { |
1616 | /* heartbeat doesn't work unless a local node number is | ||
1617 | * configured and doing so brings up the o2net_wq, so we can | ||
1618 | * use it.. */ | ||
1619 | queue_delayed_work(o2net_wq, &nn->nn_connect_expired, | ||
1620 | msecs_to_jiffies(o2net_idle_timeout(node))); | ||
1621 | |||
1622 | /* believe it or not, accept and node hearbeating testing | 1697 | /* believe it or not, accept and node hearbeating testing |
1623 | * can succeed for this node before we got here.. so | 1698 | * can succeed for this node before we got here.. so |
1624 | * only use set_nn_state to clear the persistent error | 1699 | * only use set_nn_state to clear the persistent error |
1625 | * if that hasn't already happened */ | 1700 | * if that hasn't already happened */ |
1626 | spin_lock(&nn->nn_lock); | 1701 | spin_lock(&nn->nn_lock); |
1702 | atomic_set(&nn->nn_timeout, 0); | ||
1627 | if (nn->nn_persistent_error) | 1703 | if (nn->nn_persistent_error) |
1628 | o2net_set_nn_state(nn, NULL, 0, 0); | 1704 | o2net_set_nn_state(nn, NULL, 0, 0); |
1629 | spin_unlock(&nn->nn_lock); | 1705 | spin_unlock(&nn->nn_lock); |
@@ -1747,6 +1823,7 @@ static int o2net_accept_one(struct socket *sock) | |||
1747 | new_sock = NULL; | 1823 | new_sock = NULL; |
1748 | 1824 | ||
1749 | spin_lock(&nn->nn_lock); | 1825 | spin_lock(&nn->nn_lock); |
1826 | atomic_set(&nn->nn_timeout, 0); | ||
1750 | o2net_set_nn_state(nn, sc, 0, 0); | 1827 | o2net_set_nn_state(nn, sc, 0, 0); |
1751 | spin_unlock(&nn->nn_lock); | 1828 | spin_unlock(&nn->nn_lock); |
1752 | 1829 | ||
@@ -1922,6 +1999,9 @@ int o2net_init(void) | |||
1922 | 1999 | ||
1923 | o2quo_init(); | 2000 | o2quo_init(); |
1924 | 2001 | ||
2002 | if (o2net_debugfs_init()) | ||
2003 | return -ENOMEM; | ||
2004 | |||
1925 | o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL); | 2005 | o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL); |
1926 | o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); | 2006 | o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); |
1927 | o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); | 2007 | o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); |
@@ -1941,6 +2021,7 @@ int o2net_init(void) | |||
1941 | for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) { | 2021 | for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) { |
1942 | struct o2net_node *nn = o2net_nn_from_num(i); | 2022 | struct o2net_node *nn = o2net_nn_from_num(i); |
1943 | 2023 | ||
2024 | atomic_set(&nn->nn_timeout, 0); | ||
1944 | spin_lock_init(&nn->nn_lock); | 2025 | spin_lock_init(&nn->nn_lock); |
1945 | INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect); | 2026 | INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect); |
1946 | INIT_DELAYED_WORK(&nn->nn_connect_expired, | 2027 | INIT_DELAYED_WORK(&nn->nn_connect_expired, |
@@ -1962,4 +2043,5 @@ void o2net_exit(void) | |||
1962 | kfree(o2net_hand); | 2043 | kfree(o2net_hand); |
1963 | kfree(o2net_keep_req); | 2044 | kfree(o2net_keep_req); |
1964 | kfree(o2net_keep_resp); | 2045 | kfree(o2net_keep_resp); |
2046 | o2net_debugfs_exit(); | ||
1965 | } | 2047 | } |
diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h index f36f66aab3dd..a705d5d19036 100644 --- a/fs/ocfs2/cluster/tcp.h +++ b/fs/ocfs2/cluster/tcp.h | |||
@@ -117,4 +117,36 @@ int o2net_num_connected_peers(void); | |||
117 | int o2net_init(void); | 117 | int o2net_init(void); |
118 | void o2net_exit(void); | 118 | void o2net_exit(void); |
119 | 119 | ||
120 | struct o2net_send_tracking; | ||
121 | struct o2net_sock_container; | ||
122 | |||
123 | #ifdef CONFIG_DEBUG_FS | ||
124 | int o2net_debugfs_init(void); | ||
125 | void o2net_debugfs_exit(void); | ||
126 | void o2net_debug_add_nst(struct o2net_send_tracking *nst); | ||
127 | void o2net_debug_del_nst(struct o2net_send_tracking *nst); | ||
128 | void o2net_debug_add_sc(struct o2net_sock_container *sc); | ||
129 | void o2net_debug_del_sc(struct o2net_sock_container *sc); | ||
130 | #else | ||
131 | static int o2net_debugfs_init(void) | ||
132 | { | ||
133 | return 0; | ||
134 | } | ||
135 | static void o2net_debugfs_exit(void) | ||
136 | { | ||
137 | } | ||
138 | static void o2net_debug_add_nst(struct o2net_send_tracking *nst) | ||
139 | { | ||
140 | } | ||
141 | static void o2net_debug_del_nst(struct o2net_send_tracking *nst) | ||
142 | { | ||
143 | } | ||
144 | static void o2net_debug_add_sc(struct o2net_sock_container *sc) | ||
145 | { | ||
146 | } | ||
147 | static void o2net_debug_del_sc(struct o2net_sock_container *sc) | ||
148 | { | ||
149 | } | ||
150 | #endif /* CONFIG_DEBUG_FS */ | ||
151 | |||
120 | #endif /* O2CLUSTER_TCP_H */ | 152 | #endif /* O2CLUSTER_TCP_H */ |
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index d25b9af28500..8d58cfe410b1 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h | |||
@@ -95,6 +95,8 @@ struct o2net_node { | |||
95 | unsigned nn_sc_valid:1; | 95 | unsigned nn_sc_valid:1; |
96 | /* if this is set tx just returns it */ | 96 | /* if this is set tx just returns it */ |
97 | int nn_persistent_error; | 97 | int nn_persistent_error; |
98 | /* It is only set to 1 after the idle time out. */ | ||
99 | atomic_t nn_timeout; | ||
98 | 100 | ||
99 | /* threads waiting for an sc to arrive wait on the wq for generation | 101 | /* threads waiting for an sc to arrive wait on the wq for generation |
100 | * to increase. it is increased when a connecting socket succeeds | 102 | * to increase. it is increased when a connecting socket succeeds |
@@ -164,7 +166,9 @@ struct o2net_sock_container { | |||
164 | /* original handlers for the sockets */ | 166 | /* original handlers for the sockets */ |
165 | void (*sc_state_change)(struct sock *sk); | 167 | void (*sc_state_change)(struct sock *sk); |
166 | void (*sc_data_ready)(struct sock *sk, int bytes); | 168 | void (*sc_data_ready)(struct sock *sk, int bytes); |
167 | 169 | #ifdef CONFIG_DEBUG_FS | |
170 | struct list_head sc_net_debug_item; | ||
171 | #endif | ||
168 | struct timeval sc_tv_timer; | 172 | struct timeval sc_tv_timer; |
169 | struct timeval sc_tv_data_ready; | 173 | struct timeval sc_tv_data_ready; |
170 | struct timeval sc_tv_advance_start; | 174 | struct timeval sc_tv_advance_start; |
@@ -206,4 +210,24 @@ struct o2net_status_wait { | |||
206 | struct list_head ns_node_item; | 210 | struct list_head ns_node_item; |
207 | }; | 211 | }; |
208 | 212 | ||
213 | #ifdef CONFIG_DEBUG_FS | ||
214 | /* just for state dumps */ | ||
215 | struct o2net_send_tracking { | ||
216 | struct list_head st_net_debug_item; | ||
217 | struct task_struct *st_task; | ||
218 | struct o2net_sock_container *st_sc; | ||
219 | u32 st_id; | ||
220 | u32 st_msg_type; | ||
221 | u32 st_msg_key; | ||
222 | u8 st_node; | ||
223 | struct timeval st_sock_time; | ||
224 | struct timeval st_send_time; | ||
225 | struct timeval st_status_time; | ||
226 | }; | ||
227 | #else | ||
228 | struct o2net_send_tracking { | ||
229 | u32 dummy; | ||
230 | }; | ||
231 | #endif /* CONFIG_DEBUG_FS */ | ||
232 | |||
209 | #endif /* O2CLUSTER_TCP_INTERNAL_H */ | 233 | #endif /* O2CLUSTER_TCP_INTERNAL_H */ |