diff options
author | Jeff Layton <jlayton@primarydata.com> | 2014-11-21 14:19:31 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-12-09 11:29:14 -0500 |
commit | 83a712e0afefaf68555f816ea78ecd2862c6cf30 (patch) | |
tree | 05e25469b98a7f437209ea0a50580d7f291c3d90 /net/sunrpc | |
parent | b1691bc03d4eddb959234409167bef9be9e62d74 (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>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 22 |
1 files changed, 15 insertions, 7 deletions
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) | |||
322 | static void svc_xprt_do_enqueue(struct svc_xprt *xprt) | 322 | static 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(); |
401 | out: | ||
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 | 439 | out: | |
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 | } |
526 | EXPORT_SYMBOL_GPL(svc_wake_up); | 532 | EXPORT_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); |
780 | out: | ||
781 | trace_svc_handle_xprt(xprt, len); | ||
774 | return len; | 782 | return len; |
775 | } | 783 | } |
776 | 784 | ||