aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-11-21 14:19:31 -0500
committerJ. Bruce Fields <bfields@redhat.com>2014-12-09 11:29:14 -0500
commit83a712e0afefaf68555f816ea78ecd2862c6cf30 (patch)
tree05e25469b98a7f437209ea0a50580d7f291c3d90
parentb1691bc03d4eddb959234409167bef9be9e62d74 (diff)
sunrpc: add some tracepoints around enqueue and dequeue of svc_xprt
These were useful when I was tracking down a race condition between svc_xprt_do_enqueue and svc_get_next_xprt. Signed-off-by: Jeff Layton <jlayton@primarydata.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--include/trace/events/sunrpc.h94
-rw-r--r--net/sunrpc/svc_xprt.c22
2 files changed, 109 insertions, 7 deletions
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index ee4438a63a48..b9c1dc6c825a 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -8,6 +8,7 @@
8#include <linux/sunrpc/clnt.h> 8#include <linux/sunrpc/clnt.h>
9#include <linux/sunrpc/svc.h> 9#include <linux/sunrpc/svc.h>
10#include <linux/sunrpc/xprtsock.h> 10#include <linux/sunrpc/xprtsock.h>
11#include <linux/sunrpc/svc_xprt.h>
11#include <net/tcp_states.h> 12#include <net/tcp_states.h>
12#include <linux/net.h> 13#include <linux/net.h>
13#include <linux/tracepoint.h> 14#include <linux/tracepoint.h>
@@ -480,6 +481,99 @@ DEFINE_EVENT(svc_rqst_status, svc_send,
480 TP_PROTO(struct svc_rqst *rqst, int status), 481 TP_PROTO(struct svc_rqst *rqst, int status),
481 TP_ARGS(rqst, status)); 482 TP_ARGS(rqst, status));
482 483
484#define show_svc_xprt_flags(flags) \
485 __print_flags(flags, "|", \
486 { (1UL << XPT_BUSY), "XPT_BUSY"}, \
487 { (1UL << XPT_CONN), "XPT_CONN"}, \
488 { (1UL << XPT_CLOSE), "XPT_CLOSE"}, \
489 { (1UL << XPT_DATA), "XPT_DATA"}, \
490 { (1UL << XPT_TEMP), "XPT_TEMP"}, \
491 { (1UL << XPT_DEAD), "XPT_DEAD"}, \
492 { (1UL << XPT_CHNGBUF), "XPT_CHNGBUF"}, \
493 { (1UL << XPT_DEFERRED), "XPT_DEFERRED"}, \
494 { (1UL << XPT_OLD), "XPT_OLD"}, \
495 { (1UL << XPT_LISTENER), "XPT_LISTENER"}, \
496 { (1UL << XPT_CACHE_AUTH), "XPT_CACHE_AUTH"}, \
497 { (1UL << XPT_LOCAL), "XPT_LOCAL"})
498
499TRACE_EVENT(svc_xprt_do_enqueue,
500 TP_PROTO(struct svc_xprt *xprt, struct svc_rqst *rqst),
501
502 TP_ARGS(xprt, rqst),
503
504 TP_STRUCT__entry(
505 __field(struct svc_xprt *, xprt)
506 __field(struct svc_rqst *, rqst)
507 ),
508
509 TP_fast_assign(
510 __entry->xprt = xprt;
511 __entry->rqst = rqst;
512 ),
513
514 TP_printk("xprt=0x%p addr=%pIScp pid=%d flags=%s", __entry->xprt,
515 (struct sockaddr *)&__entry->xprt->xpt_remote,
516 __entry->rqst ? __entry->rqst->rq_task->pid : 0,
517 show_svc_xprt_flags(__entry->xprt->xpt_flags))
518);
519
520TRACE_EVENT(svc_xprt_dequeue,
521 TP_PROTO(struct svc_xprt *xprt),
522
523 TP_ARGS(xprt),
524
525 TP_STRUCT__entry(
526 __field(struct svc_xprt *, xprt)
527 __field_struct(struct sockaddr_storage, ss)
528 __field(unsigned long, flags)
529 ),
530
531 TP_fast_assign(
532 __entry->xprt = xprt,
533 xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
534 __entry->flags = xprt ? xprt->xpt_flags : 0;
535 ),
536
537 TP_printk("xprt=0x%p addr=%pIScp flags=%s", __entry->xprt,
538 (struct sockaddr *)&__entry->ss,
539 show_svc_xprt_flags(__entry->flags))
540);
541
542TRACE_EVENT(svc_wake_up,
543 TP_PROTO(int pid),
544
545 TP_ARGS(pid),
546
547 TP_STRUCT__entry(
548 __field(int, pid)
549 ),
550
551 TP_fast_assign(
552 __entry->pid = pid;
553 ),
554
555 TP_printk("pid=%d", __entry->pid)
556);
557
558TRACE_EVENT(svc_handle_xprt,
559 TP_PROTO(struct svc_xprt *xprt, int len),
560
561 TP_ARGS(xprt, len),
562
563 TP_STRUCT__entry(
564 __field(struct svc_xprt *, xprt)
565 __field(int, len)
566 ),
567
568 TP_fast_assign(
569 __entry->xprt = xprt;
570 __entry->len = len;
571 ),
572
573 TP_printk("xprt=0x%p addr=%pIScp len=%d flags=%s", __entry->xprt,
574 (struct sockaddr *)&__entry->xprt->xpt_remote, __entry->len,
575 show_svc_xprt_flags(__entry->xprt->xpt_flags))
576);
483#endif /* _TRACE_SUNRPC_H */ 577#endif /* _TRACE_SUNRPC_H */
484 578
485#include <trace/define_trace.h> 579#include <trace/define_trace.h>
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index ed90d955f733..73d40bd1839a 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -322,12 +322,12 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
322static void svc_xprt_do_enqueue(struct svc_xprt *xprt) 322static void svc_xprt_do_enqueue(struct svc_xprt *xprt)
323{ 323{
324 struct svc_pool *pool; 324 struct svc_pool *pool;
325 struct svc_rqst *rqstp; 325 struct svc_rqst *rqstp = NULL;
326 int cpu; 326 int cpu;
327 bool queued = false; 327 bool queued = false;
328 328
329 if (!svc_xprt_has_something_to_do(xprt)) 329 if (!svc_xprt_has_something_to_do(xprt))
330 return; 330 goto out;
331 331
332 /* Mark transport as busy. It will remain in this state until 332 /* Mark transport as busy. It will remain in this state until
333 * the provider calls svc_xprt_received. We update XPT_BUSY 333 * the provider calls svc_xprt_received. We update XPT_BUSY
@@ -337,7 +337,7 @@ static void svc_xprt_do_enqueue(struct svc_xprt *xprt)
337 if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) { 337 if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) {
338 /* Don't enqueue transport while already enqueued */ 338 /* Don't enqueue transport while already enqueued */
339 dprintk("svc: transport %p busy, not enqueued\n", xprt); 339 dprintk("svc: transport %p busy, not enqueued\n", xprt);
340 return; 340 goto out;
341 } 341 }
342 342
343 cpu = get_cpu(); 343 cpu = get_cpu();
@@ -377,7 +377,7 @@ redo_search:
377 atomic_long_inc(&pool->sp_stats.threads_woken); 377 atomic_long_inc(&pool->sp_stats.threads_woken);
378 wake_up_process(rqstp->rq_task); 378 wake_up_process(rqstp->rq_task);
379 put_cpu(); 379 put_cpu();
380 return; 380 goto out;
381 } 381 }
382 rcu_read_unlock(); 382 rcu_read_unlock();
383 383
@@ -396,7 +396,10 @@ redo_search:
396 spin_unlock_bh(&pool->sp_lock); 396 spin_unlock_bh(&pool->sp_lock);
397 goto redo_search; 397 goto redo_search;
398 } 398 }
399 rqstp = NULL;
399 put_cpu(); 400 put_cpu();
401out:
402 trace_svc_xprt_do_enqueue(xprt, rqstp);
400} 403}
401 404
402/* 405/*
@@ -420,7 +423,7 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
420 struct svc_xprt *xprt = NULL; 423 struct svc_xprt *xprt = NULL;
421 424
422 if (list_empty(&pool->sp_sockets)) 425 if (list_empty(&pool->sp_sockets))
423 return NULL; 426 goto out;
424 427
425 spin_lock_bh(&pool->sp_lock); 428 spin_lock_bh(&pool->sp_lock);
426 if (likely(!list_empty(&pool->sp_sockets))) { 429 if (likely(!list_empty(&pool->sp_sockets))) {
@@ -433,7 +436,8 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
433 xprt, atomic_read(&xprt->xpt_ref.refcount)); 436 xprt, atomic_read(&xprt->xpt_ref.refcount));
434 } 437 }
435 spin_unlock_bh(&pool->sp_lock); 438 spin_unlock_bh(&pool->sp_lock);
436 439out:
440 trace_svc_xprt_dequeue(xprt);
437 return xprt; 441 return xprt;
438} 442}
439 443
@@ -515,6 +519,7 @@ void svc_wake_up(struct svc_serv *serv)
515 rcu_read_unlock(); 519 rcu_read_unlock();
516 dprintk("svc: daemon %p woken up.\n", rqstp); 520 dprintk("svc: daemon %p woken up.\n", rqstp);
517 wake_up_process(rqstp->rq_task); 521 wake_up_process(rqstp->rq_task);
522 trace_svc_wake_up(rqstp->rq_task->pid);
518 return; 523 return;
519 } 524 }
520 rcu_read_unlock(); 525 rcu_read_unlock();
@@ -522,6 +527,7 @@ void svc_wake_up(struct svc_serv *serv)
522 /* No free entries available */ 527 /* No free entries available */
523 set_bit(SP_TASK_PENDING, &pool->sp_flags); 528 set_bit(SP_TASK_PENDING, &pool->sp_flags);
524 smp_wmb(); 529 smp_wmb();
530 trace_svc_wake_up(0);
525} 531}
526EXPORT_SYMBOL_GPL(svc_wake_up); 532EXPORT_SYMBOL_GPL(svc_wake_up);
527 533
@@ -740,7 +746,7 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
740 dprintk("svc_recv: found XPT_CLOSE\n"); 746 dprintk("svc_recv: found XPT_CLOSE\n");
741 svc_delete_xprt(xprt); 747 svc_delete_xprt(xprt);
742 /* Leave XPT_BUSY set on the dead xprt: */ 748 /* Leave XPT_BUSY set on the dead xprt: */
743 return 0; 749 goto out;
744 } 750 }
745 if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { 751 if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
746 struct svc_xprt *newxpt; 752 struct svc_xprt *newxpt;
@@ -771,6 +777,8 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
771 } 777 }
772 /* clear XPT_BUSY: */ 778 /* clear XPT_BUSY: */
773 svc_xprt_received(xprt); 779 svc_xprt_received(xprt);
780out:
781 trace_svc_handle_xprt(xprt, len);
774 return len; 782 return len;
775} 783}
776 784