diff options
author | Sunil Mushran <sunil.mushran@oracle.com> | 2010-12-22 15:39:42 -0500 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-12-22 21:40:38 -0500 |
commit | db02754c8a1205b24beac70562c45ca5d671151f (patch) | |
tree | 320bf20f6940f4967388c56ca0fee576571eb005 /fs/ocfs2 | |
parent | e453039f8bf44abf82f3ecfb34177e0cb04bce12 (diff) |
ocfs2/cluster: Show o2net timing statistics
Adds debugfs dentry o2net/stats to show the o2net timing statistics.
Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/cluster/netdebug.c | 211 |
1 files changed, 157 insertions, 54 deletions
diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c index 536a93d13a06..61df89cedded 100644 --- a/fs/ocfs2/cluster/netdebug.c +++ b/fs/ocfs2/cluster/netdebug.c | |||
@@ -46,10 +46,15 @@ | |||
46 | #define O2NET_DEBUG_DIR "o2net" | 46 | #define O2NET_DEBUG_DIR "o2net" |
47 | #define SC_DEBUG_NAME "sock_containers" | 47 | #define SC_DEBUG_NAME "sock_containers" |
48 | #define NST_DEBUG_NAME "send_tracking" | 48 | #define NST_DEBUG_NAME "send_tracking" |
49 | #define STATS_DEBUG_NAME "stats" | ||
50 | |||
51 | #define SHOW_SOCK_CONTAINERS 0 | ||
52 | #define SHOW_SOCK_STATS 1 | ||
49 | 53 | ||
50 | static struct dentry *o2net_dentry; | 54 | static struct dentry *o2net_dentry; |
51 | static struct dentry *sc_dentry; | 55 | static struct dentry *sc_dentry; |
52 | static struct dentry *nst_dentry; | 56 | static struct dentry *nst_dentry; |
57 | static struct dentry *stats_dentry; | ||
53 | 58 | ||
54 | static DEFINE_SPINLOCK(o2net_debug_lock); | 59 | static DEFINE_SPINLOCK(o2net_debug_lock); |
55 | 60 | ||
@@ -232,6 +237,11 @@ void o2net_debug_del_sc(struct o2net_sock_container *sc) | |||
232 | spin_unlock(&o2net_debug_lock); | 237 | spin_unlock(&o2net_debug_lock); |
233 | } | 238 | } |
234 | 239 | ||
240 | struct o2net_sock_debug { | ||
241 | int dbg_ctxt; | ||
242 | struct o2net_sock_container *dbg_sock; | ||
243 | }; | ||
244 | |||
235 | static struct o2net_sock_container | 245 | static struct o2net_sock_container |
236 | *next_sc(struct o2net_sock_container *sc_start) | 246 | *next_sc(struct o2net_sock_container *sc_start) |
237 | { | 247 | { |
@@ -257,7 +267,8 @@ static struct o2net_sock_container | |||
257 | 267 | ||
258 | static void *sc_seq_start(struct seq_file *seq, loff_t *pos) | 268 | static void *sc_seq_start(struct seq_file *seq, loff_t *pos) |
259 | { | 269 | { |
260 | struct o2net_sock_container *sc, *dummy_sc = seq->private; | 270 | struct o2net_sock_debug *sd = seq->private; |
271 | struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; | ||
261 | 272 | ||
262 | spin_lock(&o2net_debug_lock); | 273 | spin_lock(&o2net_debug_lock); |
263 | sc = next_sc(dummy_sc); | 274 | sc = next_sc(dummy_sc); |
@@ -268,7 +279,8 @@ static void *sc_seq_start(struct seq_file *seq, loff_t *pos) | |||
268 | 279 | ||
269 | static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 280 | static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
270 | { | 281 | { |
271 | struct o2net_sock_container *sc, *dummy_sc = seq->private; | 282 | struct o2net_sock_debug *sd = seq->private; |
283 | struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; | ||
272 | 284 | ||
273 | spin_lock(&o2net_debug_lock); | 285 | spin_lock(&o2net_debug_lock); |
274 | sc = next_sc(dummy_sc); | 286 | sc = next_sc(dummy_sc); |
@@ -280,63 +292,107 @@ static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
280 | return sc; /* unused, just needs to be null when done */ | 292 | return sc; /* unused, just needs to be null when done */ |
281 | } | 293 | } |
282 | 294 | ||
283 | static int sc_seq_show(struct seq_file *seq, void *v) | 295 | #ifdef CONFIG_OCFS2_FS_STATS |
296 | # define sc_send_count(_s) ((_s)->sc_send_count) | ||
297 | # define sc_recv_count(_s) ((_s)->sc_recv_count) | ||
298 | # define sc_tv_acquiry_total_ns(_s) (ktime_to_ns((_s)->sc_tv_acquiry_total)) | ||
299 | # define sc_tv_send_total_ns(_s) (ktime_to_ns((_s)->sc_tv_send_total)) | ||
300 | # define sc_tv_status_total_ns(_s) (ktime_to_ns((_s)->sc_tv_status_total)) | ||
301 | # define sc_tv_process_total_ns(_s) (ktime_to_ns((_s)->sc_tv_process_total)) | ||
302 | #else | ||
303 | # define sc_send_count(_s) (0U) | ||
304 | # define sc_recv_count(_s) (0U) | ||
305 | # define sc_tv_acquiry_total_ns(_s) (0LL) | ||
306 | # define sc_tv_send_total_ns(_s) (0LL) | ||
307 | # define sc_tv_status_total_ns(_s) (0LL) | ||
308 | # define sc_tv_process_total_ns(_s) (0LL) | ||
309 | #endif | ||
310 | |||
311 | /* So that debugfs.ocfs2 can determine which format is being used */ | ||
312 | #define O2NET_STATS_STR_VERSION 1 | ||
313 | static void sc_show_sock_stats(struct seq_file *seq, | ||
314 | struct o2net_sock_container *sc) | ||
284 | { | 315 | { |
285 | struct o2net_sock_container *sc, *dummy_sc = seq->private; | 316 | if (!sc) |
317 | return; | ||
318 | |||
319 | seq_printf(seq, "%d,%u,%lu,%lld,%lld,%lld,%lu,%lld\n", O2NET_STATS_STR_VERSION, | ||
320 | sc->sc_node->nd_num, (unsigned long)sc_send_count(sc), | ||
321 | (long long)sc_tv_acquiry_total_ns(sc), | ||
322 | (long long)sc_tv_send_total_ns(sc), | ||
323 | (long long)sc_tv_status_total_ns(sc), | ||
324 | (unsigned long)sc_recv_count(sc), | ||
325 | (long long)sc_tv_process_total_ns(sc)); | ||
326 | } | ||
286 | 327 | ||
287 | spin_lock(&o2net_debug_lock); | 328 | static void sc_show_sock_container(struct seq_file *seq, |
288 | sc = next_sc(dummy_sc); | 329 | struct o2net_sock_container *sc) |
330 | { | ||
331 | struct inet_sock *inet = NULL; | ||
332 | __be32 saddr = 0, daddr = 0; | ||
333 | __be16 sport = 0, dport = 0; | ||
334 | |||
335 | if (!sc) | ||
336 | return; | ||
337 | |||
338 | if (sc->sc_sock) { | ||
339 | inet = inet_sk(sc->sc_sock->sk); | ||
340 | /* the stack's structs aren't sparse endian clean */ | ||
341 | saddr = (__force __be32)inet->inet_saddr; | ||
342 | daddr = (__force __be32)inet->inet_daddr; | ||
343 | sport = (__force __be16)inet->inet_sport; | ||
344 | dport = (__force __be16)inet->inet_dport; | ||
345 | } | ||
289 | 346 | ||
290 | if (sc != NULL) { | 347 | /* XXX sigh, inet-> doesn't have sparse annotation so any |
291 | struct inet_sock *inet = NULL; | 348 | * use of it here generates a warning with -Wbitwise */ |
349 | seq_printf(seq, "%p:\n" | ||
350 | " krefs: %d\n" | ||
351 | " sock: %pI4:%u -> " | ||
352 | "%pI4:%u\n" | ||
353 | " remote node: %s\n" | ||
354 | " page off: %zu\n" | ||
355 | " handshake ok: %u\n" | ||
356 | " timer: %lld usecs\n" | ||
357 | " data ready: %lld usecs\n" | ||
358 | " advance start: %lld usecs\n" | ||
359 | " advance stop: %lld usecs\n" | ||
360 | " func start: %lld usecs\n" | ||
361 | " func stop: %lld usecs\n" | ||
362 | " func key: 0x%08x\n" | ||
363 | " func type: %u\n", | ||
364 | sc, | ||
365 | atomic_read(&sc->sc_kref.refcount), | ||
366 | &saddr, inet ? ntohs(sport) : 0, | ||
367 | &daddr, inet ? ntohs(dport) : 0, | ||
368 | sc->sc_node->nd_name, | ||
369 | sc->sc_page_off, | ||
370 | sc->sc_handshake_ok, | ||
371 | (long long)ktime_to_us(sc->sc_tv_timer), | ||
372 | (long long)ktime_to_us(sc->sc_tv_data_ready), | ||
373 | (long long)ktime_to_us(sc->sc_tv_advance_start), | ||
374 | (long long)ktime_to_us(sc->sc_tv_advance_stop), | ||
375 | (long long)ktime_to_us(sc->sc_tv_func_start), | ||
376 | (long long)ktime_to_us(sc->sc_tv_func_stop), | ||
377 | sc->sc_msg_key, | ||
378 | sc->sc_msg_type); | ||
379 | } | ||
292 | 380 | ||
293 | __be32 saddr = 0, daddr = 0; | 381 | static int sc_seq_show(struct seq_file *seq, void *v) |
294 | __be16 sport = 0, dport = 0; | 382 | { |
383 | struct o2net_sock_debug *sd = seq->private; | ||
384 | struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; | ||
295 | 385 | ||
296 | if (sc->sc_sock) { | 386 | spin_lock(&o2net_debug_lock); |
297 | inet = inet_sk(sc->sc_sock->sk); | 387 | sc = next_sc(dummy_sc); |
298 | /* the stack's structs aren't sparse endian clean */ | ||
299 | saddr = (__force __be32)inet->inet_saddr; | ||
300 | daddr = (__force __be32)inet->inet_daddr; | ||
301 | sport = (__force __be16)inet->inet_sport; | ||
302 | dport = (__force __be16)inet->inet_dport; | ||
303 | } | ||
304 | 388 | ||
305 | /* XXX sigh, inet-> doesn't have sparse annotation so any | 389 | if (sc) { |
306 | * use of it here generates a warning with -Wbitwise */ | 390 | if (sd->dbg_ctxt == SHOW_SOCK_CONTAINERS) |
307 | seq_printf(seq, "%p:\n" | 391 | sc_show_sock_container(seq, sc); |
308 | " krefs: %d\n" | 392 | else |
309 | " sock: %pI4:%u -> " | 393 | sc_show_sock_stats(seq, sc); |
310 | "%pI4:%u\n" | ||
311 | " remote node: %s\n" | ||
312 | " page off: %zu\n" | ||
313 | " handshake ok: %u\n" | ||
314 | " timer: %lld usecs\n" | ||
315 | " data ready: %lld usecs\n" | ||
316 | " advance start: %lld usecs\n" | ||
317 | " advance stop: %lld usecs\n" | ||
318 | " func start: %lld usecs\n" | ||
319 | " func stop: %lld usecs\n" | ||
320 | " func key: 0x%08x\n" | ||
321 | " func type: %u\n", | ||
322 | sc, | ||
323 | atomic_read(&sc->sc_kref.refcount), | ||
324 | &saddr, inet ? ntohs(sport) : 0, | ||
325 | &daddr, inet ? ntohs(dport) : 0, | ||
326 | sc->sc_node->nd_name, | ||
327 | sc->sc_page_off, | ||
328 | sc->sc_handshake_ok, | ||
329 | (long long)ktime_to_us(sc->sc_tv_timer), | ||
330 | (long long)ktime_to_us(sc->sc_tv_data_ready), | ||
331 | (long long)ktime_to_us(sc->sc_tv_advance_start), | ||
332 | (long long)ktime_to_us(sc->sc_tv_advance_stop), | ||
333 | (long long)ktime_to_us(sc->sc_tv_func_start), | ||
334 | (long long)ktime_to_us(sc->sc_tv_func_stop), | ||
335 | sc->sc_msg_key, | ||
336 | sc->sc_msg_type); | ||
337 | } | 394 | } |
338 | 395 | ||
339 | |||
340 | spin_unlock(&o2net_debug_lock); | 396 | spin_unlock(&o2net_debug_lock); |
341 | 397 | ||
342 | return 0; | 398 | return 0; |
@@ -353,7 +409,7 @@ static const struct seq_operations sc_seq_ops = { | |||
353 | .show = sc_seq_show, | 409 | .show = sc_seq_show, |
354 | }; | 410 | }; |
355 | 411 | ||
356 | static int sc_fop_open(struct inode *inode, struct file *file) | 412 | static int sc_common_open(struct file *file, struct o2net_sock_debug *sd) |
357 | { | 413 | { |
358 | struct o2net_sock_container *dummy_sc; | 414 | struct o2net_sock_container *dummy_sc; |
359 | struct seq_file *seq; | 415 | struct seq_file *seq; |
@@ -371,7 +427,8 @@ static int sc_fop_open(struct inode *inode, struct file *file) | |||
371 | goto out; | 427 | goto out; |
372 | 428 | ||
373 | seq = file->private_data; | 429 | seq = file->private_data; |
374 | seq->private = dummy_sc; | 430 | seq->private = sd; |
431 | sd->dbg_sock = dummy_sc; | ||
375 | o2net_debug_add_sc(dummy_sc); | 432 | o2net_debug_add_sc(dummy_sc); |
376 | 433 | ||
377 | dummy_sc = NULL; | 434 | dummy_sc = NULL; |
@@ -384,12 +441,48 @@ out: | |||
384 | static int sc_fop_release(struct inode *inode, struct file *file) | 441 | static int sc_fop_release(struct inode *inode, struct file *file) |
385 | { | 442 | { |
386 | struct seq_file *seq = file->private_data; | 443 | struct seq_file *seq = file->private_data; |
387 | struct o2net_sock_container *dummy_sc = seq->private; | 444 | struct o2net_sock_debug *sd = seq->private; |
445 | struct o2net_sock_container *dummy_sc = sd->dbg_sock; | ||
388 | 446 | ||
389 | o2net_debug_del_sc(dummy_sc); | 447 | o2net_debug_del_sc(dummy_sc); |
390 | return seq_release_private(inode, file); | 448 | return seq_release_private(inode, file); |
391 | } | 449 | } |
392 | 450 | ||
451 | static int stats_fop_open(struct inode *inode, struct file *file) | ||
452 | { | ||
453 | struct o2net_sock_debug *sd; | ||
454 | |||
455 | sd = kmalloc(sizeof(struct o2net_sock_debug), GFP_KERNEL); | ||
456 | if (sd == NULL) | ||
457 | return -ENOMEM; | ||
458 | |||
459 | sd->dbg_ctxt = SHOW_SOCK_STATS; | ||
460 | sd->dbg_sock = NULL; | ||
461 | |||
462 | return sc_common_open(file, sd); | ||
463 | } | ||
464 | |||
465 | static const struct file_operations stats_seq_fops = { | ||
466 | .open = stats_fop_open, | ||
467 | .read = seq_read, | ||
468 | .llseek = seq_lseek, | ||
469 | .release = sc_fop_release, | ||
470 | }; | ||
471 | |||
472 | static int sc_fop_open(struct inode *inode, struct file *file) | ||
473 | { | ||
474 | struct o2net_sock_debug *sd; | ||
475 | |||
476 | sd = kmalloc(sizeof(struct o2net_sock_debug), GFP_KERNEL); | ||
477 | if (sd == NULL) | ||
478 | return -ENOMEM; | ||
479 | |||
480 | sd->dbg_ctxt = SHOW_SOCK_CONTAINERS; | ||
481 | sd->dbg_sock = NULL; | ||
482 | |||
483 | return sc_common_open(file, sd); | ||
484 | } | ||
485 | |||
393 | static const struct file_operations sc_seq_fops = { | 486 | static const struct file_operations sc_seq_fops = { |
394 | .open = sc_fop_open, | 487 | .open = sc_fop_open, |
395 | .read = seq_read, | 488 | .read = seq_read, |
@@ -421,8 +514,17 @@ int o2net_debugfs_init(void) | |||
421 | goto bail; | 514 | goto bail; |
422 | } | 515 | } |
423 | 516 | ||
517 | stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, S_IFREG|S_IRUSR, | ||
518 | o2net_dentry, NULL, | ||
519 | &stats_seq_fops); | ||
520 | if (!stats_dentry) { | ||
521 | mlog_errno(-ENOMEM); | ||
522 | goto bail; | ||
523 | } | ||
524 | |||
424 | return 0; | 525 | return 0; |
425 | bail: | 526 | bail: |
527 | debugfs_remove(stats_dentry); | ||
426 | debugfs_remove(sc_dentry); | 528 | debugfs_remove(sc_dentry); |
427 | debugfs_remove(nst_dentry); | 529 | debugfs_remove(nst_dentry); |
428 | debugfs_remove(o2net_dentry); | 530 | debugfs_remove(o2net_dentry); |
@@ -431,6 +533,7 @@ bail: | |||
431 | 533 | ||
432 | void o2net_debugfs_exit(void) | 534 | void o2net_debugfs_exit(void) |
433 | { | 535 | { |
536 | debugfs_remove(stats_dentry); | ||
434 | debugfs_remove(sc_dentry); | 537 | debugfs_remove(sc_dentry); |
435 | debugfs_remove(nst_dentry); | 538 | debugfs_remove(nst_dentry); |
436 | debugfs_remove(o2net_dentry); | 539 | debugfs_remove(o2net_dentry); |